Skip to content

Commit

Permalink
Show experience loading progress (#185)
Browse files Browse the repository at this point in the history
fbshipit-source-id: f379be4
  • Loading branch information
janicduplessis authored and expbot committed Aug 9, 2017
1 parent 3745c2a commit e6a3f99
Show file tree
Hide file tree
Showing 24 changed files with 282 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import com.amplitude.api.Amplitude;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.soloader.SoLoader;

import host.exp.exponent.branch.BranchManager;
Expand All @@ -34,6 +35,7 @@
import java.io.UnsupportedEncodingException;
import java.lang.ref.WeakReference;

import javax.annotation.Nullable;
import javax.inject.Inject;

import de.greenrobot.event.EventBus;
Expand Down Expand Up @@ -86,6 +88,18 @@ public class ExperienceActivity extends BaseExperienceActivity implements Expone
@Inject
ExponentManifest mExponentManifest;

private DevBundleDownloadProgressListener mDevBundleDownloadProgressListener = new DevBundleDownloadProgressListener() {
@Override
public void onProgress(final @Nullable String status, final @Nullable Integer done, final @Nullable Integer total) {
UiThreadUtil.runOnUiThread(new Runnable() {
@Override
public void run() {
updateLoadingProgress(status, done, total);
}
});
}
};

/*
*
* Lifecycle
Expand Down Expand Up @@ -477,7 +491,7 @@ protected void startReactInstance() {
Exponent.getInstance().testPackagerStatus(isDebugModeEnabled(), mManifest, new Exponent.PackagerStatusCallback() {
@Override
public void onSuccess() {
mReactInstanceManager = startReactInstance(ExperienceActivity.this, mIntentUri, mLinkingPackage, mSDKVersion, mNotification, mIsShellApp, null);
mReactInstanceManager = startReactInstance(ExperienceActivity.this, mIntentUri, mLinkingPackage, mSDKVersion, mNotification, mIsShellApp, null, mDevBundleDownloadProgressListener);
}

@Override
Expand Down
50 changes: 0 additions & 50 deletions android/app/src/main/res/layout/loading_view.xml

This file was deleted.

51 changes: 23 additions & 28 deletions android/expoview/src/main/java/host/exp/exponent/LoadingView.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import android.content.Context;
import android.graphics.Color;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
Expand All @@ -15,12 +16,15 @@
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;

import org.json.JSONObject;

import java.util.Locale;

import host.exp.exponent.analytics.EXL;
import host.exp.exponent.utils.AsyncCondition;
import host.exp.exponent.utils.ColorParser;
Expand All @@ -36,7 +40,9 @@ public class LoadingView extends RelativeLayout {
ProgressBar mProgressBar;
ImageView mImageView;
ImageView mBackgroundImageView;
View mMadeForExponent;
View mStatusBarView;
TextView mStatusTextView;
TextView mPercentageTextView;

private Handler mProgressBarHandler = new Handler();
private boolean mShowIcon = false;
Expand All @@ -63,7 +69,9 @@ private void init() {
mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
mImageView = (ImageView) findViewById(R.id.image_view);
mBackgroundImageView = (ImageView) findViewById(R.id.background_image_view);
mMadeForExponent = findViewById(R.id.made_for_exponent);
mStatusBarView = findViewById(R.id.status_bar);
mStatusTextView = (TextView) findViewById(R.id.status_text_view);
mPercentageTextView = (TextView) findViewById(R.id.percentage_text_view);
setBackgroundColor(Color.WHITE);
showProgressBar();
}
Expand Down Expand Up @@ -120,20 +128,14 @@ public void setManifest(JSONObject manifest) {
mIsLoadingImageView = false;

if (manifest == null) {
revealView(mMadeForExponent);
return;
}

JSONObject loadingInfo = manifest.optJSONObject(ExponentManifest.MANIFEST_LOADING_INFO_KEY);
if (loadingInfo == null) {
revealView(mMadeForExponent);
return;
}

if (!loadingInfo.optBoolean(ExponentManifest.MANIFEST_LOADING_HIDE_EXPONENT_TEXT_KEY)) {
revealView(mMadeForExponent);
}

if (loadingInfo.has(ExponentManifest.MANIFEST_LOADING_ICON_URL)) {
mImageView.setVisibility(View.GONE);
final String iconUrl = loadingInfo.optString(ExponentManifest.MANIFEST_LOADING_ICON_URL);
Expand Down Expand Up @@ -224,42 +226,35 @@ public void execute() {
});
}

public void updateProgress(@Nullable String status, @Nullable Integer done, @Nullable Integer total) {
mStatusBarView.setVisibility(VISIBLE);
mStatusTextView.setText(status != null ? status : "Building JavaScript bundle...");
if (done != null && total != null && total > 0) {
float percent = ((float)done / (float)total * 100.f);
mPercentageTextView.setText(String.format(Locale.getDefault(), "%.2f%%", percent));
}
}

private void showIcon() {
if (!mShowIcon || !mIsLoading) {
return;
}

mImageView.clearAnimation();
mImageView.setVisibility(View.VISIBLE);

AlphaAnimation animation = new AlphaAnimation(0.0f, 1.0f);
animation.setStartOffset(50);
animation.setDuration(700);
animation.setDuration(300);
animation.setInterpolator(new AccelerateDecelerateInterpolator());
animation.setFillAfter(true);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
mImageView.setVisibility(View.VISIBLE);
}

@Override
public void onAnimationEnd(Animation animation) {
hideIcon();
}

@Override
public void onAnimationRepeat(Animation animation) {

}
});
mImageView.startAnimation(animation);
}

private void hideIcon() {
mImageView.clearAnimation();

AlphaAnimation animation = new AlphaAnimation(1.0f, 0.0f);
animation.setDuration(700);
animation.setDuration(300);
animation.setInterpolator(new AccelerateDecelerateInterpolator());
animation.setFillAfter(true);
animation.setAnimationListener(new Animation.AnimationListener() {
Expand All @@ -270,7 +265,7 @@ public void onAnimationStart(Animation animation) {

@Override
public void onAnimationEnd(Animation animation) {
showIcon();
mImageView.setVisibility(GONE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright 2015-present 650 Industries. All rights reserved.

package host.exp.exponent.experience;

import android.support.annotation.Nullable;

public interface DevBundleDownloadProgressListener {
void onProgress(@Nullable String status, @Nullable Integer done, @Nullable Integer total);
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.devsupport.DoubleTapReloadRecognizer;
import com.facebook.react.devsupport.interfaces.DevSupportManager;

import org.json.JSONArray;
import org.json.JSONException;
Expand Down Expand Up @@ -160,6 +159,10 @@ protected void stopLoading() {
mLoadingHandler.removeCallbacksAndMessages(null);
}

protected void updateLoadingProgress(String status, Integer done, Integer total) {
mLoadingView.updateProgress(status, done, total);
}

protected void removeViews() {
mContainer.removeAllViews();
}
Expand Down Expand Up @@ -346,7 +349,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {

public RNObject startReactInstance(final Exponent.StartReactInstanceDelegate delegate, final String mIntentUri, final RNObject mLinkingPackage,
final String mSDKVersion, final ExponentNotification mNotification, final boolean mIsShellApp,
final List<? extends Object> extraNativeModules) {
final List<? extends Object> extraNativeModules, DevBundleDownloadProgressListener progressListener) {

if (mIsCrashed || !delegate.isInForeground()) {
// Can sometimes get here after an error has occurred. Return early or else we'll hit
Expand Down Expand Up @@ -380,6 +383,16 @@ public RNObject startReactInstance(final Exponent.StartReactInstanceDelegate del
String debuggerHost = mManifest.optString(ExponentManifest.MANIFEST_DEBUGGER_HOST_KEY);
String mainModuleName = mManifest.optString(ExponentManifest.MANIFEST_MAIN_MODULE_NAME_KEY);
Exponent.enableDeveloperSupport(mSDKVersion, debuggerHost, mainModuleName, builder);

if (ABIVersion.toNumber(mSDKVersion) >= ABIVersion.toNumber("20.0.0")) {
RNObject devLoadingView = new RNObject("com.facebook.react.devsupport.DevLoadingViewController").loadVersion(mSDKVersion);
devLoadingView.callRecursive("setDevLoadingEnabled", false);

RNObject devBundleDownloadListener = new RNObject("host.exp.exponent.ExponentDevBundleDownloadListener")
.loadVersion(mSDKVersion)
.construct(progressListener);
builder.callRecursive("setDevBundleDownloadListener", devBundleDownloadListener.get());
}
}

Bundle bundle = new Bundle();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ protected void startReactInstance() {
@Override
public void onSuccess() {
// TODO: annoying that we need to use RNObject.UNVERSIONED here
mReactInstanceManager = startReactInstance(ExponentActivity.this, null, null, RNObject.UNVERSIONED, null, true, reactPackages());
mReactInstanceManager = startReactInstance(ExponentActivity.this, null, null, RNObject.UNVERSIONED, null, true, reactPackages(), null);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package versioned.host.exp.exponent;

import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;

import javax.annotation.Nullable;

import host.exp.exponent.experience.DevBundleDownloadProgressListener;

/**
* Acts as a bridge between the versioned DevBundleDownloadListener and unversioned
* DevBundleDownloadProgressListener
*/
public class ExponentDevBundleDownloadListener implements DevBundleDownloadListener {
private DevBundleDownloadProgressListener mListener;

public ExponentDevBundleDownloadListener(DevBundleDownloadProgressListener listener) {
mListener = listener;
}

@Override
public void onSuccess() {

}

@Override
public void onProgress(@Nullable String status, @Nullable Integer done, @Nullable Integer total) {
mListener.onProgress(status, done, total);
}

@Override
public void onFailure(Exception cause) {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:left="-1px"
android:right="-1px"
android:bottom="-1px">
<shape
android:shape="rectangle">
<stroke android:width="1px" android:color="#f3f3f3" />
<solid android:color="#fafafa" />
</shape>
</item>
</layer-list>
30 changes: 19 additions & 11 deletions android/expoview/src/main/res/layout/loading_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,27 @@
android:src="@drawable/big_logo_dark_filled"
android:visibility="gone"/>

<FrameLayout
android:id="@+id/made_for_exponent"
<LinearLayout
android:id="@+id/status_bar"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_alignParentBottom="true"
android:visibility="gone">
android:layout_height="wrap_content"
android:padding="10dp"
android:background="@drawable/loading_status_bar_background"
android:layout_alignParentBottom="true">
<TextView
android:id="@+id/status_text_view"
android:textSize="12sp"
android:textColor="#a7a7a7"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"/>

<TextView
android:id="@+id/percentage_text_view"
android:textSize="12sp"
android:textColor="#a7a7a7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Made with Exponent"
android:textColor="#cccccc"
android:textSize="14sp"/>
</FrameLayout>
android:layout_height="wrap_content"/>
</LinearLayout>
</RelativeLayout>
2 changes: 1 addition & 1 deletion ios/Exponent/Api/EXApiUtil.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ + (void)fetchAndVerifySignatureWithPublicKeyUrl:(NSURL *)publicKeyUrl
remoteUrl:publicKeyUrl
cachePath:nil];
EXCachedResourceBehavior cacheBehavior = useCache ? kEXCachedResourceUseCacheImmediately : kEXCachedResourceNoCache;
[publicKeyResource loadResourceWithBehavior:cacheBehavior successBlock:^(NSData *publicKeyData) {
[publicKeyResource loadResourceWithBehavior:cacheBehavior progressBlock:nil successBlock:^(NSData *publicKeyData) {
dispatch_async(dispatch_get_main_queue(), ^{
SecKeyRef publicKey = [self keyRefFromPEMData:publicKeyData];

Expand Down
Loading

0 comments on commit e6a3f99

Please sign in to comment.