1 package com.moiseum.wolnelektury.view.book;
 
   3 import android.os.Bundle;
 
   4 import android.util.Log;
 
   6 import com.folioreader.util.AppUtil;
 
   7 import com.moiseum.wolnelektury.base.WLApplication;
 
   8 import com.moiseum.wolnelektury.base.mvp.FragmentPresenter;
 
   9 import com.moiseum.wolnelektury.connection.downloads.FileCacheUtils;
 
  10 import com.moiseum.wolnelektury.connection.downloads.FileDownloadIntentService;
 
  11 import com.moiseum.wolnelektury.connection.models.BookDetailsModel;
 
  12 import com.moiseum.wolnelektury.connection.models.BookModel;
 
  13 import com.moiseum.wolnelektury.connection.models.FavouriteStateModel;
 
  14 import com.moiseum.wolnelektury.connection.models.ReadingStateModel;
 
  15 import com.moiseum.wolnelektury.connection.services.BooksService;
 
  16 import com.moiseum.wolnelektury.events.BookFavouriteEvent;
 
  17 import com.moiseum.wolnelektury.storage.BookStorage;
 
  18 import com.moiseum.wolnelektury.utils.SharedPreferencesUtils;
 
  19 import com.moiseum.wolnelektury.view.book.components.ProgressDownloadButton;
 
  21 import org.greenrobot.eventbus.EventBus;
 
  22 import org.greenrobot.eventbus.Subscribe;
 
  23 import org.greenrobot.eventbus.ThreadMode;
 
  25 import java.util.ArrayList;
 
  26 import java.util.List;
 
  28 import io.reactivex.Completable;
 
  29 import io.reactivex.Single;
 
  30 import io.reactivex.android.schedulers.AndroidSchedulers;
 
  31 import io.reactivex.schedulers.Schedulers;
 
  34  * Created by Piotr Ostrowski on 17.11.2017.
 
  37 class BookPresenter extends FragmentPresenter<BookView> {
 
  39         private static final String TAG = BookPresenter.class.getSimpleName();
 
  41         private BookDetailsModel book;
 
  42         private BookModel storedBook;
 
  43         private String bookSlug;
 
  44         private BookType bookType;
 
  46         private SharedPreferencesUtils preferences = WLApplication.getInstance().getPreferences();
 
  47         private BooksService booksService = WLApplication.getInstance().getRestClient().obtainBookService();
 
  48         private BookStorage storage = WLApplication.getInstance().getBookStorage();
 
  50         BookPresenter(String slug, BookType type, BookView view) {
 
  57         public void onViewCreated(Bundle savedInstanceState) {
 
  58                 super.onViewCreated(savedInstanceState);
 
  60                 getView().showPremiumLock(!preferences.isUserPremium() && bookType.shouldShowPremiumLock());
 
  61                 EventBus.getDefault().register(this);
 
  65         public void onResume() {
 
  67                 this.storedBook = storage.find(bookSlug);
 
  68                 if (storedBook != null && storedBook.isEbookDownloaded()) {
 
  69                         getView().changeDownloadButtonState(ProgressDownloadButton.ProgressDownloadButtonState.STATE_READING, false);
 
  70                         getView().updateReadingProgress(storedBook.getCurrentChapter(), storedBook.getTotalChapters(), false);
 
  72                 if (storedBook != null && storedBook.isAudioDownloaded()) {
 
  73                         getView().changeDownloadButtonState(ProgressDownloadButton.ProgressDownloadButtonState.STATE_READING, true);
 
  74                         getView().updateReadingProgress(storedBook.getCurrentAudioChapter(), storedBook.getTotalAudioChapters(), true);
 
  79         public void onDestroy() {
 
  81                 EventBus.getDefault().unregister(this);
 
  84         @Subscribe(threadMode = ThreadMode.MAIN)
 
  85         public void onMessageEvent(FileCacheUtils.DownloadProgressEvent event) {
 
  86                 if (event.getFileUrl().equals(book.getEpub())) {
 
  87                         int percentage = (int) ((double) event.getDownloaded() / (double) event.getTotal() * 100.0);
 
  88                         getView().changeDownloadButtonState(ProgressDownloadButton.ProgressDownloadButtonState.STATE_DOWNLOADING, false);
 
  89                         getView().showCurrentStateProgress(percentage, false);
 
  90                 } else if (book.getAudiobookFilesUrls().contains(event.getFileUrl())) {
 
  91                         ArrayList<String> filesUrls = book.getAudiobookFilesUrls();
 
  92                         int fileIndex = filesUrls.indexOf(event.getFileUrl());
 
  93                         double part = (double) event.getDownloaded() / (double) event.getTotal() / (double) filesUrls.size();
 
  94                         double completed = (double) fileIndex / (double) filesUrls.size();
 
  95                         int percentage = (int) ((part + completed) * 100.0);
 
  96                         getView().changeDownloadButtonState(ProgressDownloadButton.ProgressDownloadButtonState.STATE_DOWNLOADING, true);
 
  97                         getView().showCurrentStateProgress(percentage, true);
 
 101         @Subscribe(threadMode = ThreadMode.MAIN)
 
 102         public void onMessageEvent(FileDownloadIntentService.DownloadFileEvent event) {
 
 103                 if (event.getFileUrl().equals(book.getEpub())) {
 
 104                         if (event.isSuccess()) {
 
 105                 storeDownloadedBook(false);
 
 106                                 getView().showCurrentStateProgress(0, false);
 
 107                                 getView().changeDownloadButtonState(ProgressDownloadButton.ProgressDownloadButtonState.STATE_READING, false);
 
 110                                 getView().showCurrentStateProgress(0, false);
 
 111                                 getView().changeDownloadButtonState(ProgressDownloadButton.ProgressDownloadButtonState.STATE_INITIAL, false);
 
 112                                 getView().showDownloadFileError();
 
 114                 } else if (book.getAudiobookFilesUrls().contains(event.getFileUrl())) {
 
 115                         if (event.isSuccess()) {
 
 116                                 ArrayList<String> filesUrls = book.getAudiobookFilesUrls();
 
 117                                 int fileIndex = filesUrls.indexOf(event.getFileUrl());
 
 118                                 if (fileIndex == filesUrls.size() - 1) {
 
 119                     storeDownloadedBook(true);
 
 120                                         getView().showCurrentStateProgress(0, true);
 
 121                                         getView().changeDownloadButtonState(ProgressDownloadButton.ProgressDownloadButtonState.STATE_READING, true);
 
 124                                         int percentage = (int) ((fileIndex + 1.0) / ((double) filesUrls.size()) * 100.0);
 
 125                                         getView().changeDownloadButtonState(ProgressDownloadButton.ProgressDownloadButtonState.STATE_DOWNLOADING, true);
 
 126                                         getView().showCurrentStateProgress(percentage, true);
 
 129                                 getView().showCurrentStateProgress(0, true);
 
 130                                 getView().changeDownloadButtonState(ProgressDownloadButton.ProgressDownloadButtonState.STATE_INITIAL, true);
 
 131                                 getView().showDownloadFileError();
 
 137         void launchEbookForState(ProgressDownloadButton.ProgressDownloadButtonState state) {
 
 138                 if (state.isDownloaded()) {
 
 141                         getView().changeDownloadButtonState(ProgressDownloadButton.ProgressDownloadButtonState.STATE_DOWNLOADING, false);
 
 142                         FileDownloadIntentService.downloadFile(getView().getContext(), book.getEpub());
 
 146         void launchAudiobookForState(ProgressDownloadButton.ProgressDownloadButtonState state) {
 
 147                 if (state.isDownloaded()) {
 
 150                         getView().changeDownloadButtonState(ProgressDownloadButton.ProgressDownloadButtonState.STATE_DOWNLOADING, true);
 
 151                         FileDownloadIntentService.downloadFiles(getView().getContext(), book.getAudiobookFilesUrls());
 
 155         void reloadBookDetails() {
 
 160                 addDisposable(FileCacheUtils.deleteEbookFile(book.getEpub())
 
 161                                 .andThen(Completable.fromAction(this::updateStoredBookAfterDeletion))
 
 162                                 .subscribeOn(Schedulers.io())
 
 163                                 .observeOn(AndroidSchedulers.mainThread())
 
 165                                                 () -> getView().changeDownloadButtonState(ProgressDownloadButton.ProgressDownloadButtonState.STATE_INITIAL, false),
 
 171         void deleteAudiobook() {
 
 172                 addDisposable(FileCacheUtils.deleteAudiobookFiles(book.getAudiobookFilesUrls())
 
 173                                 .andThen(Completable.fromAction(this::updateStoredAudiobookAfterDeletion))
 
 174                                 .subscribeOn(Schedulers.io())
 
 175                                 .observeOn(AndroidSchedulers.mainThread())
 
 177                                                 () -> getView().changeDownloadButtonState(ProgressDownloadButton.ProgressDownloadButtonState.STATE_INITIAL, true),
 
 183         void onShareEbookClicked() {
 
 184                 getView().startShareActivity(book.getUrl());
 
 187         void onFavouriteEbookClicked() {
 
 188                 if (!book.getFavouriteState()) {
 
 189                         getView().startLikeClicked();
 
 190                         updateFavouriteState(true);
 
 192                         getView().stopLikeClicked();
 
 193                         updateFavouriteState(false);
 
 197         void onBackFromReader(String bookName, int currentChapter, int count) {
 
 198                 storedBook.setEbookName(bookName);
 
 199                 storedBook.setCurrentChapter(currentChapter);
 
 200                 storedBook.setTotalChapters(count);
 
 201                 storage.update(storedBook);
 
 202                 getView().updateReadingProgress(currentChapter, count, false);
 
 204                 if (currentChapter == count && book.getState() == ReadingStateModel.ReadingState.STATE_READING) {
 
 205                         updateReadingState(ReadingStateModel.ReadingState.STATE_COMPLETED);
 
 209         // ------------------------------------------------------------------------------------------------------------------------------------------
 
 211         // ------------------------------------------------------------------------------------------------------------------------------------------
 
 213         private void updateStoredBookAfterDeletion() {
 
 214                 if (!storedBook.isAudioDownloaded()) {
 
 215                         storage.remove(storedBook.getSlug(), true);
 
 220                 AppUtil.removeBookState(WLApplication.getInstance().getApplicationContext(), storedBook.getEbookName());
 
 221                 storedBook.setEbookName(null);
 
 222                 storedBook.setEbookFileUrl(null);
 
 223                 storedBook.setCurrentChapter(0);
 
 224                 storedBook.setTotalChapters(0);
 
 225                 storage.update(storedBook);
 
 228         private void updateStoredAudiobookAfterDeletion() {
 
 229                 if (!storedBook.isEbookDownloaded()) {
 
 230                         storage.remove(storedBook.getSlug(), true);
 
 235                 storedBook.setAudioFileUrls(null);
 
 236                 storedBook.setCurrentAudioChapter(0);
 
 237                 storedBook.setTotalAudioChapters(0);
 
 238                 storage.update(storedBook);
 
 241         private Single<BookDetailsModel> getBookDetails() {
 
 242                 Single<ReadingStateModel> readingStateSingle = preferences.isUserLoggedIn() ? booksService.getReadingState(bookSlug) : Single.just(new ReadingStateModel());
 
 243                 Single<FavouriteStateModel> favouriteStateModelSingle = preferences.isUserLoggedIn() ? booksService.getFavouriteState(bookSlug) : Single.just(new FavouriteStateModel());
 
 244                 Single<BookDetailsModel> bookDetailsSingle = Single.zip(
 
 246                                 favouriteStateModelSingle,
 
 247                                 booksService.getBookDetails(bookSlug),
 
 248                                 (readingStateModel, favouriteStateModel, bookDetailsModel) -> {
 
 249                                         bookDetailsModel.setState(readingStateModel.getState());
 
 250                                         bookDetailsModel.setFavouriteState(favouriteStateModel.getState());
 
 251                         return bookDetailsModel;
 
 253                 return bookDetailsSingle.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
 
 256         private void loadBookDetails() {
 
 257                 addDisposable(getBookDetails().subscribe(bookDetailsModel -> {
 
 258                         book = bookDetailsModel;
 
 259                         getView().initializeBookView(bookDetailsModel);
 
 260                 }, error -> getView().showInitializationError()));
 
 263         private void updateReadingState(ReadingStateModel.ReadingState state) {
 
 264                 if (preferences.isUserLoggedIn()) {
 
 265                         addDisposable(booksService.setReadingState(bookSlug, state.getStateName())
 
 266                                         .subscribeOn(Schedulers.io())
 
 267                                         .observeOn(AndroidSchedulers.mainThread())
 
 268                                         .subscribe(updatedState -> book.setState(updatedState.getState()), error -> Log.e(TAG, "Failed to update reading state.", error)));
 
 272         private void updateFavouriteState(boolean state) {
 
 273                 addDisposable(booksService.setFavouriteState(bookSlug, book.getFavouriteString(state))
 
 274                                 .subscribeOn(Schedulers.io())
 
 275                                 .observeOn(AndroidSchedulers.mainThread())
 
 276                                 .subscribe(updatedState -> {
 
 277                                         book.setFavouriteState(state);
 
 278                                         EventBus.getDefault().post(new BookFavouriteEvent(state));
 
 279                                 }, error -> Log.e(TAG, "Failed to update favourite state.", error)));
 
 282         private void launchFolioReader() {
 
 283                 if (book.getState() == ReadingStateModel.ReadingState.STATE_NOT_STARTED) {
 
 284                         updateReadingState(ReadingStateModel.ReadingState.STATE_READING);
 
 286                 String downloadedBookUrl = FileCacheUtils.getCachedFileForUrl(book.getEpub());
 
 287                 if (downloadedBookUrl != null) {
 
 288                         getView().openBook(downloadedBookUrl);
 
 292         private void launchAudioPlayer() {
 
 293                 if (book.getState() == ReadingStateModel.ReadingState.STATE_NOT_STARTED) {
 
 294                         updateReadingState(ReadingStateModel.ReadingState.STATE_READING);
 
 296                 getView().launchPlayer(book);
 
 299         private void storeDownloadedBook(boolean forAudiobook) {
 
 300                 BookModel stored = storedBook == null ? book.getStorageModel(bookSlug) : storedBook;
 
 302                     List<String> mediaUrls = book.getAudiobookFilesUrls();
 
 303                         stored.setAudioFileUrls(mediaUrls);
 
 304                         stored.setTotalAudioChapters(mediaUrls.size());
 
 306                         stored.setEbookFileUrl(book.getEpub());
 
 308                 if (storedBook == null) {
 
 310                         storage.add(storedBook);
 
 312                         storage.update(stored);
 
 316         public void showFavouriteButton(BookDetailsModel book) {
 
 317                 if(preferences.isUserLoggedIn()) {
 
 318                         getView().showFavouriteButton(book);