1
0
mirror of https://gitcode.com/gh_mirrors/re/react-native-pushy.git synced 2025-09-16 12:51:44 +08:00
Code Issues Packages Projects Releases Wiki Activity GitHub Gitee

Compare commits

...

31 Commits

Author SHA1 Message Date
sunnylqm
a1c2679427 v5.9.0 2020-09-27 22:32:30 +08:00
sunnylqm
17ff366f51 Implement download and install apk 2020-09-27 22:16:27 +08:00
sunnylqm
3c5792423e v5.8.3 2020-09-24 22:45:12 +08:00
sunnylqm
d071fbfc2b Fix ios bridge reload 2020-09-24 22:44:50 +08:00
sunnylqm
17dffa1eb5 Rename hashname -> hash 2020-09-24 22:44:37 +08:00
sunnylqm
bcd61315e9 v5.8.2 2020-09-24 19:36:09 +08:00
sunnylqm
f626cc1933 Fix download event and remove unzip event 2020-09-24 19:31:27 +08:00
sunnylqm
4ba3f25972 v5.8.1 2020-09-17 23:20:32 +08:00
sunnylqm
cd695b1ffb Revert rctreloadcommand 2020-09-17 23:18:17 +08:00
sunnylqm
37a1a5a18b Merge branch 'master' of github.com:reactnativecn/react-native-pushy
# Conflicts:
#	package.json
2020-09-16 17:35:16 +08:00
sunnylqm
5a2ebf8df7 Fix example setState 2020-09-16 14:42:45 +08:00
sunnylqm
95ba5f364b v5.8.0 2020-09-16 14:37:32 +08:00
sunnylqm
841228c341 Fix example 2020-09-16 14:36:37 +08:00
sunnylqm
93049f1e54 v5.8.0-beta1 2020-09-16 13:02:53 +08:00
sunnylqm
a966655faf Implement download progress 2020-09-16 13:01:14 +08:00
sunnylqm
a4052091e0 Update example to 0.63 2020-09-01 15:29:13 +08:00
sunnylqm
ebb5defb10 v5.7.2 2020-09-01 10:51:43 +08:00
sunnylqm
a509ff8e30 Cleanup 2020-09-01 10:51:15 +08:00
sunnylqm
59fcba15ee Implement blockupdate on android 2020-08-31 18:39:03 +08:00
sunnylqm
c6f9bb20a1 Add client info and uuid 2020-08-31 11:47:08 +08:00
sunnylqm
9e6c7ea769 setBlockUpdate 2020-08-31 01:17:28 +08:00
sunnylqm
f461c8ddd2 Update endpoint and example 2020-08-26 00:44:34 +08:00
sunnylqm
4cbeb7bec4 v5.7.0 2020-08-13 00:32:52 +08:00
sunnylqm
ed7f5ac606 Detect android bundle url 2020-08-13 00:32:07 +08:00
sunnylqm
6abb2c7a5d Unify download progress event 2020-08-09 00:08:30 +08:00
sunnylqm
a4a372f17e Revert "Exclude backup"
This reverts commit 2d805fb38e.
2020-08-08 21:09:15 +08:00
sunnylqm
48693e3b45 v5.7.0-beta1 2020-08-04 13:05:14 +08:00
sunnylqm
2d805fb38e Exclude backup 2020-08-04 13:03:53 +08:00
sunnylqm
92c421b30f Fix typo 2020-08-04 13:03:37 +08:00
sunnylqm
dbd0880295 Fix custom endpoints 2020-07-28 23:34:06 +08:00
sunnylqm
f110df1206 Add custom endpoints 2020-07-28 23:15:42 +08:00
38 changed files with 3424 additions and 4918 deletions

7
.gitignore vendored
View File

@@ -1,7 +1,6 @@
/.idea
/node_modules
/android/build
/android/obj
.vscode
android/build
android/obj
*.iml
# OSX

View File

@@ -1,11 +1,11 @@
/.idea
/.babelrc
/.npmignore
/.eslintrc
/.nvmrc
/.travis.yml
/Example
/android/build
.babelrc
.npmignore
.eslintrc
.nvmrc
.travis.yml
Example
android/build
.vscode
# OSX
#
@@ -45,4 +45,5 @@ Example
yarn.lock
android/jni
domains.json
domains.json
endpoints.json

View File

@@ -1,75 +0,0 @@
[ignore]
; We fork some components by platform
.*/*[.]android.js
; Ignore "BUCK" generated dirs
<PROJECT_ROOT>/\.buckd/
; Ignore polyfills
node_modules/react-native/Libraries/polyfills/.*
; These should not be required directly
; require from fbjs/lib instead: require('fbjs/lib/warning')
node_modules/warning/.*
; Flow doesn't support platforms
.*/Libraries/Utilities/LoadingView.js
[untyped]
.*/node_modules/@react-native-community/cli/.*/.*
[include]
[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/flow/
[options]
emoji=true
esproposal.optional_chaining=enable
esproposal.nullish_coalescing=enable
module.file_ext=.js
module.file_ext=.json
module.file_ext=.ios.js
munge_underscores=true
module.name_mapper='^react-native$' -> '<PROJECT_ROOT>/node_modules/react-native/Libraries/react-native/react-native-implementation'
module.name_mapper='^react-native/\(.*\)$' -> '<PROJECT_ROOT>/node_modules/react-native/\1'
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '<PROJECT_ROOT>/node_modules/react-native/Libraries/Image/RelativeImageStub'
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FlowFixMeProps
suppress_type=$FlowFixMeState
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
[lints]
sketchy-null-number=warn
sketchy-null-mixed=warn
sketchy-number=warn
untyped-type-import=warn
nonstrict-import=warn
deprecated-type=warn
unsafe-getters-setters=warn
inexact-spread=warn
unnecessary-invariant=warn
signature-verification-failure=warn
deprecated-utility=error
[strict]
deprecated-type
nonstrict-import
sketchy-null
unclear-type
unsafe-getters-setters
untyped-import
untyped-type-import
[version]
^0.105.0

View File

@@ -15,10 +15,12 @@ import com.android.build.OutputFile
* // the name of the generated asset file containing your JS bundle
* bundleAssetName: "index.android.bundle",
*
* // the entry file for bundle generation
* // the entry file for bundle generation. If none specified and
* // "index.android.js" exists, it will be used. Otherwise "index.js" is
* // default. Can be overridden with ENTRY_FILE environment variable.
* entryFile: "index.android.js",
*
* // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format
* // https://reactnative.dev/docs/performance#enable-the-ram-format
* bundleCommand: "ram-bundle",
*
* // whether to bundle JS and assets in debug mode
@@ -76,7 +78,6 @@ import com.android.build.OutputFile
*/
project.ext.react = [
entryFile: "index.js",
enableHermes: false, // clean and rebuild if changing
]
@@ -156,12 +157,13 @@ android {
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://facebook.github.io/react-native/docs/signed-apk-android.
// see https://reactnative.dev/docs/signed-apk-android.
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
@@ -180,8 +182,24 @@ android {
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'
}
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
exclude group:'com.squareup.okhttp3', module:'okhttp'
}
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
}
if (enableHermes) {
def hermesPath = "../../node_modules/hermes-engine/android/";
debugImplementation files(hermesPath + "hermes-debug.aar")
@@ -198,4 +216,4 @@ task copyDownloadableDepsToLibs(type: Copy) {
into 'libs'
}
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)

View File

@@ -0,0 +1,72 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
*/
package com.testhotupdate;
import android.content.Context;
import com.facebook.flipper.android.AndroidFlipperClient;
import com.facebook.flipper.android.utils.FlipperUtils;
import com.facebook.flipper.core.FlipperClient;
import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
import com.facebook.flipper.plugins.inspector.DescriptorMapping;
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
import com.facebook.flipper.plugins.react.ReactFlipperPlugin;
import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.modules.network.NetworkingModule;
import okhttp3.OkHttpClient;
public class ReactNativeFlipper {
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
if (FlipperUtils.shouldEnableFlipper(context)) {
final FlipperClient client = AndroidFlipperClient.getInstance(context);
client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
client.addPlugin(new ReactFlipperPlugin());
client.addPlugin(new DatabasesFlipperPlugin(context));
client.addPlugin(new SharedPreferencesFlipperPlugin(context));
client.addPlugin(CrashReporterPlugin.getInstance());
NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
NetworkingModule.setCustomClientBuilder(
new NetworkingModule.CustomClientBuilder() {
@Override
public void apply(OkHttpClient.Builder builder) {
builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
}
});
client.addPlugin(networkFlipperPlugin);
client.start();
// Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
// Hence we run if after all native modules have been initialized
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
if (reactContext == null) {
reactInstanceManager.addReactInstanceEventListener(
new ReactInstanceManager.ReactInstanceEventListener() {
@Override
public void onReactContextInitialized(ReactContext reactContext) {
reactInstanceManager.removeReactInstanceEventListener(this);
reactContext.runOnNativeModulesQueueThread(
new Runnable() {
@Override
public void run() {
client.addPlugin(new FrescoFlipperPlugin());
}
});
}
});
} else {
client.addPlugin(new FrescoFlipperPlugin());
}
}
}
}

View File

@@ -14,7 +14,8 @@
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@@ -4,6 +4,7 @@ import android.app.Application;
import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;
@@ -50,23 +51,28 @@ public class MainApplication extends Application implements ReactApplication {
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this); // Remove this line if you don't want Flipper enabled
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}
/**
* Loads Flipper in React Native templates.
/**
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
*
* @param context
* @param reactInstanceManager
*/
private static void initializeFlipper(Context context) {
private static void initializeFlipper(
Context context, ReactInstanceManager reactInstanceManager) {
if (BuildConfig.DEBUG) {
try {
/*
We use reflection here to pick up the class that initializes Flipper,
since Flipper library is not available in release mode
*/
Class<?> aClass = Class.forName("com.facebook.flipper.ReactNativeFlipper");
aClass.getMethod("initializeFlipper", Context.class).invoke(null, context);
Class<?> aClass = Class.forName("com.testhotupdate.ReactNativeFlipper");
aClass
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
.invoke(null, context, reactInstanceManager);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {

View File

@@ -2,17 +2,17 @@
buildscript {
ext {
buildToolsVersion = "28.0.3"
minSdkVersion = 16
compileSdkVersion = 28
targetSdkVersion = 28
buildToolsVersion = "29.0.2"
minSdkVersion = 21
compileSdkVersion = 29
targetSdkVersion = 29
}
repositories {
google()
jcenter()
}
dependencies {
classpath('com.android.tools.build:gradle:3.5.1')
classpath('com.android.tools.build:gradle:3.5.3')
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@@ -33,6 +33,6 @@ allprojects {
google()
jcenter()
maven { url 'https://jitpack.io' }
maven { url 'https://www.jitpack.io' }
}
}

View File

@@ -17,5 +17,12 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
# Version of flipper SDK to use with React Native
FLIPPER_VERSION=0.54.0

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -7,7 +7,7 @@
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
@@ -125,8 +125,8 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
@@ -154,19 +154,19 @@ if $cygwin ; then
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
i=`expr $i + 1`
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
@@ -175,14 +175,9 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
exec "$JAVACMD" "$@"

View File

@@ -5,7 +5,7 @@
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem http://www.apache.org/licenses/LICENSE-2.0
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@@ -97,4 +100,4 @@ exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
:omega

View File

@@ -1,39 +1,20 @@
platform :ios, '9.0'
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
platform :ios, '10.0'
target 'testHotUpdate' do
# Pods for testHotUpdate
pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
pod 'React', :path => '../node_modules/react-native/'
pod 'React-Core', :path => '../node_modules/react-native/'
pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'
config = use_native_modules!
pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon"
pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
use_react_native!(:path => config["reactNativePath"])
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
use_native_modules!
# Enables Flipper.
#
# Note that if you have use_frameworks! enabled, Flipper will not work and
# you should disable these next few lines.
use_flipper!('Flipper' => '0.54.0')
post_install do |installer|
flipper_post_install(installer)
end
end

View File

@@ -1,245 +1,346 @@
PODS:
- boost-for-react-native (1.63.0)
- CocoaAsyncSocket (7.6.4)
- CocoaLibEvent (1.0.0)
- DoubleConversion (1.1.6)
- FBLazyVector (0.61.4)
- FBReactNativeSpec (0.61.4):
- Folly (= 2018.10.22.00)
- RCTRequired (= 0.61.4)
- RCTTypeSafety (= 0.61.4)
- React-Core (= 0.61.4)
- React-jsi (= 0.61.4)
- ReactCommon/turbomodule/core (= 0.61.4)
- Folly (2018.10.22.00):
- FBLazyVector (0.63.2)
- FBReactNativeSpec (0.63.2):
- Folly (= 2020.01.13.00)
- RCTRequired (= 0.63.2)
- RCTTypeSafety (= 0.63.2)
- React-Core (= 0.63.2)
- React-jsi (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- Flipper (0.54.0):
- Flipper-Folly (~> 2.2)
- Flipper-RSocket (~> 1.1)
- Flipper-DoubleConversion (1.1.7)
- Flipper-Folly (2.2.0):
- boost-for-react-native
- CocoaLibEvent (~> 1.0)
- Flipper-DoubleConversion
- Flipper-Glog
- OpenSSL-Universal (= 1.0.2.19)
- Flipper-Glog (0.3.6)
- Flipper-PeerTalk (0.0.4)
- Flipper-RSocket (1.1.0):
- Flipper-Folly (~> 2.2)
- FlipperKit (0.54.0):
- FlipperKit/Core (= 0.54.0)
- FlipperKit/Core (0.54.0):
- Flipper (~> 0.54.0)
- FlipperKit/CppBridge
- FlipperKit/FBCxxFollyDynamicConvert
- FlipperKit/FBDefines
- FlipperKit/FKPortForwarding
- FlipperKit/CppBridge (0.54.0):
- Flipper (~> 0.54.0)
- FlipperKit/FBCxxFollyDynamicConvert (0.54.0):
- Flipper-Folly (~> 2.2)
- FlipperKit/FBDefines (0.54.0)
- FlipperKit/FKPortForwarding (0.54.0):
- CocoaAsyncSocket (~> 7.6)
- Flipper-PeerTalk (~> 0.0.4)
- FlipperKit/FlipperKitHighlightOverlay (0.54.0)
- FlipperKit/FlipperKitLayoutPlugin (0.54.0):
- FlipperKit/Core
- FlipperKit/FlipperKitHighlightOverlay
- FlipperKit/FlipperKitLayoutTextSearchable
- YogaKit (~> 1.18)
- FlipperKit/FlipperKitLayoutTextSearchable (0.54.0)
- FlipperKit/FlipperKitNetworkPlugin (0.54.0):
- FlipperKit/Core
- FlipperKit/FlipperKitReactPlugin (0.54.0):
- FlipperKit/Core
- FlipperKit/FlipperKitUserDefaultsPlugin (0.54.0):
- FlipperKit/Core
- FlipperKit/SKIOSNetworkPlugin (0.54.0):
- FlipperKit/Core
- FlipperKit/FlipperKitNetworkPlugin
- Folly (2020.01.13.00):
- boost-for-react-native
- DoubleConversion
- Folly/Default (= 2018.10.22.00)
- Folly/Default (= 2020.01.13.00)
- glog
- Folly/Default (2018.10.22.00):
- Folly/Default (2020.01.13.00):
- boost-for-react-native
- DoubleConversion
- glog
- glog (0.3.5)
- RCTRequired (0.61.4)
- RCTTypeSafety (0.61.4):
- FBLazyVector (= 0.61.4)
- Folly (= 2018.10.22.00)
- RCTRequired (= 0.61.4)
- React-Core (= 0.61.4)
- React (0.61.4):
- React-Core (= 0.61.4)
- React-Core/DevSupport (= 0.61.4)
- React-Core/RCTWebSocket (= 0.61.4)
- React-RCTActionSheet (= 0.61.4)
- React-RCTAnimation (= 0.61.4)
- React-RCTBlob (= 0.61.4)
- React-RCTImage (= 0.61.4)
- React-RCTLinking (= 0.61.4)
- React-RCTNetwork (= 0.61.4)
- React-RCTSettings (= 0.61.4)
- React-RCTText (= 0.61.4)
- React-RCTVibration (= 0.61.4)
- React-Core (0.61.4):
- Folly (= 2018.10.22.00)
- OpenSSL-Universal (1.0.2.19):
- OpenSSL-Universal/Static (= 1.0.2.19)
- OpenSSL-Universal/Static (1.0.2.19)
- RCTRequired (0.63.2)
- RCTTypeSafety (0.63.2):
- FBLazyVector (= 0.63.2)
- Folly (= 2020.01.13.00)
- RCTRequired (= 0.63.2)
- React-Core (= 0.63.2)
- React (0.63.2):
- React-Core (= 0.63.2)
- React-Core/DevSupport (= 0.63.2)
- React-Core/RCTWebSocket (= 0.63.2)
- React-RCTActionSheet (= 0.63.2)
- React-RCTAnimation (= 0.63.2)
- React-RCTBlob (= 0.63.2)
- React-RCTImage (= 0.63.2)
- React-RCTLinking (= 0.63.2)
- React-RCTNetwork (= 0.63.2)
- React-RCTSettings (= 0.63.2)
- React-RCTText (= 0.63.2)
- React-RCTVibration (= 0.63.2)
- React-callinvoker (0.63.2)
- React-Core (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default (= 0.61.4)
- React-cxxreact (= 0.61.4)
- React-jsi (= 0.61.4)
- React-jsiexecutor (= 0.61.4)
- React-Core/Default (= 0.63.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/CoreModulesHeaders (0.61.4):
- Folly (= 2018.10.22.00)
- React-Core/CoreModulesHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.4)
- React-jsi (= 0.61.4)
- React-jsiexecutor (= 0.61.4)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/Default (0.61.4):
- Folly (= 2018.10.22.00)
- React-Core/Default (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-cxxreact (= 0.61.4)
- React-jsi (= 0.61.4)
- React-jsiexecutor (= 0.61.4)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/DevSupport (0.61.4):
- Folly (= 2018.10.22.00)
- React-Core/DevSupport (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default (= 0.61.4)
- React-Core/RCTWebSocket (= 0.61.4)
- React-cxxreact (= 0.61.4)
- React-jsi (= 0.61.4)
- React-jsiexecutor (= 0.61.4)
- React-jsinspector (= 0.61.4)
- React-Core/Default (= 0.63.2)
- React-Core/RCTWebSocket (= 0.63.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- React-jsinspector (= 0.63.2)
- Yoga
- React-Core/RCTActionSheetHeaders (0.61.4):
- Folly (= 2018.10.22.00)
- React-Core/RCTActionSheetHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.4)
- React-jsi (= 0.61.4)
- React-jsiexecutor (= 0.61.4)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTAnimationHeaders (0.61.4):
- Folly (= 2018.10.22.00)
- React-Core/RCTAnimationHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.4)
- React-jsi (= 0.61.4)
- React-jsiexecutor (= 0.61.4)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTBlobHeaders (0.61.4):
- Folly (= 2018.10.22.00)
- React-Core/RCTBlobHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.4)
- React-jsi (= 0.61.4)
- React-jsiexecutor (= 0.61.4)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTImageHeaders (0.61.4):
- Folly (= 2018.10.22.00)
- React-Core/RCTImageHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.4)
- React-jsi (= 0.61.4)
- React-jsiexecutor (= 0.61.4)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTLinkingHeaders (0.61.4):
- Folly (= 2018.10.22.00)
- React-Core/RCTLinkingHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.4)
- React-jsi (= 0.61.4)
- React-jsiexecutor (= 0.61.4)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTNetworkHeaders (0.61.4):
- Folly (= 2018.10.22.00)
- React-Core/RCTNetworkHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.4)
- React-jsi (= 0.61.4)
- React-jsiexecutor (= 0.61.4)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTSettingsHeaders (0.61.4):
- Folly (= 2018.10.22.00)
- React-Core/RCTSettingsHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.4)
- React-jsi (= 0.61.4)
- React-jsiexecutor (= 0.61.4)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTTextHeaders (0.61.4):
- Folly (= 2018.10.22.00)
- React-Core/RCTTextHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.4)
- React-jsi (= 0.61.4)
- React-jsiexecutor (= 0.61.4)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTVibrationHeaders (0.61.4):
- Folly (= 2018.10.22.00)
- React-Core/RCTVibrationHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.4)
- React-jsi (= 0.61.4)
- React-jsiexecutor (= 0.61.4)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTWebSocket (0.61.4):
- Folly (= 2018.10.22.00)
- React-Core/RCTWebSocket (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default (= 0.61.4)
- React-cxxreact (= 0.61.4)
- React-jsi (= 0.61.4)
- React-jsiexecutor (= 0.61.4)
- React-Core/Default (= 0.63.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-CoreModules (0.61.4):
- FBReactNativeSpec (= 0.61.4)
- Folly (= 2018.10.22.00)
- RCTTypeSafety (= 0.61.4)
- React-Core/CoreModulesHeaders (= 0.61.4)
- React-RCTImage (= 0.61.4)
- ReactCommon/turbomodule/core (= 0.61.4)
- React-cxxreact (0.61.4):
- React-CoreModules (0.63.2):
- FBReactNativeSpec (= 0.63.2)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.2)
- React-Core/CoreModulesHeaders (= 0.63.2)
- React-jsi (= 0.63.2)
- React-RCTImage (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- React-cxxreact (0.63.2):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-jsinspector (= 0.61.4)
- React-jsi (0.61.4):
- React-callinvoker (= 0.63.2)
- React-jsinspector (= 0.63.2)
- React-jsi (0.63.2):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-jsi/Default (= 0.61.4)
- React-jsi/Default (0.61.4):
- React-jsi/Default (= 0.63.2)
- React-jsi/Default (0.63.2):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-jsiexecutor (0.61.4):
- React-jsiexecutor (0.63.2):
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-cxxreact (= 0.61.4)
- React-jsi (= 0.61.4)
- React-jsinspector (0.61.4)
- react-native-update (5.5.8):
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsinspector (0.63.2)
- react-native-update (5.7.2):
- React
- react-native-update/BSDiff (= 5.5.8)
- react-native-update/RCTPushy (= 5.5.8)
- react-native-update/BSDiff (= 5.7.2)
- react-native-update/RCTPushy (= 5.7.2)
- SSZipArchive
- react-native-update/BSDiff (5.5.8):
- react-native-update/BSDiff (5.7.2):
- React
- SSZipArchive
- react-native-update/RCTPushy (5.5.8):
- react-native-update/RCTPushy (5.7.2):
- React
- SSZipArchive
- React-RCTActionSheet (0.61.4):
- React-Core/RCTActionSheetHeaders (= 0.61.4)
- React-RCTAnimation (0.61.4):
- React-Core/RCTAnimationHeaders (= 0.61.4)
- React-RCTBlob (0.61.4):
- React-Core/RCTBlobHeaders (= 0.61.4)
- React-Core/RCTWebSocket (= 0.61.4)
- React-jsi (= 0.61.4)
- React-RCTNetwork (= 0.61.4)
- React-RCTImage (0.61.4):
- React-Core/RCTImageHeaders (= 0.61.4)
- React-RCTNetwork (= 0.61.4)
- React-RCTLinking (0.61.4):
- React-Core/RCTLinkingHeaders (= 0.61.4)
- React-RCTNetwork (0.61.4):
- React-Core/RCTNetworkHeaders (= 0.61.4)
- React-RCTSettings (0.61.4):
- React-Core/RCTSettingsHeaders (= 0.61.4)
- React-RCTText (0.61.4):
- React-Core/RCTTextHeaders (= 0.61.4)
- React-RCTVibration (0.61.4):
- React-Core/RCTVibrationHeaders (= 0.61.4)
- ReactCommon/jscallinvoker (0.61.4):
- React-RCTActionSheet (0.63.2):
- React-Core/RCTActionSheetHeaders (= 0.63.2)
- React-RCTAnimation (0.63.2):
- FBReactNativeSpec (= 0.63.2)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.2)
- React-Core/RCTAnimationHeaders (= 0.63.2)
- React-jsi (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- React-RCTBlob (0.63.2):
- FBReactNativeSpec (= 0.63.2)
- Folly (= 2020.01.13.00)
- React-Core/RCTBlobHeaders (= 0.63.2)
- React-Core/RCTWebSocket (= 0.63.2)
- React-jsi (= 0.63.2)
- React-RCTNetwork (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- React-RCTImage (0.63.2):
- FBReactNativeSpec (= 0.63.2)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.2)
- React-Core/RCTImageHeaders (= 0.63.2)
- React-jsi (= 0.63.2)
- React-RCTNetwork (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- React-RCTLinking (0.63.2):
- FBReactNativeSpec (= 0.63.2)
- React-Core/RCTLinkingHeaders (= 0.63.2)
- React-jsi (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- React-RCTNetwork (0.63.2):
- FBReactNativeSpec (= 0.63.2)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.2)
- React-Core/RCTNetworkHeaders (= 0.63.2)
- React-jsi (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- React-RCTSettings (0.63.2):
- FBReactNativeSpec (= 0.63.2)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.2)
- React-Core/RCTSettingsHeaders (= 0.63.2)
- React-jsi (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- React-RCTText (0.63.2):
- React-Core/RCTTextHeaders (= 0.63.2)
- React-RCTVibration (0.63.2):
- FBReactNativeSpec (= 0.63.2)
- Folly (= 2020.01.13.00)
- React-Core/RCTVibrationHeaders (= 0.63.2)
- React-jsi (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- ReactCommon/turbomodule/core (0.63.2):
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-cxxreact (= 0.61.4)
- ReactCommon/turbomodule/core (0.61.4):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-Core (= 0.61.4)
- React-cxxreact (= 0.61.4)
- React-jsi (= 0.61.4)
- ReactCommon/jscallinvoker (= 0.61.4)
- SSZipArchive (2.2.2)
- React-callinvoker (= 0.63.2)
- React-Core (= 0.63.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- SSZipArchive (2.2.3)
- Yoga (1.14.0)
- YogaKit (1.18.1):
- Yoga (~> 1.14)
DEPENDENCIES:
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec`)
- Flipper (= 0.54.0)
- Flipper-DoubleConversion (= 1.1.7)
- Flipper-Folly (~> 2.2)
- Flipper-Glog (= 0.3.6)
- Flipper-PeerTalk (~> 0.0.4)
- Flipper-RSocket (~> 1.1)
- FlipperKit (= 0.54.0)
- FlipperKit/Core (= 0.54.0)
- FlipperKit/CppBridge (= 0.54.0)
- FlipperKit/FBCxxFollyDynamicConvert (= 0.54.0)
- FlipperKit/FBDefines (= 0.54.0)
- FlipperKit/FKPortForwarding (= 0.54.0)
- FlipperKit/FlipperKitHighlightOverlay (= 0.54.0)
- FlipperKit/FlipperKitLayoutPlugin (= 0.54.0)
- FlipperKit/FlipperKitLayoutTextSearchable (= 0.54.0)
- FlipperKit/FlipperKitNetworkPlugin (= 0.54.0)
- FlipperKit/FlipperKitReactPlugin (= 0.54.0)
- FlipperKit/FlipperKitUserDefaultsPlugin (= 0.54.0)
- FlipperKit/SKIOSNetworkPlugin (= 0.54.0)
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
- React (from `../node_modules/react-native/`)
- React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`)
- React-Core (from `../node_modules/react-native/`)
- React-Core/DevSupport (from `../node_modules/react-native/`)
- React-Core/RCTWebSocket (from `../node_modules/react-native/`)
@@ -258,14 +359,24 @@ DEPENDENCIES:
- React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`)
- React-RCTText (from `../node_modules/react-native/Libraries/Text`)
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
- ReactCommon/jscallinvoker (from `../node_modules/react-native/ReactCommon`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
SPEC REPOS:
trunk:
- boost-for-react-native
- CocoaAsyncSocket
- CocoaLibEvent
- Flipper
- Flipper-DoubleConversion
- Flipper-Folly
- Flipper-Glog
- Flipper-PeerTalk
- Flipper-RSocket
- FlipperKit
- OpenSSL-Universal
- SSZipArchive
- YogaKit
EXTERNAL SOURCES:
DoubleConversion:
@@ -284,6 +395,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/Libraries/TypeSafety"
React:
:path: "../node_modules/react-native/"
React-callinvoker:
:path: "../node_modules/react-native/ReactCommon/callinvoker"
React-Core:
:path: "../node_modules/react-native/"
React-CoreModules:
@@ -323,34 +436,46 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
FBLazyVector: feb35a6b7f7b50f367be07f34012f34a79282fa3
FBReactNativeSpec: 51477b84b1bf7ab6f9ef307c24e3dd675391be44
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
glog: 1f3da668190260b06b429bb211bfbee5cd790c28
RCTRequired: f3b3fb6f4723e8e52facb229d0c75fdc76773849
RCTTypeSafety: 2ec60de6abb1db050b56ecc4b60188026078fd10
React: 10e0130b57e55a7cd8c3dee37c1261102ce295f4
React-Core: 636212410772d05f3a1eb79d965df2962ca1c70b
React-CoreModules: 6f70d5e41919289c582f88c9ad9923fe5c87400a
React-cxxreact: ddecbe9157ec1743f52ea17bf8d95debc0d6e846
React-jsi: ca921f4041505f9d5197139b2d09eeb020bb12e8
React-jsiexecutor: 8dfb73b987afa9324e4009bdce62a18ce23d983c
React-jsinspector: d15478d0a8ada19864aa4d1cc1c697b41b3fa92f
react-native-update: 491cb5902a18f1ebeeb903f1a619df94662fc52a
React-RCTActionSheet: 7369b7c85f99b6299491333affd9f01f5a130c22
React-RCTAnimation: d07be15b2bd1d06d89417eb0343f98ffd2b099a7
React-RCTBlob: 8e0b23d95c9baa98f6b0e127e07666aaafd96c34
React-RCTImage: 443050d14a66e8c2332e9c055f45689d23e15cc7
React-RCTLinking: ce9a90ba155aec41be49e75ec721bbae2d48a47e
React-RCTNetwork: 41fe54bacc67dd00e6e4c4d30dd98a13e4beabc8
React-RCTSettings: 45e3e0a6470310b2dab2ccc6d1d73121ba3ea936
React-RCTText: 21934e0a51d522abcd0a275407e80af45d6fd9ec
React-RCTVibration: 0f76400ee3cec6edb9c125da49fed279340d145a
ReactCommon: a6a294e7028ed67b926d29551aa9394fd989c24c
SSZipArchive: fa16b8cc4cdeceb698e5e5d9f67e9558532fbf23
Yoga: ba3d99dbee6c15ea6bbe3783d1f0cb1ffb79af0f
CocoaAsyncSocket: 694058e7c0ed05a9e217d1b3c7ded962f4180845
CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f
DoubleConversion: cde416483dac037923206447da6e1454df403714
FBLazyVector: 3ef4a7f62e7db01092f9d517d2ebc0d0677c4a37
FBReactNativeSpec: dc7fa9088f0f2a998503a352b0554d69a4391c5a
Flipper: be611d4b742d8c87fbae2ca5f44603a02539e365
Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41
Flipper-Folly: c12092ea368353b58e992843a990a3225d4533c3
Flipper-Glog: 1dfd6abf1e922806c52ceb8701a3599a79a200a6
Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9
Flipper-RSocket: 64e7431a55835eb953b0bf984ef3b90ae9fdddd7
FlipperKit: ab353d41aea8aae2ea6daaf813e67496642f3d7d
Folly: b73c3869541e86821df3c387eb0af5f65addfab4
glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3
OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355
RCTRequired: f13f25e7b12f925f1f6a6a8c69d929a03c0129fe
RCTTypeSafety: 44982c5c8e43ff4141eb519a8ddc88059acd1f3a
React: e1c65dd41cb9db13b99f24608e47dd595f28ca9a
React-callinvoker: 552a6a6bc8b3bb794cf108ad59e5a9e2e3b4fc98
React-Core: 9d341e725dc9cd2f49e4c49ad1fc4e8776aa2639
React-CoreModules: 5335e168165da7f7083ce7147768d36d3e292318
React-cxxreact: d3261ec5f7d11743fbf21e263a34ea51d1f13ebc
React-jsi: 54245e1d5f4b690dec614a73a3795964eeef13a8
React-jsiexecutor: 8ca588cc921e70590820ce72b8789b02c67cce38
React-jsinspector: b14e62ebe7a66e9231e9581279909f2fc3db6606
react-native-update: 7602220eccf4ccac05bc90035a541300f2c0189a
React-RCTActionSheet: 910163b6b09685a35c4ebbc52b66d1bfbbe39fc5
React-RCTAnimation: 9a883bbe1e9d2e158d4fb53765ed64c8dc2200c6
React-RCTBlob: 39cf0ece1927996c4466510e25d2105f67010e13
React-RCTImage: de355d738727b09ad3692f2a979affbd54b5f378
React-RCTLinking: 8122f221d395a63364b2c0078ce284214bd04575
React-RCTNetwork: 8f96c7b49ea6a0f28f98258f347b6ad218bc0830
React-RCTSettings: 8a49622aff9c1925f5455fa340b6fe4853d64ab6
React-RCTText: 1b6773e776e4b33f90468c20fe3b16ca3e224bb8
React-RCTVibration: 4d2e726957f4087449739b595f107c0d4b6c2d2d
ReactCommon: a0a1edbebcac5e91338371b72ffc66aa822792ce
SSZipArchive: 62d4947b08730e4cda640473b0066d209ff033c9
Yoga: 7740b94929bbacbddda59bf115b5317e9a161598
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
PODFILE CHECKSUM: 244ba888c650d3945bf72a8d01516fb0f1b3b097
PODFILE CHECKSUM: 449e295f5242b426c8459fd24a8812cc985916d0
COCOAPODS: 1.9.1
COCOAPODS: 1.9.3

View File

@@ -0,0 +1,9 @@
//
// dummy.swift
// testHotUpdate
//
// Created by Qingming, Sunny Luo on 9/1/20.
// Copyright © 2020 Facebook. All rights reserved.
//
import Foundation

View File

@@ -0,0 +1,4 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//

View File

@@ -12,6 +12,7 @@
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
7610A16EF1CB8A7644EAFA55 /* libPods-testHotUpdate.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 28C264AEBE1E206870F9D871 /* libPods-testHotUpdate.a */; };
F1CBCFD724FE1CF80019170D /* dummy.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1CBCFD624FE1CF80019170D /* dummy.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -37,6 +38,8 @@
ED1DB2CEADC1A82A43867C0E /* Pods-testHotUpdateTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-testHotUpdateTests.release.xcconfig"; path = "Target Support Files/Pods-testHotUpdateTests/Pods-testHotUpdateTests.release.xcconfig"; sourceTree = "<group>"; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; };
F1CBCFD524FE1CF80019170D /* testHotUpdate-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "testHotUpdate-Bridging-Header.h"; sourceTree = "<group>"; };
F1CBCFD624FE1CF80019170D /* dummy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dummy.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -76,6 +79,8 @@
13B07FB61A68108700A75B9A /* Info.plist */,
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
13B07FB71A68108700A75B9A /* main.m */,
F1CBCFD624FE1CF80019170D /* dummy.swift */,
F1CBCFD524FE1CF80019170D /* testHotUpdate-Bridging-Header.h */,
);
name = testHotUpdate;
sourceTree = "<group>";
@@ -154,6 +159,12 @@
attributes = {
LastUpgradeCheck = 0940;
ORGANIZATIONNAME = Facebook;
TargetAttributes = {
13B07F861A680F5B00A75B9A = {
DevelopmentTeam = JD75Q9JJL2;
LastSwiftMigration = 1160;
};
};
};
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "testHotUpdate" */;
compatibilityVersion = "Xcode 3.2";
@@ -199,7 +210,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh";
shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n";
};
1CD78CE8A2E7B88FAE48FCEE /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
@@ -208,10 +219,12 @@
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-testHotUpdate/Pods-testHotUpdate-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
"${PODS_ROOT}/../../../../ios/pushy_build_time.txt",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/pushy_build_time.txt",
);
runOnlyForDeploymentPostprocessing = 0;
@@ -268,6 +281,7 @@
buildActionMask = 2147483647;
files = (
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
F1CBCFD724FE1CF80019170D /* dummy.swift in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -292,8 +306,10 @@
baseConfigurationReference = 84EBA9C1A760F4136B306391 /* Pods-testHotUpdate.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = NO;
DEVELOPMENT_TEAM = JD75Q9JJL2;
INFOPLIST_FILE = testHotUpdate/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = (
@@ -303,6 +319,9 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = testHotUpdate;
SWIFT_OBJC_BRIDGING_HEADER = "testHotUpdate-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
@@ -312,7 +331,9 @@
baseConfigurationReference = 1A3E77317B15A5C3816ACE3A /* Pods-testHotUpdate.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = JD75Q9JJL2;
INFOPLIST_FILE = testHotUpdate/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = (
@@ -322,6 +343,8 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = testHotUpdate;
SWIFT_OBJC_BRIDGING_HEADER = "testHotUpdate-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;

View File

@@ -55,6 +55,15 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "testHotUpdate.app"
BlueprintName = "testHotUpdate"
ReferencedContainer = "container:testHotUpdate.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
@@ -67,17 +76,6 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "testHotUpdate.app"
BlueprintName = "testHotUpdate"
ReferencedContainer = "container:testHotUpdate.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -99,8 +97,6 @@
ReferencedContainer = "container:testHotUpdate.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"

View File

@@ -12,10 +12,32 @@
#import <React/RCTRootView.h>
#import "RCTPushy.h"
#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>
static void InitializeFlipper(UIApplication *application) {
FlipperClient *client = [FlipperClient sharedClient];
SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
[client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
[client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
[client addPlugin:[FlipperKitReactPlugin new]];
[client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
[client start];
}
#endif
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#ifdef FB_SONARKIT_ENABLED
InitializeFlipper(application);
#endif
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"testHotUpdate"

View File

@@ -10,19 +10,19 @@
"lint": "eslint ."
},
"dependencies": {
"react": "16.9.0",
"react-native": "0.61.4",
"react": "16.13.1",
"react-native": "0.63.2",
"react-native-update": "link:../.."
},
"devDependencies": {
"@babel/core": "^7.6.2",
"@babel/runtime": "^7.6.2",
"@react-native-community/eslint-config": "^0.0.5",
"babel-jest": "^24.9.0",
"@babel/core": "^7.8.4",
"@babel/runtime": "^7.8.4",
"@react-native-community/eslint-config": "^1.1.0",
"babel-jest": "^25.1.0",
"eslint": "^6.5.1",
"jest": "^24.9.0",
"metro-react-native-babel-preset": "^0.56.0",
"react-test-renderer": "16.9.0"
"jest": "^25.1.0",
"metro-react-native-babel-preset": "^0.59.0",
"react-test-renderer": "16.13.1"
},
"jest": {
"preset": "react-native"

View File

@@ -8,6 +8,7 @@ import {
TouchableOpacity,
Linking,
Image,
NativeModules,
} from 'react-native';
import {
@@ -20,12 +21,17 @@ import {
switchVersion,
switchVersionLater,
markSuccess,
downloadAndInstallApk,
} from 'react-native-update';
import _updateConfig from '../update.json';
const {appKey} = _updateConfig[Platform.OS];
export default class App extends Component {
state = {
received: 0,
total: 0,
};
componentDidMount() {
if (isRolledBack) {
Alert.alert('提示', '刚刚更新失败了,版本被回滚.');
@@ -50,23 +56,34 @@ export default class App extends Component {
);
}
}
doUpdate = async info => {
const hash = await downloadUpdate(info);
Alert.alert('提示', '下载完毕,是否重启应用?', [
{
text: '是',
onPress: () => {
switchVersion(hash);
doUpdate = async (info) => {
try {
const hash = await downloadUpdate(info, {
onDownloadProgress: ({received, total}) => {
this.setState({
received,
total,
});
},
},
{text: '否'},
{
text: '下次启动时',
onPress: () => {
switchVersionLater(hash);
});
Alert.alert('提示', '下载完毕,是否重启应用?', [
{
text: '',
onPress: () => {
switchVersion(hash);
},
},
},
]);
{text: '否'},
{
text: '下次启动时',
onPress: () => {
switchVersionLater(hash);
},
},
]);
} catch (err) {
Alert.alert('更新失败', err.message);
}
};
checkUpdate = async () => {
@@ -74,15 +91,33 @@ export default class App extends Component {
try {
info = await checkUpdate(appKey);
} catch (err) {
console.warn(err);
Alert.alert('更新检查失败', err.message);
return;
}
if (info.expired) {
Alert.alert('提示', '您的应用版本已更新,请前往应用商店下载新的版本', [
Alert.alert('提示', '您的应用版本已更新,点击确定下载安装新版本', [
{
text: '确定',
onPress: () => {
info.downloadUrl && Linking.openURL(info.downloadUrl);
if (info.downloadUrl) {
// apk可直接下载安装
if (
Platform.OS === 'android' &&
info.downloadUrl.endsWith('.apk')
) {
downloadAndInstallApk({
url: info.downloadUrl,
onDownloadProgress: ({received, total}) => {
this.setState({
received,
total,
});
},
});
} else {
Linking.openURL(info.downloadUrl);
}
}
},
},
]);
@@ -106,21 +141,25 @@ export default class App extends Component {
};
render() {
const { received, total } = this.state;
return (
<View style={styles.container}>
<Text style={styles.welcome}>欢迎使用热更新服务</Text>
<Image
resizeMode={'contain'}
source={require('./assets/shoucang.png')}
source={require('./assets/shezhi.png')}
style={styles.image}
/>
<Text style={styles.instructions}>
这是版本一 {'\n'}
当前包版本号: {packageVersion}
当前原生包版本号: {packageVersion}
{'\n'}
当前版本Hash: {currentVersion || '(空)'}
当前热更新版本Hash: {currentVersion || '(空)'}
{'\n'}
</Text>
<Text>
下载进度{received} / {total}
</Text>
<TouchableOpacity onPress={this.checkUpdate}>
<Text style={styles.instructions}>点击这里检查更新</Text>
</TouchableOpacity>

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.reactnative.modules.update">
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<application>
<meta-data android:name="pushy_build_time" android:value="@string/pushy_build_time" />
<provider
android:name=".PushyFileProvider"
android:authorities="${applicationId}.pushy.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>

View File

@@ -41,6 +41,7 @@ class DownloadTask extends AsyncTask<DownloadTaskParams, long[], Void> {
final int DOWNLOAD_CHUNK_SIZE = 4096;
Context context;
String hash;
DownloadTask(Context context) {
this.context = context;
@@ -69,7 +70,10 @@ class DownloadTask extends AsyncTask<DownloadTaskParams, long[], Void> {
}
}
private void downloadFile(String url, File writePath) throws IOException {
private void downloadFile(DownloadTaskParams param) throws IOException {
String url = param.url;
File writePath = param.targetFile;
this.hash = param.hash;
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url)
.build();
@@ -92,23 +96,25 @@ class DownloadTask extends AsyncTask<DownloadTaskParams, long[], Void> {
}
long bytesRead = 0;
long totalRead = 0;
double lastProgressValue=0;
long received = 0;
int currentPercentage = 0;
while ((bytesRead = source.read(sink.buffer(), DOWNLOAD_CHUNK_SIZE)) != -1) {
totalRead += bytesRead;
received += bytesRead;
sink.emit();
if (UpdateContext.DEBUG) {
Log.d("RNUpdate", "Progress " + totalRead + "/" + contentLength);
Log.d("RNUpdate", "Progress " + received + "/" + contentLength);
}
double progress = Math.round(((double) totalRead * 100) / contentLength);
if ((progress != lastProgressValue) || (totalRead == contentLength)) {
lastProgressValue = progress;
publishProgress(new long[]{(long)progress,totalRead, contentLength});
int percentage = (int)(received * 100.0 / contentLength + 0.5);
if (percentage > currentPercentage) {
currentPercentage = percentage;
publishProgress(new long[]{received, contentLength});
}
}
if (totalRead != contentLength) {
throw new Error("Unexpected eof while reading ppk");
if (received != contentLength) {
throw new Error("Unexpected eof while reading downloaded update");
}
publishProgress(new long[]{received, contentLength});
sink.writeAll(source);
sink.close();
@@ -121,10 +127,10 @@ class DownloadTask extends AsyncTask<DownloadTaskParams, long[], Void> {
protected void onProgressUpdate(long[]... values) {
super.onProgressUpdate(values);
WritableMap params = Arguments.createMap();
params.putDouble("progress", (values[0][0]));
params.putDouble("totalRead", (values[0][1]));
params.putDouble("contentLength", (values[0][2]));
sendEvent("progress", params);
params.putDouble("received", (values[0][0]));
params.putDouble("total", (values[0][1]));
params.putString("hash", this.hash);
sendEvent("RCTPushyDownloadProgress", params);
}
@@ -237,10 +243,10 @@ class DownloadTask extends AsyncTask<DownloadTaskParams, long[], Void> {
copyFilesWithBlacklist("", from, to, blackList);
}
private void doDownload(DownloadTaskParams param) throws IOException {
downloadFile(param.url, param.zipFilePath);
private void doFullPatch(DownloadTaskParams param) throws IOException {
downloadFile(param);
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(param.zipFilePath)));
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(param.targetFile)));
ZipEntry ze;
String filename;
@@ -295,9 +301,9 @@ class DownloadTask extends AsyncTask<DownloadTaskParams, long[], Void> {
}
private void doPatchFromApk(DownloadTaskParams param) throws IOException, JSONException {
downloadFile(param.url, param.zipFilePath);
downloadFile(param);
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(param.zipFilePath)));
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(param.targetFile)));
ZipEntry ze;
int count;
String filename;
@@ -371,9 +377,9 @@ class DownloadTask extends AsyncTask<DownloadTaskParams, long[], Void> {
}
private void doPatchFromPpk(DownloadTaskParams param) throws IOException, JSONException {
downloadFile(param.url, param.zipFilePath);
downloadFile(param);
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(param.zipFilePath)));
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(param.targetFile)));
ZipEntry ze;
int count;
String filename;
@@ -458,8 +464,8 @@ class DownloadTask extends AsyncTask<DownloadTaskParams, long[], Void> {
protected Void doInBackground(DownloadTaskParams... params) {
try {
switch (params[0].type) {
case DownloadTaskParams.TASK_TYPE_FULL_DOWNLOAD:
doDownload(params[0]);
case DownloadTaskParams.TASK_TYPE_PATCH_FULL:
doFullPatch(params[0]);
break;
case DownloadTaskParams.TASK_TYPE_PATCH_FROM_APK:
doPatchFromApk(params[0]);
@@ -467,11 +473,18 @@ class DownloadTask extends AsyncTask<DownloadTaskParams, long[], Void> {
case DownloadTaskParams.TASK_TYPE_PATCH_FROM_PPK:
doPatchFromPpk(params[0]);
break;
case DownloadTaskParams.TASK_TYPE_CLEARUP:
case DownloadTaskParams.TASK_TYPE_CLEANUP:
doCleanUp(params[0]);
break;
case DownloadTaskParams.TASK_TYPE_PLAIN_DOWNLOAD:
downloadFile(params[0]);
break;
default:
break;
}
if (params[0].listener != null) {
params[0].listener.onDownloadCompleted(params[0]);
}
params[0].listener.onDownloadCompleted();
} catch (Throwable e) {
if (UpdateContext.DEBUG) {
e.printStackTrace();

View File

@@ -8,17 +8,18 @@ import java.io.File;
* Created by tdzl2003 on 3/31/16.
*/
class DownloadTaskParams {
static final int TASK_TYPE_FULL_DOWNLOAD = 1;
static final int TASK_TYPE_PATCH_FULL = 1;
static final int TASK_TYPE_PATCH_FROM_APK = 2;
static final int TASK_TYPE_PATCH_FROM_PPK = 3;
static final int TASK_TYPE_PLAIN_DOWNLOAD = 4;
static final int TASK_TYPE_CLEARUP = 0; //Keep hash & originHash
static final int TASK_TYPE_CLEANUP = 0; //Keep hash & originHash
int type;
String url;
String hash;
String originHash;
File zipFilePath;
File targetFile;
File unzipDirectory;
File originDirectory;
UpdateContext.DownloadFileListener listener;

View File

@@ -0,0 +1,14 @@
package cn.reactnative.modules.update;
import android.support.v4.content.FileProvider;
/**
* Providing a custom {@code FileProvider} prevents manifest {@code <provider>} name collisions.
*
* See https://developer.android.com/guide/topics/manifest/provider-element.html for details.
*/
public class PushyFileProvider extends FileProvider {
// This class intentionally left blank.
}

View File

@@ -7,6 +7,8 @@ import android.content.pm.PackageManager;
import android.util.Log;
import com.facebook.react.ReactInstanceManager;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -23,6 +25,7 @@ public class UpdateContext {
public static boolean DEBUG = false;
private static ReactInstanceManager mReactInstanceManager;
private static boolean isUsingBundleUrl = false;
public UpdateContext(Context context) {
this.context = context;
@@ -43,7 +46,7 @@ public class UpdateContext {
editor.putString("packageVersion", packageVersion);
editor.apply();
this.clearUp();
this.cleanUp();
}
}
@@ -67,55 +70,81 @@ public class UpdateContext {
return context.getString(R.string.pushy_build_time);
}
public String getUuid() {
return sp.getString("uuid", null);
}
public Map getBlockUpdate() {
return new HashMap<String, Object>() {{
put("until", sp.getInt("blockUntil", 0));
put("reason", sp.getString("blockReason", null));
}};
}
public boolean getIsUsingBundleUrl() {
return isUsingBundleUrl;
}
public interface DownloadFileListener {
void onDownloadCompleted();
void onDownloadCompleted(DownloadTaskParams params);
void onDownloadFailed(Throwable error);
}
public void downloadFile(String url, String hashName, DownloadFileListener listener) {
public void downloadFullUpdate(String url, String hash, DownloadFileListener listener) {
DownloadTaskParams params = new DownloadTaskParams();
params.type = DownloadTaskParams.TASK_TYPE_FULL_DOWNLOAD;
params.type = DownloadTaskParams.TASK_TYPE_PATCH_FULL;
params.url = url;
params.hash = hashName;
params.hash = hash;
params.listener = listener;
params.zipFilePath = new File(rootDir, hashName + ".ppk");
params.unzipDirectory = new File(rootDir, hashName);
params.targetFile = new File(rootDir, hash + ".ppk");
params.unzipDirectory = new File(rootDir, hash);
new DownloadTask(context).executeOnExecutor(this.executor, params);
}
public void downloadPatchFromApk(String url, String hashName, DownloadFileListener listener) {
public void downloadFile(String url, String hash, String fileName, DownloadFileListener listener) {
DownloadTaskParams params = new DownloadTaskParams();
params.type = DownloadTaskParams.TASK_TYPE_PLAIN_DOWNLOAD;
params.url = url;
params.hash = hash;
params.listener = listener;
params.targetFile = new File(rootDir, fileName);
// params.unzipDirectory = new File(rootDir, hash);
new DownloadTask(context).executeOnExecutor(this.executor, params);
}
public void downloadPatchFromApk(String url, String hash, DownloadFileListener listener) {
DownloadTaskParams params = new DownloadTaskParams();
params.type = DownloadTaskParams.TASK_TYPE_PATCH_FROM_APK;
params.url = url;
params.hash = hashName;
params.hash = hash;
params.listener = listener;
params.zipFilePath = new File(rootDir, hashName + ".apk.patch");
params.unzipDirectory = new File(rootDir, hashName);
params.targetFile = new File(rootDir, hash + ".apk.patch");
params.unzipDirectory = new File(rootDir, hash);
new DownloadTask(context).executeOnExecutor(this.executor, params);
}
public void downloadPatchFromPpk(String url, String hashName, String originHashName, DownloadFileListener listener) {
public void downloadPatchFromPpk(String url, String hash, String originHash, DownloadFileListener listener) {
DownloadTaskParams params = new DownloadTaskParams();
params.type = DownloadTaskParams.TASK_TYPE_PATCH_FROM_PPK;
params.url = url;
params.hash = hashName;
params.originHash = originHashName;
params.hash = hash;
params.originHash = originHash;
params.listener = listener;
params.zipFilePath = new File(rootDir, originHashName + "-" + hashName + ".ppk.patch");
params.unzipDirectory = new File(rootDir, hashName);
params.originDirectory = new File(rootDir, originHashName);
params.targetFile = new File(rootDir, originHash + "-" + hash + ".ppk.patch");
params.unzipDirectory = new File(rootDir, hash);
params.originDirectory = new File(rootDir, originHash);
new DownloadTask(context).executeOnExecutor(this.executor, params);
}
private SharedPreferences sp;
public void switchVersion(String hashName) {
if (!new File(rootDir, hashName+"/index.bundlejs").exists()) {
throw new Error("Bundle version " + hashName + " not found.");
public void switchVersion(String hash) {
if (!new File(rootDir, hash+"/index.bundlejs").exists()) {
throw new Error("Bundle version " + hash + " not found.");
}
String lastVersion = getCurrentVersion();
SharedPreferences.Editor editor = sp.edit();
editor.putString("currentVersion", hashName);
editor.putString("currentVersion", hash);
if (lastVersion != null) {
editor.putString("lastVersion", lastVersion);
}
@@ -125,6 +154,19 @@ public class UpdateContext {
editor.apply();
}
public void setUuid(String uuid) {
SharedPreferences.Editor editor = sp.edit();
editor.putString("uuid", uuid);
editor.apply();
}
public void setBlockUpdate(int until, String reason) {
SharedPreferences.Editor editor = sp.edit();
editor.putInt("blockUntil", until);
editor.putString("blockReason", reason);
editor.apply();
}
public String getCurrentVersion() {
return sp.getString("currentVersion", null);
}
@@ -143,7 +185,7 @@ public class UpdateContext {
editor.remove("lastVersion");
editor.apply();
this.clearUp();
this.cleanUp();
}
public void clearFirstTime() {
@@ -151,7 +193,7 @@ public class UpdateContext {
editor.putBoolean("firstTime", false);
editor.apply();
this.clearUp();
this.cleanUp();
}
public void clearRollbackMark() {
@@ -159,7 +201,7 @@ public class UpdateContext {
editor.putBoolean("rolledBack", false);
editor.apply();
this.clearUp();
this.cleanUp();
}
@@ -184,6 +226,7 @@ public class UpdateContext {
}
public String getBundleUrl(String defaultAssetsUrl) {
isUsingBundleUrl = true;
String currentVersion = getCurrentVersion();
if (currentVersion == null) {
return defaultAssetsUrl;
@@ -224,21 +267,12 @@ public class UpdateContext {
return lastVersion;
}
private void clearUp() {
private void cleanUp() {
DownloadTaskParams params = new DownloadTaskParams();
params.type = DownloadTaskParams.TASK_TYPE_CLEARUP;
params.type = DownloadTaskParams.TASK_TYPE_CLEANUP;
params.hash = sp.getString("currentVersion", null);
params.originHash = sp.getString("lastVersion", null);
params.unzipDirectory = rootDir;
params.listener = new DownloadFileListener() {
@Override
public void onDownloadCompleted() {
}
@Override
public void onDownloadFailed(Throwable error) {
}
};
new DownloadTask(context).executeOnExecutor(this.executor, params);
}
}

View File

@@ -3,6 +3,8 @@ package cn.reactnative.modules.update;
import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import com.facebook.react.ReactApplication;
@@ -18,11 +20,14 @@ import com.facebook.react.bridge.JSBundleLoader;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import static android.support.v4.content.FileProvider.getUriForFile;
/**
* Created by tdzl2003 on 3/31/16.
*/
@@ -46,6 +51,7 @@ public class UpdateModule extends ReactContextBaseJavaModule{
constants.put("packageVersion", updateContext.getPackageVersion());
constants.put("currentVersion", updateContext.getCurrentVersion());
constants.put("buildTime", updateContext.getBuildTime());
constants.put("isUsingBundleUrl", updateContext.getIsUsingBundleUrl());
boolean isFirstTime = updateContext.isFirstTime();
constants.put("isFirstTime", isFirstTime);
if (isFirstTime) {
@@ -56,6 +62,8 @@ public class UpdateModule extends ReactContextBaseJavaModule{
if (isRolledBack) {
updateContext.clearRollbackMark();
}
constants.put("blockUpdate", updateContext.getBlockUpdate());
constants.put("uuid", updateContext.getUuid());
return constants;
}
@@ -67,10 +75,10 @@ public class UpdateModule extends ReactContextBaseJavaModule{
@ReactMethod
public void downloadUpdate(ReadableMap options, final Promise promise){
String url = options.getString("updateUrl");
String hash = options.getString("hashName");
updateContext.downloadFile(url, hash, new UpdateContext.DownloadFileListener() {
String hash = options.getString("hash");
updateContext.downloadFullUpdate(url, hash, new UpdateContext.DownloadFileListener() {
@Override
public void onDownloadCompleted() {
public void onDownloadCompleted(DownloadTaskParams params) {
promise.resolve(null);
}
@@ -81,13 +89,58 @@ public class UpdateModule extends ReactContextBaseJavaModule{
});
}
@ReactMethod
public void downloadAndInstallApk(ReadableMap options, final Promise promise){
String url = options.getString("url");
String hash = options.getString("hash");
String target = options.getString("target");
updateContext.downloadFile(url, hash, target, new UpdateContext.DownloadFileListener() {
@Override
public void onDownloadCompleted(DownloadTaskParams params) {
installApk(params.targetFile);
promise.resolve(null);
}
@Override
public void onDownloadFailed(Throwable error) {
promise.reject(error);
}
});
}
// install downloaded apk
@ReactMethod
public static void installApk(String url) {
File toInstall = new File(url);
installApk(toInstall);
}
public static void installApk(File toInstall) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri apkUri = getUriForFile(mContext, mContext.getPackageName() + ".pushy.fileprovider", toInstall);
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setData(apkUri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
} else {
Uri apkUri = Uri.fromFile(toInstall);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
}
@ReactMethod
public void downloadPatchFromPackage(ReadableMap options, final Promise promise){
String url = options.getString("updateUrl");
String hash = options.getString("hashName");
String hash = options.getString("hash");
updateContext.downloadPatchFromApk(url, hash, new UpdateContext.DownloadFileListener() {
@Override
public void onDownloadCompleted() {
public void onDownloadCompleted(DownloadTaskParams params) {
promise.resolve(null);
}
@@ -101,11 +154,11 @@ public class UpdateModule extends ReactContextBaseJavaModule{
@ReactMethod
public void downloadPatchFromPpk(ReadableMap options, final Promise promise){
String url = options.getString("updateUrl");
String hash = options.getString("hashName");
String originHash = options.getString("originHashName");
String hash = options.getString("hash");
String originHash = options.getString("originHash");
updateContext.downloadPatchFromPpk(url, hash, originHash, new UpdateContext.DownloadFileListener() {
@Override
public void onDownloadCompleted() {
public void onDownloadCompleted(DownloadTaskParams params) {
promise.resolve(null);
}
@@ -118,7 +171,7 @@ public class UpdateModule extends ReactContextBaseJavaModule{
@ReactMethod
public void reloadUpdate(ReadableMap options) {
final String hash = options.getString("hashName");
final String hash = options.getString("hash");
UiThreadUtil.runOnUiThread(new Runnable() {
@Override
@@ -134,14 +187,14 @@ public class UpdateModule extends ReactContextBaseJavaModule{
}
try {
Field jsBundleField = instanceManager.getClass().getDeclaredField("mJSBundleFile");
jsBundleField.setAccessible(true);
jsBundleField.set(instanceManager, UpdateContext.getBundleUrl(application));
} catch (Throwable err) {
JSBundleLoader loader = JSBundleLoader.createFileLoader(UpdateContext.getBundleUrl(application));
Field loadField = instanceManager.getClass().getDeclaredField("mBundleLoader");
loadField.setAccessible(true);
loadField.set(instanceManager, loader);
} catch (Throwable err) {
Field jsBundleField = instanceManager.getClass().getDeclaredField("mJSBundleFile");
jsBundleField.setAccessible(true);
jsBundleField.set(instanceManager, UpdateContext.getBundleUrl(application));
}
try {
@@ -159,7 +212,7 @@ public class UpdateModule extends ReactContextBaseJavaModule{
@ReactMethod
public void setNeedUpdate(ReadableMap options) {
final String hash = options.getString("hashName");
final String hash = options.getString("hash");
UiThreadUtil.runOnUiThread(new Runnable() {
@Override
@@ -183,6 +236,28 @@ public class UpdateModule extends ReactContextBaseJavaModule{
});
}
@ReactMethod
public void setBlockUpdate(ReadableMap options) {
final int until = options.getInt("until");
final String reason = options.getString("reason");
UiThreadUtil.runOnUiThread(new Runnable() {
@Override
public void run() {
updateContext.setBlockUpdate(until, reason);
}
});
}
@ReactMethod
public void setUuid(final String uuid) {
UiThreadUtil.runOnUiThread(new Runnable() {
@Override
public void run() {
updateContext.setUuid(uuid);
}
});
}
/* 发送事件*/
public static void sendEvent(String eventName, WritableMap params) {
((ReactContext) mContext).getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName,

View File

@@ -0,0 +1,3 @@
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="." path="."/>
</paths>

1
endpoints.json Normal file
View File

@@ -0,0 +1 @@
["https://update.react-native.cn/api", "https://update.reactnative.cn/api"]

View File

@@ -6,13 +6,11 @@
// Copyright © 2016 erica. All rights reserved.
//
#if __has_include(<React/RCTBridge.h>)
#import <React/RCTBridgeModule.h>
#else
#import "RCTBridgeModule.h"
#endif
#import <React/RCTEventEmitter.h>
@interface RCTPushy : NSObject<RCTBridgeModule>
@interface RCTPushy : RCTEventEmitter<RCTBridgeModule>
+ (NSURL *)bundleURL;

View File

@@ -10,23 +10,19 @@
#import "RCTPushyDownloader.h"
#import "RCTPushyManager.h"
#if __has_include(<React/RCTBridge.h>)
#import "React/RCTEventDispatcher.h"
#import <React/RCTConvert.h>
#import <React/RCTLog.h>
#else
#import "RCTEventDispatcher.h"
#import "RCTConvert.h"
#import "RCTLog.h"
#endif
// #import <React/RCTReloadCommand.h>
//
static NSString *const keyPushyInfo = @"REACTNATIVECN_PUSHY_INFO_KEY";
static NSString *const paramPackageVersion = @"packageVersion";
static NSString *const paramLastVersion = @"lastVersion";
static NSString *const paramCurrentVersion = @"currentVersion";
static NSString *const paramIsFirstTime = @"isFirstTime";
static NSString *const paramIsFirstLoadOk = @"isFirstLoadOK";
static NSString *const keyBlockUpdate = @"REACTNATIVECN_PUSHY_BLOCKUPDATE";
static NSString *const keyUuid = @"REACTNATIVECN_PUSHY_UUID";
static NSString *const keyFirstLoadMarked = @"REACTNATIVECN_PUSHY_FIRSTLOADMARKED_KEY";
static NSString *const keyRolledBackMarked = @"REACTNATIVECN_PUSHY_ROLLEDBACKMARKED_KEY";
static NSString *const KeyPackageUpdatedMarked = @"REACTNATIVECN_PUSHY_ISPACKAGEUPDATEDMARKED_KEY";
@@ -47,8 +43,8 @@ static NSString * const ERROR_FILE_OPERATION = @"file operation error";
// event def
static NSString * const EVENT_PROGRESS_DOWNLOAD = @"RCTPushyDownloadProgress";
static NSString * const EVENT_PROGRESS_UNZIP = @"RCTPushyUnzipProgress";
static NSString * const PARAM_PROGRESS_HASHNAME = @"hashname";
// static NSString * const EVENT_PROGRESS_UNZIP = @"RCTPushyUnzipProgress";
static NSString * const PARAM_PROGRESS_HASH = @"hash";
static NSString * const PARAM_PROGRESS_RECEIVED = @"received";
static NSString * const PARAM_PROGRESS_TOTAL = @"total";
@@ -63,9 +59,9 @@ static BOOL ignoreRollback = false;
@implementation RCTPushy {
RCTPushyManager *_fileManager;
bool hasListeners;
}
@synthesize bridge = _bridge;
@synthesize methodQueue = _methodQueue;
RCT_EXPORT_MODULE(RCTPushy);
@@ -93,10 +89,10 @@ RCT_EXPORT_MODULE(RCTPushy);
BOOL isFirstTime = [pushyInfo[paramIsFirstTime] boolValue];
BOOL isFirstLoadOK = [pushyInfo[paramIsFirstLoadOk] boolValue];
NSString *loadVersioin = curVersion;
BOOL needRollback = (!ignoreRollback && isFirstTime == NO && isFirstLoadOK == NO) || loadVersioin.length<=0;
NSString *loadVersion = curVersion;
BOOL needRollback = (!ignoreRollback && isFirstTime == NO && isFirstLoadOK == NO) || loadVersion.length<=0;
if (needRollback) {
loadVersioin = lastVersion;
loadVersion = lastVersion;
if (lastVersion.length) {
// roll back to last version
@@ -125,10 +121,10 @@ RCT_EXPORT_MODULE(RCTPushy);
[defaults synchronize];
}
if (loadVersioin.length) {
if (loadVersion.length) {
NSString *downloadDir = [RCTPushy downloadDir];
NSString *bundlePath = [[downloadDir stringByAppendingPathComponent:loadVersioin] stringByAppendingPathComponent:BUNDLE_FILE_NAME];
NSString *bundlePath = [[downloadDir stringByAppendingPathComponent:loadVersion] stringByAppendingPathComponent:BUNDLE_FILE_NAME];
if ([[NSFileManager defaultManager] fileExistsAtPath:bundlePath isDirectory:NULL]) {
NSURL *bundleURL = [NSURL fileURLWithPath:bundlePath];
return bundleURL;
@@ -155,6 +151,8 @@ RCT_EXPORT_MODULE(RCTPushy);
ret[@"buildTime"] = [RCTPushy buildTime];
ret[@"isRolledBack"] = [defaults objectForKey:keyRolledBackMarked];
ret[@"isFirstTime"] = [defaults objectForKey:keyFirstLoadMarked];
ret[@"blockUpdate"] = [defaults objectForKey:keyBlockUpdate];
ret[@"uuid"] = [defaults objectForKey:keyUuid];
NSDictionary *pushyInfo = [defaults dictionaryForKey:keyPushyInfo];
ret[@"currentVersion"] = [pushyInfo objectForKey:paramCurrentVersion];
@@ -188,6 +186,23 @@ RCT_EXPORT_MODULE(RCTPushy);
return self;
}
RCT_EXPORT_METHOD(setBlockUpdate:(NSDictionary *)options)
{
// NSMutableDictionary *blockUpdateInfo = [NSMutableDictionary new];
// blockUpdateInfo[@"reason"] = options[@"reason"];
// blockUpdateInfo[@"until"] = options[@"until"];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:options forKey:keyBlockUpdate];
[defaults synchronize];
}
RCT_EXPORT_METHOD(setUuid:(NSString *)uuid)
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:uuid forKey:keyUuid];
[defaults synchronize];
}
RCT_EXPORT_METHOD(downloadUpdate:(NSDictionary *)options
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
@@ -232,8 +247,8 @@ RCT_EXPORT_METHOD(downloadPatchFromPpk:(NSDictionary *)options
RCT_EXPORT_METHOD(setNeedUpdate:(NSDictionary *)options)
{
NSString *hashName = options[@"hashName"];
if (hashName.length) {
NSString *hash = options[@"hash"];
if (hash.length) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *lastVersion = nil;
if ([defaults objectForKey:keyPushyInfo]) {
@@ -242,7 +257,7 @@ RCT_EXPORT_METHOD(setNeedUpdate:(NSDictionary *)options)
}
NSMutableDictionary *newInfo = [[NSMutableDictionary alloc] init];
newInfo[paramCurrentVersion] = hashName;
newInfo[paramCurrentVersion] = hash;
newInfo[paramLastVersion] = lastVersion;
newInfo[paramIsFirstTime] = @(YES);
newInfo[paramIsFirstLoadOk] = @(NO);
@@ -255,15 +270,18 @@ RCT_EXPORT_METHOD(setNeedUpdate:(NSDictionary *)options)
RCT_EXPORT_METHOD(reloadUpdate:(NSDictionary *)options)
{
NSString *hashName = options[@"hashName"];
if (hashName.length) {
NSString *hash = options[@"hash"];
if (hash.length) {
[self setNeedUpdate:options];
// reload
dispatch_async(dispatch_get_main_queue(), ^{
[_bridge setValue:[[self class] bundleURL] forKey:@"bundleURL"];
[_bridge reload];
});
// reload 0.62+
// RCTReloadCommandSetBundleURL([[self class] bundleURL]);
// RCTTriggerReloadCommandListeners(@"pushy reload");
dispatch_async(dispatch_get_main_queue(), ^{
[self.bridge setValue:[[self class] bundleURL] forKey:@"bundleURL"];
[self.bridge reload];
});
}
}
@@ -281,17 +299,40 @@ RCT_EXPORT_METHOD(markSuccess)
[self clearInvalidFiles];
}
#pragma mark - private
- (NSArray<NSString *> *)supportedEvents
{
return @[
EVENT_PROGRESS_DOWNLOAD,
// EVENT_PROGRESS_UNZIP
];
}
// Will be called when this module's first listener is added.
-(void)startObserving {
hasListeners = YES;
// Set up any upstream listeners or background tasks as necessary
}
// Will be called when this module's last listener is removed, or on dealloc.
-(void)stopObserving {
hasListeners = NO;
// Remove upstream listeners, stop unnecessary background tasks
}
- (void)doPushy:(PushyType)type options:(NSDictionary *)options callback:(void (^)(NSError *error))callback
{
NSString *updateUrl = [RCTConvert NSString:options[@"updateUrl"]];
NSString *hashName = [RCTConvert NSString:options[@"hashName"]];
if (updateUrl.length<=0 || hashName.length<=0) {
NSString *hash = [RCTConvert NSString:options[@"hash"]];
if (updateUrl.length <= 0 || hash.length <= 0) {
callback([self errorWithMessage:ERROR_OPTIONS]);
return;
}
NSString *originHashName = [RCTConvert NSString:options[@"originHashName"]];
if (type == PushyTypePatchFromPpk && originHashName<=0) {
NSString *originHash = [RCTConvert NSString:options[@"originHash"]];
if (type == PushyTypePatchFromPpk && originHash <= 0) {
callback([self errorWithMessage:ERROR_OPTIONS]);
return;
}
@@ -302,35 +343,38 @@ RCT_EXPORT_METHOD(markSuccess)
callback([self errorWithMessage:ERROR_FILE_OPERATION]);
return;
}
NSString *zipFilePath = [dir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@%@",hashName, [self zipExtension:type]]];
NSString *unzipDir = [dir stringByAppendingPathComponent:hashName];
NSString *zipFilePath = [dir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@%@",hash, [self zipExtension:type]]];
// NSString *unzipDir = [dir stringByAppendingPathComponent:hash];
RCTLogInfo(@"RCTPushy -- download file %@", updateUrl);
[RCTPushyDownloader download:updateUrl savePath:zipFilePath progressHandler:^(long long receivedBytes, long long totalBytes) {
[self.bridge.eventDispatcher sendAppEventWithName:EVENT_PROGRESS_DOWNLOAD
body:@{
PARAM_PROGRESS_HASHNAME:hashName,
PARAM_PROGRESS_RECEIVED:[NSNumber numberWithLongLong:receivedBytes],
PARAM_PROGRESS_TOTAL:[NSNumber numberWithLongLong:totalBytes]
}];
if (self->hasListeners) {
[self sendEventWithName:EVENT_PROGRESS_DOWNLOAD body:@{
PARAM_PROGRESS_HASH:hash,
PARAM_PROGRESS_RECEIVED:[NSNumber numberWithLongLong:receivedBytes],
PARAM_PROGRESS_TOTAL:[NSNumber numberWithLongLong:totalBytes]
}];
}
} completionHandler:^(NSString *path, NSError *error) {
if (error) {
callback(error);
}
else {
RCTLogInfo(@"RCTPushy -- unzip file %@", zipFilePath);
NSString *unzipFilePath = [dir stringByAppendingPathComponent:hashName];
[_fileManager unzipFileAtPath:zipFilePath toDestination:unzipFilePath progressHandler:^(NSString *entry,long entryNumber, long total) {
[self.bridge.eventDispatcher sendAppEventWithName:EVENT_PROGRESS_UNZIP
body:@{
PARAM_PROGRESS_HASHNAME:hashName,
PARAM_PROGRESS_RECEIVED:[NSNumber numberWithLong:entryNumber],
PARAM_PROGRESS_TOTAL:[NSNumber numberWithLong:total]
}];
NSString *unzipFilePath = [dir stringByAppendingPathComponent:hash];
[self->_fileManager unzipFileAtPath:zipFilePath toDestination:unzipFilePath progressHandler:^(NSString *entry,long entryNumber, long total) {
// if (self->hasListeners) {
// [self sendEventWithName:EVENT_PROGRESS_UNZIP
// body:@{
// PARAM_PROGRESS_HASH:hash,
// PARAM_PROGRESS_RECEIVED:[NSNumber numberWithLong:entryNumber],
// PARAM_PROGRESS_TOTAL:[NSNumber numberWithLong:total]
// }];
// }
} completionHandler:^(NSString *path, BOOL succeeded, NSError *error) {
dispatch_async(_methodQueue, ^{
dispatch_async(self->_methodQueue, ^{
if (error) {
callback(error);
}
@@ -340,16 +384,16 @@ RCT_EXPORT_METHOD(markSuccess)
{
NSString *sourceOrigin = [[NSBundle mainBundle] resourcePath];
NSString *bundleOrigin = [[RCTPushy binaryBundleURL] path];
[self patch:hashName fromBundle:bundleOrigin source:sourceOrigin callback:callback];
[self patch:hash fromBundle:bundleOrigin source:sourceOrigin callback:callback];
}
break;
case PushyTypePatchFromPpk:
{
NSString *lastVersionDir = [dir stringByAppendingPathComponent:originHashName];
NSString *lastVersionDir = [dir stringByAppendingPathComponent:originHash];
NSString *sourceOrigin = lastVersionDir;
NSString *bundleOrigin = [lastVersionDir stringByAppendingPathComponent:BUNDLE_FILE_NAME];
[self patch:hashName fromBundle:bundleOrigin source:sourceOrigin callback:callback];
[self patch:hash fromBundle:bundleOrigin source:sourceOrigin callback:callback];
}
break;
default:
@@ -363,9 +407,9 @@ RCT_EXPORT_METHOD(markSuccess)
}];
}
- (void)patch:(NSString *)hashName fromBundle:(NSString *)bundleOrigin source:(NSString *)sourceOrigin callback:(void (^)(NSError *error))callback
- (void)patch:(NSString *)hash fromBundle:(NSString *)bundleOrigin source:(NSString *)sourceOrigin callback:(void (^)(NSError *error))callback
{
NSString *unzipDir = [[RCTPushy downloadDir] stringByAppendingPathComponent:hashName];
NSString *unzipDir = [[RCTPushy downloadDir] stringByAppendingPathComponent:hash];
NSString *sourcePatch = [unzipDir stringByAppendingPathComponent:SOURCE_PATCH_NAME];
NSString *bundlePatch = [unzipDir stringByAppendingPathComponent:BUNDLE_PATCH_NAME];
@@ -383,7 +427,7 @@ RCT_EXPORT_METHOD(markSuccess)
NSDictionary *copies = json[@"copies"];
NSDictionary *deletes = json[@"deletes"];
[_fileManager copyFiles:copies fromDir:sourceOrigin toDir:unzipDir deletes:deletes completionHandler:^(NSError *error) {
[self->_fileManager copyFiles:copies fromDir:sourceOrigin toDir:unzipDir deletes:deletes completionHandler:^(NSError *error) {
if (error) {
callback(error);
}

89
lib/endpoint.js Normal file
View File

@@ -0,0 +1,89 @@
let currentEndpoint = 'https://update.react-native.cn/api';
function ping(url, rejectImmediate) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = (e) => {
if (xhr.readyState !== 4) {
return;
}
if (xhr.status === 200) {
resolve(url);
} else {
rejectImmediate ? reject() : setTimeout(reject, 5000);
}
};
xhr.open('HEAD', url);
xhr.send();
xhr.timeout = 5000;
xhr.ontimeout = reject;
});
}
function logger(...args) {
// console.warn('pushy', ...args);
}
let backupEndpoints = [];
let backupEndpointsQueryUrl =
'https://cdn.jsdelivr.net/gh/reactnativecn/react-native-pushy@master/endpoints.json';
export async function tryBackupEndpoints() {
if (!backupEndpoints.length && !backupEndpointsQueryUrl) {
return;
}
try {
await ping(getStatusUrl(), true);
logger('current endpoint ok');
return;
} catch (e) {
logger('current endpoint failed');
}
if (!backupEndpoints.length && backupEndpointsQueryUrl) {
try {
const resp = await fetch(backupEndpointsQueryUrl);
backupEndpoints = await resp.json();
logger('get remote endpoints:', backupEndpoints);
} catch (e) {
logger('get remote endpoints failed');
return;
}
}
await pickFatestAvailableEndpoint();
}
async function pickFatestAvailableEndpoint(endpoints = backupEndpoints) {
const fastestEndpoint = await Promise.race(
endpoints.map(pingAndReturnEndpoint),
);
if (typeof fastestEndpoint === 'string') {
logger(`pick endpoint: ${fastestEndpoint}`);
currentEndpoint = fastestEndpoint;
} else {
logger('all remote endpoints failed');
}
}
async function pingAndReturnEndpoint(endpoint = currentEndpoint) {
return ping(getStatusUrl(endpoint)).then(() => endpoint);
}
function getStatusUrl(endpoint = currentEndpoint) {
return `${endpoint}/status`;
}
export function getCheckUrl(APPKEY, endpoint = currentEndpoint) {
return `${endpoint}/checkUpdate/${APPKEY}`;
}
export function setCustomEndpoints({ main, backups, backupQueryUrl }) {
currentEndpoint = main;
backupEndpointsQueryUrl = null;
if (Array.isArray(backups) && backups.length > 0) {
backupEndpoints = backups;
pickFatestAvailableEndpoint();
}
if (typeof backupQueryUrl === 'string') {
backupEndpointsQueryUrl = backupQueryUrl;
}
}

View File

@@ -1,57 +0,0 @@
let availableDomain = 'update.react-native.cn';
function ping(domain, rejectImmediate) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = e => {
if (xhr.readyState !== 4) {
return;
}
if (xhr.status === 200) {
resolve(domain);
} else {
rejectImmediate ? reject() : setTimeout(reject, 5000);
}
};
xhr.open('HEAD', `https://${domain}`);
xhr.send();
xhr.timeout = 5000;
xhr.ontimeout = reject;
});
}
function logger(...args) {
// console.warn('pushy', ...args);
}
export async function tryBackupDomains() {
try {
await ping(availableDomain, true);
logger('main domain ok');
return;
} catch (e) {
logger('main domain failed');
}
let backupDomains = [];
try {
const resp = await fetch(
'https://cdn.jsdelivr.net/gh/reactnativecn/react-native-pushy@master/domains.json',
);
backupDomains = await resp.json();
logger('get remote domains:', backupDomains);
} catch (e) {
logger('get remote domains failed');
return;
}
const fastestDomain = await Promise.race(backupDomains.map(ping));
if (typeof fastestDomain === 'string') {
logger(`pick domain: ${fastestDomain}`);
availableDomain = fastestDomain;
} else {
logger('all remote domains failed');
}
}
export default function getHost() {
return `https://${availableDomain}/api`;
}

44
lib/index.d.ts vendored
View File

@@ -20,17 +20,55 @@ export interface UpdateAvailableResult {
description: string;
metaInfo: string;
pdiffUrl: string;
diffUrl: string;
diffUrl?: string;
}
export type CheckResult = Partial<ExpiredResult & UpTodateResult & UpdateAvailableResult>;
export type CheckResult =
| ExpiredResult
| UpTodateResult
| UpdateAvailableResult;
export function checkUpdate(appkey: string): Promise<CheckResult>;
export function downloadUpdate(options: UpdateAvailableResult): Promise<undefined | string>;
export function downloadUpdate(
info: UpdateAvailableResult,
eventListeners?: {
onDownloadProgress?: (data: ProgressData) => void;
},
): Promise<undefined | string>;
export function switchVersion(hash: string): void;
export function switchVersionLater(hash: string): void;
export function markSuccess(): void;
export async function downloadAndInstallApk({
url,
onDownloadProgress,
}: {
url: string;
onDownloadProgress?: (data: ProgressData) => void;
}): void;
/**
* @param {string} main - The main api endpoint
* @param {string[]} [backups] - The back up endpoints.
* @param {string} [backupQueryUrl] - An url that return a json file containing an array of endpoint.
* like: ["https://backup.api/1", "https://backup.api/2"]
*/
export function setCustomEndpoints({
main,
backups,
backupQueryUrl,
}: {
main: string;
backups?: string[];
backupQueryUrl?: string;
}): void;
interface ProgressData {
hash: string;
received: number;
total: number;
}

View File

@@ -1,5 +1,14 @@
import getHost, { tryBackupDomains } from './getHost';
import { NativeAppEventEmitter, NativeModules } from 'react-native';
import {
tryBackupEndpoints,
getCheckUrl,
setCustomEndpoints,
} from './endpoint';
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
export { setCustomEndpoints };
const {
version: v,
} = require('react-native/Libraries/Core/ReactNativeVersion');
const RNVersion = `${v.major}.${v.minor}.${v.patch}`;
let Pushy = NativeModules.Pushy;
@@ -13,10 +22,31 @@ export const currentVersion = Pushy.currentVersion;
export const isFirstTime = Pushy.isFirstTime;
export const isRolledBack = Pushy.isRolledBack;
export const buildTime = Pushy.buildTime;
let blockUpdate = Pushy.blockUpdate;
let uuid = Pushy.uuid;
if (Platform.OS === 'android' && !Pushy.isUsingBundleUrl) {
throw new Error(
'react-native-update模块无法加载请对照文档检查Bundle URL的配置',
);
}
const eventEmitter = new NativeEventEmitter(Pushy);
if (!uuid) {
uuid = require('uuid/v4')();
Pushy.setUuid(uuid);
}
function logger(text) {
console.log(`Pushy: ${text}`);
}
logger('uuid: ' + uuid);
/*
Return json:
Package was expired:
Package expired:
{
expired: true,
downloadUrl: 'http://appstore/downloadUrl',
@@ -45,9 +75,20 @@ function assertRelease() {
export async function checkUpdate(APPKEY, isRetry) {
assertRelease();
if (blockUpdate && blockUpdate.until > Date.now() / 1000) {
throw new Error(
`热更新已暂停,原因:${blockUpdate.reason}。请在"${new Date(
blockUpdate.until * 1000,
).toLocaleString()}"之后重试。`,
);
}
if (typeof APPKEY !== 'string') {
throw new Error('未检查到合法的APPKEY请查看update.json文件是否正确生成');
}
logger('checking update');
let resp;
try {
resp = await fetch(`${getHost()}/checkUpdate/${APPKEY}`, {
resp = await fetch(getCheckUrl(APPKEY), {
method: 'POST',
headers: {
Accept: 'application/json',
@@ -57,69 +98,113 @@ export async function checkUpdate(APPKEY, isRetry) {
packageVersion,
hash: currentVersion,
buildTime,
cInfo: {
pushy: require('../package.json').version,
rn: RNVersion,
os: Platform.OS + ' ' + Platform.Version,
uuid,
},
}),
});
} catch (e) {
if (isRetry) {
throw new Error('Could not connect to pushy server');
}
await tryBackupDomains();
await tryBackupEndpoints(APPKEY);
return checkUpdate(APPKEY, true);
}
const result = await resp.json();
checkOperation(result.op);
if (resp.status !== 200) {
throw new Error((await resp.json()).message);
throw new Error(result.message);
}
return resp.json();
return result;
}
export async function downloadUpdate(options) {
function checkOperation(op) {
if (!Array.isArray(op)) {
return;
}
op.forEach((action) => {
if (action.type === 'block') {
blockUpdate = {
reason: action.reason,
until: (Date.now() + action.duration) / 1000,
};
Pushy.setBlockUpdate(blockUpdate);
}
});
}
export async function downloadUpdate(options, eventListeners) {
assertRelease();
if (!options.update) {
return;
}
let progressHandler;
if (eventListeners) {
if (eventListeners.onDownloadProgress) {
const downloadCallback = eventListeners.onDownloadProgress;
progressHandler = eventEmitter.addListener('RCTPushyDownloadProgress', (progressData) => {
if (progressData.hash === options.hash) {
downloadCallback(progressData);
}
});
}
}
if (options.diffUrl) {
logger('downloading diff');
await Pushy.downloadPatchFromPpk({
updateUrl: options.diffUrl,
hashName: options.hash,
originHashName: currentVersion,
hash: options.hash,
originHash: currentVersion,
});
} else if (options.pdiffUrl) {
logger('downloading pdiff');
await Pushy.downloadPatchFromPackage({
updateUrl: options.pdiffUrl,
hashName: options.hash,
});
} else {
await Pushy.downloadUpdate({
updateUrl: options.updateUrl,
hashName: options.hash,
hash: options.hash,
});
}
progressHandler && progressHandler.remove();
return options.hash;
}
export function switchVersion(hash) {
assertRelease();
Pushy.reloadUpdate({ hashName: hash });
logger('switchVersion');
Pushy.reloadUpdate({ hash });
}
export function switchVersionLater(hash) {
assertRelease();
Pushy.setNeedUpdate({ hashName: hash });
logger('switchVersionLater');
Pushy.setNeedUpdate({ hash });
}
export function markSuccess() {
assertRelease();
logger('markSuccess');
Pushy.markSuccess();
}
// function report(action) {
// // ${project}.${host}/logstores/${logstore}/track?APIVersion=0.6.0&key1=val1
// fetch(`${logUrl}&action=${action}`);
// }
NativeAppEventEmitter.addListener('RCTPushyDownloadProgress', params => {});
NativeAppEventEmitter.addListener('RCTPushyUnzipProgress', params => {});
export async function downloadAndInstallApk({ url, onDownloadProgress }) {
logger('downloadAndInstallApk');
let hash = Date.now().toString();
let progressHandler;
if (onDownloadProgress) {
progressHandler = eventEmitter.addListener('RCTPushyDownloadProgress', (progressData) => {
if (progressData.hash === hash) {
onDownloadProgress(progressData);
}
});
}
await Pushy.downloadAndInstallApk({
url,
target: 'update.apk',
hash,
});
progressHandler && progressHandler.remove();
}

View File

@@ -1,6 +1,6 @@
{
"name": "react-native-update",
"version": "5.6.0",
"version": "5.9.0",
"description": "react-native hot update",
"main": "lib/index.js",
"scripts": {
@@ -26,5 +26,7 @@
"react-native": ">=0.27.0"
},
"homepage": "https://github.com/reactnativecn/react-native-pushy#readme",
"dependencies": {}
"dependencies": {
"uuid": "3"
}
}

2593
yarn.lock

File diff suppressed because it is too large Load Diff