package org.bookdash.android.presentation.bookinfo; import android.app.Activity; import android.content.Intent; import android.content.pm.ActivityInfo; import android.databinding.DataBindingUtil; import android.graphics.Bitmap; import android.graphics.Typeface; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.GradientDrawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.support.annotation.StringRes; import android.support.design.widget.AppBarLayout; import android.support.design.widget.CollapsingToolbarLayout; import android.support.design.widget.CoordinatorLayout; import android.support.design.widget.Snackbar; import android.support.v4.content.ContextCompat; import android.support.v4.graphics.ColorUtils; import android.support.v7.app.ActionBar; import android.support.v7.graphics.Palette; import android.support.v7.widget.CardView; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.transition.Transition; import android.util.DisplayMetrics; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewTreeObserver; import android.view.Window; import android.view.animation.AccelerateInterpolator; import android.view.animation.OvershootInterpolator; import android.widget.Button; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import com.bumptech.glide.Glide; import com.bumptech.glide.request.animation.GlideAnimation; import com.bumptech.glide.request.target.SimpleTarget; import com.firebase.ui.storage.images.FirebaseImageLoader; import com.google.firebase.storage.StorageReference; import org.bookdash.android.BookDashApplication; import org.bookdash.android.Injection; import org.bookdash.android.R; import org.bookdash.android.databinding.ActivityBookInformationBinding; import org.bookdash.android.domain.model.firebase.FireBookDetails; import org.bookdash.android.domain.model.firebase.FireContributor; import org.bookdash.android.domain.model.gson.BookPages; import org.bookdash.android.presentation.activity.BaseAppCompatActivity; import org.bookdash.android.presentation.readbook.BookDetailActivity; import java.util.List; import mbanje.kurt.fabbutton.FabButton; import rx.android.schedulers.AndroidSchedulers; import rx.schedulers.Schedulers; public class BookInfoActivity extends BaseAppCompatActivity implements BookInfoContract.View { public static final String BOOK_PARCEL = "book_parcel"; private static final String TAG = "BookInfoActivity"; /** * Presenter object */ private BookInfoContract.Presenter bookInfoPresenter; /** * Views */ private CollapsingToolbarLayout collapsingToolbarLayout; private FabButton floatingActionButton; private View gradientBackground; private RecyclerView contributorRecyclerView; private View scrollView; private ImageView imageViewBook; private AppBarLayout appBarLayout; private CoordinatorLayout coordinatorLayout; private View errorLayout; private TextView errorText; private ActivityBookInformationBinding binding; private ProgressBar loadingProgressBar; private CardView contributorCard, mainBookCard; private Toolbar toolbar; private ActionBar actionBar; private FireBookDetails bookInfo; private Button errorRetryButton; private int progress = 0; public static void startBookInfo(Activity activity, FireBookDetails bookDetails) { Intent intent = new Intent(activity, BookInfoActivity.class); intent.putExtra(BookInfoActivity.BOOK_PARCEL, bookDetails); activity.startActivity(intent); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = DataBindingUtil.setContentView(this, R.layout.activity_book_information); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { getWindow().getSharedElementReturnTransition().addListener(new Transition.TransitionListener() { @Override public void onTransitionStart(Transition transition) { floatingActionButton.animate().scaleY(0).scaleX(0).setInterpolator(new AccelerateInterpolator()) .setDuration(getResources().getInteger(android.R.integer.config_shortAnimTime)).start(); } @Override public void onTransitionEnd(Transition transition) { enterAnimation(); } @Override public void onTransitionCancel(Transition transition) { } @Override public void onTransitionPause(Transition transition) { } @Override public void onTransitionResume(Transition transition) { } }); postponeEnterTransition(); } contributorRecyclerView = (RecyclerView) findViewById(R.id.recyclerview_contributors); contributorCard = (CardView) findViewById(R.id.contributor_card); imageViewBook = (ImageView) findViewById(R.id.image_view_book_cover); appBarLayout = (AppBarLayout) findViewById(R.id.app_bar_layout); mainBookCard = (CardView) findViewById(R.id.card_view_main_book_info); toolbar = (Toolbar) findViewById(R.id.toolbar); coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinator_layout_content); errorLayout = findViewById(R.id.linear_layout_error); errorText = (TextView) findViewById(R.id.text_view_error_screen); errorRetryButton = (Button) findViewById(R.id.button_retry); loadingProgressBar = (ProgressBar) findViewById(R.id.activity_loading_book_info); setSupportActionBar(toolbar); actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); } scrollView = findViewById(R.id.scrollViewBookInfo); collapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar); gradientBackground = findViewById(R.id.toolbar_background_gradient); floatingActionButton = (FabButton) findViewById(R.id.fab_download); floatingActionButton.setScaleX(0); floatingActionButton.setScaleY(0); binding.setDownloadClick(new View.OnClickListener() { @Override public void onClick(View v) { if (bookInfo == null) { showSnackBarMessage(R.string.book_not_available); return; } if (!bookInfo.isDownloadedAlready()) { floatingActionButton.resetIcon(); floatingActionButton.showProgress(true); floatingActionButton.setProgress(0); } bookInfoPresenter.downloadBook(bookInfo); } }); bookInfoPresenter = new BookInfoPresenter(Injection.provideBookService(), Injection.provideDownloadService(), Injection.provideAnalytics(), Schedulers.io(), AndroidSchedulers.mainThread()); bookInfoPresenter.attachView(this); calculateLayoutHeight(); imageViewBook.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { imageViewBook.getViewTreeObserver().removeOnPreDrawListener(this); enterAnimation(); return true; } }); final FireBookDetails bookDetailParcelable = getIntent().getParcelableExtra(BOOK_PARCEL); if (bookDetailParcelable != null) { setBookInfoBinding(bookDetailParcelable); startLoadingBook(bookDetailParcelable); showBookDetailView(); } else { onNewIntent(getIntent()); } } private void enterAnimation() { floatingActionButton.setScaleX(0); floatingActionButton.setScaleY(0); floatingActionButton.animate().setStartDelay(500).scaleY(1).scaleX(1) .setInterpolator(new OvershootInterpolator()) .setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime)).start(); } @SuppressWarnings("SuspiciousNameCombination") private void calculateLayoutHeight() { if (getResources().getConfiguration().orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { Log.d(TAG, "Setting image height"); DisplayMetrics dMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dMetrics); CollapsingToolbarLayout.LayoutParams lp = (CollapsingToolbarLayout.LayoutParams) imageViewBook .getLayoutParams(); lp.height = dMetrics.widthPixels; imageViewBook.setLayoutParams(lp); CoordinatorLayout.LayoutParams lp2 = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams(); lp2.height = dMetrics.widthPixels; appBarLayout.setLayoutParams(lp2); } } private void startLoadingBook(final FireBookDetails bookDetailId) { errorRetryButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { bookInfoPresenter.loadContributorInformation(bookDetailId); } }); bookInfoPresenter.loadContributorInformation(bookDetailId); showBookDetailView(); } @Override public void showBookDetailView() { mainBookCard.setVisibility(View.VISIBLE); loadingProgressBar.setVisibility(View.GONE); errorLayout.setVisibility(View.GONE); coordinatorLayout.setVisibility(View.VISIBLE); scrollView.setVisibility(View.VISIBLE); floatingActionButton.setVisibility(View.VISIBLE); } protected void onNewIntent(Intent intent) { super.onNewIntent(intent); String action = intent.getAction(); String data = intent.getDataString(); Log.d(TAG, "onNewIntent() called: action" + action); if (Intent.ACTION_VIEW.equals(action) && data != null) { Uri uri = Uri.parse(data); String bookId = uri.getLastPathSegment(); String invitationId = uri.getQueryParameter("invitation_id"); Log.d(TAG, "Action View: book id:" + bookId + ". Full URL:" + uri .toString() + ". InvitationId:" + invitationId); // startLoadingBook(bookId); } } private void loadImage(StorageReference url) { Glide.with(this).using(new FirebaseImageLoader()).load(url).asBitmap().into(new SimpleTarget<Bitmap>() { @Override public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) { onImageLoaded(resource); extractPaletteColors(resource); } }); } private void onImageLoaded(Bitmap bitmap) { imageViewBook.setImageBitmap(bitmap); } private void extractPaletteColors(Bitmap resource) { Palette.from(resource).generate(new Palette.PaletteAsyncListener() { @Override public void onGenerated(Palette palette) { if (null == palette) { return; } Log.d("onGenerated", palette.toString()); Palette.Swatch toolbarSwatch = palette.getMutedSwatch(); int toolbarColor = toolbarSwatch != null ? toolbarSwatch.getRgb() : ContextCompat .getColor(getApplicationContext(), R.color.colorPrimary); int accentColor = palette .getVibrantColor(ContextCompat.getColor(getApplicationContext(), R.color.colorAccent)); setToolbarColor(toolbarColor); setAccentColor(accentColor); if (toolbarSwatch != null) { float[] darkerShade = toolbarSwatch.getHsl(); darkerShade[2] = darkerShade[2] * 0.8f; //Make it a darker shade for the status bar setStatusBarColor(ColorUtils.HSLToColor(darkerShade)); } else { setStatusBarColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimaryDark)); } } }); } private void setToolbarColor(int color) { if (collapsingToolbarLayout != null) { collapsingToolbarLayout.setStatusBarScrimColor(color); collapsingToolbarLayout.setContentScrimColor(color); } else { actionBar.setBackgroundDrawable(new ColorDrawable(color)); } floatingActionButton.setRingProgressColor(color); if (gradientBackground != null) { GradientDrawable gradientDrawable = new GradientDrawable(); gradientDrawable.setColor(color); gradientDrawable.setAlpha(140); gradientBackground.setBackground(gradientDrawable); } } private void setAccentColor(int accentColor) { floatingActionButton.setColor(accentColor); } private void setStatusBarColor(int color) { if (isFinishing()) { return; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = getWindow(); window.setStatusBarColor(color); } } @Override public void showError(String errorMessage) { loadingProgressBar.setVisibility(View.GONE); errorLayout.setVisibility(View.VISIBLE); errorText.setText(errorMessage); } @Override public void showError(@StringRes int stringRes) { showError(getString(stringRes)); } @Override public void showSnackBarMessage(final int message, final String errorDetail) { Snackbar.make(scrollView, getString(message, errorDetail), Snackbar.LENGTH_LONG).show(); } @Override public void showSnackBarMessage(int message) { Snackbar.make(scrollView, message, Snackbar.LENGTH_LONG).show(); } @Override public void showDownloadProgress(final int downloadProgress) { if (progress == downloadProgress || downloadProgress == 0) { return; } progress = downloadProgress; Log.d(TAG, "Download progress:" + downloadProgress); runOnUiThread(new Runnable() { @Override public void run() { floatingActionButton.setProgress(downloadProgress); } }); } @Override public void showDownloadFinished() { Log.d(TAG, "Download finished"); floatingActionButton.setProgress(100.0f); } @Override public void setToolbarTitle(String title) { toolbar.setTitle(title); ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setTitle(title); } if (collapsingToolbarLayout != null) { collapsingToolbarLayout.setTitle(title); } } @Override public void setBookInfoBinding(FireBookDetails bookInfo) { this.bookInfo = bookInfo; binding.setBookInfo(bookInfo); if (bookInfo.isDownloadedAlready()) { showDownloadFinished(); } loadImage(bookInfo.getFirebaseBookCoverUrl()); } @Override public void openBook(FireBookDetails bookDetail, BookPages bookPages, String location) { if (isFinishing()) { return; } Intent intent = new Intent(BookInfoActivity.this, BookDetailActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra(BookDetailActivity.BOOK_PAGES, bookPages); intent.putExtra(BookDetailActivity.BOOK_ARG, bookDetail.getBookTitle()); intent.putExtra(BookDetailActivity.LOCATION_BOOK, location); startActivity(intent); } @Override public void showContributors(List<FireContributor> list) { if (list == null || list.size() == 0) { contributorCard.setVisibility(View.GONE); return; } contributorCard.setVisibility(View.VISIBLE); ContributorAdapter contributorAdapter = new ContributorAdapter(list, this); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); contributorRecyclerView.setLayoutManager(linearLayoutManager); contributorRecyclerView.setAdapter(contributorAdapter); } @Override public void sendShareEvent(String bookTitle) { Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.sharing_book_title, bookTitle)); sendIntent.setType("text/plain"); startActivity(sendIntent); } @Override protected String getScreenName() { return "BookInfoActivity"; } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_book_info, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_share_book) { bookInfoPresenter.shareBookClicked(bookInfo); return true; } else if (id == android.R.id.home) { onBackPressed(); return true; } return super.onOptionsItemSelected(item); } @Override protected void onDestroy() { super.onDestroy(); bookInfoPresenter.detachView(); } }