package com.thebluealliance.androidclient.activities;
import com.thebluealliance.androidclient.BuildConfig;
import com.thebluealliance.androidclient.Constants;
import com.thebluealliance.androidclient.R;
import com.thebluealliance.androidclient.TBAAndroid;
import com.thebluealliance.androidclient.TbaLogger;
import com.thebluealliance.androidclient.accounts.AccountController;
import com.thebluealliance.androidclient.adapters.FirstLaunchPagerAdapter;
import com.thebluealliance.androidclient.auth.AuthProvider;
import com.thebluealliance.androidclient.background.LoadTBADataTaskFragment;
import com.thebluealliance.androidclient.background.firstlaunch.LoadTBAData;
import com.thebluealliance.androidclient.di.components.DaggerAuthComponent;
import com.thebluealliance.androidclient.di.components.DaggerDatafeedComponent;
import com.thebluealliance.androidclient.di.components.DatafeedComponent;
import com.thebluealliance.androidclient.di.components.HasDatafeedComponent;
import com.thebluealliance.androidclient.helpers.ConnectionDetector;
import com.thebluealliance.androidclient.views.DisableSwipeViewPager;
import com.thebluealliance.androidclient.views.MyTBAOnboardingViewPager;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import javax.inject.Inject;
import javax.inject.Named;
import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class OnboardingActivity extends AppCompatActivity
implements LoadTBAData.LoadTBADataCallbacks,
MyTBAOnboardingViewPager.Callbacks, HasDatafeedComponent {
private static final String CURRENT_LOADING_MESSAGE_KEY = "current_loading_message";
private static final String LOADING_COMPLETE = "loading_complete";
private static final String MYTBA_LOGIN_COMPLETE = "mytba_login_complete";
private static final String LOAD_FRAGMENT_TAG = "loadFragment";
private static final int SIGNIN_CODE = 254;
private DatafeedComponent mComponent;
@Bind(R.id.view_pager)
DisableSwipeViewPager viewPager;
@Bind(R.id.mytba_view_pager)
MyTBAOnboardingViewPager mMyTBAOnboardingViewPager;
@Bind(R.id.loading_message)
TextView loadingMessage;
@Bind(R.id.loading_progress_bar)
ProgressBar loadingProgressBar;
@Bind(R.id.continue_to_end)
View continueToEndButton;
private String currentLoadingMessage = "";
private LoadTBADataTaskFragment loadFragment;
private boolean isDataFinishedLoading = false;
private boolean isMyTBALoginComplete = false;
@Inject @Named("firebase_auth") AuthProvider mAuthProvider;
@Inject AccountController mAccountController;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TBAAndroid application = (TBAAndroid) getApplication();
DaggerAuthComponent.builder()
.accountModule(application.getAccountModule())
.authModule(application.getAuthModule())
.build()
.inject(this);
setContentView(R.layout.activity_onboarding);
ButterKnife.bind(this);
viewPager.setSwipeEnabled(false);
viewPager.setOffscreenPageLimit(10);
viewPager.setAdapter(new FirstLaunchPagerAdapter(this));
mMyTBAOnboardingViewPager.setCallbacks(this);
// If the activity is being recreated after a config change, restore the message that was
// being shown when the last activity was destroyed
if (savedInstanceState != null) {
if (savedInstanceState.containsKey(CURRENT_LOADING_MESSAGE_KEY)) {
currentLoadingMessage = savedInstanceState.getString(CURRENT_LOADING_MESSAGE_KEY);
loadingMessage.setText(currentLoadingMessage);
}
if (savedInstanceState.containsKey(LOADING_COMPLETE)) {
isDataFinishedLoading = savedInstanceState.getBoolean(LOADING_COMPLETE);
}
if (savedInstanceState.containsKey(MYTBA_LOGIN_COMPLETE)) {
isMyTBALoginComplete = savedInstanceState.getBoolean(MYTBA_LOGIN_COMPLETE);
}
}
loadFragment = (LoadTBADataTaskFragment) getSupportFragmentManager()
.findFragmentByTag(LOAD_FRAGMENT_TAG);
if (loadFragment != null) {
viewPager.setCurrentItem(1, false);
LoadTBAData.LoadProgressInfo info = loadFragment.getLastProgressUpdate();
if (info != null) {
if (!loadFragment.wasLastUpdateDelivered()
&& info.state != LoadTBAData.LoadProgressInfo.STATE_FINISHED) {
onProgressUpdate(info);
}
}
}
/*
If the data has already finished loading and we're being restored after an orientation
change, hide the loading indicators and show the continue button
*/
if (isDataFinishedLoading) {
loadingProgressBar.setVisibility(View.GONE);
loadingMessage.setVisibility(View.GONE);
continueToEndButton.setVisibility(View.VISIBLE);
continueToEndButton.setAlpha(1.0f);
}
if (isMyTBALoginComplete) {
mMyTBAOnboardingViewPager.setUpForLoginSuccess();
} else {
mMyTBAOnboardingViewPager.setUpForLoginPrompt();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
ButterKnife.unbind(this);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(CURRENT_LOADING_MESSAGE_KEY, currentLoadingMessage);
outState.putBoolean(LOADING_COMPLETE, isDataFinishedLoading);
outState.putBoolean(MYTBA_LOGIN_COMPLETE, isMyTBALoginComplete);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SIGNIN_CODE) {
if (resultCode == RESULT_OK) {
mAuthProvider.userFromSignInResult(requestCode, resultCode, data)
.subscribe(user -> {
TbaLogger.d("User logged in: " + user.getEmail());
mMyTBAOnboardingViewPager.setUpForLoginSuccess();
isMyTBALoginComplete = true;
mAccountController.onAccountConnect(OnboardingActivity.this, user);
}, throwable -> {
TbaLogger.e("Error logging in");
throwable.printStackTrace();
mAccountController.setMyTbaEnabled(false);
});
} else if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "Sign in canceled", Toast.LENGTH_LONG).show();
mMyTBAOnboardingViewPager.setUpForLoginPrompt();
}
}
}
@OnClick(R.id.continue_to_end)
public void onContinueToEndClient(View view) {
// If myTBA hasn't been activated yet, prompt the user one last time to sign in
if (!mMyTBAOnboardingViewPager.isOnLoginPage()) {
mMyTBAOnboardingViewPager.scrollToLoginPage();
} else if (!isMyTBALoginComplete) {
// Only show this dialog if play services are actually available
new AlertDialog.Builder(this)
.setTitle(getString(R.string.mytba_prompt_title))
.setMessage(getString(R.string.mytba_prompt_message))
.setCancelable(false)
.setPositiveButton(R.string.mytba_prompt_yes, (dialog, dialogId) -> {
// Do nothing; allow user to enable myTBA
dialog.dismiss();
})
.setNegativeButton(R.string.mytba_prompt_cancel, (dialog, dialogId) -> {
// Scroll to the last page
viewPager.setCurrentItem(2);
dialog.dismiss();
}).create().show();
} else {
viewPager.setCurrentItem(2);
}
}
@OnClick(R.id.welcome_next_page)
public void onWelcomeNextPageClick(View view) {
beginLoadingIfConnected();
}
@OnClick(R.id.finish)
public void onFinishClick(View view) {
startActivity(new Intent(this, HomeActivity.class));
finish();
}
private void beginLoadingIfConnected() {
if (ConnectionDetector.isConnectedToInternet(this)) {
viewPager.setCurrentItem(1);
beginLoading();
} else {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle(R.string.check_connection_title);
alertDialogBuilder
.setMessage(getString(R.string.warning_no_internet_connection))
.setCancelable(false)
.setPositiveButton(getString(R.string.retry), (dialog, id) -> {
beginLoadingIfConnected();
dialog.dismiss();
}).setNegativeButton(getString(R.string.cancel), (dialog, id) -> {
finish();
});
// Create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}
private void beginLoading() {
Fragment f = new LoadTBADataTaskFragment();
f.setRetainInstance(true);
getSupportFragmentManager().beginTransaction().add(f, LOAD_FRAGMENT_TAG).commit();
}
private void onError(final String stacktrace) {
PreferenceManager.getDefaultSharedPreferences(this).edit()
.putBoolean(Constants.ALL_DATA_LOADED_KEY, false)
.apply();
// Return to the first page
if (viewPager != null) {
viewPager.setCurrentItem(0);
}
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle(getString(R.string.fatal_error));
alertDialogBuilder
.setMessage(getString(R.string.fatal_error_message))
.setCancelable(false)
.setPositiveButton(R.string.contact_developer, (dialog, id) -> {
Intent emailIntent = new Intent(Intent.ACTION_SENDTO,
Uri.fromParts("mailto",
"contact@thebluealliance.com",
null));
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "FATAL ERROR");
emailIntent.putExtra(Intent.EXTRA_TEXT,
"Version: " + BuildConfig.VERSION_NAME
+ "\nStacktrace:\n" + stacktrace);
startActivity(Intent.createChooser(emailIntent,
getString(R.string.send_email)));
finish();
})
.setNegativeButton(R.string.cancel, (dialog, id) -> {
finish();
});
AlertDialog alertDialog = alertDialogBuilder.create();
try {
alertDialog.show();
} catch (WindowManager.BadTokenException e) {
// Activity is already gone. Just log the exception
TbaLogger.e("Error loading data: " + stacktrace);
e.printStackTrace();
}
}
private void onLoadFinished() {
PreferenceManager.getDefaultSharedPreferences(this).edit()
.putBoolean(Constants.ALL_DATA_LOADED_KEY, true)
.apply();
isDataFinishedLoading = true;
if (loadingMessage == null) {
return;
}
loadingMessage.setText("Loading complete");
// After two seconds, fade out the message and spinner and fade in the "continue" button
loadingMessage.postDelayed(() -> {
ValueAnimator fadeOutAnimation = ValueAnimator.ofFloat(1.0f, 0.0f);
fadeOutAnimation.addUpdateListener(animation -> {
loadingMessage.setAlpha((float) animation.getAnimatedValue());
loadingProgressBar.setAlpha((float) animation.getAnimatedValue());
});
fadeOutAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
loadingMessage.setVisibility(View.GONE);
loadingProgressBar.setVisibility(View.GONE);
}
});
fadeOutAnimation.setDuration(250);
ValueAnimator fadeInAnimation = ValueAnimator.ofFloat(0.0f, 1.0f);
fadeInAnimation.addUpdateListener(animation ->
continueToEndButton.setAlpha((float) animation.getAnimatedValue()));
fadeInAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
continueToEndButton.setAlpha(0.0f);
continueToEndButton.setVisibility(View.VISIBLE);
}
});
fadeInAnimation.setDuration(250);
AnimatorSet animationSet = new AnimatorSet();
animationSet.play(fadeOutAnimation);
animationSet.play(fadeInAnimation).after(fadeOutAnimation);
animationSet.start();
}, 2000);
}
private void onConnectionLost() {
// Scroll to first page
if (viewPager != null) {
viewPager.setCurrentItem(0);
}
// Cancel task
if (loadFragment != null) {
loadFragment.cancelTask();
}
// Show a warning
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle(R.string.connection_lost_title);
alertDialogBuilder.setMessage(getString(R.string.connection_lost)).setCancelable(false)
.setPositiveButton(getString(R.string.ok), (dialog, id) -> dialog.dismiss());
AlertDialog alertDialog = alertDialogBuilder.create();
if (!isFinishing()) {
alertDialog.show();
}
}
private void onLoadingMessageUpdated(String message) {
if (message == null) {
return;
}
currentLoadingMessage = message;
if (loadingMessage != null) {
loadingMessage.setText(message);
}
}
public void onProgressUpdate(LoadTBAData.LoadProgressInfo info) {
switch (info.state) {
case LoadTBAData.LoadProgressInfo.STATE_LOADING:
onLoadingMessageUpdated(info.message);
break;
case LoadTBAData.LoadProgressInfo.STATE_FINISHED:
onLoadFinished();
break;
case LoadTBAData.LoadProgressInfo.STATE_NO_CONNECTION:
onConnectionLost();
break;
case LoadTBAData.LoadProgressInfo.STATE_ERROR:
onError(info.message);
break;
}
}
@Override
public void onSignInButtonClicked() {
Intent signInIntent = mAuthProvider.buildSignInIntent();
if (signInIntent != null) {
startActivityForResult(signInIntent, SIGNIN_CODE);
} else {
Toast.makeText(this, R.string.mytba_no_signin_intent, Toast.LENGTH_SHORT).show();
TbaLogger.e("Unable to get login Intent");
}
}
public DatafeedComponent getComponent() {
if (mComponent == null) {
TBAAndroid application = ((TBAAndroid) getApplication());
mComponent = DaggerDatafeedComponent.builder()
.applicationComponent(application.getComponent())
.datafeedModule(application.getDatafeedModule())
.build();
}
return mComponent;
}
}