Allow manual retries of images (needs improvement)
This commit is contained in:
parent
e6c230cbe3
commit
b002a125fd
@ -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'
|
||||||
|
@ -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++)
|
||||||
|
@ -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)) {
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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) {
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -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>
|
Loading…
Reference in New Issue
Block a user