Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fix build-script #2355

Merged
merged 4 commits into from
Sep 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,9 @@ def safeExtGet(prop, fallback) {
}

apply plugin: 'com.android.library'
apply plugin: 'maven'
apply plugin: 'maven-publish'
apply plugin: 'de.undercouch.download'

def CMAKE_TOOLCHAIN_FILE = ""
if(!System.getenv('IS_TRAVIS')) {
CMAKE_TOOLCHAIN_FILE = "-DCMAKE_TOOLCHAIN_FILE=${getNdkBuildFullPath()}/../build/cmake/android.toolchain.cmake"
}

android {
buildFeatures {
Expand All @@ -111,7 +107,6 @@ android {
"-DNATIVE_DEBUG=${debugNativeLibraries}",
"-DREACT_NATIVE_TARGET_VERSION=${REACT_VERSION}",
"-DANDROID_TOOLCHAIN=clang",
"${CMAKE_TOOLCHAIN_FILE}",
"-DBOOST_VERSION=${BOOST_VERSION}",
"-DFOR_HERMES=${FOR_HERMES}"
abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
Expand Down Expand Up @@ -220,6 +215,7 @@ task downloadGlog(dependsOn: createNativeDepsDirectories, type: Download) {
// Prepare glog sources to be compiled, this task will perform steps that normally should've been
// executed by automake. This way we can avoid dependencies on make/automake
task prepareGlog(dependsOn: dependenciesPath ? [] : [downloadGlog], type: Copy) {
duplicatesStrategy = 'include'
from(dependenciesPath ?: tarTree(downloadGlog.dest))
from("$reactNativeThirdParty/glog/")
include("glog-${GLOG_VERSION}/src/**/*", "Android.mk", "config.h")
Expand Down Expand Up @@ -444,6 +440,7 @@ task packageNdkLibs(type: Copy) {
}

repositories {
jcenter()
mavenCentral()
mavenLocal()
maven {
Expand All @@ -462,7 +459,6 @@ dependencies {
implementation 'com.facebook.fbjni:fbjni:0.2.2'
implementation 'com.facebook.react:react-native:+' // From node_modules
implementation "androidx.transition:transition:1.1.0"
implementation project(path: ':react-native-screens')
extractHeaders("com.facebook.fbjni:fbjni:0.2.2:headers")
extractSO("com.facebook.fbjni:fbjni:0.2.2")

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
package com.swmansion.reanimated.layoutReanimation;

import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.uimanager.IViewManagerWithChildren;
import com.facebook.react.uimanager.NativeViewHierarchyManager;
import com.facebook.react.uimanager.RootViewManager;
import com.facebook.react.uimanager.ViewAtIndex;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.ViewManager;
import com.facebook.react.uimanager.ViewManagerRegistry;
import com.facebook.react.uimanager.layoutanimation.LayoutAnimationController;
import com.facebook.react.uimanager.layoutanimation.LayoutAnimationListener;
import com.swmansion.reanimated.ReanimatedModule;

import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

class ReaLayoutAnimator extends LayoutAnimationController {
private AnimationsManager mAnimationsManager = null;
private volatile boolean mInitialized = false;
private ReactApplicationContext mContext;
private WeakReference<NativeViewHierarchyManager> mWeakNativeViewHierarchyManage = new WeakReference<>(null);

ReaLayoutAnimator(ReactApplicationContext context, NativeViewHierarchyManager nativeViewHierarchyManager) {
mContext = context;
mWeakNativeViewHierarchyManage = new WeakReference<>(nativeViewHierarchyManager);
}

public void maybeInit() {
if (!mInitialized) {
mInitialized = true;
ReanimatedModule reanimatedModule = mContext.getNativeModule(ReanimatedModule.class);
mAnimationsManager = reanimatedModule.getNodesManager().getAnimationsManager();
mAnimationsManager.setReanimatedNativeHierarchyManager((ReanimatedNativeHierarchyManager) mWeakNativeViewHierarchyManage.get());
}
}

public boolean shouldAnimateLayout(View viewToAnimate) {
// if view parent is null, skip animation: view have been clipped, we don't want animation to
// resume when view is re-attached to parent, which is the standard android animation behavior.
// If there's a layout handling animation going on, it should be animated nonetheless since the
// ongoing animation needs to be updated.
if (viewToAnimate == null) {
return false;
}
return (viewToAnimate.getParent() != null);
}

/**
* Update layout of given view, via immediate update or animation depending on the current batch
* layout animation configuration supplied during initialization. Handles create and update
* animations.
*
* @param view the view to update layout of
* @param x the new X position for the view
* @param y the new Y position for the view
* @param width the new width value for the view
* @param height the new height value for the view
*/
public void applyLayoutUpdate(View view, int x, int y, int width, int height) {
UiThreadUtil.assertOnUiThread();
maybeInit();
// Determine which animation to use : if view is initially invisible, use create animation,
// otherwise use update animation. This approach is easier than maintaining a list of tags
// for recently created views.
if (view.getWidth() == 0 || view.getHeight() == 0) {
view.layout(x, y, x + width, y + height);
mAnimationsManager.onViewCreate(view, (ViewGroup) view.getParent(), new Snapshot(view,mWeakNativeViewHierarchyManage.get()));
} else {
Snapshot before = new Snapshot(view,mWeakNativeViewHierarchyManage.get());
view.layout(x, y, x + width, y + height);
Snapshot after = new Snapshot(view,mWeakNativeViewHierarchyManage.get());
mAnimationsManager.onViewUpdate(view, before, after);
}
}

/**
* Animate a view deletion using the layout animation configuration supplied during
* initialization.
*
* @param view The view to animate.
* @param listener Called once the animation is finished, should be used to completely remove the
* view.
*/
public void deleteView(final View view, final LayoutAnimationListener listener) {
UiThreadUtil.assertOnUiThread();
maybeInit();
Snapshot before = new Snapshot(view,mWeakNativeViewHierarchyManage.get());
mAnimationsManager.onViewRemoval(view, (ViewGroup) view.getParent(), before, () -> listener.onAnimationEnd());
NativeViewHierarchyManager nativeViewHierarchyManager = mWeakNativeViewHierarchyManage.get();
ViewManager vm = nativeViewHierarchyManager.resolveViewManager(view.getId());
if (vm instanceof ViewGroupManager) {
ViewGroupManager vgm = (ViewGroupManager) vm;
for (int i = 0; i < vgm.getChildCount((ViewGroup) view); ++i) {
dfs(vgm.getChildAt((ViewGroup)view, i), nativeViewHierarchyManager);
}
}
}

private void dfs(View view, NativeViewHierarchyManager nativeViewHierarchyManager) {
ViewManager vm = nativeViewHierarchyManager.resolveViewManager(view.getId());
if (vm != null) {
Snapshot before = new Snapshot(view,mWeakNativeViewHierarchyManage.get());
mAnimationsManager.onViewRemoval(view, (ViewGroup) view.getParent(), before, () -> {
ReanimatedNativeHierarchyManager reanimatedNativeHierarchyManager = (ReanimatedNativeHierarchyManager) nativeViewHierarchyManager;
reanimatedNativeHierarchyManager.publicDropView(view);
});
}
if (vm instanceof ViewGroupManager) {
ViewGroupManager vgm = (ViewGroupManager) vm;
for (int i = 0; i < vgm.getChildCount((ViewGroup) view); ++i) {
dfs(vgm.getChildAt((ViewGroup)view, i), nativeViewHierarchyManager);
}
}
}
}

public class ReanimatedNativeHierarchyManager extends NativeViewHierarchyManager {
private HashMap<Integer, ArrayList<View>> toBeRemoved = new HashMap();
private HashMap<Integer, Runnable> cleanerCallback = new HashMap();
private LayoutAnimationController mReaLayoutAnimator = null;
public ReanimatedNativeHierarchyManager(ViewManagerRegistry viewManagers, ReactApplicationContext reactContext) {
super(viewManagers);
Class clazz = this.getClass().getSuperclass();
try {
Field field = clazz.getDeclaredField("mLayoutAnimator");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("accessFlags");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
mReaLayoutAnimator = new ReaLayoutAnimator(reactContext, this);
field.set(this, mReaLayoutAnimator);

} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
setLayoutAnimationEnabled(true);
}

public ReanimatedNativeHierarchyManager(ViewManagerRegistry viewManagers, RootViewManager manager) {
super(viewManagers, manager);
}

public synchronized void updateLayout(int parentTag, int tag, int x, int y, int width, int height) {
super.updateLayout(parentTag, tag, x, y, width, height);
View viewToUpdate = this.resolveView(tag);
ViewManager parentViewManager = this.resolveViewManager(parentTag);
String parentViewManagerName = parentViewManager.getName();
View container = resolveView(parentTag);
if (container != null && parentViewManagerName.equals("RNSScreenContainer")) {
this.mReaLayoutAnimator.applyLayoutUpdate(viewToUpdate, 0, 0, container.getWidth(), container.getHeight());
}
}

// @Override
public synchronized void manageChildren(int tag, @Nullable int[] indicesToRemove, @Nullable ViewAtIndex[] viewsToAdd, @Nullable int[] tagsToDelete) {
ViewGroup viewGroup = (ViewGroup) resolveView(tag);
ViewGroupManager viewGroupManager = (ViewGroupManager) resolveViewManager(tag);
if (toBeRemoved.containsKey(tag)) {
ArrayList<View> childrenToBeRemoved = toBeRemoved.get(tag);
HashSet<Integer> tagsToRemove = new HashSet<Integer>();
for (View childToRemove : childrenToBeRemoved) {
tagsToRemove.add(childToRemove.getId());
}
while (viewGroupManager.getChildCount(viewGroup) != 0) {
View child = viewGroupManager.getChildAt(viewGroup, viewGroupManager.getChildCount(viewGroup)-1);
if (tagsToRemove.contains(child.getId())) {
viewGroupManager.removeViewAt(viewGroup, viewGroupManager.getChildCount(viewGroup)-1);
} else {
break;
}
}
}
if (tagsToDelete != null) {
if (!toBeRemoved.containsKey(tag)) {
toBeRemoved.put(tag, new ArrayList<>());
}
ArrayList<View> toBeRemovedChildren = toBeRemoved.get(tag);
for (Integer childtag : tagsToDelete) {
View view = resolveView(childtag);
toBeRemovedChildren.add(view);
cleanerCallback.put(view.getId(), new Runnable() {
@Override
public void run() {
toBeRemovedChildren.remove(view);
} // It's far from optimal but let's leave it as it is for now
});
}
}
int[] mock = new int[]{};
super.manageChildren(tag, indicesToRemove, viewsToAdd, mock, mock);
if (toBeRemoved.containsKey(tag)) {
ArrayList<View> childrenToBeRemoved = toBeRemoved.get(tag);
for (View child : childrenToBeRemoved) {
viewGroupManager.addView(viewGroup, child, viewGroupManager.getChildCount(viewGroup));
}
}
ViewAtIndex[] mock2 = new ViewAtIndex[]{};
super.manageChildren(tag, mock, mock2, tagsToDelete, mock);
}

public void publicDropView(View view) {
dropView(view);
}

@Override
protected synchronized void dropView(View view) {
if (toBeRemoved.containsKey(view.getId())) {
toBeRemoved.remove(view.getId());
}
if (cleanerCallback.containsKey(view.getId())) {
Runnable runnable = cleanerCallback.get(view.getId());
cleanerCallback.remove(view.getId());
runnable.run();
}
// childrens' callbacks should be cleaned by former publicDropView calls as Animation Manager
// stripes views from bottom to top
super.dropView(view);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.facebook.react.uimanager;

import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.swmansion.reanimated.layoutReanimation.ReanimatedNativeHierarchyManager;
import java.util.List;

public class ReanimatedUIImplementation extends UIImplementation {
public ReanimatedUIImplementation(ReactApplicationContext reactContext, UIManagerModule.ViewManagerResolver viewManagerResolver, EventDispatcher eventDispatcher, int minTimeLeftInFrameForNonBatchedOperationMs) {
this(reactContext, new ViewManagerRegistry(viewManagerResolver), eventDispatcher, minTimeLeftInFrameForNonBatchedOperationMs);
}

public ReanimatedUIImplementation(ReactApplicationContext reactContext, List<ViewManager> viewManagerList, EventDispatcher eventDispatcher, int minTimeLeftInFrameForNonBatchedOperationMs) {
this(reactContext, new ViewManagerRegistry(viewManagerList), eventDispatcher, minTimeLeftInFrameForNonBatchedOperationMs);
}

public ReanimatedUIImplementation(ReactApplicationContext reactContext, ViewManagerRegistry viewManagerRegistry, EventDispatcher eventDispatcher, int minTimeLeftInFrameForNonBatchedOperationMs) {
super(
reactContext,
viewManagerRegistry,
new UIViewOperationQueue(
reactContext,
new ReanimatedNativeHierarchyManager(viewManagerRegistry, reactContext),
minTimeLeftInFrameForNonBatchedOperationMs),
eventDispatcher);
}

/**
* Invoked when there is a mutation in a node tree.
*
* @param tag react tag of the node we want to manage
* @param indicesToRemove ordered (asc) list of indicies at which view should be removed
* @param viewsToAdd ordered (asc based on mIndex property) list of tag-index pairs that represent
* a view which should be added at the specified index
* @param tagsToDelete list of tags corresponding to views that should be removed
*/
public void manageChildren(
int viewTag,
@Nullable ReadableArray moveFrom,
@Nullable ReadableArray moveTo,
@Nullable ReadableArray addChildTags,
@Nullable ReadableArray addAtIndices,
@Nullable ReadableArray removeFrom) {
super.manageChildren(viewTag, moveFrom, moveTo, addChildTags, addAtIndices, removeFrom);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.facebook.react.uimanager;

import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.swmansion.reanimated.layoutReanimation.ReanimatedNativeHierarchyManager;
import java.util.List;

public class ReanimatedUIImplementation extends UIImplementation {
public ReanimatedUIImplementation(ReactApplicationContext reactContext, UIManagerModule.ViewManagerResolver viewManagerResolver, EventDispatcher eventDispatcher, int minTimeLeftInFrameForNonBatchedOperationMs) {
this(reactContext, new ViewManagerRegistry(viewManagerResolver), eventDispatcher, minTimeLeftInFrameForNonBatchedOperationMs);
}

public ReanimatedUIImplementation(ReactApplicationContext reactContext, List<ViewManager> viewManagerList, EventDispatcher eventDispatcher, int minTimeLeftInFrameForNonBatchedOperationMs) {
this(reactContext, new ViewManagerRegistry(viewManagerList), eventDispatcher, minTimeLeftInFrameForNonBatchedOperationMs);
}

public ReanimatedUIImplementation(ReactApplicationContext reactContext, ViewManagerRegistry viewManagerRegistry, EventDispatcher eventDispatcher, int minTimeLeftInFrameForNonBatchedOperationMs) {
super(
reactContext,
viewManagerRegistry,
new UIViewOperationQueue(
reactContext,
new ReanimatedNativeHierarchyManager(viewManagerRegistry, reactContext),
minTimeLeftInFrameForNonBatchedOperationMs),
eventDispatcher);
}

/**
* Invoked when there is a mutation in a node tree.
*
* @param tag react tag of the node we want to manage
* @param indicesToRemove ordered (asc) list of indicies at which view should be removed
* @param viewsToAdd ordered (asc based on mIndex property) list of tag-index pairs that represent
* a view which should be added at the specified index
* @param tagsToDelete list of tags corresponding to views that should be removed
*/
public void manageChildren(
int viewTag,
@Nullable ReadableArray moveFrom,
@Nullable ReadableArray moveTo,
@Nullable ReadableArray addChildTags,
@Nullable ReadableArray addAtIndices,
@Nullable ReadableArray removeFrom) {
super.manageChildren(viewTag, moveFrom, moveTo, addChildTags, addAtIndices, removeFrom);
}

}
Loading