Allow manual retries of images (needs improvement)

This commit is contained in:
inorichi 2015-11-16 16:44:33 +01:00
parent e6c230cbe3
commit b002a125fd
8 changed files with 106 additions and 33 deletions

View file

@ -54,7 +54,7 @@ dependencies {
final HAMCREST_VERSION = '1.3' final HAMCREST_VERSION = '1.3'
final MOCKITO_VERSION = '1.10.19' final MOCKITO_VERSION = '1.10.19'
final STORIO_VERSION = '1.6.1' final STORIO_VERSION = '1.6.1'
final NUCLEUS_VERSION = '2.0.1' final NUCLEUS_VERSION = '2.0.3'
final ICEPICK_VERSION = '3.1.0' final ICEPICK_VERSION = '3.1.0'
compile fileTree(dir: 'libs', include: ['*.jar']) compile fileTree(dir: 'libs', include: ['*.jar'])
@ -76,8 +76,6 @@ dependencies {
compile "com.pushtorefresh.storio:sqlite:$STORIO_VERSION" compile "com.pushtorefresh.storio:sqlite:$STORIO_VERSION"
compile "com.pushtorefresh.storio:sqlite-annotations:$STORIO_VERSION" compile "com.pushtorefresh.storio:sqlite-annotations:$STORIO_VERSION"
compile "info.android15.nucleus:nucleus:$NUCLEUS_VERSION" compile "info.android15.nucleus:nucleus:$NUCLEUS_VERSION"
compile "info.android15.nucleus:nucleus-support-v4:$NUCLEUS_VERSION"
compile "info.android15.nucleus:nucleus-support-v7:$NUCLEUS_VERSION"
compile 'de.greenrobot:eventbus:2.4.0' compile 'de.greenrobot:eventbus:2.4.0'
compile 'com.github.bumptech.glide:glide:3.6.1' compile 'com.github.bumptech.glide:glide:3.6.1'
compile 'com.jakewharton:butterknife:7.0.1' compile 'com.jakewharton:butterknife:7.0.1'

View file

@ -171,9 +171,9 @@ public class DownloadManager {
.doOnNext(pages -> download.downloadedImages = 0) .doOnNext(pages -> download.downloadedImages = 0)
.doOnNext(pages -> download.setStatus(Download.DOWNLOADING)) .doOnNext(pages -> download.setStatus(Download.DOWNLOADING))
// Get all the URLs to the source images, fetch pages if necessary // Get all the URLs to the source images, fetch pages if necessary
.flatMap(pageList -> Observable.merge( .flatMap(pageList -> Observable.from(pageList)
Observable.from(pageList).filter(page -> page.getImageUrl() != null), .filter(page -> page.getImageUrl() != null)
download.source.getRemainingImageUrlsFromPageList(pageList))) .mergeWith(download.source.getRemainingImageUrlsFromPageList(pageList)))
// Start downloading images, consider we can have downloaded images already // Start downloading images, consider we can have downloaded images already
.concatMap(page -> getDownloadedImage(page, download.source, download.directory)) .concatMap(page -> getDownloadedImage(page, download.source, download.directory))
.doOnNext(p -> download.downloadedImages++) .doOnNext(p -> download.downloadedImages++)

View file

@ -101,7 +101,7 @@ public abstract class Source extends BaseSource {
.concatMap(batchedPages -> batchedPages.concatMap(this::getImageUrlFromPage)); .concatMap(batchedPages -> batchedPages.concatMap(this::getImageUrlFromPage));
} }
private Observable<Page> getImageUrlFromPage(final Page page) { public Observable<Page> getImageUrlFromPage(final Page page) {
page.setStatus(Page.LOAD_PAGE); page.setStatus(Page.LOAD_PAGE);
return mNetworkService return mNetworkService
.getStringResponse(overrideRemainingPagesUrl(page.getUrl()), mRequestHeaders, null) .getStringResponse(overrideRemainingPagesUrl(page.getUrl()), mRequestHeaders, null)
@ -118,26 +118,30 @@ public abstract class Source extends BaseSource {
} }
public Observable<Page> getCachedImage(final Page page) { public Observable<Page> getCachedImage(final Page page) {
Observable<Page> obs = Observable.just(page); Observable<Page> pageObservable = Observable.just(page);
if (page.getImageUrl() == null) if (page.getImageUrl() == null)
return obs; return pageObservable;
if (!mCacheManager.isImageInCache(page.getImageUrl())) { return pageObservable
page.setStatus(Page.DOWNLOAD_IMAGE); .flatMap(p -> {
obs = cacheImage(page); if (!mCacheManager.isImageInCache(page.getImageUrl())) {
} return cacheImage(page);
}
return obs.flatMap(p -> { return Observable.just(page);
page.setImagePath(mCacheManager.getImagePath(page.getImageUrl())); })
page.setStatus(Page.READY); .flatMap(p -> {
return Observable.just(page); page.setImagePath(mCacheManager.getImagePath(page.getImageUrl()));
}).onErrorResumeNext(e -> { page.setStatus(Page.READY);
page.setStatus(Page.ERROR); return Observable.just(page);
return Observable.just(page); })
}); .onErrorResumeNext(e -> {
page.setStatus(Page.ERROR);
return Observable.just(page);
});
} }
private Observable<Page> cacheImage(final Page page) { private Observable<Page> cacheImage(final Page page) {
page.setStatus(Page.DOWNLOAD_IMAGE);
return getImageProgressResponse(page) return getImageProgressResponse(page)
.flatMap(resp -> { .flatMap(resp -> {
if (!mCacheManager.putImageToDiskCache(page.getImageUrl(), resp)) { if (!mCacheManager.putImageToDiskCache(page.getImageUrl(), resp)) {

View file

@ -0,0 +1,17 @@
package eu.kanade.mangafeed.event;
import eu.kanade.mangafeed.data.source.model.Page;
public class RetryPageEvent {
private Page page;
public RetryPageEvent(Page page) {
this.page = page;
}
public Page getPage() {
return page;
}
}

View file

@ -15,6 +15,7 @@ import eu.kanade.mangafeed.data.download.DownloadManager;
import eu.kanade.mangafeed.data.preference.PreferencesHelper; import eu.kanade.mangafeed.data.preference.PreferencesHelper;
import eu.kanade.mangafeed.data.source.base.Source; import eu.kanade.mangafeed.data.source.base.Source;
import eu.kanade.mangafeed.data.source.model.Page; import eu.kanade.mangafeed.data.source.model.Page;
import eu.kanade.mangafeed.event.RetryPageEvent;
import eu.kanade.mangafeed.event.SourceMangaChapterEvent; import eu.kanade.mangafeed.event.SourceMangaChapterEvent;
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter; import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
import eu.kanade.mangafeed.util.EventBusHook; import eu.kanade.mangafeed.util.EventBusHook;
@ -23,6 +24,7 @@ import rx.Observable;
import rx.Subscription; import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers; import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers; import rx.schedulers.Schedulers;
import rx.subjects.PublishSubject;
import timber.log.Timber; import timber.log.Timber;
public class ReaderPresenter extends BasePresenter<ReaderActivity> { public class ReaderPresenter extends BasePresenter<ReaderActivity> {
@ -40,21 +42,29 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
private boolean isDownloaded; private boolean isDownloaded;
@State int currentPage; @State int currentPage;
private PublishSubject<Page> retryPageSubject;
private Subscription nextChapterSubscription; private Subscription nextChapterSubscription;
private Subscription previousChapterSubscription; private Subscription previousChapterSubscription;
private static final int GET_PAGE_LIST = 1; private static final int GET_PAGE_LIST = 1;
private static final int GET_PAGE_IMAGES = 2; private static final int GET_PAGE_IMAGES = 2;
private static final int RETRY_IMAGES = 3;
@Override @Override
protected void onCreate(Bundle savedState) { protected void onCreate(Bundle savedState) {
super.onCreate(savedState); super.onCreate(savedState);
retryPageSubject = PublishSubject.create();
restartableLatestCache(GET_PAGE_LIST, restartableLatestCache(GET_PAGE_LIST,
() -> getPageListObservable() () -> getPageListObservable()
.doOnNext(pages -> pageList = pages) .doOnNext(pages -> pageList = pages)
.doOnCompleted(this::getAdjacentChapters) .doOnCompleted(() -> {
.doOnCompleted(() -> start(GET_PAGE_IMAGES)), getAdjacentChapters();
start(GET_PAGE_IMAGES);
start(RETRY_IMAGES);
}),
(view, pages) -> { (view, pages) -> {
view.onPageListReady(pages); view.onPageListReady(pages);
if (currentPage != 0) if (currentPage != 0)
@ -67,6 +77,10 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
(view, page) -> {}, (view, page) -> {},
(view, error) -> Timber.e("An error occurred while downloading an image")); (view, error) -> Timber.e("An error occurred while downloading an image"));
restartableLatestCache(RETRY_IMAGES,
this::getRetryPageObservable,
(view, page) -> {},
(view, error) -> Timber.e("An error occurred while downloading an image"));
} }
@Override @Override
@ -95,6 +109,14 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
loadChapter(event.getChapter()); loadChapter(event.getChapter());
} }
@EventBusHook
public void onEventMainThread(RetryPageEvent event) {
EventBus.getDefault().removeStickyEvent(event);
Page page = event.getPage();
page.setStatus(Page.QUEUE);
retryPageSubject.onNext(page);
}
private void loadChapter(Chapter chapter) { private void loadChapter(Chapter chapter) {
this.chapter = chapter; this.chapter = chapter;
isDownloaded = isChapterDownloaded(chapter); isDownloaded = isChapterDownloaded(chapter);
@ -129,9 +151,9 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
Observable<Page> pages; Observable<Page> pages;
if (!isDownloaded) { if (!isDownloaded) {
pages = Observable pages = Observable.from(pageList)
.merge(Observable.from(pageList).filter(page -> page.getImageUrl() != null), .filter(page -> page.getImageUrl() != null)
source.getRemainingImageUrlsFromPageList(pageList)) .mergeWith(source.getRemainingImageUrlsFromPageList(pageList))
.flatMap(source::getCachedImage); .flatMap(source::getCachedImage);
} else { } else {
File chapterDir = downloadManager.getAbsoluteChapterDirectory(source, manga, chapter); File chapterDir = downloadManager.getAbsoluteChapterDirectory(source, manga, chapter);
@ -144,8 +166,15 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
.observeOn(AndroidSchedulers.mainThread()); .observeOn(AndroidSchedulers.mainThread());
} }
public void retryPage(Page page) { private Observable<Page> getRetryPageObservable() {
return retryPageSubject
.flatMap(page -> {
if (page.getImageUrl() == null)
return source.getImageUrlFromPage(page);
return Observable.just(page);
})
.flatMap(source::getCachedImage)
.subscribeOn(Schedulers.io());
} }
public void setCurrentPage(int currentPage) { public void setCurrentPage(int currentPage) {

View file

@ -33,10 +33,6 @@ public abstract class BaseReader {
return getCurrentPageIndex(currentPosition); return getCurrentPageIndex(currentPosition);
} }
public void retryPage(Page page) {
activity.getPresenter().retryPage(page);
}
public void requestNextChapter() { public void requestNextChapter() {
activity.getPresenter().setCurrentPage(getCurrentPosition()); activity.getPresenter().setCurrentPage(getCurrentPosition());
activity.getPresenter().loadNextChapter(); activity.getPresenter().loadNextChapter();

View file

@ -5,6 +5,7 @@ import android.support.annotation.Nullable;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
@ -17,8 +18,11 @@ import java.util.concurrent.atomic.AtomicInteger;
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.OnClick;
import de.greenrobot.event.EventBus;
import eu.kanade.mangafeed.R; import eu.kanade.mangafeed.R;
import eu.kanade.mangafeed.data.source.model.Page; import eu.kanade.mangafeed.data.source.model.Page;
import eu.kanade.mangafeed.event.RetryPageEvent;
import eu.kanade.mangafeed.ui.base.fragment.BaseFragment; import eu.kanade.mangafeed.ui.base.fragment.BaseFragment;
import eu.kanade.mangafeed.ui.reader.ReaderActivity; import eu.kanade.mangafeed.ui.reader.ReaderActivity;
import rx.Observable; import rx.Observable;
@ -34,6 +38,7 @@ public class ViewPagerReaderFragment extends BaseFragment {
@Bind(R.id.progress) ProgressBar progressBar; @Bind(R.id.progress) ProgressBar progressBar;
@Bind(R.id.progress_text) TextView progressText; @Bind(R.id.progress_text) TextView progressText;
@Bind(R.id.image_error) TextView errorText; @Bind(R.id.image_error) TextView errorText;
@Bind(R.id.retry_button) Button retryButton;
private Page page; private Page page;
private Subscription progressSubscription; private Subscription progressSubscription;
@ -81,6 +86,11 @@ public class ViewPagerReaderFragment extends BaseFragment {
this.page = page; this.page = page;
} }
@OnClick(R.id.retry_button)
void retry() {
EventBus.getDefault().postSticky(new RetryPageEvent(page));
}
private void showImage() { private void showImage() {
if (page == null || page.getImagePath() == null) if (page == null || page.getImagePath() == null)
return; return;
@ -90,10 +100,12 @@ public class ViewPagerReaderFragment extends BaseFragment {
} }
private void showDownloading() { private void showDownloading() {
progressContainer.setVisibility(View.VISIBLE);
progressText.setVisibility(View.VISIBLE); progressText.setVisibility(View.VISIBLE);
} }
private void showLoading() { private void showLoading() {
progressContainer.setVisibility(View.VISIBLE);
progressText.setVisibility(View.VISIBLE); progressText.setVisibility(View.VISIBLE);
progressText.setText(R.string.downloading); progressText.setText(R.string.downloading);
} }
@ -101,10 +113,19 @@ public class ViewPagerReaderFragment extends BaseFragment {
private void showError() { private void showError() {
progressContainer.setVisibility(View.GONE); progressContainer.setVisibility(View.GONE);
errorText.setVisibility(View.VISIBLE); errorText.setVisibility(View.VISIBLE);
retryButton.setVisibility(View.VISIBLE);
}
private void hideError() {
errorText.setVisibility(View.GONE);
retryButton.setVisibility(View.GONE);
} }
private void processStatus(int status) { private void processStatus(int status) {
switch (status) { switch (status) {
case Page.QUEUE:
hideError();
break;
case Page.LOAD_PAGE: case Page.LOAD_PAGE:
showLoading(); showLoading();
break; break;

View file

@ -39,6 +39,14 @@
android:textSize="32sp" android:textSize="32sp"
android:visibility="gone"/> android:visibility="gone"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/retry_button"
android:text="Retry"
android:layout_gravity="center"
android:visibility="gone"/>
<include layout="@layout/chapter_image"/> <include layout="@layout/chapter_image"/>
</FrameLayout> </FrameLayout>