From 568e72db9416b33008f3ece5dc70bddaa9f2184c Mon Sep 17 00:00:00 2001 From: azim Date: Mon, 18 Nov 2024 03:50:08 +0500 Subject: [PATCH 1/7] chore: foundation to move from index based to uniqueid based component registry --- .../com/shadowlist/SLComponentRegistry.java | 12 ++-- cpp/cpp-adapter.cpp | 8 +-- .../SLElementSpec/SLElementProps.cpp | 3 +- .../components/SLElementSpec/SLElementProps.h | 3 +- cpp/registry/SLComponentRegistry.cpp | 62 ++++++++++--------- cpp/registry/SLComponentRegistry.h | 35 ++++++++--- ios/SLContainer.mm | 9 ++- ios/SLContainerChildrenManager.h | 4 +- ios/SLContainerChildrenManager.mm | 26 ++++---- src/SLElementNativeComponent.ts | 3 +- src/Shadowlist.tsx | 19 ++++-- 11 files changed, 111 insertions(+), 73 deletions(-) diff --git a/android/src/main/java/com/shadowlist/SLComponentRegistry.java b/android/src/main/java/com/shadowlist/SLComponentRegistry.java index c1a3ee6..da83027 100644 --- a/android/src/main/java/com/shadowlist/SLComponentRegistry.java +++ b/android/src/main/java/com/shadowlist/SLComponentRegistry.java @@ -12,8 +12,8 @@ public SLComponentRegistry() { } private native long nativeInit(); - private native void nativeRegisterComponent(long nativePtr, int componentId); - private native void nativeUnregisterComponent(long nativePtr, int componentId); + private native void nativeRegisterComponent(long nativePtr, int index); + private native void nativeUnregisterComponent(long nativePtr, int index); private native void nativeMountRange(long nativePtr, int visibleStartIndex, int visibleEndIndex); private native void nativeMount(long nativePtr, int[] indices); private native void nativeUnmount(long nativePtr, int[] indices); @@ -25,12 +25,12 @@ public interface SLObserver { void onVisibilityChanged(int id, boolean isVisible); } - public void registerComponent(int componentId) { - nativeRegisterComponent(mNativePtr, componentId); + public void registerComponent(int index) { + nativeRegisterComponent(mNativePtr, index); } - public void unregisterComponent(int componentId) { - nativeUnregisterComponent(mNativePtr, componentId); + public void unregisterComponent(int index) { + nativeUnregisterComponent(mNativePtr, index); } public void mountRange(int visibleStartIndex, int visibleEndIndex) { diff --git a/cpp/cpp-adapter.cpp b/cpp/cpp-adapter.cpp index 3f77f9e..eb51f2b 100644 --- a/cpp/cpp-adapter.cpp +++ b/cpp/cpp-adapter.cpp @@ -10,15 +10,15 @@ JNIEXPORT jlong JNICALL Java_com_shadowlist_SLComponentRegistry_nativeInit(JNIEn } extern "C" -JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeRegisterComponent(JNIEnv *env, jobject thiz, jlong registryPtr, jint componentId) { +JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeRegisterComponent(JNIEnv *env, jobject thiz, jlong registryPtr, jint index) { auto *registry = reinterpret_cast(registryPtr); - registry->registerComponent(componentId); + registry->registerComponent(index); } extern "C" -JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeUnregisterComponent(JNIEnv *env, jobject thiz, jlong registryPtr, jint componentId) { +JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeUnregisterComponent(JNIEnv *env, jobject thiz, jlong registryPtr, jint index) { auto *registry = reinterpret_cast(registryPtr); - registry->unregisterComponent(componentId); + registry->unregisterComponent(index); } extern "C" diff --git a/cpp/react/renderer/components/SLElementSpec/SLElementProps.cpp b/cpp/react/renderer/components/SLElementSpec/SLElementProps.cpp index 0c5fa9c..85f4331 100644 --- a/cpp/react/renderer/components/SLElementSpec/SLElementProps.cpp +++ b/cpp/react/renderer/components/SLElementSpec/SLElementProps.cpp @@ -9,7 +9,8 @@ SLElementProps::SLElementProps( const SLElementProps &sourceProps, const RawProps &rawProps): ViewProps(context, sourceProps, rawProps), - index(convertRawProp(context, rawProps, "index", sourceProps.index, {0})) + index(convertRawProp(context, rawProps, "index", sourceProps.index, {0})), + uniqueId(convertRawProp(context, rawProps, "uniqueId", sourceProps.uniqueId, "")) {} } diff --git a/cpp/react/renderer/components/SLElementSpec/SLElementProps.h b/cpp/react/renderer/components/SLElementSpec/SLElementProps.h index cfea9b4..18b47af 100644 --- a/cpp/react/renderer/components/SLElementSpec/SLElementProps.h +++ b/cpp/react/renderer/components/SLElementSpec/SLElementProps.h @@ -11,7 +11,8 @@ class SLElementProps final : public ViewProps { SLElementProps(const PropsParserContext& context, const SLElementProps &sourceProps, const RawProps &rawProps); #pragma mark - Props - int index{0}; + int index; + std::string uniqueId; }; } diff --git a/cpp/registry/SLComponentRegistry.cpp b/cpp/registry/SLComponentRegistry.cpp index 6b691d0..7c48ed1 100644 --- a/cpp/registry/SLComponentRegistry.cpp +++ b/cpp/registry/SLComponentRegistry.cpp @@ -1,7 +1,11 @@ #include "SLComponentRegistry.h" -int SLComponent::getComponentId() const { - return componentId; +int SLComponent::getIndex() const { + return index; +} + +std::string SLComponent::getUniqueId() const { + return uniqueId; } bool SLComponent::getVisible() const { @@ -14,14 +18,14 @@ void SLComponent::setVisible(bool visible) { SLComponentRegistry::SLComponentRegistry() {} -void SLComponentRegistry::registerComponent(int componentId) { - components.emplace(componentId, SLComponent{componentId}); +void SLComponentRegistry::registerComponent(std::string uniqueId, int index) { + components.emplace(index, SLComponent{uniqueId, index}); } -void SLComponentRegistry::unregisterComponent(int componentId) { - auto componentIter = components.find(componentId); +void SLComponentRegistry::unregisterComponent(std::string uniqueId, int index) { + auto componentIter = components.find(index); if (componentIter != components.end()) { - notifyObservers({componentIter->second.getComponentId()}, false); + notifyObservers({componentIter->second}, false); components.erase(componentIter); } } @@ -32,25 +36,25 @@ void SLComponentRegistry::mountRange(int visibleStartIndex, int visibleEndIndex) mount(indices); } -void SLComponentRegistry::mount(const std::vector& indices) { +void SLComponentRegistry::mount(const std::vector &indices) { std::unordered_set componentSet(indices.begin(), indices.end()); - for (auto& componentPair : components) { - SLComponent& component = componentPair.second; - int componentId = component.getComponentId(); - bool nextVisible = componentSet.count(componentId) > 0; + for (auto &componentPair : components) { + SLComponent &component = componentPair.second; + int index = component.getIndex(); + bool nextVisible = componentSet.count(index) > 0; if (component.getVisible() != nextVisible) { component.setVisible(nextVisible); - notifyObservers({componentId}, nextVisible); + notifyObservers({component}, nextVisible); } } } -void SLComponentRegistry::unmount(const std::vector& indices) { - for (int componentId : indices) { - auto componentIter = components.find(componentId); +void SLComponentRegistry::unmount(const std::vector &indices) { + for (int index : indices) { + auto componentIter = components.find(index); if (componentIter != components.end()) { componentIter->second.setVisible(false); - notifyObservers({componentIter->first}, false); + notifyObservers({componentIter->second}, false); } } } @@ -62,31 +66,33 @@ void SLComponentRegistry::mountObserver(const SLObserver &observer) { void SLComponentRegistry::unmountObserver(const SLObserver &observer) { observers.erase( std::remove_if(observers.begin(), observers.end(), - [&observer](const SLObserver& obs) { + [&observer](const SLObserver &obs) { return obs.target() == observer.target(); }), observers.end()); } -void SLComponentRegistry::notifyObservers(const std::unordered_set& updatedComponents, bool isVisible) { - for (int componentId : updatedComponents) { - for (const auto& observerFunction : observers) { - observerFunction(componentId, isVisible); +void SLComponentRegistry::notifyObservers(const std::unordered_set &updatedComponents, bool isVisible) { + for (const SLComponent &component : updatedComponents) { + for (const auto &observerFunction : observers) { + observerFunction(component.getUniqueId(), component.getIndex(), isVisible); } } } -void SLComponentRegistry::updateVisibility(const std::vector& indices, bool visible) { - std::unordered_set updatedComponents; - for (int componentId : indices) { - auto componentIter = components.find(componentId); +void SLComponentRegistry::updateVisibility(const std::vector &indices, bool visible) { + std::unordered_set updatedComponents; + + for (int index : indices) { + auto componentIter = components.find(index); if (componentIter != components.end()) { - SLComponent& component = componentIter->second; + SLComponent &component = componentIter->second; if (component.getVisible() != visible) { component.setVisible(visible); - updatedComponents.insert(component.getComponentId()); + updatedComponents.insert(component); } } } + notifyObservers(updatedComponents, visible); } diff --git a/cpp/registry/SLComponentRegistry.h b/cpp/registry/SLComponentRegistry.h index 4f3a1bd..2a5d110 100644 --- a/cpp/registry/SLComponentRegistry.h +++ b/cpp/registry/SLComponentRegistry.h @@ -10,26 +10,32 @@ class SLComponent { public: - SLComponent(int componentId) : componentId(componentId), isVisible(false) {} - int getComponentId() const; + SLComponent(std::string uniqueId, int index) : index(index), uniqueId(uniqueId), isVisible(false) {} + int getIndex() const; + std::string getUniqueId() const; bool getVisible() const; void setVisible(bool visible); + bool operator==(const SLComponent& other) const { + return uniqueId == other.uniqueId && index == other.index; + } + private: - int componentId; + int index; + std::string uniqueId; bool isVisible; }; class SLComponentRegistry { public: - using SLObserver = std::function; + using SLObserver = std::function; SLComponentRegistry(); - void registerComponent(int componentId); - void unregisterComponent(int componentId); + void registerComponent(std::string uniqueId, int index); + void unregisterComponent(std::string uniqueId, int index); void mountRange(int visibleStartIndex, int visibleEndIndex); - void mount(const std::vector& indices); - void unmount(const std::vector& indices); + void mount(const std::vector &indices); + void unmount(const std::vector &indices); void mountObserver(const SLObserver &observer); void unmountObserver(const SLObserver &observer); @@ -38,8 +44,17 @@ class SLComponentRegistry { std::vector observers; int initialNumToRender; - void updateVisibility(const std::vector& indices, bool visible); - void notifyObservers(const std::unordered_set& updatedComponents, bool isVisible); + void updateVisibility(const std::vector &indices, bool visible); + void notifyObservers(const std::unordered_set &updatedComponents, bool isVisible); }; +namespace std { + template <> + struct hash { + size_t operator()(const SLComponent& component) const { + return hash()(component.getUniqueId()) ^ hash()(component.getIndex()); + } + }; +} + #endif diff --git a/ios/SLContainer.mm b/ios/SLContainer.mm index 0ec58a9..e2da3cc 100644 --- a/ios/SLContainer.mm +++ b/ios/SLContainer.mm @@ -6,6 +6,7 @@ #import "SLContainerHelpers.h" #import "SLContainerChildrenManager.h" #import "SLScrollable.h" +#import "SLElementProps.h" #import #import @@ -52,12 +53,16 @@ - (instancetype)initWithFrame:(CGRect)frame - (void)mountChildComponentView:(UIView *)childComponentView index:(NSInteger)index { - [self->_containerChildrenManager mountChildComponentView:childComponentView index:index]; + const auto &nextViewProps = *std::static_pointer_cast([childComponentView props]); + const auto uniqueId = [NSString stringWithUTF8String:nextViewProps.uniqueId.c_str()]; + [self->_containerChildrenManager mountChildComponentView:childComponentView uniqueId:uniqueId index:index]; } - (void)unmountChildComponentView:(UIView *)childComponentView index:(NSInteger)index { - [self->_containerChildrenManager unmountChildComponentView:childComponentView index:index]; + const auto &nextViewProps = *std::static_pointer_cast([childComponentView props]); + const auto uniqueId = [NSString stringWithUTF8String:nextViewProps.uniqueId.c_str()]; + [self->_containerChildrenManager unmountChildComponentView:childComponentView uniqueId:uniqueId index:index]; } - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps diff --git a/ios/SLContainerChildrenManager.h b/ios/SLContainerChildrenManager.h index 86d35f9..fd780e2 100644 --- a/ios/SLContainerChildrenManager.h +++ b/ios/SLContainerChildrenManager.h @@ -9,8 +9,8 @@ @interface SLContainerChildrenManager : NSObject - (instancetype)initWithContentView:(UIView *)contentView; -- (void)mountChildComponentView:(UIView *)childComponentView index:(NSInteger)index; -- (void)unmountChildComponentView:(UIView *)childComponentView index:(NSInteger)index; +- (void)mountChildComponentView:(UIView *)childComponentView uniqueId:(NSString *)uniqueId index:(NSInteger)index; +- (void)unmountChildComponentView:(UIView *)childComponentView uniqueId:(NSString *)uniqueId index:(NSInteger)index; - (void)mount:(int)visibleStartIndex end:(int)visibleEndIndex; @end diff --git a/ios/SLContainerChildrenManager.mm b/ios/SLContainerChildrenManager.mm index b7d308c..18c7ade 100644 --- a/ios/SLContainerChildrenManager.mm +++ b/ios/SLContainerChildrenManager.mm @@ -3,14 +3,14 @@ @implementation SLContainerChildrenManager { UIView *_scrollContent; SLComponentRegistry _childrenRegistry; - NSMutableDictionary *> *_childrenPool; + NSMutableDictionary *> *_childrenPool; } - (instancetype)initWithContentView:(UIView *)contentView { if (self = [super init]) { _childrenRegistry = SLComponentRegistry(); - _childrenRegistry.mountObserver([self](int index, bool isVisible) { - [self mountObserver:index isVisible:isVisible]; + _childrenRegistry.mountObserver([self](std::string uniqueId, int index, bool isVisible) { + [self mountObserver:uniqueId index:index isVisible:isVisible]; }); _childrenPool = [NSMutableDictionary dictionary]; _scrollContent = contentView; @@ -18,24 +18,26 @@ - (instancetype)initWithContentView:(UIView *)contentView { return self; } -- (void)mountObserver:(int)index isVisible:(bool)isVisible { +- (void)mountObserver:(std::string)uniqueId index:(int)index isVisible:(bool)isVisible { + auto childComponent = [_childrenPool objectForKey:[NSString stringWithUTF8String:uniqueId.c_str()]]; + if (isVisible) { - [_scrollContent insertSubview:[_childrenPool objectForKey:@(index)] atIndex:index]; + [_scrollContent insertSubview:childComponent atIndex:index]; } else { - [[_childrenPool objectForKey:@(index)] removeFromSuperview]; + [childComponent removeFromSuperview]; } } -- (void)mountChildComponentView:(UIView *)childComponentView index:(NSInteger)index +- (void)mountChildComponentView:(UIView *)childComponentView uniqueId:(NSString *)uniqueId index:(NSInteger)index { - [self->_childrenPool setObject:childComponentView forKey:@(index)]; - self->_childrenRegistry.registerComponent(index); + [self->_childrenPool setObject:childComponentView forKey:uniqueId]; + self->_childrenRegistry.registerComponent([uniqueId UTF8String], index); } -- (void)unmountChildComponentView:(UIView *)childComponentView index:(NSInteger)index +- (void)unmountChildComponentView:(UIView *)childComponentView uniqueId:(NSString *)uniqueId index:(NSInteger)index { - self->_childrenRegistry.unregisterComponent(index); - [self->_childrenPool removeObjectForKey:@(index)]; + self->_childrenRegistry.unregisterComponent([uniqueId UTF8String], index); + [self->_childrenPool removeObjectForKey:uniqueId]; } - (void)mount:(int)visibleStartIndex end:(int)visibleEndIndex diff --git a/src/SLElementNativeComponent.ts b/src/SLElementNativeComponent.ts index 9afd132..c699a10 100644 --- a/src/SLElementNativeComponent.ts +++ b/src/SLElementNativeComponent.ts @@ -3,7 +3,8 @@ import type { ViewProps } from 'react-native'; import type { Int32 } from 'react-native/Libraries/Types/CodegenTypes'; export interface SLElementNativeProps extends ViewProps { - index?: Int32; + index: Int32; + uniqueId: string; } export default codegenNativeComponent('SLElement', { diff --git a/src/Shadowlist.tsx b/src/Shadowlist.tsx index 8377645..f70455a 100644 --- a/src/Shadowlist.tsx +++ b/src/Shadowlist.tsx @@ -21,7 +21,7 @@ const invoker = (Component: Component) => { export type ShadowlistProps = { data: any[]; renderItem: (payload: { item: any; index: number }) => React.ReactElement; - keyExtractor?: ((item: any, index: number) => string) | undefined; + keyExtractor: (item: any, index: number) => string; contentContainerStyle?: ViewStyle; ListHeaderComponent?: Component; ListHeaderComponentStyle?: ViewStyle; @@ -73,11 +73,18 @@ export const Shadowlist = React.forwardRef( * ListChildrenComponent */ const ListChildrenComponent = React.useMemo(() => { - return props.data.map((item, index) => ( - - {props.renderItem({ item, index })} - - )); + return props.data.map((item, index) => { + const uniqueId = props.keyExtractor(item, index); + return ( + + {props.renderItem({ item, index })} + + ); + }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.data, props.renderItem, props.keyExtractor]); From 3ec409f7632890425ff70f353b07ec49baa89629 Mon Sep 17 00:00:00 2001 From: azim Date: Mon, 18 Nov 2024 21:42:55 +0500 Subject: [PATCH 2/7] chore: move component registry keys from index to uniqueId --- cpp/registry/SLComponentRegistry.cpp | 39 ++++++++++------------------ cpp/registry/SLComponentRegistry.h | 23 +++++++--------- ios/SLContainerChildrenManager.mm | 32 ++++++++++++++++------- src/Shadowlist.tsx | 2 +- 4 files changed, 48 insertions(+), 48 deletions(-) diff --git a/cpp/registry/SLComponentRegistry.cpp b/cpp/registry/SLComponentRegistry.cpp index 7c48ed1..84ebcba 100644 --- a/cpp/registry/SLComponentRegistry.cpp +++ b/cpp/registry/SLComponentRegistry.cpp @@ -1,9 +1,5 @@ #include "SLComponentRegistry.h" -int SLComponent::getIndex() const { - return index; -} - std::string SLComponent::getUniqueId() const { return uniqueId; } @@ -18,30 +14,23 @@ void SLComponent::setVisible(bool visible) { SLComponentRegistry::SLComponentRegistry() {} -void SLComponentRegistry::registerComponent(std::string uniqueId, int index) { - components.emplace(index, SLComponent{uniqueId, index}); +void SLComponentRegistry::registerComponent(std::string uniqueId) { + components.emplace(uniqueId, SLComponent{uniqueId}); } -void SLComponentRegistry::unregisterComponent(std::string uniqueId, int index) { - auto componentIter = components.find(index); +void SLComponentRegistry::unregisterComponent(std::string uniqueId) { + auto componentIter = components.find(uniqueId); if (componentIter != components.end()) { notifyObservers({componentIter->second}, false); components.erase(componentIter); } } -void SLComponentRegistry::mountRange(int visibleStartIndex, int visibleEndIndex) { - std::vector indices(visibleEndIndex - visibleStartIndex); - std::iota(indices.begin(), indices.end(), visibleStartIndex); - mount(indices); -} - -void SLComponentRegistry::mount(const std::vector &indices) { - std::unordered_set componentSet(indices.begin(), indices.end()); +void SLComponentRegistry::mount(const std::vector &uniqueIds) { + std::unordered_set componentSet(uniqueIds.begin(), uniqueIds.end()); for (auto &componentPair : components) { SLComponent &component = componentPair.second; - int index = component.getIndex(); - bool nextVisible = componentSet.count(index) > 0; + bool nextVisible = componentSet.count(component.getUniqueId()) > 0; if (component.getVisible() != nextVisible) { component.setVisible(nextVisible); notifyObservers({component}, nextVisible); @@ -49,9 +38,9 @@ void SLComponentRegistry::mount(const std::vector &indices) { } } -void SLComponentRegistry::unmount(const std::vector &indices) { - for (int index : indices) { - auto componentIter = components.find(index); +void SLComponentRegistry::unmount(const std::vector &uniqueIds) { + for (std::string uniqueId : uniqueIds) { + auto componentIter = components.find(uniqueId); if (componentIter != components.end()) { componentIter->second.setVisible(false); notifyObservers({componentIter->second}, false); @@ -75,16 +64,16 @@ void SLComponentRegistry::unmountObserver(const SLObserver &observer) { void SLComponentRegistry::notifyObservers(const std::unordered_set &updatedComponents, bool isVisible) { for (const SLComponent &component : updatedComponents) { for (const auto &observerFunction : observers) { - observerFunction(component.getUniqueId(), component.getIndex(), isVisible); + observerFunction(component.getUniqueId(), isVisible); } } } -void SLComponentRegistry::updateVisibility(const std::vector &indices, bool visible) { +void SLComponentRegistry::updateVisibility(const std::vector &uniqueIds, bool visible) { std::unordered_set updatedComponents; - for (int index : indices) { - auto componentIter = components.find(index); + for (std::string uniqueId : uniqueIds) { + auto componentIter = components.find(uniqueId); if (componentIter != components.end()) { SLComponent &component = componentIter->second; if (component.getVisible() != visible) { diff --git a/cpp/registry/SLComponentRegistry.h b/cpp/registry/SLComponentRegistry.h index 2a5d110..79cbbf8 100644 --- a/cpp/registry/SLComponentRegistry.h +++ b/cpp/registry/SLComponentRegistry.h @@ -10,41 +10,38 @@ class SLComponent { public: - SLComponent(std::string uniqueId, int index) : index(index), uniqueId(uniqueId), isVisible(false) {} - int getIndex() const; + SLComponent(std::string uniqueId) : uniqueId(uniqueId), isVisible(false) {} std::string getUniqueId() const; bool getVisible() const; void setVisible(bool visible); bool operator==(const SLComponent& other) const { - return uniqueId == other.uniqueId && index == other.index; + return uniqueId == other.uniqueId; } private: - int index; std::string uniqueId; bool isVisible; }; class SLComponentRegistry { public: - using SLObserver = std::function; + using SLObserver = std::function; SLComponentRegistry(); - void registerComponent(std::string uniqueId, int index); - void unregisterComponent(std::string uniqueId, int index); - void mountRange(int visibleStartIndex, int visibleEndIndex); - void mount(const std::vector &indices); - void unmount(const std::vector &indices); + void registerComponent(std::string uniqueId); + void unregisterComponent(std::string uniqueId); + void mount(const std::vector &uniqueIds); + void unmount(const std::vector &uniqueIds); void mountObserver(const SLObserver &observer); void unmountObserver(const SLObserver &observer); private: - std::unordered_map components; + std::unordered_map components; std::vector observers; int initialNumToRender; - void updateVisibility(const std::vector &indices, bool visible); + void updateVisibility(const std::vector &uniqueIds, bool visible); void notifyObservers(const std::unordered_set &updatedComponents, bool isVisible); }; @@ -52,7 +49,7 @@ namespace std { template <> struct hash { size_t operator()(const SLComponent& component) const { - return hash()(component.getUniqueId()) ^ hash()(component.getIndex()); + return hash()(component.getUniqueId()); } }; } diff --git a/ios/SLContainerChildrenManager.mm b/ios/SLContainerChildrenManager.mm index 18c7ade..12cd231 100644 --- a/ios/SLContainerChildrenManager.mm +++ b/ios/SLContainerChildrenManager.mm @@ -1,4 +1,7 @@ #import "SLContainerChildrenManager.h" +#import "SLElementProps.h" + +using namespace facebook::react; @implementation SLContainerChildrenManager { UIView *_scrollContent; @@ -9,8 +12,8 @@ @implementation SLContainerChildrenManager { - (instancetype)initWithContentView:(UIView *)contentView { if (self = [super init]) { _childrenRegistry = SLComponentRegistry(); - _childrenRegistry.mountObserver([self](std::string uniqueId, int index, bool isVisible) { - [self mountObserver:uniqueId index:index isVisible:isVisible]; + _childrenRegistry.mountObserver([self](std::string uniqueId, bool isVisible) { + [self mountObserver:uniqueId isVisible:isVisible]; }); _childrenPool = [NSMutableDictionary dictionary]; _scrollContent = contentView; @@ -18,25 +21,27 @@ - (instancetype)initWithContentView:(UIView *)contentView { return self; } -- (void)mountObserver:(std::string)uniqueId index:(int)index isVisible:(bool)isVisible { - auto childComponent = [_childrenPool objectForKey:[NSString stringWithUTF8String:uniqueId.c_str()]]; +- (void)mountObserver:(std::string)uniqueId isVisible:(bool)isVisible { + auto childComponentView = [_childrenPool objectForKey:[NSString stringWithUTF8String:uniqueId.c_str()]]; + const auto &childViewProps = *std::static_pointer_cast([childComponentView props]); if (isVisible) { - [_scrollContent insertSubview:childComponent atIndex:index]; + [_scrollContent insertSubview:childComponentView atIndex:childViewProps.index]; } else { - [childComponent removeFromSuperview]; + NSLog(@"dbg unmount %d", childViewProps.index); + [childComponentView removeFromSuperview]; } } - (void)mountChildComponentView:(UIView *)childComponentView uniqueId:(NSString *)uniqueId index:(NSInteger)index { [self->_childrenPool setObject:childComponentView forKey:uniqueId]; - self->_childrenRegistry.registerComponent([uniqueId UTF8String], index); + self->_childrenRegistry.registerComponent([uniqueId UTF8String]); } - (void)unmountChildComponentView:(UIView *)childComponentView uniqueId:(NSString *)uniqueId index:(NSInteger)index { - self->_childrenRegistry.unregisterComponent([uniqueId UTF8String], index); + self->_childrenRegistry.unregisterComponent([uniqueId UTF8String]); [self->_childrenPool removeObjectForKey:uniqueId]; } @@ -50,7 +55,16 @@ - (void)mount:(int)visibleStartIndex end:(int)visibleEndIndex * components before they are actually added to the pool. */ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 16 * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{ - self->_childrenRegistry.mountRange(visibleStartIndex, visibleEndIndex); + std::vector mounted = {}; + for (NSString *key in self->_childrenPool) { + UIView *childComponentView = self->_childrenPool[key]; + const auto &childViewProps = *std::static_pointer_cast([childComponentView props]); + + if (childViewProps.index >= visibleStartIndex && childViewProps.index <= visibleEndIndex) + mounted.push_back(childViewProps.uniqueId); + } + + self->_childrenRegistry.mount(mounted); }); } diff --git a/src/Shadowlist.tsx b/src/Shadowlist.tsx index f70455a..b63debd 100644 --- a/src/Shadowlist.tsx +++ b/src/Shadowlist.tsx @@ -79,7 +79,7 @@ export const Shadowlist = React.forwardRef( {props.renderItem({ item, index })} From feeef9a5f158db9d4a8990ecb4961b37a81d3017 Mon Sep 17 00:00:00 2001 From: azim Date: Tue, 19 Nov 2024 01:06:18 +0500 Subject: [PATCH 3/7] chore: fix android build with new slelement component integration --- .../com/shadowlist/SLComponentRegistry.java | 29 +++--- .../main/java/com/shadowlist/SLContainer.java | 2 +- .../SLContainerChildrenManager.java | 32 ++++-- .../com/shadowlist/SLContainerPackage.java | 1 + .../main/java/com/shadowlist/SLElement.java | 50 ++++++++++ .../java/com/shadowlist/SLElementManager.java | 61 ++++++++++++ cpp/cpp-adapter.cpp | 97 ++++++++++--------- cpp/registry/SLComponentRegistry.h | 1 + ios/SLContainerChildrenManager.mm | 1 - 9 files changed, 201 insertions(+), 73 deletions(-) create mode 100644 android/src/main/java/com/shadowlist/SLElement.java create mode 100644 android/src/main/java/com/shadowlist/SLElementManager.java diff --git a/android/src/main/java/com/shadowlist/SLComponentRegistry.java b/android/src/main/java/com/shadowlist/SLComponentRegistry.java index da83027..d26ab0b 100644 --- a/android/src/main/java/com/shadowlist/SLComponentRegistry.java +++ b/android/src/main/java/com/shadowlist/SLComponentRegistry.java @@ -12,11 +12,10 @@ public SLComponentRegistry() { } private native long nativeInit(); - private native void nativeRegisterComponent(long nativePtr, int index); - private native void nativeUnregisterComponent(long nativePtr, int index); - private native void nativeMountRange(long nativePtr, int visibleStartIndex, int visibleEndIndex); - private native void nativeMount(long nativePtr, int[] indices); - private native void nativeUnmount(long nativePtr, int[] indices); + private native void nativeRegisterComponent(long nativePtr, String uniqueId); + private native void nativeUnregisterComponent(long nativePtr, String uniqueId); + private native void nativeMount(long nativePtr, String[] uniqueIds); + private native void nativeUnmount(long nativePtr, String[] uniqueIds); private native void nativeMountObserver(long nativePtr, SLObserver observer); private native void nativeUnmountObserver(long nativePtr, SLObserver observer); private native void nativeDestroy(long nativePtr); @@ -25,24 +24,20 @@ public interface SLObserver { void onVisibilityChanged(int id, boolean isVisible); } - public void registerComponent(int index) { - nativeRegisterComponent(mNativePtr, index); + public void registerComponent(String uniqueId) { + nativeRegisterComponent(mNativePtr, uniqueId); } - public void unregisterComponent(int index) { - nativeUnregisterComponent(mNativePtr, index); + public void unregisterComponent(String uniqueId) { + nativeUnregisterComponent(mNativePtr, uniqueId); } - public void mountRange(int visibleStartIndex, int visibleEndIndex) { - nativeMountRange(mNativePtr, visibleStartIndex, visibleEndIndex); + public void mount(String[] uniqueIds) { + nativeMount(mNativePtr, uniqueIds); } - public void mount(int[] indices) { - nativeMount(mNativePtr, indices); - } - - public void unmount(int[] indices) { - nativeUnmount(mNativePtr, indices); + public void unmount(String[] uniqueIds) { + nativeUnmount(mNativePtr, uniqueIds); } public void mountObserver(SLObserver observer) { diff --git a/android/src/main/java/com/shadowlist/SLContainer.java b/android/src/main/java/com/shadowlist/SLContainer.java index ffb12b6..b0bfd99 100644 --- a/android/src/main/java/com/shadowlist/SLContainer.java +++ b/android/src/main/java/com/shadowlist/SLContainer.java @@ -125,7 +125,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { @Override public void addView(View child, int index) { - mContainerChildrenManager.mountChildComponentView(child, index); + mContainerChildrenManager.mountChildComponentView(child, ((SLElement)child).getUniqueId()); } @Override diff --git a/android/src/main/java/com/shadowlist/SLContainerChildrenManager.java b/android/src/main/java/com/shadowlist/SLContainerChildrenManager.java index c097b2f..907d727 100644 --- a/android/src/main/java/com/shadowlist/SLContainerChildrenManager.java +++ b/android/src/main/java/com/shadowlist/SLContainerChildrenManager.java @@ -2,13 +2,14 @@ import android.view.View; import com.facebook.react.views.view.ReactViewGroup; + import java.util.HashMap; import java.util.Map; public class SLContainerChildrenManager { private ReactViewGroup mScrollContent; private SLComponentRegistry mChildrenRegistry; - private Map mChildrenPool; + private Map mChildrenPool; public SLContainerChildrenManager(ReactViewGroup contentView) { this.mScrollContent = contentView; @@ -33,23 +34,34 @@ private void mountObserver(int index, boolean isVisible) { } } - public void mountChildComponentView(View childComponentView, int index) { - mChildrenPool.put(index, childComponentView); - mChildrenRegistry.registerComponent(index); + public void mountChildComponentView(View childComponentView, String uniqueId) { + mChildrenPool.put(uniqueId, childComponentView); + mChildrenRegistry.registerComponent(uniqueId); } - public void unmountChildComponentView(View childComponentView, int index) { - mChildrenRegistry.unregisterComponent(index); - mChildrenPool.remove(index); + public void unmountChildComponentView(View childComponentView, String uniqueId) { + mChildrenRegistry.unregisterComponent(uniqueId); + mChildrenPool.remove(uniqueId); } public void mount(int visibleStartIndex, int visibleEndIndex) { - mChildrenRegistry.mountRange(visibleStartIndex, visibleEndIndex); + String[] mounted = new String[mChildrenPool.size()]; + int index = 0; + + for (Map.Entry entry : mChildrenPool.entrySet()) { + SLElement childComponentView = (SLElement)entry.getValue(); + + if (childComponentView.getIndex() >= visibleStartIndex && childComponentView.getIndex() <= visibleEndIndex) { + mounted[index++] = childComponentView.getUniqueId(); + } + } + + mChildrenRegistry.mount(mounted); } public void destroy() { - for (Integer index : mChildrenPool.keySet()) { - unmountChildComponentView(mChildrenPool.get(index), index); + for (String uniqueId : mChildrenPool.keySet()) { + unmountChildComponentView(mChildrenPool.get(uniqueId), uniqueId); } mChildrenRegistry.destroy(); } diff --git a/android/src/main/java/com/shadowlist/SLContainerPackage.java b/android/src/main/java/com/shadowlist/SLContainerPackage.java index 35d30f3..05bd830 100644 --- a/android/src/main/java/com/shadowlist/SLContainerPackage.java +++ b/android/src/main/java/com/shadowlist/SLContainerPackage.java @@ -14,6 +14,7 @@ public class SLContainerPackage implements ReactPackage { public List createViewManagers(ReactApplicationContext reactContext) { List viewManagers = new ArrayList<>(); viewManagers.add(new SLContainerManager()); + viewManagers.add(new SLElementManager()); return viewManagers; } diff --git a/android/src/main/java/com/shadowlist/SLElement.java b/android/src/main/java/com/shadowlist/SLElement.java new file mode 100644 index 0000000..0f3c238 --- /dev/null +++ b/android/src/main/java/com/shadowlist/SLElement.java @@ -0,0 +1,50 @@ +package com.shadowlist; + +import android.content.Context; +import android.widget.HorizontalScrollView; +import android.widget.ScrollView; +import android.view.View; +import android.graphics.Canvas; +import android.util.AttributeSet; +import androidx.annotation.Nullable; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.facebook.react.bridge.WritableNativeMap; +import com.facebook.react.common.mapbuffer.MapBuffer; +import com.facebook.react.uimanager.PixelUtil; +import com.facebook.react.uimanager.StateWrapper; +import com.facebook.react.views.view.ReactViewGroup; + +public class SLElement extends ReactViewGroup { + private int mIndex; + private String mUniqueId; + + public SLElement(Context context) { + super(context); + init(context); + } + + public SLElement(Context context, AttributeSet attrs) { + super(context); + init(context); + } + + private void init(Context context) { + } + + public int getIndex() { + return this.mIndex; + } + + public String getUniqueId() { + return this.mUniqueId; + } + + public void setIndex(int index) { + this.mIndex = index; + } + + public void setUniqueId(String uniqueId) { + this.mUniqueId = uniqueId; + } +} diff --git a/android/src/main/java/com/shadowlist/SLElementManager.java b/android/src/main/java/com/shadowlist/SLElementManager.java new file mode 100644 index 0000000..49598ed --- /dev/null +++ b/android/src/main/java/com/shadowlist/SLElementManager.java @@ -0,0 +1,61 @@ +package com.shadowlist; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.facebook.react.bridge.ReactContext; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.common.MapBuilder; +import com.facebook.react.module.annotations.ReactModule; +import com.facebook.react.uimanager.ReactStylesDiffMap; +import com.facebook.react.uimanager.StateWrapper; +import com.facebook.react.uimanager.UIManagerHelper; +import com.facebook.react.uimanager.ViewGroupManager; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewManagerDelegate; +import com.facebook.react.uimanager.annotations.ReactProp; +import com.facebook.react.common.mapbuffer.MapBuffer; +import com.facebook.react.uimanager.events.EventDispatcher; +import com.facebook.react.viewmanagers.SLElementManagerInterface; +import com.facebook.react.viewmanagers.SLElementManagerDelegate; + +import java.util.Map; + +@ReactModule(name = SLElementManager.NAME) +public class SLElementManager extends ViewGroupManager + implements SLElementManagerInterface { + + private final ViewManagerDelegate mDelegate; + + public SLElementManager() { + mDelegate = new SLElementManagerDelegate(this); + } + + @Override + public ViewManagerDelegate getDelegate() { + return mDelegate; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public SLElement createViewInstance(ThemedReactContext context) { + SLElement view = new SLElement(context); + return view; + } + + public static final String NAME = "SLElement"; + + @Override + public void setIndex(SLElement view, @Nullable int value) { + view.setIndex(value); + } + + @Override + public void setUniqueId(SLElement view, @Nullable String value) { + view.setUniqueId(value); + } +} diff --git a/cpp/cpp-adapter.cpp b/cpp/cpp-adapter.cpp index eb51f2b..c69da22 100644 --- a/cpp/cpp-adapter.cpp +++ b/cpp/cpp-adapter.cpp @@ -1,6 +1,7 @@ #ifdef ANDROID #include #include +#include #include "SLComponentRegistry.h" extern "C" @@ -10,75 +11,83 @@ JNIEXPORT jlong JNICALL Java_com_shadowlist_SLComponentRegistry_nativeInit(JNIEn } extern "C" -JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeRegisterComponent(JNIEnv *env, jobject thiz, jlong registryPtr, jint index) { +JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeRegisterComponent(JNIEnv *env, jobject thiz, jlong registryPtr, jstring uniqueId) { + const char *uniqueIdChars = env->GetStringUTFChars(uniqueId, nullptr); + std::string uniqueIdStr(uniqueIdChars); + env->ReleaseStringUTFChars(uniqueId, uniqueIdChars); auto *registry = reinterpret_cast(registryPtr); - registry->registerComponent(index); + registry->registerComponent(uniqueIdStr); } extern "C" -JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeUnregisterComponent(JNIEnv *env, jobject thiz, jlong registryPtr, jint index) { +JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeUnregisterComponent(JNIEnv *env, jobject thiz, jlong registryPtr, jstring uniqueId) { + const char *uniqueIdChars = env->GetStringUTFChars(uniqueId, nullptr); + std::string uniqueIdStr(uniqueIdChars); + env->ReleaseStringUTFChars(uniqueId, uniqueIdChars); auto *registry = reinterpret_cast(registryPtr); - registry->unregisterComponent(index); + registry->unregisterComponent(uniqueIdStr); } extern "C" -JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeMountRange(JNIEnv *env, jobject thiz, jlong registryPtr, jint visibleStartIndex, jint visibleEndIndex) { +JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeMount(JNIEnv *env, jobject thiz, jlong registryPtr, jobjectArray uniqueIds) { auto *registry = reinterpret_cast(registryPtr); - registry->mountRange(visibleStartIndex, visibleEndIndex); -} - -extern "C" -JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeMount(JNIEnv *env, jobject thiz, jlong registryPtr, jintArray indices) { - auto *registry = reinterpret_cast(registryPtr); - jint *elements = env->GetIntArrayElements(indices, nullptr); - jsize length = env->GetArrayLength(indices); + jsize length = env->GetArrayLength(uniqueIds); + + std::vector indexVector; + for (jsize i = 0; i < length; ++i) { + jstring uniqueId = (jstring) env->GetObjectArrayElement(uniqueIds, i); + const char *uniqueIdChars = env->GetStringUTFChars(uniqueId, nullptr); + indexVector.push_back(std::string(uniqueIdChars)); + env->ReleaseStringUTFChars(uniqueId, uniqueIdChars); + } - std::vector indexVector(elements, elements + length); registry->mount(indexVector); - - env->ReleaseIntArrayElements(indices, elements, 0); } extern "C" -JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeUnmount(JNIEnv *env, jobject thiz, jlong registryPtr, jintArray indices) { +JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeUnmount(JNIEnv *env, jobject thiz, jlong registryPtr, jobjectArray uniqueIds) { auto *registry = reinterpret_cast(registryPtr); - jint *elements = env->GetIntArrayElements(indices, nullptr); - jsize length = env->GetArrayLength(indices); + jsize length = env->GetArrayLength(uniqueIds); + + std::vector indexVector; + for (jsize i = 0; i < length; ++i) { + jstring uniqueId = (jstring) env->GetObjectArrayElement(uniqueIds, i); + const char *uniqueIdChars = env->GetStringUTFChars(uniqueId, nullptr); + indexVector.push_back(std::string(uniqueIdChars)); + env->ReleaseStringUTFChars(uniqueId, uniqueIdChars); + } - std::vector indexVector(elements, elements + length); registry->unmount(indexVector); - - env->ReleaseIntArrayElements(indices, elements, 0); } extern "C" JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeMountObserver(JNIEnv *env, jobject thiz, jlong registryPtr, jobject observer) { - auto *registry = reinterpret_cast(registryPtr); - - jobject globalObserver = env->NewGlobalRef(observer); - auto observerCallback = [env, globalObserver](int index, bool isVisible) { - jclass observerClass = env->GetObjectClass(globalObserver); - jmethodID methodId = env->GetMethodID(observerClass, "onVisibilityChanged", "(IZ)V"); - env->CallVoidMethod(globalObserver, methodId, index, static_cast(isVisible)); - }; - - registry->mountObserver(observerCallback); - // env->DeleteGlobalRef(globalObserver); +// auto *registry = reinterpret_cast(registryPtr); +// +// jobject globalObserver = env->NewGlobalRef(observer); +// auto observerCallback = [env, globalObserver](int index, bool isVisible) { +// jclass observerClass = env->GetObjectClass(globalObserver); +// jmethodID methodId = env->GetMethodID(observerClass, "onVisibilityChanged", "(IZ)V"); +// env->CallVoidMethod(globalObserver, methodId, index, static_cast(isVisible)); +// }; +// +// registry->mountObserver(observerCallback); +// // env->DeleteGlobalRef(globalObserver); } extern "C" JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeUnmountObserver(JNIEnv *env, jobject thiz, jlong registryPtr, jobject observer) { - auto *registry = reinterpret_cast(registryPtr); - - jobject globalObserver = env->NewGlobalRef(observer); - auto observerCallback = [env, globalObserver](int index, bool isVisible) { - jclass observerClass = env->GetObjectClass(globalObserver); - jmethodID methodId = env->GetMethodID(observerClass, "onVisibilityChanged", "(IZ)V"); - env->CallVoidMethod(globalObserver, methodId, index, static_cast(isVisible)); - }; - - registry->unmountObserver(observerCallback); - // env->DeleteGlobalRef(globalObserver); +// auto *registry = reinterpret_cast(registryPtr); +// +// jobject globalObserver = env->NewGlobalRef(observer); +// auto observerCallback = [env, globalObserver](int index, bool isVisible) { +// jclass observerClass = env->GetObjectClass(globalObserver); +// jmethodID methodId = env->GetMethodID(observerClass, "onVisibilityChanged", "(IZ)V"); +// env->CallVoidMethod(globalObserver, methodId, index, static_cast(isVisible)); +// }; +// +// registry->unmountObserver(observerCallback); +// // env->DeleteGlobalRef(globalObserver); } extern "C" diff --git a/cpp/registry/SLComponentRegistry.h b/cpp/registry/SLComponentRegistry.h index 79cbbf8..57b0732 100644 --- a/cpp/registry/SLComponentRegistry.h +++ b/cpp/registry/SLComponentRegistry.h @@ -7,6 +7,7 @@ #include #include #include +#include class SLComponent { public: diff --git a/ios/SLContainerChildrenManager.mm b/ios/SLContainerChildrenManager.mm index 12cd231..5dd3a61 100644 --- a/ios/SLContainerChildrenManager.mm +++ b/ios/SLContainerChildrenManager.mm @@ -28,7 +28,6 @@ - (void)mountObserver:(std::string)uniqueId isVisible:(bool)isVisible { if (isVisible) { [_scrollContent insertSubview:childComponentView atIndex:childViewProps.index]; } else { - NSLog(@"dbg unmount %d", childViewProps.index); [childComponentView removeFromSuperview]; } } From 857232227d286512b04c9720e4182617960be150 Mon Sep 17 00:00:00 2001 From: azim Date: Tue, 19 Nov 2024 15:36:44 +0500 Subject: [PATCH 4/7] chore: fix android build for newly added component, temporarily disable jni adapter --- cpp/CMakeLists.txt | 23 +++-- cpp/SLElementSpec.cpp | 11 +++ cpp/SLElementSpec.h | 15 +++ cpp/cpp-adapter.cpp | 95 ++++++++++--------- .../components/SLElementSpec/SLElementState.h | 17 ++++ example/android/gradle.properties | 2 + react-native.config.js | 1 + 7 files changed, 106 insertions(+), 58 deletions(-) create mode 100644 cpp/SLElementSpec.cpp create mode 100644 cpp/SLElementSpec.h diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index c850fe9..26bced3 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -1,11 +1,7 @@ cmake_minimum_required(VERSION 3.13) set(CMAKE_VERBOSE_MAKEFILE ON) -set(LIB_LITERAL SLContainerSpec) -set(LIB_LITERAL_FENWICK fenwick) -set(LIB_LITERAL_REGISTRY registry) -set(LIB_TARGET_NAME react_codegen_${LIB_LITERAL}) - +set(LIB_TARGET_NAME react_codegen_SLContainerSpec) set(LIB_ANDROID_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../android) set(LIB_COMMON_DIR ${CMAKE_CURRENT_SOURCE_DIR}) @@ -18,11 +14,13 @@ add_compile_options( -Wno-gnu-zero-variadic-macro-arguments ) -file(GLOB LIB_IMPORT_SRCS CONFIGURE_DEPENDS SLContainerSpec.cpp) file(GLOB LIB_CUSTOM_SRCS CONFIGURE_DEPENDS - ${LIB_COMMON_DIR}/react/renderer/components/${LIB_LITERAL}/*.cpp - ${LIB_COMMON_DIR}/${LIB_LITERAL_FENWICK}/*.cpp - ${LIB_COMMON_DIR}/${LIB_LITERAL_REGISTRY}/*.cpp + SLContainerSpec.cpp + SLElementSpec.cpp + ${LIB_COMMON_DIR}/react/renderer/components/SLContainerSpec/*.cpp + ${LIB_COMMON_DIR}/react/renderer/components/SLElementSpec/*.cpp + ${LIB_COMMON_DIR}/fenwick/*.cpp + ${LIB_COMMON_DIR}/registry/*.cpp ) add_library( @@ -39,9 +37,10 @@ target_include_directories( ${LIB_COMMON_DIR} ${LIB_IMPORT_SRCS} ${LIB_CUSTOM_SRCS} - ${LIB_COMMON_DIR}/react/renderer/components/${LIB_LITERAL} - ${LIB_COMMON_DIR}/${LIB_LITERAL_FENWICK} - ${LIB_COMMON_DIR}/${LIB_LITERAL_REGISTRY} + ${LIB_COMMON_DIR}/react/renderer/components/SLContainerSpec + ${LIB_COMMON_DIR}/react/renderer/components/SLElementSpec + ${LIB_COMMON_DIR}/fenwick + ${LIB_COMMON_DIR}/registry ) target_link_libraries( diff --git a/cpp/SLElementSpec.cpp b/cpp/SLElementSpec.cpp new file mode 100644 index 0000000..e8bb02d --- /dev/null +++ b/cpp/SLElementSpec.cpp @@ -0,0 +1,11 @@ +#ifdef ANDROID +#include "SLElementSpec.h" + +namespace facebook::react { + +std::shared_ptr SLElementSpec_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams ¶ms) { + return nullptr; +} + +} +#endif diff --git a/cpp/SLElementSpec.h b/cpp/SLElementSpec.h new file mode 100644 index 0000000..43e0bf3 --- /dev/null +++ b/cpp/SLElementSpec.h @@ -0,0 +1,15 @@ +#pragma once + +#ifdef ANDROID +#include +#include +#include +#include "SLElementComponentDescriptor.h" + +namespace facebook::react { + +JSI_EXPORT +std::shared_ptr SLElementSpec_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams ¶ms); + +} +#endif diff --git a/cpp/cpp-adapter.cpp b/cpp/cpp-adapter.cpp index c69da22..235ba2d 100644 --- a/cpp/cpp-adapter.cpp +++ b/cpp/cpp-adapter.cpp @@ -30,64 +30,67 @@ JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeUnregisterC extern "C" JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeMount(JNIEnv *env, jobject thiz, jlong registryPtr, jobjectArray uniqueIds) { - auto *registry = reinterpret_cast(registryPtr); - jsize length = env->GetArrayLength(uniqueIds); - - std::vector indexVector; - for (jsize i = 0; i < length; ++i) { - jstring uniqueId = (jstring) env->GetObjectArrayElement(uniqueIds, i); - const char *uniqueIdChars = env->GetStringUTFChars(uniqueId, nullptr); - indexVector.push_back(std::string(uniqueIdChars)); - env->ReleaseStringUTFChars(uniqueId, uniqueIdChars); - } - - registry->mount(indexVector); +// auto *registry = reinterpret_cast(registryPtr); +// jsize length = env->GetArrayLength(uniqueIds); +// +// std::vector indexVector; +// for (jsize i = 0; i < length; ++i) { +// jstring uniqueId = (jstring) env->GetObjectArrayElement(uniqueIds, i); +// const char *uniqueIdChars = env->GetStringUTFChars(uniqueId, nullptr); +// indexVector.push_back(std::string(uniqueIdChars)); +// env->ReleaseStringUTFChars(uniqueId, uniqueIdChars); +// } +// +// registry->mount(indexVector); } extern "C" JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeUnmount(JNIEnv *env, jobject thiz, jlong registryPtr, jobjectArray uniqueIds) { - auto *registry = reinterpret_cast(registryPtr); - jsize length = env->GetArrayLength(uniqueIds); - - std::vector indexVector; - for (jsize i = 0; i < length; ++i) { - jstring uniqueId = (jstring) env->GetObjectArrayElement(uniqueIds, i); - const char *uniqueIdChars = env->GetStringUTFChars(uniqueId, nullptr); - indexVector.push_back(std::string(uniqueIdChars)); - env->ReleaseStringUTFChars(uniqueId, uniqueIdChars); - } - - registry->unmount(indexVector); +// auto *registry = reinterpret_cast(registryPtr); +// jsize length = env->GetArrayLength(uniqueIds); +// +// std::vector indexVector; +// for (jsize i = 0; i < length; ++i) { +// jstring uniqueId = (jstring) env->GetObjectArrayElement(uniqueIds, i); +// const char *uniqueIdChars = env->GetStringUTFChars(uniqueId, nullptr); +// indexVector.push_back(std::string(uniqueIdChars)); +// env->ReleaseStringUTFChars(uniqueId, uniqueIdChars); +// } +// +// registry->unmount(indexVector); } extern "C" JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeMountObserver(JNIEnv *env, jobject thiz, jlong registryPtr, jobject observer) { -// auto *registry = reinterpret_cast(registryPtr); -// -// jobject globalObserver = env->NewGlobalRef(observer); -// auto observerCallback = [env, globalObserver](int index, bool isVisible) { -// jclass observerClass = env->GetObjectClass(globalObserver); -// jmethodID methodId = env->GetMethodID(observerClass, "onVisibilityChanged", "(IZ)V"); -// env->CallVoidMethod(globalObserver, methodId, index, static_cast(isVisible)); -// }; -// -// registry->mountObserver(observerCallback); -// // env->DeleteGlobalRef(globalObserver); + auto *registry = reinterpret_cast(registryPtr); + + jobject globalObserver = env->NewGlobalRef(observer); + auto observerCallback = [env, globalObserver](const std::string& uniqueId, bool isVisible) { + jclass observerClass = env->GetObjectClass(globalObserver); + jmethodID methodId = env->GetMethodID(observerClass, "onVisibilityChanged", "(IZ)V"); + jstring jUniqueId = env->NewStringUTF(uniqueId.c_str()); + env->CallVoidMethod(globalObserver, methodId, jUniqueId, static_cast(isVisible)); + env->DeleteLocalRef(jUniqueId); + }; + + registry->mountObserver(observerCallback); + // env->DeleteGlobalRef(globalObserver); } extern "C" JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeUnmountObserver(JNIEnv *env, jobject thiz, jlong registryPtr, jobject observer) { -// auto *registry = reinterpret_cast(registryPtr); -// -// jobject globalObserver = env->NewGlobalRef(observer); -// auto observerCallback = [env, globalObserver](int index, bool isVisible) { -// jclass observerClass = env->GetObjectClass(globalObserver); -// jmethodID methodId = env->GetMethodID(observerClass, "onVisibilityChanged", "(IZ)V"); -// env->CallVoidMethod(globalObserver, methodId, index, static_cast(isVisible)); -// }; -// -// registry->unmountObserver(observerCallback); -// // env->DeleteGlobalRef(globalObserver); + auto *registry = reinterpret_cast(registryPtr); + + jobject globalObserver = env->NewGlobalRef(observer); + auto observerCallback = [env, globalObserver](const std::string& uniqueId, bool isVisible) { + jclass observerClass = env->GetObjectClass(globalObserver); + jmethodID methodId = env->GetMethodID(observerClass, "onVisibilityChanged", "(IZ)V"); + jstring jUniqueId = env->NewStringUTF(uniqueId.c_str()); + env->CallVoidMethod(globalObserver, methodId, jUniqueId, static_cast(isVisible)); + env->DeleteLocalRef(jUniqueId); + }; + registry->unmountObserver(observerCallback); + // env->DeleteGlobalRef(globalObserver); } extern "C" diff --git a/cpp/react/renderer/components/SLElementSpec/SLElementState.h b/cpp/react/renderer/components/SLElementSpec/SLElementState.h index 81b482d..60f0088 100644 --- a/cpp/react/renderer/components/SLElementSpec/SLElementState.h +++ b/cpp/react/renderer/components/SLElementSpec/SLElementState.h @@ -3,11 +3,28 @@ #include #include +#ifdef ANDROID +#include +#include +#include +#endif + + namespace facebook::react { class SLElementState { public: SLElementState() = default; + +#ifdef ANDROID + SLElementState(const SLElementState& previousState, folly::dynamic data) {}; + folly::dynamic getDynamic() const { + return {}; + }; + MapBuffer getMapBuffer() const { + return MapBufferBuilder::EMPTY(); + }; +#endif }; } diff --git a/example/android/gradle.properties b/example/android/gradle.properties index 5e24e3a..cd8d9b4 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -37,3 +37,5 @@ newArchEnabled=true # Use this property to enable or disable the Hermes JS engine. # If set to false, you will be using JSC instead. hermesEnabled=true + +org.gradle.caching=false diff --git a/react-native.config.js b/react-native.config.js index 54fd693..6381867 100644 --- a/react-native.config.js +++ b/react-native.config.js @@ -5,6 +5,7 @@ module.exports = { dependency: { platforms: { android: { + componentDescriptors: ['SLContainerComponentDescriptor'], cmakeListsPath: '../cpp/CMakeLists.txt', }, }, From fea1c534701c41df502af3c22928aaf0a3903e9a Mon Sep 17 00:00:00 2001 From: azim Date: Tue, 19 Nov 2024 16:22:08 +0500 Subject: [PATCH 5/7] chore: fix android build and add uniquid ref support to jni adapter --- .../com/shadowlist/SLComponentRegistry.java | 2 +- .../SLContainerChildrenManager.java | 25 +++++---- cpp/cpp-adapter.cpp | 52 +++++++++---------- 3 files changed, 42 insertions(+), 37 deletions(-) diff --git a/android/src/main/java/com/shadowlist/SLComponentRegistry.java b/android/src/main/java/com/shadowlist/SLComponentRegistry.java index d26ab0b..6a2798f 100644 --- a/android/src/main/java/com/shadowlist/SLComponentRegistry.java +++ b/android/src/main/java/com/shadowlist/SLComponentRegistry.java @@ -21,7 +21,7 @@ public SLComponentRegistry() { private native void nativeDestroy(long nativePtr); public interface SLObserver { - void onVisibilityChanged(int id, boolean isVisible); + void onVisibilityChanged(String uniqueId, boolean isVisible); } public void registerComponent(String uniqueId) { diff --git a/android/src/main/java/com/shadowlist/SLContainerChildrenManager.java b/android/src/main/java/com/shadowlist/SLContainerChildrenManager.java index 907d727..07a8780 100644 --- a/android/src/main/java/com/shadowlist/SLContainerChildrenManager.java +++ b/android/src/main/java/com/shadowlist/SLContainerChildrenManager.java @@ -3,8 +3,10 @@ import android.view.View; import com.facebook.react.views.view.ReactViewGroup; -import java.util.HashMap; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.HashMap; public class SLContainerChildrenManager { private ReactViewGroup mScrollContent; @@ -15,17 +17,17 @@ public SLContainerChildrenManager(ReactViewGroup contentView) { this.mScrollContent = contentView; this.mChildrenRegistry = new SLComponentRegistry(); - mChildrenRegistry.mountObserver((index, isVisible) -> { + mChildrenRegistry.mountObserver((uniqueId, isVisible) -> { try { - mountObserver(index, isVisible); + mountObserver(uniqueId, isVisible); } catch (IndexOutOfBoundsException e) {} }); this.mChildrenPool = new HashMap<>(); } - private void mountObserver(int index, boolean isVisible) { - View child = mChildrenPool.get(index); + private void mountObserver(String uniqueId, boolean isVisible) { + View child = mChildrenPool.get(uniqueId); if (isVisible) { mScrollContent.addView(child); @@ -45,20 +47,23 @@ public void unmountChildComponentView(View childComponentView, String uniqueId) } public void mount(int visibleStartIndex, int visibleEndIndex) { - String[] mounted = new String[mChildrenPool.size()]; - int index = 0; + List mounted = new ArrayList<>(); for (Map.Entry entry : mChildrenPool.entrySet()) { - SLElement childComponentView = (SLElement)entry.getValue(); + SLElement childComponentView = (SLElement) entry.getValue(); if (childComponentView.getIndex() >= visibleStartIndex && childComponentView.getIndex() <= visibleEndIndex) { - mounted[index++] = childComponentView.getUniqueId(); + mounted.add(childComponentView.getUniqueId()); } } - mChildrenRegistry.mount(mounted); + // Convert the List to an array if needed + String[] mountedArray = mounted.toArray(new String[0]); + + mChildrenRegistry.mount(mountedArray); } + public void destroy() { for (String uniqueId : mChildrenPool.keySet()) { unmountChildComponentView(mChildrenPool.get(uniqueId), uniqueId); diff --git a/cpp/cpp-adapter.cpp b/cpp/cpp-adapter.cpp index 235ba2d..9880180 100644 --- a/cpp/cpp-adapter.cpp +++ b/cpp/cpp-adapter.cpp @@ -30,34 +30,34 @@ JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeUnregisterC extern "C" JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeMount(JNIEnv *env, jobject thiz, jlong registryPtr, jobjectArray uniqueIds) { -// auto *registry = reinterpret_cast(registryPtr); -// jsize length = env->GetArrayLength(uniqueIds); -// -// std::vector indexVector; -// for (jsize i = 0; i < length; ++i) { -// jstring uniqueId = (jstring) env->GetObjectArrayElement(uniqueIds, i); -// const char *uniqueIdChars = env->GetStringUTFChars(uniqueId, nullptr); -// indexVector.push_back(std::string(uniqueIdChars)); -// env->ReleaseStringUTFChars(uniqueId, uniqueIdChars); -// } -// -// registry->mount(indexVector); + auto *registry = reinterpret_cast(registryPtr); + jsize length = env->GetArrayLength(uniqueIds); + + std::vector indexVector; + for (jsize i = 0; i < length; ++i) { + jstring uniqueId = (jstring) env->GetObjectArrayElement(uniqueIds, i); + const char *uniqueIdChars = env->GetStringUTFChars(uniqueId, nullptr); + indexVector.push_back(std::string(uniqueIdChars)); + env->ReleaseStringUTFChars(uniqueId, uniqueIdChars); + } + + registry->mount(indexVector); } extern "C" JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeUnmount(JNIEnv *env, jobject thiz, jlong registryPtr, jobjectArray uniqueIds) { -// auto *registry = reinterpret_cast(registryPtr); -// jsize length = env->GetArrayLength(uniqueIds); -// -// std::vector indexVector; -// for (jsize i = 0; i < length; ++i) { -// jstring uniqueId = (jstring) env->GetObjectArrayElement(uniqueIds, i); -// const char *uniqueIdChars = env->GetStringUTFChars(uniqueId, nullptr); -// indexVector.push_back(std::string(uniqueIdChars)); -// env->ReleaseStringUTFChars(uniqueId, uniqueIdChars); -// } -// -// registry->unmount(indexVector); + auto *registry = reinterpret_cast(registryPtr); + jsize length = env->GetArrayLength(uniqueIds); + + std::vector indexVector; + for (jsize i = 0; i < length; ++i) { + jstring uniqueId = (jstring) env->GetObjectArrayElement(uniqueIds, i); + const char *uniqueIdChars = env->GetStringUTFChars(uniqueId, nullptr); + indexVector.push_back(std::string(uniqueIdChars)); + env->ReleaseStringUTFChars(uniqueId, uniqueIdChars); + } + + registry->unmount(indexVector); } extern "C" @@ -67,7 +67,7 @@ JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeMountObserv jobject globalObserver = env->NewGlobalRef(observer); auto observerCallback = [env, globalObserver](const std::string& uniqueId, bool isVisible) { jclass observerClass = env->GetObjectClass(globalObserver); - jmethodID methodId = env->GetMethodID(observerClass, "onVisibilityChanged", "(IZ)V"); + jmethodID methodId = env->GetMethodID(observerClass, "onVisibilityChanged", "(Ljava/lang/String;Z)V"); jstring jUniqueId = env->NewStringUTF(uniqueId.c_str()); env->CallVoidMethod(globalObserver, methodId, jUniqueId, static_cast(isVisible)); env->DeleteLocalRef(jUniqueId); @@ -84,7 +84,7 @@ JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeUnmountObse jobject globalObserver = env->NewGlobalRef(observer); auto observerCallback = [env, globalObserver](const std::string& uniqueId, bool isVisible) { jclass observerClass = env->GetObjectClass(globalObserver); - jmethodID methodId = env->GetMethodID(observerClass, "onVisibilityChanged", "(IZ)V"); + jmethodID methodId = env->GetMethodID(observerClass, "onVisibilityChanged", "(Ljava/lang/String;Z)V"); jstring jUniqueId = env->NewStringUTF(uniqueId.c_str()); env->CallVoidMethod(globalObserver, methodId, jUniqueId, static_cast(isVisible)); env->DeleteLocalRef(jUniqueId); From 633e61aedfb9482830b5825d7ef99b795dbea5a7 Mon Sep 17 00:00:00 2001 From: azim Date: Tue, 19 Nov 2024 18:59:28 +0500 Subject: [PATCH 6/7] chore: update obsolete readme, adjust indentation --- README.md | 8 ++------ android/src/main/java/com/shadowlist/SLContainer.java | 2 +- .../java/com/shadowlist/SLContainerChildrenManager.java | 4 +--- cpp/cpp-adapter.cpp | 3 ++- example/android/gradle.properties | 2 -- 5 files changed, 6 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index f22c8ab..5050e45 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -# shadowlist (ios alpha release) +# shadowlist [alpha release] ShadowList is a new alternative to FlatList for React Native, created to address common performance issues and enhance the UX when dealing with large lists of data. -It invokes Yoga for precise layout measurements of Shadow Nodes and constructs a Fenwick Tree with layout metrics for efficient offset calculations. By virtualizing children and rendering only items within the visible area, ShadowList ensures optimal performance. It's built on Fabric and works with React Native version 0.74 and newer. +It invokes Yoga for precise layout measurements of Shadow Nodes and constructs a Fenwick Tree with layout metrics for efficient offset calculations. By virtualizing children and rendering only items within the visible area, ShadowList ensures optimal performance. It's built on Fabric and works with React Native version 0.75 and newer. ## Out of box comparison to FlatList | Feature | ShadowList | FlatList | @@ -77,10 +77,6 @@ import {SLContainer} from 'shadowlist'; | `scrollToIndex` | Function | Scrolls the list to the specified index. | | `scrollToOffset`| Function | Scrolls the list to the specified offset. | -## Contributing - -See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow. - ## License MIT diff --git a/android/src/main/java/com/shadowlist/SLContainer.java b/android/src/main/java/com/shadowlist/SLContainer.java index b0bfd99..8c4b0cf 100644 --- a/android/src/main/java/com/shadowlist/SLContainer.java +++ b/android/src/main/java/com/shadowlist/SLContainer.java @@ -125,7 +125,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { @Override public void addView(View child, int index) { - mContainerChildrenManager.mountChildComponentView(child, ((SLElement)child).getUniqueId()); + mContainerChildrenManager.mountChildComponentView(child, ((SLElement)child).getUniqueId()); } @Override diff --git a/android/src/main/java/com/shadowlist/SLContainerChildrenManager.java b/android/src/main/java/com/shadowlist/SLContainerChildrenManager.java index 07a8780..a1a310d 100644 --- a/android/src/main/java/com/shadowlist/SLContainerChildrenManager.java +++ b/android/src/main/java/com/shadowlist/SLContainerChildrenManager.java @@ -57,10 +57,8 @@ public void mount(int visibleStartIndex, int visibleEndIndex) { } } - // Convert the List to an array if needed String[] mountedArray = mounted.toArray(new String[0]); - - mChildrenRegistry.mount(mountedArray); + mChildrenRegistry.mount(mountedArray); } diff --git a/cpp/cpp-adapter.cpp b/cpp/cpp-adapter.cpp index 9880180..d69e512 100644 --- a/cpp/cpp-adapter.cpp +++ b/cpp/cpp-adapter.cpp @@ -73,7 +73,7 @@ JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeMountObserv env->DeleteLocalRef(jUniqueId); }; - registry->mountObserver(observerCallback); + registry->mountObserver(observerCallback); // env->DeleteGlobalRef(globalObserver); } @@ -89,6 +89,7 @@ JNIEXPORT void JNICALL Java_com_shadowlist_SLComponentRegistry_nativeUnmountObse env->CallVoidMethod(globalObserver, methodId, jUniqueId, static_cast(isVisible)); env->DeleteLocalRef(jUniqueId); }; + registry->unmountObserver(observerCallback); // env->DeleteGlobalRef(globalObserver); } diff --git a/example/android/gradle.properties b/example/android/gradle.properties index cd8d9b4..5e24e3a 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -37,5 +37,3 @@ newArchEnabled=true # Use this property to enable or disable the Hermes JS engine. # If set to false, you will be using JSC instead. hermesEnabled=true - -org.gradle.caching=false From f973a722d7dfe20b0ca0f10d7ef076d9bccf9c18 Mon Sep 17 00:00:00 2001 From: azim Date: Tue, 19 Nov 2024 21:06:45 +0500 Subject: [PATCH 7/7] chore: validate ios build --- example/ios/Podfile.lock | 2 +- shadowlist.podspec | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index deaa8d5..0898fbd 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1783,7 +1783,7 @@ SPEC CHECKSUMS: React-utils: cbe8b8b3d7b2ac282e018e46f0e7b25cdc87c5a0 ReactCodegen: 4bcb34e6b5ebf6eef5cee34f55aa39991ea1c1f1 ReactCommon: 6a952e50c2a4b694731d7682aaa6c79bc156e4ad - shadowlist: 0ba026e36420a23603bcef766e8a64c2b12e0bcd + shadowlist: 523681bd3cc7c831e9c4da6e21db7777350f5109 SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d Yoga: 055f92ad73f8c8600a93f0e25ac0b2344c3b07e6 diff --git a/shadowlist.podspec b/shadowlist.podspec index 461b11e..bcebbe3 100644 --- a/shadowlist.podspec +++ b/shadowlist.podspec @@ -14,11 +14,9 @@ Pod::Spec.new do |s| s.platforms = { :ios => min_ios_version_supported } s.source = { :git => "https://github.com/azimgd/shadowlist.git", :tag => "#{s.version}" } - s.source_files = "{ios,cpp}/**/*.{h,hpp,m,mm,cpp}" - s.exclude_files = "ios/generated/**/*" + s.source_files = ["{ios,cpp}/**/*.{h,hpp,m,mm,cpp}"] + s.exclude_files = ["ios/generated/**/*", "!ios/generated/build/generated/ios/react/**"] - # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0. - # See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79. if respond_to?(:install_modules_dependencies, true) install_modules_dependencies(s) else @@ -27,10 +25,10 @@ Pod::Spec.new do |s| # Don't install the dependencies when we run `pod install` in the old architecture. if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1" - s.pod_target_xcconfig = { - "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"", - "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1", - "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" + s.pod_target_xcconfig = { + "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"", + "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1", + "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" } s.dependency "React-RCTFabric" s.dependency "React-Codegen"