@onekeyfe/react-native-skeleton 3.0.96 → 3.0.98
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/main/java/com/margelo/nitro/skeleton/OneKeySkeletonRenderer.kt +173 -0
- package/android/src/main/java/com/margelo/nitro/skeleton/Skeleton.kt +63 -194
- package/ios/Skeleton.swift +58 -272
- package/ios/SkeletonRenderer.swift +146 -0
- package/lib/nitrogen/generated/android/c++/views/JHybridSkeletonStateUpdater.cpp +42 -23
- package/lib/nitrogen/generated/android/c++/views/JHybridSkeletonStateUpdater.hpp +6 -1
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/skeleton/views/HybridSkeletonManager.kt +26 -10
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/skeleton/views/HybridSkeletonStateUpdater.kt +2 -2
- package/lib/nitrogen/generated/ios/c++/views/HybridSkeletonComponent.mm +50 -27
- package/lib/nitrogen/generated/shared/c++/views/HybridSkeletonComponent.cpp +7 -65
- package/lib/nitrogen/generated/shared/c++/views/HybridSkeletonComponent.hpp +26 -50
- package/nitrogen/generated/android/c++/views/JHybridSkeletonStateUpdater.cpp +42 -23
- package/nitrogen/generated/android/c++/views/JHybridSkeletonStateUpdater.hpp +6 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/skeleton/views/HybridSkeletonManager.kt +26 -10
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/skeleton/views/HybridSkeletonStateUpdater.kt +2 -2
- package/nitrogen/generated/ios/c++/views/HybridSkeletonComponent.mm +50 -27
- package/nitrogen/generated/shared/c++/views/HybridSkeletonComponent.cpp +7 -65
- package/nitrogen/generated/shared/c++/views/HybridSkeletonComponent.hpp +26 -50
- package/package.json +4 -4
|
@@ -20,6 +20,14 @@ import com.margelo.nitro.skeleton.*
|
|
|
20
20
|
* Represents the React Native `ViewManager` for the "Skeleton" Nitro HybridView.
|
|
21
21
|
*/
|
|
22
22
|
public class HybridSkeletonManager: SimpleViewManager<View>() {
|
|
23
|
+
/**
|
|
24
|
+
* Represents the View and its last state snapshot (mutable)
|
|
25
|
+
*/
|
|
26
|
+
private class HybridViewHolder(
|
|
27
|
+
val hybridView: HybridSkeleton,
|
|
28
|
+
var lastState: StateWrapper? = null,
|
|
29
|
+
)
|
|
30
|
+
|
|
23
31
|
init {
|
|
24
32
|
if (RecyclableView::class.java.isAssignableFrom(HybridSkeleton::class.java)) {
|
|
25
33
|
// Enable view recycling
|
|
@@ -34,33 +42,41 @@ public class HybridSkeletonManager: SimpleViewManager<View>() {
|
|
|
34
42
|
override fun createViewInstance(reactContext: ThemedReactContext): View {
|
|
35
43
|
val hybridView = HybridSkeleton(reactContext)
|
|
36
44
|
val view = hybridView.view
|
|
37
|
-
view.setTag(associated_hybrid_view_tag, hybridView)
|
|
45
|
+
view.setTag(associated_hybrid_view_tag, HybridViewHolder(hybridView))
|
|
38
46
|
return view
|
|
39
47
|
}
|
|
40
48
|
|
|
41
49
|
override fun updateState(view: View, props: ReactStylesDiffMap, stateWrapper: StateWrapper): Any? {
|
|
42
|
-
val
|
|
50
|
+
val holder = getHybridViewHolder(view)
|
|
43
51
|
?: throw Error("Couldn't find view $view in local views table!")
|
|
52
|
+
val hybridView = holder.hybridView
|
|
53
|
+
val oldState = holder.lastState
|
|
54
|
+
val newState = stateWrapper
|
|
44
55
|
|
|
45
56
|
// 1. Update each prop individually
|
|
46
57
|
hybridView.beforeUpdate()
|
|
47
|
-
HybridSkeletonStateUpdater.updateViewProps(hybridView,
|
|
58
|
+
HybridSkeletonStateUpdater.updateViewProps(hybridView, newState, oldState)
|
|
48
59
|
hybridView.afterUpdate()
|
|
60
|
+
holder.lastState = newState
|
|
49
61
|
|
|
50
62
|
// 2. Continue in base View props
|
|
51
|
-
return super.updateState(view, props,
|
|
63
|
+
return super.updateState(view, props, newState)
|
|
52
64
|
}
|
|
53
65
|
|
|
54
66
|
override fun onDropViewInstance(view: View) {
|
|
55
|
-
val
|
|
56
|
-
|
|
67
|
+
val holder = getHybridViewHolder(view)
|
|
68
|
+
holder?.lastState = null
|
|
69
|
+
holder?.hybridView?.onDropView()
|
|
57
70
|
return super.onDropViewInstance(view)
|
|
58
71
|
}
|
|
59
72
|
|
|
60
73
|
protected override fun prepareToRecycleView(reactContext: ThemedReactContext, view: View): View? {
|
|
61
|
-
super.prepareToRecycleView(reactContext, view)
|
|
62
|
-
|
|
74
|
+
val preparedView = super.prepareToRecycleView(reactContext, view)
|
|
75
|
+
?: return null
|
|
76
|
+
val holder = getHybridViewHolder(preparedView)
|
|
63
77
|
?: return null
|
|
78
|
+
val hybridView = holder.hybridView
|
|
79
|
+
holder.lastState = null
|
|
64
80
|
|
|
65
81
|
@Suppress("USELESS_IS_CHECK")
|
|
66
82
|
if (hybridView is RecyclableView) {
|
|
@@ -74,7 +90,7 @@ public class HybridSkeletonManager: SimpleViewManager<View>() {
|
|
|
74
90
|
}
|
|
75
91
|
}
|
|
76
92
|
|
|
77
|
-
private fun
|
|
78
|
-
return view.getTag(associated_hybrid_view_tag) as?
|
|
93
|
+
private fun getHybridViewHolder(view: View): HybridViewHolder? {
|
|
94
|
+
return view.getTag(associated_hybrid_view_tag) as? HybridViewHolder
|
|
79
95
|
}
|
|
80
96
|
}
|
|
@@ -14,10 +14,10 @@ internal class HybridSkeletonStateUpdater {
|
|
|
14
14
|
companion object {
|
|
15
15
|
/**
|
|
16
16
|
* Updates the props for [view] through C++.
|
|
17
|
-
* The [
|
|
17
|
+
* The [newState] prop is expected to contain [view]'s props as wrapped Fabric state.
|
|
18
18
|
*/
|
|
19
19
|
@Suppress("KotlinJniMissingFunction")
|
|
20
20
|
@JvmStatic
|
|
21
|
-
external fun updateViewProps(view: HybridSkeletonSpec,
|
|
21
|
+
external fun updateViewProps(view: HybridSkeletonSpec, newState: StateWrapper, oldState: StateWrapper?)
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -37,6 +37,7 @@ using namespace margelo::nitro::skeleton::views;
|
|
|
37
37
|
|
|
38
38
|
@implementation HybridSkeletonComponent {
|
|
39
39
|
std::shared_ptr<HybridSkeletonSpecSwift> _hybridView;
|
|
40
|
+
BOOL _didDropView;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
+ (void) load {
|
|
@@ -50,6 +51,7 @@ using namespace margelo::nitro::skeleton::views;
|
|
|
50
51
|
|
|
51
52
|
- (instancetype) init {
|
|
52
53
|
if (self = [super init]) {
|
|
54
|
+
_props = HybridSkeletonShadowNode::defaultSharedProps();
|
|
53
55
|
std::shared_ptr<HybridSkeletonSpec> hybridView = Skeleton::SkeletonAutolinking::createSkeleton();
|
|
54
56
|
_hybridView = std::dynamic_pointer_cast<HybridSkeletonSpecSwift>(hybridView);
|
|
55
57
|
[self updateView];
|
|
@@ -69,40 +71,61 @@ using namespace margelo::nitro::skeleton::views;
|
|
|
69
71
|
[self setContentView:view];
|
|
70
72
|
}
|
|
71
73
|
|
|
74
|
+
- (void) notifyOnDropView {
|
|
75
|
+
// A recycled component can later be invalidated. Notify only once per mount.
|
|
76
|
+
if (_didDropView) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
Skeleton::HybridSkeletonSpec_cxx& swiftPart = _hybridView->getSwiftPart();
|
|
80
|
+
swiftPart.onDropView();
|
|
81
|
+
_didDropView = YES;
|
|
82
|
+
}
|
|
83
|
+
|
|
72
84
|
- (void) updateProps:(const std::shared_ptr<const react::Props>&)props
|
|
73
85
|
oldProps:(const std::shared_ptr<const react::Props>&)oldProps {
|
|
86
|
+
// A props update marks a newly mounted or still-active component.
|
|
87
|
+
_didDropView = NO;
|
|
88
|
+
|
|
74
89
|
// 1. Downcast props
|
|
75
|
-
const auto&
|
|
76
|
-
auto
|
|
90
|
+
const auto& newViewProps = *std::static_pointer_cast<const HybridSkeletonProps>(props);
|
|
91
|
+
const auto* oldViewProps = static_cast<const HybridSkeletonProps*>(oldProps.get());
|
|
77
92
|
Skeleton::HybridSkeletonSpec_cxx& swiftPart = _hybridView->getSwiftPart();
|
|
78
93
|
|
|
79
|
-
// 2. Update
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (
|
|
84
|
-
swiftPart.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
// 2. Update only props that differ from the previous Props snapshot.
|
|
95
|
+
const bool hasTransactionPropChanges = oldViewProps == nullptr
|
|
96
|
+
? newViewProps.hasAnyProvidedProps()
|
|
97
|
+
: !newViewProps.hasSameProps(*oldViewProps);
|
|
98
|
+
if (hasTransactionPropChanges) {
|
|
99
|
+
swiftPart.beforeUpdate();
|
|
100
|
+
|
|
101
|
+
// shimmerSpeed: optional
|
|
102
|
+
if (oldViewProps == nullptr
|
|
103
|
+
? newViewProps.shimmerSpeed.isProvided()
|
|
104
|
+
: !newViewProps.shimmerSpeed.hasSameValue(oldViewProps->shimmerSpeed)) {
|
|
105
|
+
swiftPart.setShimmerSpeed(newViewProps.shimmerSpeed.get());
|
|
106
|
+
}
|
|
107
|
+
// shimmerGradientColors: optional
|
|
108
|
+
if (oldViewProps == nullptr
|
|
109
|
+
? newViewProps.shimmerGradientColors.isProvided()
|
|
110
|
+
: !newViewProps.shimmerGradientColors.hasSameValue(oldViewProps->shimmerGradientColors)) {
|
|
111
|
+
swiftPart.setShimmerGradientColors(newViewProps.shimmerGradientColors.get());
|
|
112
|
+
}
|
|
94
113
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
maybeFunc.
|
|
114
|
+
// Update hybridRef if it changed
|
|
115
|
+
if (oldViewProps == nullptr
|
|
116
|
+
? newViewProps.hybridRef.isProvided()
|
|
117
|
+
: !newViewProps.hybridRef.hasSameValue(oldViewProps->hybridRef)) {
|
|
118
|
+
// hybridRef changed - call it with new this
|
|
119
|
+
const auto& maybeFunc = newViewProps.hybridRef.get();
|
|
120
|
+
if (maybeFunc.has_value()) {
|
|
121
|
+
maybeFunc.value()(_hybridView);
|
|
122
|
+
}
|
|
101
123
|
}
|
|
102
|
-
|
|
124
|
+
|
|
125
|
+
swiftPart.afterUpdate();
|
|
103
126
|
}
|
|
104
127
|
|
|
105
|
-
//
|
|
128
|
+
// 3. Continue in base class
|
|
106
129
|
[super updateProps:props oldProps:oldProps];
|
|
107
130
|
}
|
|
108
131
|
|
|
@@ -111,6 +134,7 @@ using namespace margelo::nitro::skeleton::views;
|
|
|
111
134
|
}
|
|
112
135
|
|
|
113
136
|
- (void)prepareForRecycle {
|
|
137
|
+
[self notifyOnDropView];
|
|
114
138
|
[super prepareForRecycle];
|
|
115
139
|
Skeleton::HybridSkeletonSpec_cxx& swiftPart = _hybridView->getSwiftPart();
|
|
116
140
|
swiftPart.maybePrepareForRecycle();
|
|
@@ -118,8 +142,7 @@ using namespace margelo::nitro::skeleton::views;
|
|
|
118
142
|
|
|
119
143
|
#ifdef ENABLE_RCT_COMPONENT_VIEW_INVALIDATE
|
|
120
144
|
- (void)invalidate {
|
|
121
|
-
|
|
122
|
-
swiftPart.onDropView();
|
|
145
|
+
[self notifyOnDropView];
|
|
123
146
|
[super invalidate];
|
|
124
147
|
}
|
|
125
148
|
#endif
|
|
@@ -7,55 +7,22 @@
|
|
|
7
7
|
|
|
8
8
|
#include "HybridSkeletonComponent.hpp"
|
|
9
9
|
|
|
10
|
-
#include <
|
|
11
|
-
#include <
|
|
12
|
-
#include <utility>
|
|
13
|
-
#include <NitroModules/NitroDefines.hpp>
|
|
14
|
-
#include <NitroModules/JSIConverter.hpp>
|
|
15
|
-
#include <NitroModules/PropNameIDCache.hpp>
|
|
16
|
-
#include <react/renderer/core/RawValue.h>
|
|
17
|
-
#include <react/renderer/core/ShadowNode.h>
|
|
18
|
-
#include <react/renderer/core/ComponentDescriptor.h>
|
|
19
|
-
#include <react/renderer/components/view/ViewProps.h>
|
|
10
|
+
#include <NitroModules/NitroHash.hpp>
|
|
11
|
+
#include <NitroModules/ReactProp.hpp>
|
|
20
12
|
|
|
21
13
|
namespace margelo::nitro::skeleton::views {
|
|
22
14
|
|
|
15
|
+
using namespace facebook;
|
|
16
|
+
|
|
23
17
|
extern const char HybridSkeletonComponentName[] = "Skeleton";
|
|
24
18
|
|
|
25
19
|
HybridSkeletonProps::HybridSkeletonProps(const react::PropsParserContext& context,
|
|
26
20
|
const HybridSkeletonProps& sourceProps,
|
|
27
21
|
const react::RawProps& rawProps):
|
|
28
22
|
react::ViewProps(context, sourceProps, rawProps, filterObjectKeys),
|
|
29
|
-
shimmerSpeed(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (rawValue == nullptr) return sourceProps.shimmerSpeed;
|
|
33
|
-
const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
|
|
34
|
-
return CachedProp<std::optional<double>>::fromRawValue(*runtime, value, sourceProps.shimmerSpeed);
|
|
35
|
-
} catch (const std::exception& exc) {
|
|
36
|
-
throw std::runtime_error(std::string("Skeleton.shimmerSpeed: ") + exc.what());
|
|
37
|
-
}
|
|
38
|
-
}()),
|
|
39
|
-
shimmerGradientColors([&]() -> CachedProp<std::optional<std::vector<std::string>>> {
|
|
40
|
-
try {
|
|
41
|
-
const react::RawValue* rawValue = rawProps.at("shimmerGradientColors", nullptr, nullptr);
|
|
42
|
-
if (rawValue == nullptr) return sourceProps.shimmerGradientColors;
|
|
43
|
-
const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
|
|
44
|
-
return CachedProp<std::optional<std::vector<std::string>>>::fromRawValue(*runtime, value, sourceProps.shimmerGradientColors);
|
|
45
|
-
} catch (const std::exception& exc) {
|
|
46
|
-
throw std::runtime_error(std::string("Skeleton.shimmerGradientColors: ") + exc.what());
|
|
47
|
-
}
|
|
48
|
-
}()),
|
|
49
|
-
hybridRef([&]() -> CachedProp<std::optional<std::function<void(const std::shared_ptr<HybridSkeletonSpec>& /* ref */)>>> {
|
|
50
|
-
try {
|
|
51
|
-
const react::RawValue* rawValue = rawProps.at("hybridRef", nullptr, nullptr);
|
|
52
|
-
if (rawValue == nullptr) return sourceProps.hybridRef;
|
|
53
|
-
const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
|
|
54
|
-
return CachedProp<std::optional<std::function<void(const std::shared_ptr<HybridSkeletonSpec>& /* ref */)>>>::fromRawValue(*runtime, value.asObject(*runtime).getProperty(*runtime, PropNameIDCache::get(*runtime, "f")), sourceProps.hybridRef);
|
|
55
|
-
} catch (const std::exception& exc) {
|
|
56
|
-
throw std::runtime_error(std::string("Skeleton.hybridRef: ") + exc.what());
|
|
57
|
-
}
|
|
58
|
-
}()) { }
|
|
23
|
+
shimmerSpeed(nitro::ReactProp<std::optional<double>>::fromRawValue("Skeleton", "shimmerSpeed", rawProps, sourceProps.shimmerSpeed)),
|
|
24
|
+
shimmerGradientColors(nitro::ReactProp<std::optional<std::vector<std::string>>>::fromRawValue("Skeleton", "shimmerGradientColors", rawProps, sourceProps.shimmerGradientColors)),
|
|
25
|
+
hybridRef(nitro::ReactProp<std::optional<std::function<void(const std::shared_ptr<HybridSkeletonSpec>& /* ref */)>>>::fromRawValue("Skeleton", "hybridRef", rawProps, sourceProps.hybridRef)) { }
|
|
59
26
|
|
|
60
27
|
bool HybridSkeletonProps::filterObjectKeys(const std::string& propName) {
|
|
61
28
|
switch (hashString(propName)) {
|
|
@@ -66,29 +33,4 @@ namespace margelo::nitro::skeleton::views {
|
|
|
66
33
|
}
|
|
67
34
|
}
|
|
68
35
|
|
|
69
|
-
HybridSkeletonComponentDescriptor::HybridSkeletonComponentDescriptor(const react::ComponentDescriptorParameters& parameters)
|
|
70
|
-
: ConcreteComponentDescriptor(parameters,
|
|
71
|
-
react::RawPropsParser()) {}
|
|
72
|
-
|
|
73
|
-
std::shared_ptr<const react::Props> HybridSkeletonComponentDescriptor::cloneProps(const react::PropsParserContext& context,
|
|
74
|
-
const std::shared_ptr<const react::Props>& props,
|
|
75
|
-
react::RawProps rawProps) const {
|
|
76
|
-
// 1. Prepare raw props parser
|
|
77
|
-
rawProps.parse(rawPropsParser_);
|
|
78
|
-
// 2. Copy props with Nitro's cached copy constructor
|
|
79
|
-
return HybridSkeletonShadowNode::Props(context, /* & */ rawProps, props);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
#ifdef ANDROID
|
|
83
|
-
void HybridSkeletonComponentDescriptor::adopt(react::ShadowNode& shadowNode) const {
|
|
84
|
-
// This is called immediately after `ShadowNode` is created, cloned or in progress.
|
|
85
|
-
// On Android, we need to wrap props in our state, which gets routed through Java and later unwrapped in JNI/C++.
|
|
86
|
-
auto& concreteShadowNode = static_cast<HybridSkeletonShadowNode&>(shadowNode);
|
|
87
|
-
const std::shared_ptr<const HybridSkeletonProps>& constProps = concreteShadowNode.getConcreteSharedProps();
|
|
88
|
-
const std::shared_ptr<HybridSkeletonProps>& props = std::const_pointer_cast<HybridSkeletonProps>(constProps);
|
|
89
|
-
HybridSkeletonState state{props};
|
|
90
|
-
concreteShadowNode.setStateData(std::move(state));
|
|
91
|
-
}
|
|
92
|
-
#endif
|
|
93
|
-
|
|
94
36
|
} // namespace margelo::nitro::skeleton::views
|
|
@@ -7,14 +7,15 @@
|
|
|
7
7
|
|
|
8
8
|
#pragma once
|
|
9
9
|
|
|
10
|
-
#include <
|
|
11
|
-
#include <NitroModules/
|
|
12
|
-
#include <NitroModules/
|
|
13
|
-
#include <NitroModules/CachedProp.hpp>
|
|
14
|
-
#include <react/renderer/core/ConcreteComponentDescriptor.h>
|
|
15
|
-
#include <react/renderer/core/PropsParserContext.h>
|
|
10
|
+
#include <NitroModules/ReactProp.hpp>
|
|
11
|
+
#include <NitroModules/ViewComponentDescriptor.hpp>
|
|
12
|
+
#include <NitroModules/ViewPropsHolderState.hpp>
|
|
16
13
|
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
17
14
|
#include <react/renderer/components/view/ViewProps.h>
|
|
15
|
+
#include <react/renderer/core/PropsParserContext.h>
|
|
16
|
+
#include <react/renderer/core/RawProps.h>
|
|
17
|
+
|
|
18
|
+
#include <string>
|
|
18
19
|
|
|
19
20
|
#include <optional>
|
|
20
21
|
#include <string>
|
|
@@ -43,9 +44,23 @@ namespace margelo::nitro::skeleton::views {
|
|
|
43
44
|
const react::RawProps& rawProps);
|
|
44
45
|
|
|
45
46
|
public:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
nitro::ReactProp<std::optional<double>> shimmerSpeed;
|
|
48
|
+
nitro::ReactProp<std::optional<std::vector<std::string>>> shimmerGradientColors;
|
|
49
|
+
nitro::ReactProp<std::optional<std::function<void(const std::shared_ptr<HybridSkeletonSpec>& /* ref */)>>> hybridRef;
|
|
50
|
+
|
|
51
|
+
[[nodiscard]]
|
|
52
|
+
bool hasSameProps(const HybridSkeletonProps& other) const noexcept {
|
|
53
|
+
return shimmerSpeed.hasSameValue(other.shimmerSpeed) &&
|
|
54
|
+
shimmerGradientColors.hasSameValue(other.shimmerGradientColors) &&
|
|
55
|
+
hybridRef.hasSameValue(other.hybridRef);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
[[nodiscard]]
|
|
59
|
+
bool hasAnyProvidedProps() const noexcept {
|
|
60
|
+
return shimmerSpeed.isProvided() ||
|
|
61
|
+
shimmerGradientColors.isProvided() ||
|
|
62
|
+
hybridRef.isProvided();
|
|
63
|
+
}
|
|
49
64
|
|
|
50
65
|
private:
|
|
51
66
|
static bool filterObjectKeys(const std::string& propName);
|
|
@@ -54,32 +69,7 @@ namespace margelo::nitro::skeleton::views {
|
|
|
54
69
|
/**
|
|
55
70
|
* State for the "Skeleton" View.
|
|
56
71
|
*/
|
|
57
|
-
|
|
58
|
-
public:
|
|
59
|
-
HybridSkeletonState() = default;
|
|
60
|
-
explicit HybridSkeletonState(const std::shared_ptr<HybridSkeletonProps>& props):
|
|
61
|
-
_props(props) {}
|
|
62
|
-
|
|
63
|
-
public:
|
|
64
|
-
[[nodiscard]]
|
|
65
|
-
const std::shared_ptr<HybridSkeletonProps>& getProps() const {
|
|
66
|
-
return _props;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
public:
|
|
70
|
-
#ifdef ANDROID
|
|
71
|
-
HybridSkeletonState(const HybridSkeletonState& /* previousState */, folly::dynamic /* data */) {}
|
|
72
|
-
folly::dynamic getDynamic() const {
|
|
73
|
-
throw std::runtime_error("HybridSkeletonState does not support folly!");
|
|
74
|
-
}
|
|
75
|
-
react::MapBuffer getMapBuffer() const {
|
|
76
|
-
throw std::runtime_error("HybridSkeletonState does not support MapBuffer!");
|
|
77
|
-
};
|
|
78
|
-
#endif
|
|
79
|
-
|
|
80
|
-
private:
|
|
81
|
-
std::shared_ptr<HybridSkeletonProps> _props;
|
|
82
|
-
};
|
|
72
|
+
using HybridSkeletonState = nitro::ViewPropsHolderState<HybridSkeletonProps>;
|
|
83
73
|
|
|
84
74
|
/**
|
|
85
75
|
* The Shadow Node for the "Skeleton" View.
|
|
@@ -92,21 +82,7 @@ namespace margelo::nitro::skeleton::views {
|
|
|
92
82
|
/**
|
|
93
83
|
* The Component Descriptor for the "Skeleton" View.
|
|
94
84
|
*/
|
|
95
|
-
|
|
96
|
-
public:
|
|
97
|
-
explicit HybridSkeletonComponentDescriptor(const react::ComponentDescriptorParameters& parameters);
|
|
98
|
-
|
|
99
|
-
public:
|
|
100
|
-
/**
|
|
101
|
-
* A faster path for cloning props - reuses the caching logic from `HybridSkeletonProps`.
|
|
102
|
-
*/
|
|
103
|
-
std::shared_ptr<const react::Props> cloneProps(const react::PropsParserContext& context,
|
|
104
|
-
const std::shared_ptr<const react::Props>& props,
|
|
105
|
-
react::RawProps rawProps) const override;
|
|
106
|
-
#ifdef ANDROID
|
|
107
|
-
void adopt(react::ShadowNode& shadowNode) const override;
|
|
108
|
-
#endif
|
|
109
|
-
};
|
|
85
|
+
using HybridSkeletonComponentDescriptor = nitro::ViewComponentDescriptor<HybridSkeletonShadowNode>;
|
|
110
86
|
|
|
111
87
|
/* The actual view for "Skeleton" needs to be implemented in platform-specific code. */
|
|
112
88
|
|
|
@@ -15,45 +15,64 @@ namespace margelo::nitro::skeleton::views {
|
|
|
15
15
|
using namespace facebook;
|
|
16
16
|
using ConcreteStateData = react::ConcreteState<HybridSkeletonState>;
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
std::shared_ptr<const HybridSkeletonProps> JHybridSkeletonStateUpdater::getPropsFromStateWrapper(
|
|
19
|
+
jni::alias_ref<JStateWrapper::javaobject> stateWrapper) {
|
|
20
|
+
if (stateWrapper.get() == nullptr) {
|
|
21
|
+
return nullptr;
|
|
22
|
+
}
|
|
23
23
|
// Get concrete StateWrapperImpl from passed StateWrapper interface object
|
|
24
|
-
jobject rawStateWrapper =
|
|
25
|
-
if (!
|
|
26
|
-
|
|
24
|
+
jobject rawStateWrapper = stateWrapper.get();
|
|
25
|
+
if (!stateWrapper->isInstanceOf(react::StateWrapperImpl::javaClassStatic())) [[unlikely]] {
|
|
26
|
+
throw std::runtime_error("StateWrapper is not a StateWrapperImpl");
|
|
27
|
+
}
|
|
28
|
+
auto stateWrapperImpl = jni::alias_ref<react::StateWrapperImpl::javaobject>{
|
|
29
|
+
static_cast<react::StateWrapperImpl::javaobject>(rawStateWrapper)
|
|
30
|
+
};
|
|
31
|
+
std::shared_ptr<const react::State> state = stateWrapperImpl->cthis()->getState();
|
|
32
|
+
if (state == nullptr) {
|
|
33
|
+
return nullptr;
|
|
27
34
|
}
|
|
28
|
-
auto stateWrapper = jni::alias_ref<react::StateWrapperImpl::javaobject>{
|
|
29
|
-
static_cast<react::StateWrapperImpl::javaobject>(rawStateWrapper)};
|
|
30
|
-
std::shared_ptr<const react::State> state = stateWrapper->cthis()->getState();
|
|
31
35
|
auto concreteState = std::static_pointer_cast<const ConcreteStateData>(state);
|
|
32
36
|
const HybridSkeletonState& data = concreteState->getData();
|
|
33
|
-
const std::shared_ptr<HybridSkeletonProps>& props = data.getProps();
|
|
37
|
+
const std::shared_ptr<const HybridSkeletonProps>& props = data.getProps();
|
|
34
38
|
if (props == nullptr) [[unlikely]] {
|
|
35
|
-
// Props aren't set yet!
|
|
36
39
|
throw std::runtime_error("HybridSkeletonState's data doesn't contain any props!");
|
|
37
40
|
}
|
|
41
|
+
return props;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
void JHybridSkeletonStateUpdater::updateViewProps(jni::alias_ref<jni::JClass> /* class */,
|
|
45
|
+
jni::alias_ref<JHybridSkeletonSpec::JavaPart> javaView,
|
|
46
|
+
jni::alias_ref<JStateWrapper::javaobject> newState,
|
|
47
|
+
jni::alias_ref<JStateWrapper::javaobject> oldState) {
|
|
48
|
+
std::shared_ptr<JHybridSkeletonSpec> hybridView = javaView->getJHybridSkeletonSpec();
|
|
49
|
+
std::shared_ptr<const HybridSkeletonProps> newProps = getPropsFromStateWrapper(newState);
|
|
50
|
+
std::shared_ptr<const HybridSkeletonProps> oldProps = getPropsFromStateWrapper(oldState);
|
|
51
|
+
if (newProps == nullptr) [[unlikely]] {
|
|
52
|
+
throw std::runtime_error("Current StateWrapper doesn't contain any props!");
|
|
53
|
+
}
|
|
38
54
|
|
|
39
|
-
// Update
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
|
|
55
|
+
// Update only props that differ from the previous State snapshot.
|
|
56
|
+
if (oldProps == nullptr
|
|
57
|
+
? newProps->shimmerSpeed.isProvided()
|
|
58
|
+
: !newProps->shimmerSpeed.hasSameValue(oldProps->shimmerSpeed)) {
|
|
59
|
+
hybridView->setShimmerSpeed(newProps->shimmerSpeed.get());
|
|
43
60
|
}
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
|
|
61
|
+
if (oldProps == nullptr
|
|
62
|
+
? newProps->shimmerGradientColors.isProvided()
|
|
63
|
+
: !newProps->shimmerGradientColors.hasSameValue(oldProps->shimmerGradientColors)) {
|
|
64
|
+
hybridView->setShimmerGradientColors(newProps->shimmerGradientColors.get());
|
|
47
65
|
}
|
|
48
66
|
|
|
49
67
|
// Update hybridRef if it changed
|
|
50
|
-
if (
|
|
68
|
+
if (oldProps == nullptr
|
|
69
|
+
? newProps->hybridRef.isProvided()
|
|
70
|
+
: !newProps->hybridRef.hasSameValue(oldProps->hybridRef)) {
|
|
51
71
|
// hybridRef changed - call it with new this
|
|
52
|
-
const auto& maybeFunc =
|
|
72
|
+
const auto& maybeFunc = newProps->hybridRef.get();
|
|
53
73
|
if (maybeFunc.has_value()) {
|
|
54
74
|
maybeFunc.value()(hybridView);
|
|
55
75
|
}
|
|
56
|
-
props->hybridRef.isDirty = false;
|
|
57
76
|
}
|
|
58
77
|
}
|
|
59
78
|
|
|
@@ -31,7 +31,12 @@ public:
|
|
|
31
31
|
public:
|
|
32
32
|
static void updateViewProps(jni::alias_ref<jni::JClass> /* class */,
|
|
33
33
|
jni::alias_ref<JHybridSkeletonSpec::JavaPart> view,
|
|
34
|
-
jni::alias_ref<JStateWrapper::javaobject>
|
|
34
|
+
jni::alias_ref<JStateWrapper::javaobject> newState,
|
|
35
|
+
jni::alias_ref<JStateWrapper::javaobject> oldState);
|
|
36
|
+
|
|
37
|
+
private:
|
|
38
|
+
static std::shared_ptr<const HybridSkeletonProps> getPropsFromStateWrapper(
|
|
39
|
+
jni::alias_ref<JStateWrapper::javaobject> stateWrapper);
|
|
35
40
|
|
|
36
41
|
public:
|
|
37
42
|
static void registerNatives() {
|
package/nitrogen/generated/android/kotlin/com/margelo/nitro/skeleton/views/HybridSkeletonManager.kt
CHANGED
|
@@ -20,6 +20,14 @@ import com.margelo.nitro.skeleton.*
|
|
|
20
20
|
* Represents the React Native `ViewManager` for the "Skeleton" Nitro HybridView.
|
|
21
21
|
*/
|
|
22
22
|
public class HybridSkeletonManager: SimpleViewManager<View>() {
|
|
23
|
+
/**
|
|
24
|
+
* Represents the View and its last state snapshot (mutable)
|
|
25
|
+
*/
|
|
26
|
+
private class HybridViewHolder(
|
|
27
|
+
val hybridView: HybridSkeleton,
|
|
28
|
+
var lastState: StateWrapper? = null,
|
|
29
|
+
)
|
|
30
|
+
|
|
23
31
|
init {
|
|
24
32
|
if (RecyclableView::class.java.isAssignableFrom(HybridSkeleton::class.java)) {
|
|
25
33
|
// Enable view recycling
|
|
@@ -34,33 +42,41 @@ public class HybridSkeletonManager: SimpleViewManager<View>() {
|
|
|
34
42
|
override fun createViewInstance(reactContext: ThemedReactContext): View {
|
|
35
43
|
val hybridView = HybridSkeleton(reactContext)
|
|
36
44
|
val view = hybridView.view
|
|
37
|
-
view.setTag(associated_hybrid_view_tag, hybridView)
|
|
45
|
+
view.setTag(associated_hybrid_view_tag, HybridViewHolder(hybridView))
|
|
38
46
|
return view
|
|
39
47
|
}
|
|
40
48
|
|
|
41
49
|
override fun updateState(view: View, props: ReactStylesDiffMap, stateWrapper: StateWrapper): Any? {
|
|
42
|
-
val
|
|
50
|
+
val holder = getHybridViewHolder(view)
|
|
43
51
|
?: throw Error("Couldn't find view $view in local views table!")
|
|
52
|
+
val hybridView = holder.hybridView
|
|
53
|
+
val oldState = holder.lastState
|
|
54
|
+
val newState = stateWrapper
|
|
44
55
|
|
|
45
56
|
// 1. Update each prop individually
|
|
46
57
|
hybridView.beforeUpdate()
|
|
47
|
-
HybridSkeletonStateUpdater.updateViewProps(hybridView,
|
|
58
|
+
HybridSkeletonStateUpdater.updateViewProps(hybridView, newState, oldState)
|
|
48
59
|
hybridView.afterUpdate()
|
|
60
|
+
holder.lastState = newState
|
|
49
61
|
|
|
50
62
|
// 2. Continue in base View props
|
|
51
|
-
return super.updateState(view, props,
|
|
63
|
+
return super.updateState(view, props, newState)
|
|
52
64
|
}
|
|
53
65
|
|
|
54
66
|
override fun onDropViewInstance(view: View) {
|
|
55
|
-
val
|
|
56
|
-
|
|
67
|
+
val holder = getHybridViewHolder(view)
|
|
68
|
+
holder?.lastState = null
|
|
69
|
+
holder?.hybridView?.onDropView()
|
|
57
70
|
return super.onDropViewInstance(view)
|
|
58
71
|
}
|
|
59
72
|
|
|
60
73
|
protected override fun prepareToRecycleView(reactContext: ThemedReactContext, view: View): View? {
|
|
61
|
-
super.prepareToRecycleView(reactContext, view)
|
|
62
|
-
|
|
74
|
+
val preparedView = super.prepareToRecycleView(reactContext, view)
|
|
75
|
+
?: return null
|
|
76
|
+
val holder = getHybridViewHolder(preparedView)
|
|
63
77
|
?: return null
|
|
78
|
+
val hybridView = holder.hybridView
|
|
79
|
+
holder.lastState = null
|
|
64
80
|
|
|
65
81
|
@Suppress("USELESS_IS_CHECK")
|
|
66
82
|
if (hybridView is RecyclableView) {
|
|
@@ -74,7 +90,7 @@ public class HybridSkeletonManager: SimpleViewManager<View>() {
|
|
|
74
90
|
}
|
|
75
91
|
}
|
|
76
92
|
|
|
77
|
-
private fun
|
|
78
|
-
return view.getTag(associated_hybrid_view_tag) as?
|
|
93
|
+
private fun getHybridViewHolder(view: View): HybridViewHolder? {
|
|
94
|
+
return view.getTag(associated_hybrid_view_tag) as? HybridViewHolder
|
|
79
95
|
}
|
|
80
96
|
}
|
|
@@ -14,10 +14,10 @@ internal class HybridSkeletonStateUpdater {
|
|
|
14
14
|
companion object {
|
|
15
15
|
/**
|
|
16
16
|
* Updates the props for [view] through C++.
|
|
17
|
-
* The [
|
|
17
|
+
* The [newState] prop is expected to contain [view]'s props as wrapped Fabric state.
|
|
18
18
|
*/
|
|
19
19
|
@Suppress("KotlinJniMissingFunction")
|
|
20
20
|
@JvmStatic
|
|
21
|
-
external fun updateViewProps(view: HybridSkeletonSpec,
|
|
21
|
+
external fun updateViewProps(view: HybridSkeletonSpec, newState: StateWrapper, oldState: StateWrapper?)
|
|
22
22
|
}
|
|
23
23
|
}
|