From 063c14ab45b782c4b99c118c71b363477aeb30f4 Mon Sep 17 00:00:00 2001 From: tdzl2003 <tdzl2003@gmail.com> Date: Mon, 4 Apr 2016 23:02:28 +0800 Subject: [PATCH] bugfixes --- .../modules/update/DownloadTask.java | 294 +++++++++--------- .../modules/update/DownloadTaskParams.java | 2 + .../modules/update/UpdateContext.java | 123 +++++++- .../modules/update/UpdateModule.java | 46 ++- index.js | 28 +- lib/hooks.js | 8 - lib/index.js | 84 +++++ lib/resolveAssetSource.js | 144 --------- local-cli/src/api.js | 9 +- local-cli/src/package.js | 2 +- 10 files changed, 394 insertions(+), 346 deletions(-) delete mode 100644 lib/hooks.js create mode 100644 lib/index.js delete mode 100644 lib/resolveAssetSource.js diff --git a/android/src/main/java/cn/reactnative/modules/update/DownloadTask.java b/android/src/main/java/cn/reactnative/modules/update/DownloadTask.java index 5febe47..91974e2 100644 --- a/android/src/main/java/cn/reactnative/modules/update/DownloadTask.java +++ b/android/src/main/java/cn/reactnative/modules/update/DownloadTask.java @@ -9,6 +9,7 @@ import com.squareup.okhttp.Request; import com.squareup.okhttp.Response; import com.squareup.okhttp.ResponseBody; +import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; @@ -212,45 +213,37 @@ class DownloadTask extends AsyncTask<DownloadTaskParams, Void, Void> { copyFilesWithBlacklist("", from, to, blackList); } - private void doDownload(DownloadTaskParams param) { - try { - downloadFile(param.url, param.zipFilePath); + private void doDownload(DownloadTaskParams param) throws IOException { + downloadFile(param.url, param.zipFilePath); - ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(param.zipFilePath))); - ZipEntry ze; - String filename; + ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(param.zipFilePath))); + ZipEntry ze; + String filename; - removeDirectory(param.unzipDirectory); - param.unzipDirectory.mkdirs(); + removeDirectory(param.unzipDirectory); + param.unzipDirectory.mkdirs(); - while ((ze = zis.getNextEntry()) != null) - { - String fn = ze.getName(); - File fmd = new File(param.unzipDirectory, fn); - - if (UpdateContext.DEBUG) { - Log.d("RNUpdate", "Unzipping " + fn); - } - - if (ze.isDirectory()) { - fmd.mkdirs(); - continue; - } - - unzipToFile(zis, fmd); - } - - zis.close(); + while ((ze = zis.getNextEntry()) != null) + { + String fn = ze.getName(); + File fmd = new File(param.unzipDirectory, fn); if (UpdateContext.DEBUG) { - Log.d("RNUpdate", "Unzip finished"); + Log.d("RNUpdate", "Unzipping " + fn); } - } catch (Throwable e) { - if (UpdateContext.DEBUG) { - e.printStackTrace(); + if (ze.isDirectory()) { + fmd.mkdirs(); + continue; } - param.listener.onDownloadFailed(e); + + unzipToFile(zis, fmd); + } + + zis.close(); + + if (UpdateContext.DEBUG) { + Log.d("RNUpdate", "Unzip finished"); } } @@ -268,162 +261,161 @@ class DownloadTask extends AsyncTask<DownloadTaskParams, Void, Void> { } } - private void doPatchFromApk(DownloadTaskParams param) { - try { - downloadFile(param.url, param.zipFilePath); + private void doPatchFromApk(DownloadTaskParams param) throws IOException, JSONException { + downloadFile(param.url, param.zipFilePath); - ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(param.zipFilePath))); - ZipEntry ze; - int count; - String filename; + ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(param.zipFilePath))); + ZipEntry ze; + int count; + String filename; - removeDirectory(param.unzipDirectory); - param.unzipDirectory.mkdirs(); + removeDirectory(param.unzipDirectory); + param.unzipDirectory.mkdirs(); - while ((ze = zis.getNextEntry()) != null) - { - String fn = ze.getName(); + while ((ze = zis.getNextEntry()) != null) + { + String fn = ze.getName(); - if (fn.equals("__diff.json")) { - // copy files from assets - byte[] bytes = readBytes(zis); - String json = new String(bytes, "UTF-8"); - JSONObject obj = (JSONObject)new JSONTokener(json).nextValue(); + if (fn.equals("__diff.json")) { + // copy files from assets + byte[] bytes = readBytes(zis); + String json = new String(bytes, "UTF-8"); + JSONObject obj = (JSONObject)new JSONTokener(json).nextValue(); - JSONObject copies = obj.getJSONObject("copies"); - Iterator<?> keys = copies.keys(); - while( keys.hasNext() ) { - String to = (String)keys.next(); - String from = copies.getString(to); - if (from.isEmpty()) { - from = to; - } - copyFromResource(from, new File(param.unzipDirectory, to)); + JSONObject copies = obj.getJSONObject("copies"); + Iterator<?> keys = copies.keys(); + while( keys.hasNext() ) { + String to = (String)keys.next(); + String from = copies.getString(to); + if (from.isEmpty()) { + from = to; } - continue; + copyFromResource(from, new File(param.unzipDirectory, to)); } - if (fn.equals("index.bundlejs.patch")) { - // do bsdiff patch - byte[] patched = bsdiffPatch(readOriginBundle(), readBytes(zis)); - - FileOutputStream fout = new FileOutputStream(new File(param.unzipDirectory, "index.bundlejs")); - fout.write(patched); - fout.close(); - continue; - } - File fmd = new File(param.unzipDirectory, fn); - - if (UpdateContext.DEBUG) { - Log.d("RNUpdate", "Unzipping " + fn); - } - - if (ze.isDirectory()) { - fmd.mkdirs(); - continue; - } - - unzipToFile(zis, fmd); + continue; } + if (fn.equals("index.bundlejs.patch")) { + // do bsdiff patch + byte[] patched = bsdiffPatch(readOriginBundle(), readBytes(zis)); - zis.close(); + FileOutputStream fout = new FileOutputStream(new File(param.unzipDirectory, "index.bundlejs")); + fout.write(patched); + fout.close(); + continue; + } + File fmd = new File(param.unzipDirectory, fn); if (UpdateContext.DEBUG) { - Log.d("RNUpdate", "Unzip finished"); + Log.d("RNUpdate", "Unzipping " + fn); } - } catch (Throwable e) { - if (UpdateContext.DEBUG) { - e.printStackTrace(); + if (ze.isDirectory()) { + fmd.mkdirs(); + continue; } - param.listener.onDownloadFailed(e); + + unzipToFile(zis, fmd); } + + zis.close(); + + if (UpdateContext.DEBUG) { + Log.d("RNUpdate", "Unzip finished"); + } + } - private void doPatchFromPpk(DownloadTaskParams param) { - try { - downloadFile(param.url, param.zipFilePath); + private void doPatchFromPpk(DownloadTaskParams param) throws IOException, JSONException { + downloadFile(param.url, param.zipFilePath); - ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(param.zipFilePath))); - ZipEntry ze; - int count; - String filename; + ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(param.zipFilePath))); + ZipEntry ze; + int count; + String filename; - removeDirectory(param.unzipDirectory); - param.unzipDirectory.mkdirs(); + removeDirectory(param.unzipDirectory); + param.unzipDirectory.mkdirs(); - while ((ze = zis.getNextEntry()) != null) - { - String fn = ze.getName(); + while ((ze = zis.getNextEntry()) != null) + { + String fn = ze.getName(); - if (fn.equals("__diff.json")) { - // copy files from assets - byte[] bytes = readBytes(zis); - String json = new String(bytes, "UTF-8"); - JSONObject obj = (JSONObject)new JSONTokener(json).nextValue(); + if (fn.equals("__diff.json")) { + // copy files from assets + byte[] bytes = readBytes(zis); + String json = new String(bytes, "UTF-8"); + JSONObject obj = (JSONObject)new JSONTokener(json).nextValue(); - JSONObject copies = obj.getJSONObject("copies"); - Iterator<?> keys = copies.keys(); - while( keys.hasNext() ) { - String to = (String)keys.next(); - String from = copies.getString(to); - if (from.isEmpty()) { - from = to; - } - copyFile(new File(param.originDirectory, from), new File(param.unzipDirectory, to)); + JSONObject copies = obj.getJSONObject("copies"); + Iterator<?> keys = copies.keys(); + while( keys.hasNext() ) { + String to = (String)keys.next(); + String from = copies.getString(to); + if (from.isEmpty()) { + from = to; } - JSONObject blackList = obj.getJSONObject("deletes"); - copyFilesWithBlacklist(param.originDirectory, param.unzipDirectory, blackList); - continue; + copyFile(new File(param.originDirectory, from), new File(param.unzipDirectory, to)); } - if (fn.equals("index.bundlejs.patch")) { - // do bsdiff patch - byte[] patched = bsdiffPatch(readFile(new File(param.originDirectory, "index.bundlejs")), readBytes(zis)); - - FileOutputStream fout = new FileOutputStream(new File(param.unzipDirectory, "index.bundlejs")); - fout.write(patched); - fout.close(); - continue; - } - File fmd = new File(param.unzipDirectory, fn); - - if (UpdateContext.DEBUG) { - Log.d("RNUpdate", "Unzipping " + fn); - } - - if (ze.isDirectory()) { - fmd.mkdirs(); - continue; - } - - unzipToFile(zis, fmd); + JSONObject blackList = obj.getJSONObject("deletes"); + copyFilesWithBlacklist(param.originDirectory, param.unzipDirectory, blackList); + continue; } + if (fn.equals("index.bundlejs.patch")) { + // do bsdiff patch + byte[] patched = bsdiffPatch(readFile(new File(param.originDirectory, "index.bundlejs")), readBytes(zis)); - zis.close(); + FileOutputStream fout = new FileOutputStream(new File(param.unzipDirectory, "index.bundlejs")); + fout.write(patched); + fout.close(); + continue; + } + File fmd = new File(param.unzipDirectory, fn); if (UpdateContext.DEBUG) { - Log.d("RNUpdate", "Unzip finished"); + Log.d("RNUpdate", "Unzipping " + fn); } - } catch (Throwable e) { - if (UpdateContext.DEBUG) { - e.printStackTrace(); + if (ze.isDirectory()) { + fmd.mkdirs(); + continue; } - param.listener.onDownloadFailed(e); + + unzipToFile(zis, fmd); } + + zis.close(); + + if (UpdateContext.DEBUG) { + Log.d("RNUpdate", "Unzip finished"); + } + } + private void doCleanUp(DownloadTaskParams param) { + } @Override protected Void doInBackground(DownloadTaskParams... params) { - switch (params[0].type) { - case DownloadTaskParams.TASK_TYPE_FULL_DOWNLOAD: - doDownload(params[0]); - break; - case DownloadTaskParams.TASK_TYPE_PATCH_FROM_APK: - doPatchFromApk(params[0]); - break; - case DownloadTaskParams.TASK_TYPE_PATCH_FROM_PPK: - doPatchFromPpk(params[0]); - break; + try { + switch (params[0].type) { + case DownloadTaskParams.TASK_TYPE_FULL_DOWNLOAD: + doDownload(params[0]); + break; + case DownloadTaskParams.TASK_TYPE_PATCH_FROM_APK: + doPatchFromApk(params[0]); + break; + case DownloadTaskParams.TASK_TYPE_PATCH_FROM_PPK: + doPatchFromPpk(params[0]); + break; + case DownloadTaskParams.TASK_TYPE_CLEARUP: + doCleanUp(params[0]); + break; + } + params[0].listener.onDownloadCompleted(); + } catch (Throwable e) { + if (UpdateContext.DEBUG) { + e.printStackTrace(); + } + params[0].listener.onDownloadFailed(e); } return null; } diff --git a/android/src/main/java/cn/reactnative/modules/update/DownloadTaskParams.java b/android/src/main/java/cn/reactnative/modules/update/DownloadTaskParams.java index a7d29a4..042cb69 100644 --- a/android/src/main/java/cn/reactnative/modules/update/DownloadTaskParams.java +++ b/android/src/main/java/cn/reactnative/modules/update/DownloadTaskParams.java @@ -12,6 +12,8 @@ class DownloadTaskParams { static final int TASK_TYPE_PATCH_FROM_APK = 2; static final int TASK_TYPE_PATCH_FROM_PPK = 3; + static final int TASK_TYPE_CLEARUP = 0; //Keep hash & originHash + int type; String url; String hash; diff --git a/android/src/main/java/cn/reactnative/modules/update/UpdateContext.java b/android/src/main/java/cn/reactnative/modules/update/UpdateContext.java index c7db479..44790a8 100644 --- a/android/src/main/java/cn/reactnative/modules/update/UpdateContext.java +++ b/android/src/main/java/cn/reactnative/modules/update/UpdateContext.java @@ -1,8 +1,12 @@ package cn.reactnative.modules.update; import android.content.Context; +import android.content.SharedPreferences; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import java.io.File; +import java.net.URL; /** * Created by tdzl2003 on 3/31/16. @@ -13,13 +17,6 @@ public class UpdateContext { public static boolean DEBUG = false; - - private static UpdateContext currentInstance = null; - - static UpdateContext instance() { - return currentInstance; - } - public UpdateContext(Context context) { this.context = context; @@ -28,12 +25,26 @@ public class UpdateContext { if (!rootDir.exists()) { rootDir.mkdir(); } + + this.sp = context.getSharedPreferences("update", Context.MODE_PRIVATE); } public String getRootDir() { return rootDir.toString(); } + public String getPackageVersion() { + PackageManager pm = context.getPackageManager(); + PackageInfo pi = null; + try { + pi = pm.getPackageInfo(context.getPackageName(), 0); + return pi.versionName; + } catch( PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + return null; + } + public interface DownloadFileListener { void onDownloadCompleted(); void onDownloadFailed(Throwable error); @@ -73,4 +84,102 @@ public class UpdateContext { params.originDirectory = new File(rootDir, originHashName); new DownloadTask(context).execute(params); } + + private SharedPreferences sp; + + public void switchVersion(String hashName) { + if (!new File(rootDir, hashName).exists()) { + throw new Error("Hash name not found, must download first."); + } + String lastVersion = getCurrentVersion(); + SharedPreferences.Editor editor = sp.edit(); + editor.putString("currentVersion", hashName); + if (lastVersion != null) { + editor.putString("lastVersion", hashName); + } + editor.putBoolean("firstTime", true); + editor.putBoolean("shouldRollback", false); + editor.putBoolean("rolledBack", false); + editor.apply(); + } + + public String getCurrentVersion() { + return sp.getString("currentVersion", null); + } + + public boolean isFirstTime() { + return sp.getBoolean("firstTime", false); + } + + public boolean isRolledBack() { + return sp.getBoolean("rolledBack", false); + } + + public void clearFirstTimeMark() { + SharedPreferences.Editor editor = sp.edit(); + editor.putBoolean("firstTime", false); + editor.putBoolean("shouldRollback", false); + editor.apply(); + + this.clearUp(); + } + + public static String getBundleUrl(Context context) { + return new UpdateContext(context.getApplicationContext()).getBundleUrl(); + } + + public static String getBundleUrl(Context context, String defaultAssetsUrl) { + return new UpdateContext(context.getApplicationContext()).getBundleUrl(defaultAssetsUrl); + } + + public String getBundleUrl() { + return getBundleUrl("assets://index.android.bundle"); + } + + public String getBundleUrl(String defaultAssetsUrl) { + // Test should rollback. + if (sp.getBoolean("shouldRollback", false)) { + this.rollBack(); + } + String currentVersion = getCurrentVersion(); + if (currentVersion == null) { + return defaultAssetsUrl; + } + if (sp.getBoolean("firstTime", false)) { + SharedPreferences.Editor editor = sp.edit(); + editor.putBoolean("shouldRollback", true); + editor.apply(); + } + return new File(rootDir, currentVersion+"/index.bundlejs").toURI().toString(); + } + + private void rollBack() { + String lastVersion = sp.getString("lastVersion", null); + if (lastVersion == null) { + throw new Error("This should never happen"); + } + SharedPreferences.Editor editor = sp.edit(); + editor.putString("currentVersion", lastVersion); + editor.putBoolean("shouldRollback", false); + editor.putBoolean("firstTime", false); + editor.putBoolean("rolledBack", true); + editor.apply(); + } + + private void clearUp() { + DownloadTaskParams params = new DownloadTaskParams(); + params.type = DownloadTaskParams.TASK_TYPE_CLEARUP; + params.hash = sp.getString("currentVersion", null); + params.originHash = sp.getString("lastVersion", null);; + params.listener = new DownloadFileListener() { + @Override + public void onDownloadCompleted() { + } + + @Override + public void onDownloadFailed(Throwable error) { + } + }; + new DownloadTask(context).execute(params); + } } diff --git a/android/src/main/java/cn/reactnative/modules/update/UpdateModule.java b/android/src/main/java/cn/reactnative/modules/update/UpdateModule.java index ac9cf3f..447b4fc 100644 --- a/android/src/main/java/cn/reactnative/modules/update/UpdateModule.java +++ b/android/src/main/java/cn/reactnative/modules/update/UpdateModule.java @@ -1,10 +1,14 @@ package cn.reactnative.modules.update; +import android.app.Activity; +import android.content.Intent; + import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.UiThreadUtil; import java.util.HashMap; import java.util.Map; @@ -15,15 +19,23 @@ import java.util.Map; public class UpdateModule extends ReactContextBaseJavaModule{ UpdateContext updateContext; - public UpdateModule(ReactApplicationContext reactContext) { + public UpdateModule(ReactApplicationContext reactContext, UpdateContext updateContext) { super(reactContext); - this.updateContext = new UpdateContext(reactContext.getApplicationContext()); + this.updateContext = updateContext; + } + + public UpdateModule(ReactApplicationContext reactContext) { + this(reactContext, new UpdateContext(reactContext.getApplicationContext())); } @Override public Map<String, Object> getConstants() { final Map<String, Object> constants = new HashMap<>(); constants.put("downloadRootDir", updateContext.getRootDir()); + constants.put("packageVersion", updateContext.getPackageVersion()); + constants.put("currentVersion", updateContext.getCurrentVersion()); + constants.put("firstTime", updateContext.isFirstTime()); + constants.put("rolledBack", updateContext.isRolledBack()); return constants; } @@ -50,7 +62,7 @@ public class UpdateModule extends ReactContextBaseJavaModule{ } @ReactMethod - public void downloadPatchFromApk(ReadableMap options, final Promise promise){ + public void downloadPatchFromPackage(ReadableMap options, final Promise promise){ String url = options.getString("updateUrl"); String hash = options.getString("hashName"); updateContext.downloadPatchFromApk(url, hash, new UpdateContext.DownloadFileListener() { @@ -83,4 +95,32 @@ public class UpdateModule extends ReactContextBaseJavaModule{ } }); } + + @ReactMethod + public void reloadUpdate(ReadableMap options) { + final String hash = options.getString("hashName"); + + UiThreadUtil.runOnUiThread(new Runnable() { + @Override + public void run() { + updateContext.switchVersion(hash); + Activity activity = getCurrentActivity(); + Intent intent = activity.getIntent(); + activity.finish(); + activity.startActivity(intent); + } + }); + } + + @ReactMethod + public void setNeedUpdate(ReadableMap options) { + final String hash = options.getString("hashName"); + + UiThreadUtil.runOnUiThread(new Runnable() { + @Override + public void run() { + updateContext.switchVersion(hash); + } + }); + } } diff --git a/index.js b/index.js index ef094c3..0250df9 100644 --- a/index.js +++ b/index.js @@ -3,30 +3,4 @@ * @providesModule react-native-update */ -//if (__DEV__){ -// if (global.__fbBatchedBridge) { -// require('fbjs/lib/warning')('Should require pushy before react-native to do hook stuff!'); -// } -//} -// -//require('./lib/hooks'); -const HotUpdate = require('react-native').NativeModules.HotUpdate; -const NativeAppEventEmitter = require('react-native').NativeAppEventEmitter; -const downloadRootDir = HotUpdate.downloadRootDir; - -export function downloadFile(options) { - HotUpdate.downloadUpdate(options, r=>{ - //console.log(r); - }) -} - -export function reloadUpdate(options) { - HotUpdate.reloadUpdate(options); -} - -export function setNeedUpdate(options) { - HotUpdate.setNeedUpdate(options); -} - - - +require('./lib/index'); diff --git a/lib/hooks.js b/lib/hooks.js deleted file mode 100644 index 269cec0..0000000 --- a/lib/hooks.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Created by tdzl2003 on 2/6/16. - */ - -// Hook resolvedAssetSource -__d('resolveAssetSource', function(_1, _2, module, _3) { - module.exports = require('./resolveAssetSource'); -}); diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..27b8a5b --- /dev/null +++ b/lib/index.js @@ -0,0 +1,84 @@ +/** + * Created by tdzl2003 on 4/4/16. + */ + +const HotUpdate = require('react-native').NativeModules.HotUpdate; + +let host = 'http://update.reactnative.cn/api'; + +export const downloadRootDir = HotUpdate.downloadRootDir; +export const packageVersion = HotUpdate.packageVersion; +export const currentVersion = HotUpdate.currentVersion; +export const isFirstTime = HotUpdate.isFirstTime; +export const isRolledBack = HotUpdate.isRolledBack; + +/* +Return json: +Package was expired: +{ + expired: true, + downloadUrl: 'http://appstore/downloadUrl', +} +Package is up to date: +{ + upToDate: true, +} +There is available update: +{ + update: true, + name: '1.0.3-rc', + hash: 'hash', + description: '添加聊天功能\n修复商城页面BUG', + metaInfo: '{"silent":true}', + updateUrl: 'http://update-packages.reactnative.cn/hash', + pdiffUrl: 'http://update-packages.reactnative.cn/hash', + diffUrl: 'http://update-packages.reactnative.cn/hash', +} + */ +export async function checkUpdate(APPKEY) { + const resp = await fetch(`${host}/checkUpdate/${APPKEY}`, { + method: 'POST', + body: JSON.stringify({ + packageVersion: packageVersion, + hash: currentVersion, + }), + }); + + if (resp.status !== 200) { + throw new Error(resp.message); + } + + return await resp.json(); +} + +export async function downloadUpdate(options) { + if (!options.update) { + return; + } + + if (options.diff) { + await HotUpdate.downloadPatchFromPpk({ + updateUrl: options.diffUrl, + hashName: options.hash, + originHash: currentVersion, + }); + } else if (options.diff) { + await HotUpdate.downloadPatchFromPackage({ + updateUrl: options.pdiffUrl, + hashName: options.hash, + }); + } else { + await HotUpdate.downloadPatchFromPackage({ + updateUrl: options.updateUrl, + hashName: options.hash, + }); + } +} + +export async function switchVersion({hash}) { + HotUpdate.reloadUpdate({hashName:hash}); +} + +export async function switchVersionLater({hash}) { + HotUpdate.setNeedUpdate({hashName:hash}); +} diff --git a/lib/resolveAssetSource.js b/lib/resolveAssetSource.js deleted file mode 100644 index 5cb2052..0000000 --- a/lib/resolveAssetSource.js +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule resolveAssetSource - * @flow - * - * Resolves an asset into a `source` for `Image`. - * - * Hooked by @tdzl2003 for react-native-pushy - */ -'use strict'; - -var AssetRegistry = require('react-native/Libraries/Image/AssetRegistry'); -var PixelRatio = require('react-native/Libraries/Utilities/PixelRatio'); -var Platform = require('react-native/Libraries/Utilities/Platform'); -var NativeModules = require('react-native/Libraries/BatchedBridge/BatchedBridgedModules/NativeModules.js'); -var SourceCode = NativeModules.SourceCode; - -var _serverURL, _offlinePath; - -function getDevServerURL() { - if (_serverURL === undefined) { - var scriptURL = SourceCode.scriptURL; - var match = scriptURL && scriptURL.match(/^https?:\/\/.*?\//); - if (match) { - // Bundle was loaded from network - _serverURL = match[0]; - } else { - // Bundle was loaded from file - _serverURL = null; - } - } - - return _serverURL; -} - -function getOfflinePath() { - if (_offlinePath === undefined) { - var scriptURL = SourceCode.scriptURL; - var match = scriptURL && scriptURL.match(/^file:\/\/(\/.*\/)/); - if (match) { - _offlinePath = match[1]; - } else { - _offlinePath = ''; - } - } - - return _offlinePath; -} - -/** - * Returns the path at which the asset can be found in the archive - */ -function getPathInArchive(asset) { - if (Platform.OS === 'android') { - var assetDir = getBasePath(asset); - // E.g. 'assets_awesomemodule_icon' - // The Android resource system picks the correct scale. - return (assetDir + '/' + asset.name) - .toLowerCase() - .replace(/\//g, '_') // Encode folder structure in file name - .replace(/([^a-z0-9_])/g, '') // Remove illegal chars - .replace(/^assets_/, ''); // Remove "assets_" prefix - } else { - // E.g. 'assets/AwesomeModule/icon@2x.png' - return getOfflinePath() + getScaledAssetPath(asset); - } -} - -/** - * Returns an absolute URL which can be used to fetch the asset - * from the devserver - */ -function getPathOnDevserver(devServerUrl, asset) { - return devServerUrl + getScaledAssetPath(asset) + '?platform=' + Platform.OS + - '&hash=' + asset.hash; -} - -/** - * Returns a path like 'assets/AwesomeModule' - */ -function getBasePath(asset) { - var path = asset.httpServerLocation; - if (path[0] === '/') { - path = path.substr(1); - } - return path; -} - -/** - * Returns a path like 'assets/AwesomeModule/icon@2x.png' - */ -function getScaledAssetPath(asset) { - var scale = pickScale(asset.scales, PixelRatio.get()); - var scaleSuffix = scale === 1 ? '' : '@' + scale + 'x'; - var assetDir = getBasePath(asset); - return assetDir + '/' + asset.name + scaleSuffix + '.' + asset.type; -} - -function pickScale(scales, deviceScale) { - // Packager guarantees that `scales` array is sorted - for (var i = 0; i < scales.length; i++) { - if (scales[i] >= deviceScale) { - return scales[i]; - } - } - - // If nothing matches, device scale is larger than any available - // scales, so we return the biggest one. Unless the array is empty, - // in which case we default to 1 - return scales[scales.length - 1] || 1; -} - -function resolveAssetSource(source){ - if (typeof source === 'object') { - return source; - } - - var asset = AssetRegistry.getAssetByID(source); - if (asset) { - return assetToImageSource(asset); - } - - return null; -} - -function assetToImageSource(asset){ - var devServerURL = getDevServerURL(); - return { - __packager_asset: true, - width: asset.width, - height: asset.height, - uri: devServerURL ? getPathOnDevserver(devServerURL, asset) : getPathInArchive(asset), - scale: pickScale(asset.scales, PixelRatio.get()), - }; -} - -module.exports = resolveAssetSource; -module.exports.pickScale = pickScale; diff --git a/local-cli/src/api.js b/local-cli/src/api.js index d1204e9..34ba63c 100644 --- a/local-cli/src/api.js +++ b/local-cli/src/api.js @@ -3,7 +3,7 @@ */ const fetch = require('isomorphic-fetch'); -let host = process.env.PUSHY_REGISTRY || 'http://update.reactnative.cn'; +let host = process.env.PUSHY_REGISTRY || 'http://update.reactnative.cn/api'; const fs = require('fs-promise'); import * as fsOrigin from 'fs'; import request from 'request'; @@ -18,7 +18,7 @@ exports.loadSession = async function() { exports.replaceSession(JSON.parse(await fs.readFile('.update', 'utf8'))); savedSession = session; } catch (e) { - console.error('Failed to parse file `.pushy`. Try to remove it manually.'); + console.error('Failed to parse file `.update`. Try to remove it manually.'); throw e; } } @@ -94,7 +94,7 @@ async function uploadFile(fn) { let realUrl = url; if (!/^https?\:\/\//.test(url)) { - url = host + url; + realUrl = host + url; } const fileSize = (await fs.stat(fn)).size; @@ -111,8 +111,7 @@ async function uploadFile(fn) { formData.file.on('data', function(data) { bar.tick(data.length); }) - request.post({ - realUrl, + request.post(realUrl, { formData, }, (err, resp, body) => { if (err) { diff --git a/local-cli/src/package.js b/local-cli/src/package.js index a3465fc..b8d3ae0 100644 --- a/local-cli/src/package.js +++ b/local-cli/src/package.js @@ -61,7 +61,7 @@ export const commands = { uploadApk: async function({args}) { const fn = args[0]; if (!fn) { - throw new Error('Usage: pushy uploadApk <ipaFile>'); + throw new Error('Usage: pushy uploadApk <apkFile>'); } const name = await getApkVersion(fn); const {appId} = await getSelectedApp('android');