Organize ui by feature instead of layer
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.activity.base;
|
||||
package eu.kanade.mangafeed.ui.base.activity;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
+2
-1
@@ -1,9 +1,10 @@
|
||||
package eu.kanade.mangafeed.ui.activity.base;
|
||||
package eu.kanade.mangafeed.ui.base.activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import eu.kanade.mangafeed.App;
|
||||
import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
|
||||
import nucleus.factory.PresenterFactory;
|
||||
import nucleus.factory.ReflectionPresenterFactory;
|
||||
import nucleus.presenter.Presenter;
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
package eu.kanade.mangafeed.ui.fragment.base;
|
||||
package eu.kanade.mangafeed.ui.base.fragment;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
import eu.kanade.mangafeed.ui.activity.base.BaseActivity;
|
||||
import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
|
||||
|
||||
public class BaseFragment extends Fragment {
|
||||
|
||||
+2
-1
@@ -1,8 +1,9 @@
|
||||
package eu.kanade.mangafeed.ui.fragment.base;
|
||||
package eu.kanade.mangafeed.ui.base.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import eu.kanade.mangafeed.App;
|
||||
import eu.kanade.mangafeed.ui.base.fragment.BaseFragment;
|
||||
import nucleus.factory.PresenterFactory;
|
||||
import nucleus.factory.ReflectionPresenterFactory;
|
||||
import nucleus.presenter.Presenter;
|
||||
@@ -0,0 +1,36 @@
|
||||
package eu.kanade.mangafeed.ui.base.presenter;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import de.greenrobot.event.EventBus;
|
||||
import icepick.Icepick;
|
||||
import nucleus.presenter.RxPresenter;
|
||||
import nucleus.view.ViewWithPresenter;
|
||||
|
||||
public class BasePresenter<V extends ViewWithPresenter> extends RxPresenter<V> {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
Icepick.restoreInstanceState(this, savedState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSave(@NonNull Bundle state) {
|
||||
super.onSave(state);
|
||||
Icepick.saveInstanceState(this, state);
|
||||
}
|
||||
|
||||
public void registerForStickyEvents() {
|
||||
EventBus.getDefault().registerSticky(this);
|
||||
}
|
||||
|
||||
public void registerForEvents() {
|
||||
EventBus.getDefault().register(this);
|
||||
}
|
||||
|
||||
public void unregisterForEvents() {
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
}
|
||||
+5
-7
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.fragment;
|
||||
package eu.kanade.mangafeed.ui.catalogue;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
@@ -22,10 +22,8 @@ import butterknife.ButterKnife;
|
||||
import butterknife.OnItemClick;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.models.Manga;
|
||||
import eu.kanade.mangafeed.presenter.CataloguePresenter;
|
||||
import eu.kanade.mangafeed.ui.activity.MangaDetailActivity;
|
||||
import eu.kanade.mangafeed.ui.holder.CatalogueHolder;
|
||||
import eu.kanade.mangafeed.ui.fragment.base.BaseRxFragment;
|
||||
import eu.kanade.mangafeed.ui.manga.MangaActivity;
|
||||
import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment;
|
||||
import eu.kanade.mangafeed.util.PageBundle;
|
||||
import eu.kanade.mangafeed.widget.EndlessScrollListener;
|
||||
import nucleus.factory.RequiresPresenter;
|
||||
@@ -125,8 +123,8 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter> {
|
||||
public void onMangaClick(int position) {
|
||||
Manga selectedManga = adapter.getItem(position);
|
||||
|
||||
Intent intent = MangaDetailActivity.newIntent(getActivity(), selectedManga);
|
||||
intent.putExtra(MangaDetailActivity.MANGA_ONLINE, true);
|
||||
Intent intent = MangaActivity.newIntent(getActivity(), selectedManga);
|
||||
intent.putExtra(MangaActivity.MANGA_ONLINE, true);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.holder;
|
||||
package eu.kanade.mangafeed.ui.catalogue;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
@@ -0,0 +1,196 @@
|
||||
package eu.kanade.mangafeed.ui.catalogue;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.pushtorefresh.storio.sqlite.operations.put.PutResult;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import eu.kanade.mangafeed.data.helpers.DatabaseHelper;
|
||||
import eu.kanade.mangafeed.data.helpers.SourceManager;
|
||||
import eu.kanade.mangafeed.data.models.Manga;
|
||||
import eu.kanade.mangafeed.sources.base.Source;
|
||||
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
||||
import eu.kanade.mangafeed.util.PageBundle;
|
||||
import eu.kanade.mangafeed.util.RxPager;
|
||||
import icepick.State;
|
||||
import rx.Observable;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
import rx.subjects.PublishSubject;
|
||||
|
||||
public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
|
||||
|
||||
@Inject SourceManager sourceManager;
|
||||
@Inject DatabaseHelper db;
|
||||
|
||||
private Source selectedSource;
|
||||
|
||||
@State protected String mSearchName;
|
||||
@State protected boolean mSearchMode;
|
||||
private final int SEARCH_TIMEOUT = 1000;
|
||||
|
||||
private int mCurrentPage;
|
||||
private RxPager pager;
|
||||
|
||||
private Subscription mQueryDebouncerSubscription;
|
||||
private Subscription mMangaDetailFetchSubscription;
|
||||
private PublishSubject<String> mQueryDebouncerSubject;
|
||||
private PublishSubject<List<Manga>> mMangaDetailPublishSubject;
|
||||
|
||||
private static final int GET_MANGA_LIST = 1;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
|
||||
restartableReplay(GET_MANGA_LIST,
|
||||
() -> pager.pages().<PageBundle<List<Manga>>>concatMap(
|
||||
page -> getMangaObs(page + 1)
|
||||
.map(mangas -> new PageBundle<>(page, mangas))
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
),
|
||||
(view, page) -> {
|
||||
view.hideProgressBar();
|
||||
view.onAddPage(page);
|
||||
if (mMangaDetailPublishSubject != null)
|
||||
mMangaDetailPublishSubject.onNext(page.data);
|
||||
});
|
||||
|
||||
initializeSearch();
|
||||
initializeMangaDetailsLoader();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTakeView(CatalogueFragment view) {
|
||||
super.onTakeView(view);
|
||||
|
||||
view.setToolbarTitle(selectedSource.getName());
|
||||
|
||||
if (mSearchMode)
|
||||
view.restoreSearch(mSearchName);
|
||||
}
|
||||
|
||||
public void startRequesting(int sourceId) {
|
||||
selectedSource = sourceManager.get(sourceId);
|
||||
restartRequest();
|
||||
}
|
||||
|
||||
private void restartRequest() {
|
||||
stop(GET_MANGA_LIST);
|
||||
mCurrentPage = 1;
|
||||
pager = new RxPager();
|
||||
if (getView() != null)
|
||||
getView().showProgressBar();
|
||||
|
||||
start(GET_MANGA_LIST);
|
||||
}
|
||||
|
||||
public void requestNext() {
|
||||
if (getView() != null)
|
||||
getView().showGridProgressBar();
|
||||
|
||||
pager.requestNext(++mCurrentPage);
|
||||
}
|
||||
|
||||
private Observable<List<Manga>> getMangaObs(int page) {
|
||||
Observable<List<Manga>> obs;
|
||||
if (mSearchMode)
|
||||
obs = selectedSource.searchMangasFromNetwork(mSearchName, page);
|
||||
else
|
||||
obs = selectedSource.pullPopularMangasFromNetwork(page);
|
||||
|
||||
return obs.subscribeOn(Schedulers.io())
|
||||
.flatMap(Observable::from)
|
||||
.map(this::networkToLocalManga)
|
||||
.toList();
|
||||
}
|
||||
|
||||
private Manga networkToLocalManga(Manga networkManga) {
|
||||
List<Manga> dbResult = db.getManga(networkManga.url).executeAsBlocking();
|
||||
Manga localManga = !dbResult.isEmpty() ? dbResult.get(0) : null;
|
||||
if (localManga == null) {
|
||||
PutResult result = db.insertManga(networkManga).executeAsBlocking();
|
||||
networkManga.id = result.insertedId();
|
||||
localManga = networkManga;
|
||||
}
|
||||
return localManga;
|
||||
}
|
||||
|
||||
private void initializeSearch() {
|
||||
if (mQueryDebouncerSubscription != null)
|
||||
return;
|
||||
|
||||
mSearchName = "";
|
||||
mSearchMode = false;
|
||||
mQueryDebouncerSubject = PublishSubject.create();
|
||||
|
||||
add(mQueryDebouncerSubscription = mQueryDebouncerSubject
|
||||
.debounce(SEARCH_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(this::queryFromSearch));
|
||||
}
|
||||
|
||||
private void initializeMangaDetailsLoader() {
|
||||
if (mMangaDetailFetchSubscription != null)
|
||||
return;
|
||||
|
||||
mMangaDetailPublishSubject = PublishSubject.create();
|
||||
|
||||
add(mMangaDetailFetchSubscription = mMangaDetailPublishSubject
|
||||
.subscribeOn(Schedulers.io())
|
||||
.flatMap(Observable::from)
|
||||
.filter(manga -> !manga.initialized)
|
||||
.window(3)
|
||||
.concatMap(pack -> pack.concatMap(this::getMangaDetails))
|
||||
.filter(manga -> manga.initialized)
|
||||
.onBackpressureBuffer()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(manga -> {
|
||||
if (getView() != null)
|
||||
getView().updateImage(manga);
|
||||
}));
|
||||
}
|
||||
|
||||
private Observable<Manga> getMangaDetails(final Manga manga) {
|
||||
return selectedSource.pullMangaFromNetwork(manga.url)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.flatMap(networkManga -> {
|
||||
Manga.copyFromNetwork(manga, networkManga);
|
||||
db.insertManga(manga).executeAsBlocking();
|
||||
return Observable.just(manga);
|
||||
});
|
||||
}
|
||||
|
||||
public void onSearchEvent(String query, boolean now) {
|
||||
// If the query is empty or not debounced, resolve it instantly
|
||||
if (now || query.equals(""))
|
||||
queryFromSearch(query);
|
||||
else if (mQueryDebouncerSubject != null)
|
||||
mQueryDebouncerSubject.onNext(query);
|
||||
}
|
||||
|
||||
private void queryFromSearch(String query) {
|
||||
// If text didn't change, do nothing
|
||||
if (mSearchName.equals(query)) {
|
||||
return;
|
||||
}
|
||||
// If going to search mode
|
||||
else if (mSearchName.equals("") && !query.equals("")) {
|
||||
mSearchMode = true;
|
||||
}
|
||||
// If going to normal mode
|
||||
else if (!mSearchName.equals("") && query.equals("")) {
|
||||
mSearchMode = false;
|
||||
}
|
||||
|
||||
mSearchName = query;
|
||||
restartRequest();
|
||||
}
|
||||
|
||||
}
|
||||
+3
-5
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.fragment;
|
||||
package eu.kanade.mangafeed.ui.catalogue;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -13,11 +13,9 @@ import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnItemClick;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.presenter.SourcePresenter;
|
||||
import eu.kanade.mangafeed.sources.base.Source;
|
||||
import eu.kanade.mangafeed.ui.activity.MainActivity;
|
||||
import eu.kanade.mangafeed.ui.holder.SourceHolder;
|
||||
import eu.kanade.mangafeed.ui.fragment.base.BaseRxFragment;
|
||||
import eu.kanade.mangafeed.ui.main.MainActivity;
|
||||
import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment;
|
||||
import nucleus.factory.RequiresPresenter;
|
||||
import uk.co.ribot.easyadapter.EasyAdapter;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.holder;
|
||||
package eu.kanade.mangafeed.ui.catalogue;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
@@ -0,0 +1,30 @@
|
||||
package eu.kanade.mangafeed.ui.catalogue;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import eu.kanade.mangafeed.data.helpers.PreferencesHelper;
|
||||
import eu.kanade.mangafeed.data.helpers.SourceManager;
|
||||
import eu.kanade.mangafeed.sources.base.Source;
|
||||
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
||||
|
||||
|
||||
public class SourcePresenter extends BasePresenter<SourceFragment> {
|
||||
|
||||
@Inject SourceManager sourceManager;
|
||||
@Inject PreferencesHelper prefs;
|
||||
|
||||
@Override
|
||||
protected void onTakeView(SourceFragment view) {
|
||||
super.onTakeView(view);
|
||||
|
||||
view.setItems(sourceManager.getSources());
|
||||
}
|
||||
|
||||
public boolean isValidSource(Source source) {
|
||||
if (!source.isLoginRequired() || source.isLogged())
|
||||
return true;
|
||||
|
||||
return !(prefs.getSourceUsername(source).equals("")
|
||||
|| prefs.getSourcePassword(source).equals(""));
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -1,9 +1,8 @@
|
||||
package eu.kanade.mangafeed.ui.adapter;
|
||||
package eu.kanade.mangafeed.ui.download;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import eu.kanade.mangafeed.data.models.Download;
|
||||
import eu.kanade.mangafeed.ui.holder.DownloadHolder;
|
||||
import uk.co.ribot.easyadapter.EasyRecyclerAdapter;
|
||||
|
||||
public class DownloadAdapter extends EasyRecyclerAdapter<Download> {
|
||||
+6
-8
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.fragment;
|
||||
package eu.kanade.mangafeed.ui.download;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
@@ -15,20 +15,18 @@ import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.models.Download;
|
||||
import eu.kanade.mangafeed.presenter.DownloadQueuePresenter;
|
||||
import eu.kanade.mangafeed.ui.adapter.DownloadAdapter;
|
||||
import eu.kanade.mangafeed.ui.fragment.base.BaseRxFragment;
|
||||
import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment;
|
||||
import nucleus.factory.RequiresPresenter;
|
||||
|
||||
@RequiresPresenter(DownloadQueuePresenter.class)
|
||||
public class DownloadQueueFragment extends BaseRxFragment<DownloadQueuePresenter> {
|
||||
@RequiresPresenter(DownloadPresenter.class)
|
||||
public class DownloadFragment extends BaseRxFragment<DownloadPresenter> {
|
||||
|
||||
@Bind(R.id.download_list) RecyclerView downloadList;
|
||||
private LinearLayoutManager downloadListLayout;
|
||||
private DownloadAdapter adapter;
|
||||
|
||||
public static DownloadQueueFragment newInstance() {
|
||||
return new DownloadQueueFragment();
|
||||
public static DownloadFragment newInstance() {
|
||||
return new DownloadFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.holder;
|
||||
package eu.kanade.mangafeed.ui.download;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
@@ -0,0 +1,163 @@
|
||||
package eu.kanade.mangafeed.ui.download;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import eu.kanade.mangafeed.data.helpers.DownloadManager;
|
||||
import eu.kanade.mangafeed.data.models.Download;
|
||||
import eu.kanade.mangafeed.data.models.DownloadQueue;
|
||||
import eu.kanade.mangafeed.data.models.Page;
|
||||
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
||||
import rx.Observable;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
import rx.subjects.PublishSubject;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class DownloadPresenter extends BasePresenter<DownloadFragment> {
|
||||
|
||||
@Inject DownloadManager downloadManager;
|
||||
|
||||
private DownloadQueue downloadQueue;
|
||||
private Subscription statusSubscription;
|
||||
private HashMap<Download, Subscription> progressSubscriptions;
|
||||
private HashMap<Download, Subscription> pageStatusSubscriptions;
|
||||
|
||||
public final static int GET_DOWNLOAD_QUEUE = 1;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
|
||||
downloadQueue = downloadManager.getQueue();
|
||||
progressSubscriptions = new HashMap<>();
|
||||
pageStatusSubscriptions = new HashMap<>();
|
||||
|
||||
restartableLatestCache(GET_DOWNLOAD_QUEUE,
|
||||
() -> Observable.just(downloadQueue.get()),
|
||||
DownloadFragment::onNextDownloads,
|
||||
(view, error) -> Timber.e(error.getMessage()));
|
||||
|
||||
if (savedState == null)
|
||||
start(GET_DOWNLOAD_QUEUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTakeView(DownloadFragment view) {
|
||||
super.onTakeView(view);
|
||||
|
||||
add(statusSubscription = downloadQueue.getStatusObservable()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(download -> {
|
||||
processStatus(download, view);
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDropView() {
|
||||
destroySubscriptions();
|
||||
super.onDropView();
|
||||
}
|
||||
|
||||
private void processStatus(Download download, DownloadFragment view) {
|
||||
switch (download.getStatus()) {
|
||||
case Download.DOWNLOADING:
|
||||
observeProgress(download, view);
|
||||
observePagesStatus(download, view);
|
||||
break;
|
||||
case Download.DOWNLOADED:
|
||||
unsubscribeProgress(download);
|
||||
unsubscribePagesStatus(download);
|
||||
view.updateProgress(download);
|
||||
view.updateDownloadedPages(download);
|
||||
break;
|
||||
case Download.ERROR:
|
||||
unsubscribeProgress(download);
|
||||
unsubscribePagesStatus(download);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void observeProgress(Download download, DownloadFragment view) {
|
||||
Subscription subscription = Observable.interval(50, TimeUnit.MILLISECONDS, Schedulers.newThread())
|
||||
.flatMap(tick -> Observable.from(download.pages)
|
||||
.map(Page::getProgress)
|
||||
.reduce((x, y) -> x + y))
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(progress -> {
|
||||
if (download.totalProgress != progress) {
|
||||
download.totalProgress = progress;
|
||||
view.updateProgress(download);
|
||||
}
|
||||
});
|
||||
|
||||
// Avoid leaking subscriptions
|
||||
Subscription oldSubscription = progressSubscriptions.remove(download);
|
||||
if (oldSubscription != null) oldSubscription.unsubscribe();
|
||||
|
||||
progressSubscriptions.put(download, subscription);
|
||||
}
|
||||
|
||||
private void observePagesStatus(Download download, DownloadFragment view) {
|
||||
PublishSubject<Integer> pageStatusSubject = PublishSubject.create();
|
||||
for (Page page : download.pages) {
|
||||
if (page.getStatus() != Page.READY)
|
||||
page.setStatusSubject(pageStatusSubject);
|
||||
}
|
||||
|
||||
Subscription subscription = pageStatusSubject
|
||||
.filter(status -> status == Page.READY)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(status -> {
|
||||
view.updateDownloadedPages(download);
|
||||
});
|
||||
|
||||
// Avoid leaking subscriptions
|
||||
Subscription oldSubscription = pageStatusSubscriptions.remove(download);
|
||||
if (oldSubscription != null) oldSubscription.unsubscribe();
|
||||
|
||||
pageStatusSubscriptions.put(download, subscription);
|
||||
}
|
||||
|
||||
private void unsubscribeProgress(Download download) {
|
||||
Subscription subscription = progressSubscriptions.remove(download);
|
||||
if (subscription != null)
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
|
||||
private void unsubscribePagesStatus(Download download) {
|
||||
if (download.pages != null) {
|
||||
for (Page page : download.pages)
|
||||
page.setStatusSubject(null);
|
||||
}
|
||||
|
||||
Subscription subscription = pageStatusSubscriptions.remove(download);
|
||||
if (subscription != null)
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
|
||||
private void destroySubscriptions() {
|
||||
for (Download download : pageStatusSubscriptions.keySet()) {
|
||||
for (Page page : download.pages)
|
||||
page.setStatusSubject(null);
|
||||
}
|
||||
for (Subscription subscription : pageStatusSubscriptions.values()) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
pageStatusSubscriptions.clear();
|
||||
|
||||
for (Subscription subscription : progressSubscriptions.values()) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
progressSubscriptions.clear();
|
||||
|
||||
remove(statusSubscription);
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.adapter;
|
||||
package eu.kanade.mangafeed.ui.library;
|
||||
|
||||
import android.content.Context;
|
||||
import android.widget.Filter;
|
||||
@@ -7,7 +7,7 @@ import android.widget.Filterable;
|
||||
import java.util.List;
|
||||
|
||||
import eu.kanade.mangafeed.data.models.Manga;
|
||||
import eu.kanade.mangafeed.ui.holder.LibraryHolder;
|
||||
import eu.kanade.mangafeed.ui.library.LibraryHolder;
|
||||
import rx.Observable;
|
||||
import uk.co.ribot.easyadapter.EasyAdapter;
|
||||
|
||||
+4
-6
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.fragment;
|
||||
package eu.kanade.mangafeed.ui.library;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
@@ -20,10 +20,8 @@ import butterknife.OnItemClick;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.models.Manga;
|
||||
import eu.kanade.mangafeed.data.services.LibraryUpdateService;
|
||||
import eu.kanade.mangafeed.presenter.LibraryPresenter;
|
||||
import eu.kanade.mangafeed.ui.activity.MangaDetailActivity;
|
||||
import eu.kanade.mangafeed.ui.adapter.LibraryAdapter;
|
||||
import eu.kanade.mangafeed.ui.fragment.base.BaseRxFragment;
|
||||
import eu.kanade.mangafeed.ui.manga.MangaActivity;
|
||||
import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment;
|
||||
import nucleus.factory.RequiresPresenter;
|
||||
|
||||
@RequiresPresenter(LibraryPresenter.class)
|
||||
@@ -107,7 +105,7 @@ public class LibraryFragment extends BaseRxFragment<LibraryPresenter> {
|
||||
|
||||
@OnItemClick(R.id.gridView)
|
||||
protected void onMangaClick(int position) {
|
||||
Intent intent = MangaDetailActivity.newIntent(
|
||||
Intent intent = MangaActivity.newIntent(
|
||||
getActivity(),
|
||||
adapter.getItem(position)
|
||||
);
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.holder;
|
||||
package eu.kanade.mangafeed.ui.library;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
@@ -0,0 +1,63 @@
|
||||
package eu.kanade.mangafeed.ui.library;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.SparseBooleanArray;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import eu.kanade.mangafeed.data.helpers.DatabaseHelper;
|
||||
import eu.kanade.mangafeed.data.helpers.PreferencesHelper;
|
||||
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
||||
import rx.Observable;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
public class LibraryPresenter extends BasePresenter<LibraryFragment> {
|
||||
|
||||
@Inject DatabaseHelper db;
|
||||
@Inject PreferencesHelper prefs;
|
||||
|
||||
private Subscription mFavoriteMangasSubscription;
|
||||
private Subscription mDeleteMangaSubscription;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTakeView(LibraryFragment view) {
|
||||
super.onTakeView(view);
|
||||
getFavoriteMangas();
|
||||
}
|
||||
|
||||
public void getFavoriteMangas() {
|
||||
if (mFavoriteMangasSubscription != null)
|
||||
return;
|
||||
|
||||
add(mFavoriteMangasSubscription = db.getMangasWithUnread().createObservable()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.compose(deliverLatestCache())
|
||||
.subscribe(this.split(LibraryFragment::onNextMangas)));
|
||||
}
|
||||
|
||||
public void onDelete(SparseBooleanArray checkedItems, LibraryAdapter adapter) {
|
||||
if (mDeleteMangaSubscription != null)
|
||||
remove(mDeleteMangaSubscription);
|
||||
|
||||
add(mDeleteMangaSubscription = Observable.range(0, checkedItems.size())
|
||||
.observeOn(Schedulers.io())
|
||||
.map(checkedItems::keyAt)
|
||||
.map(adapter::getItem)
|
||||
.map(manga -> {
|
||||
manga.favorite = false;
|
||||
return manga;
|
||||
})
|
||||
.toList()
|
||||
.flatMap(mangas -> db.insertMangas(mangas).createObservable())
|
||||
.subscribe());
|
||||
}
|
||||
|
||||
}
|
||||
+7
-6
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.activity;
|
||||
package eu.kanade.mangafeed.ui.main;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
@@ -14,10 +14,11 @@ import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.ui.activity.base.BaseActivity;
|
||||
import eu.kanade.mangafeed.ui.fragment.DownloadQueueFragment;
|
||||
import eu.kanade.mangafeed.ui.fragment.LibraryFragment;
|
||||
import eu.kanade.mangafeed.ui.fragment.SourceFragment;
|
||||
import eu.kanade.mangafeed.ui.preference.SettingsActivity;
|
||||
import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
|
||||
import eu.kanade.mangafeed.ui.download.DownloadFragment;
|
||||
import eu.kanade.mangafeed.ui.library.LibraryFragment;
|
||||
import eu.kanade.mangafeed.ui.catalogue.SourceFragment;
|
||||
|
||||
public class MainActivity extends BaseActivity {
|
||||
|
||||
@@ -75,7 +76,7 @@ public class MainActivity extends BaseActivity {
|
||||
setFragment(SourceFragment.newInstance());
|
||||
break;
|
||||
case R.id.nav_drawer_downloads:
|
||||
setFragment(DownloadQueueFragment.newInstance());
|
||||
setFragment(DownloadFragment.newInstance());
|
||||
break;
|
||||
case R.id.nav_drawer_settings:
|
||||
startActivity(new Intent(this, SettingsActivity.class));
|
||||
+8
-9
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.activity;
|
||||
package eu.kanade.mangafeed.ui.manga;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -16,14 +16,13 @@ import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.models.Manga;
|
||||
import eu.kanade.mangafeed.presenter.MangaDetailPresenter;
|
||||
import eu.kanade.mangafeed.ui.activity.base.BaseRxActivity;
|
||||
import eu.kanade.mangafeed.ui.fragment.MangaChaptersFragment;
|
||||
import eu.kanade.mangafeed.ui.fragment.MangaInfoFragment;
|
||||
import eu.kanade.mangafeed.ui.base.activity.BaseRxActivity;
|
||||
import eu.kanade.mangafeed.ui.manga.chapter.ChaptersFragment;
|
||||
import eu.kanade.mangafeed.ui.manga.info.MangaInfoFragment;
|
||||
import nucleus.factory.RequiresPresenter;
|
||||
|
||||
@RequiresPresenter(MangaDetailPresenter.class)
|
||||
public class MangaDetailActivity extends BaseRxActivity<MangaDetailPresenter> {
|
||||
@RequiresPresenter(MangaPresenter.class)
|
||||
public class MangaActivity extends BaseRxActivity<MangaPresenter> {
|
||||
|
||||
@Bind(R.id.toolbar) Toolbar toolbar;
|
||||
@Bind(R.id.tabs) TabLayout tabs;
|
||||
@@ -37,7 +36,7 @@ public class MangaDetailActivity extends BaseRxActivity<MangaDetailPresenter> {
|
||||
public final static String MANGA_ONLINE = "manga_online";
|
||||
|
||||
public static Intent newIntent(Context context, Manga manga) {
|
||||
Intent intent = new Intent(context, MangaDetailActivity.class);
|
||||
Intent intent = new Intent(context, MangaActivity.class);
|
||||
intent.putExtra(MANGA_ID, manga.id);
|
||||
return intent;
|
||||
}
|
||||
@@ -127,7 +126,7 @@ public class MangaDetailActivity extends BaseRxActivity<MangaDetailPresenter> {
|
||||
case INFO_FRAGMENT:
|
||||
return MangaInfoFragment.newInstance();
|
||||
case CHAPTERS_FRAGMENT:
|
||||
return MangaChaptersFragment.newInstance();
|
||||
return ChaptersFragment.newInstance();
|
||||
|
||||
default:
|
||||
return null;
|
||||
@@ -0,0 +1,56 @@
|
||||
package eu.kanade.mangafeed.ui.manga;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import de.greenrobot.event.EventBus;
|
||||
import eu.kanade.mangafeed.data.helpers.DatabaseHelper;
|
||||
import eu.kanade.mangafeed.data.models.Manga;
|
||||
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
||||
import rx.Observable;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
public class MangaPresenter extends BasePresenter<MangaActivity> {
|
||||
|
||||
@Inject DatabaseHelper db;
|
||||
|
||||
private long mangaId;
|
||||
private Manga manga;
|
||||
|
||||
private static final int DB_MANGA = 1;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
|
||||
restartableLatestCache(DB_MANGA,
|
||||
() -> getDbMangaObservable()
|
||||
.doOnNext(manga -> this.manga = manga),
|
||||
(view, manga) -> {
|
||||
view.setManga(manga);
|
||||
EventBus.getDefault().postSticky(manga);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
// Avoid fragments receiving wrong manga
|
||||
EventBus.getDefault().removeStickyEvent(Manga.class);
|
||||
}
|
||||
|
||||
private Observable<Manga> getDbMangaObservable() {
|
||||
return db.getManga(mangaId).createObservable()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.flatMap(Observable::from)
|
||||
.observeOn(AndroidSchedulers.mainThread());
|
||||
}
|
||||
|
||||
public void queryManga(long mangaId) {
|
||||
this.mangaId = mangaId;
|
||||
start(DB_MANGA);
|
||||
}
|
||||
|
||||
}
|
||||
+4
-6
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.adapter;
|
||||
package eu.kanade.mangafeed.ui.manga.chapter;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@@ -10,9 +10,7 @@ import java.util.List;
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.models.Chapter;
|
||||
import eu.kanade.mangafeed.ui.fragment.MangaChaptersFragment;
|
||||
import eu.kanade.mangafeed.ui.fragment.base.BaseFragment;
|
||||
import eu.kanade.mangafeed.ui.holder.ChaptersHolder;
|
||||
import eu.kanade.mangafeed.ui.base.fragment.BaseFragment;
|
||||
|
||||
public class ChaptersAdapter extends FlexibleAdapter<ChaptersHolder, Chapter> {
|
||||
|
||||
@@ -50,7 +48,7 @@ public class ChaptersAdapter extends FlexibleAdapter<ChaptersHolder, Chapter> {
|
||||
void onListItemLongClick(int position);
|
||||
}
|
||||
|
||||
public MangaChaptersFragment getMangaChaptersFragment() {
|
||||
return (MangaChaptersFragment) fragment;
|
||||
public ChaptersFragment getMangaChaptersFragment() {
|
||||
return (ChaptersFragment) fragment;
|
||||
}
|
||||
}
|
||||
+10
-12
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.fragment;
|
||||
package eu.kanade.mangafeed.ui.manga.chapter;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
@@ -20,17 +20,15 @@ import butterknife.ButterKnife;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.models.Chapter;
|
||||
import eu.kanade.mangafeed.data.services.DownloadService;
|
||||
import eu.kanade.mangafeed.presenter.MangaChaptersPresenter;
|
||||
import eu.kanade.mangafeed.ui.activity.MangaDetailActivity;
|
||||
import eu.kanade.mangafeed.ui.activity.ReaderActivity;
|
||||
import eu.kanade.mangafeed.ui.activity.base.BaseActivity;
|
||||
import eu.kanade.mangafeed.ui.adapter.ChaptersAdapter;
|
||||
import eu.kanade.mangafeed.ui.fragment.base.BaseRxFragment;
|
||||
import eu.kanade.mangafeed.ui.manga.MangaActivity;
|
||||
import eu.kanade.mangafeed.ui.reader.ReaderActivity;
|
||||
import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
|
||||
import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment;
|
||||
import nucleus.factory.RequiresPresenter;
|
||||
import rx.Observable;
|
||||
|
||||
@RequiresPresenter(MangaChaptersPresenter.class)
|
||||
public class MangaChaptersFragment extends BaseRxFragment<MangaChaptersPresenter> implements
|
||||
@RequiresPresenter(ChaptersPresenter.class)
|
||||
public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implements
|
||||
ActionMode.Callback, ChaptersAdapter.OnItemClickListener {
|
||||
|
||||
@Bind(R.id.chapter_list) RecyclerView chapters;
|
||||
@@ -40,8 +38,8 @@ public class MangaChaptersFragment extends BaseRxFragment<MangaChaptersPresenter
|
||||
|
||||
private ActionMode actionMode;
|
||||
|
||||
public static MangaChaptersFragment newInstance() {
|
||||
return new MangaChaptersFragment();
|
||||
public static ChaptersFragment newInstance() {
|
||||
return new ChaptersFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -103,7 +101,7 @@ public class MangaChaptersFragment extends BaseRxFragment<MangaChaptersPresenter
|
||||
}
|
||||
|
||||
public boolean isOnlineManga() {
|
||||
return ((MangaDetailActivity)getActivity()).isOnlineManga();
|
||||
return ((MangaActivity)getActivity()).isOnlineManga();
|
||||
}
|
||||
|
||||
@Override
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.holder;
|
||||
package eu.kanade.mangafeed.ui.manga.chapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
@@ -12,7 +12,7 @@ import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.models.Chapter;
|
||||
import eu.kanade.mangafeed.ui.adapter.ChaptersAdapter;
|
||||
import eu.kanade.mangafeed.ui.manga.chapter.ChaptersAdapter;
|
||||
|
||||
public class ChaptersHolder extends RecyclerView.ViewHolder implements
|
||||
View.OnClickListener, View.OnLongClickListener {
|
||||
@@ -0,0 +1,166 @@
|
||||
package eu.kanade.mangafeed.ui.manga.chapter;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import de.greenrobot.event.EventBus;
|
||||
import eu.kanade.mangafeed.data.helpers.DatabaseHelper;
|
||||
import eu.kanade.mangafeed.data.helpers.DownloadManager;
|
||||
import eu.kanade.mangafeed.data.helpers.PreferencesHelper;
|
||||
import eu.kanade.mangafeed.data.helpers.SourceManager;
|
||||
import eu.kanade.mangafeed.data.models.Chapter;
|
||||
import eu.kanade.mangafeed.data.models.Manga;
|
||||
import eu.kanade.mangafeed.events.ChapterCountEvent;
|
||||
import eu.kanade.mangafeed.events.DownloadChaptersEvent;
|
||||
import eu.kanade.mangafeed.events.SourceMangaChapterEvent;
|
||||
import eu.kanade.mangafeed.sources.base.Source;
|
||||
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
||||
import eu.kanade.mangafeed.util.EventBusHook;
|
||||
import eu.kanade.mangafeed.util.PostResult;
|
||||
import rx.Observable;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
public class ChaptersPresenter extends BasePresenter<ChaptersFragment> {
|
||||
|
||||
@Inject DatabaseHelper db;
|
||||
@Inject SourceManager sourceManager;
|
||||
@Inject PreferencesHelper preferences;
|
||||
@Inject DownloadManager downloadManager;
|
||||
|
||||
private Manga manga;
|
||||
private Source source;
|
||||
|
||||
private static final int DB_CHAPTERS = 1;
|
||||
private static final int ONLINE_CHAPTERS = 2;
|
||||
|
||||
private Subscription markReadSubscription;
|
||||
private Subscription downloadSubscription;
|
||||
private Subscription deleteSubscription;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
|
||||
restartableLatestCache(DB_CHAPTERS,
|
||||
this::getDbChaptersObs,
|
||||
(view, chapters) -> {
|
||||
view.onNextChapters(chapters);
|
||||
EventBus.getDefault().postSticky( new ChapterCountEvent(chapters.size()) );
|
||||
}
|
||||
);
|
||||
|
||||
restartableLatestCache(ONLINE_CHAPTERS,
|
||||
this::getOnlineChaptersObs,
|
||||
(view, result) -> view.onNextOnlineChapters()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTakeView(ChaptersFragment view) {
|
||||
super.onTakeView(view);
|
||||
registerForStickyEvents();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDropView() {
|
||||
unregisterForEvents();
|
||||
super.onDropView();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
EventBus.getDefault().removeStickyEvent(ChapterCountEvent.class);
|
||||
}
|
||||
|
||||
@EventBusHook
|
||||
public void onEventMainThread(Manga manga) {
|
||||
if (this.manga == null) {
|
||||
this.manga = manga;
|
||||
source = sourceManager.get(manga.source);
|
||||
start(DB_CHAPTERS);
|
||||
|
||||
// Get chapters if it's an online source
|
||||
if (getView() != null && getView().isOnlineManga()) {
|
||||
refreshChapters();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshChapters() {
|
||||
if (getView() != null)
|
||||
getView().setSwipeRefreshing();
|
||||
|
||||
start(ONLINE_CHAPTERS);
|
||||
}
|
||||
|
||||
private Observable<List<Chapter>> getDbChaptersObs() {
|
||||
return db.getChapters(manga.id).createObservable()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread());
|
||||
}
|
||||
|
||||
private Observable<PostResult> getOnlineChaptersObs() {
|
||||
return source
|
||||
.pullChaptersFromNetwork(manga.url)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.flatMap(chapters -> db.insertOrRemoveChapters(manga, chapters))
|
||||
.observeOn(AndroidSchedulers.mainThread());
|
||||
}
|
||||
|
||||
public void onChapterClicked(Chapter chapter) {
|
||||
EventBus.getDefault().postSticky(new SourceMangaChapterEvent(source, manga, chapter));
|
||||
}
|
||||
|
||||
public void markChaptersRead(Observable<Chapter> selectedChapters, boolean read) {
|
||||
add(markReadSubscription = selectedChapters
|
||||
.subscribeOn(Schedulers.io())
|
||||
.map(chapter -> {
|
||||
chapter.read = read;
|
||||
return chapter;
|
||||
})
|
||||
.toList()
|
||||
.flatMap(chapters -> db.insertChapters(chapters).createObservable())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnCompleted(() -> remove(markReadSubscription))
|
||||
.subscribe(result -> {
|
||||
}));
|
||||
}
|
||||
|
||||
public void downloadChapters(Observable<Chapter> selectedChapters) {
|
||||
add(downloadSubscription = selectedChapters
|
||||
.toList()
|
||||
.subscribe(chapters -> {
|
||||
EventBus.getDefault().postSticky(new DownloadChaptersEvent(manga, chapters));
|
||||
remove(downloadSubscription);
|
||||
}));
|
||||
}
|
||||
|
||||
public void deleteChapters(Observable<Chapter> selectedChapters) {
|
||||
deleteSubscription = selectedChapters
|
||||
.doOnCompleted( () -> remove(deleteSubscription) )
|
||||
.subscribe(chapter -> {
|
||||
downloadManager.deleteChapter(source, manga, chapter);
|
||||
chapter.downloaded = Chapter.NOT_DOWNLOADED;
|
||||
});
|
||||
}
|
||||
|
||||
public void checkIsChapterDownloaded(Chapter chapter) {
|
||||
File dir = downloadManager.getAbsoluteChapterDirectory(source, manga, chapter);
|
||||
File pageList = new File(dir, DownloadManager.PAGE_LIST_FILE);
|
||||
|
||||
if (dir.exists() && pageList.exists() && downloadManager
|
||||
.getSavedPageList(source, manga, chapter).size() + 1 == dir.listFiles().length) {
|
||||
chapter.downloaded = Chapter.DOWNLOADED;
|
||||
} else {
|
||||
chapter.downloaded = Chapter.NOT_DOWNLOADED;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+2
-3
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.fragment;
|
||||
package eu.kanade.mangafeed.ui.manga.info;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -17,8 +17,7 @@ import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.models.Manga;
|
||||
import eu.kanade.mangafeed.presenter.MangaInfoPresenter;
|
||||
import eu.kanade.mangafeed.ui.fragment.base.BaseRxFragment;
|
||||
import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment;
|
||||
import nucleus.factory.RequiresPresenter;
|
||||
|
||||
@RequiresPresenter(MangaInfoPresenter.class)
|
||||
@@ -0,0 +1,73 @@
|
||||
package eu.kanade.mangafeed.ui.manga.info;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import eu.kanade.mangafeed.data.helpers.DatabaseHelper;
|
||||
import eu.kanade.mangafeed.data.models.Manga;
|
||||
import eu.kanade.mangafeed.events.ChapterCountEvent;
|
||||
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
||||
import eu.kanade.mangafeed.util.EventBusHook;
|
||||
import rx.Observable;
|
||||
|
||||
public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
|
||||
|
||||
@Inject DatabaseHelper db;
|
||||
|
||||
private Manga manga;
|
||||
private int count = -1;
|
||||
|
||||
private static final int GET_MANGA = 1;
|
||||
private static final int GET_CHAPTER_COUNT = 2;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
|
||||
restartableLatestCache(GET_MANGA,
|
||||
() -> Observable.just(manga),
|
||||
MangaInfoFragment::setMangaInfo);
|
||||
|
||||
restartableLatestCache(GET_CHAPTER_COUNT,
|
||||
() -> Observable.just(count),
|
||||
MangaInfoFragment::setChapterCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTakeView(MangaInfoFragment view) {
|
||||
super.onTakeView(view);
|
||||
registerForStickyEvents();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDropView() {
|
||||
unregisterForEvents();
|
||||
super.onDropView();
|
||||
}
|
||||
|
||||
@EventBusHook
|
||||
public void onEventMainThread(Manga manga) {
|
||||
this.manga = manga;
|
||||
start(GET_MANGA);
|
||||
}
|
||||
|
||||
@EventBusHook
|
||||
public void onEventMainThread(ChapterCountEvent event) {
|
||||
if (count != event.getCount()) {
|
||||
count = event.getCount();
|
||||
start(GET_CHAPTER_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
public void initFavoriteIcon() {
|
||||
if (getView() != null)
|
||||
getView().setFavoriteIcon(manga.favorite);
|
||||
}
|
||||
|
||||
public void toggleFavorite() {
|
||||
manga.favorite = !manga.favorite;
|
||||
db.insertManga(manga).executeAsBlocking();
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.dialog;
|
||||
package eu.kanade.mangafeed.ui.preference;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
+2
-3
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.fragment;
|
||||
package eu.kanade.mangafeed.ui.preference;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceFragment;
|
||||
@@ -13,8 +13,7 @@ import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.helpers.PreferencesHelper;
|
||||
import eu.kanade.mangafeed.data.helpers.SourceManager;
|
||||
import eu.kanade.mangafeed.sources.base.Source;
|
||||
import eu.kanade.mangafeed.ui.activity.base.BaseActivity;
|
||||
import eu.kanade.mangafeed.ui.dialog.LoginDialogPreference;
|
||||
import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
|
||||
import rx.Observable;
|
||||
|
||||
public class SettingsAccountsFragment extends PreferenceFragment {
|
||||
+2
-3
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.activity;
|
||||
package eu.kanade.mangafeed.ui.preference;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
@@ -7,8 +7,7 @@ import android.view.MenuItem;
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.ui.activity.base.BaseActivity;
|
||||
import eu.kanade.mangafeed.ui.fragment.SettingsMainFragment;
|
||||
import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
|
||||
|
||||
public class SettingsActivity extends BaseActivity {
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.fragment;
|
||||
package eu.kanade.mangafeed.ui.preference;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.preference.ListPreference;
|
||||
@@ -10,7 +10,7 @@ import javax.inject.Inject;
|
||||
import eu.kanade.mangafeed.App;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.helpers.PreferencesHelper;
|
||||
import eu.kanade.mangafeed.ui.activity.base.BaseActivity;
|
||||
import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
|
||||
import eu.kanade.mangafeed.util.DiskUtils;
|
||||
|
||||
public class SettingsDownloadsFragment extends PreferenceFragment {
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
package eu.kanade.mangafeed.ui.fragment;
|
||||
package eu.kanade.mangafeed.ui.preference;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceFragment;
|
||||
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.ui.activity.base.BaseActivity;
|
||||
import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
|
||||
|
||||
public class SettingsMainFragment extends PreferenceFragment {
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
package eu.kanade.mangafeed.ui.fragment;
|
||||
package eu.kanade.mangafeed.ui.preference;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceFragment;
|
||||
|
||||
import eu.kanade.mangafeed.ui.activity.base.BaseActivity;
|
||||
import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
|
||||
|
||||
public class SettingsNestedFragment extends PreferenceFragment {
|
||||
|
||||
+13
-14
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.activity;
|
||||
package eu.kanade.mangafeed.ui.reader;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -20,13 +20,12 @@ import eu.kanade.mangafeed.App;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.helpers.PreferencesHelper;
|
||||
import eu.kanade.mangafeed.data.models.Page;
|
||||
import eu.kanade.mangafeed.presenter.ReaderPresenter;
|
||||
import eu.kanade.mangafeed.ui.activity.base.BaseRxActivity;
|
||||
import eu.kanade.mangafeed.ui.viewer.LeftToRightViewer;
|
||||
import eu.kanade.mangafeed.ui.viewer.RightToLeftViewer;
|
||||
import eu.kanade.mangafeed.ui.viewer.VerticalViewer;
|
||||
import eu.kanade.mangafeed.ui.viewer.WebtoonViewer;
|
||||
import eu.kanade.mangafeed.ui.viewer.base.BaseViewer;
|
||||
import eu.kanade.mangafeed.ui.base.activity.BaseRxActivity;
|
||||
import eu.kanade.mangafeed.ui.reader.viewer.base.BaseReader;
|
||||
import eu.kanade.mangafeed.ui.reader.viewer.horizontal.LeftToRightReader;
|
||||
import eu.kanade.mangafeed.ui.reader.viewer.horizontal.RightToLeftReader;
|
||||
import eu.kanade.mangafeed.ui.reader.viewer.vertical.VerticalReader;
|
||||
import eu.kanade.mangafeed.ui.reader.viewer.webtoon.WebtoonReader;
|
||||
import nucleus.factory.RequiresPresenter;
|
||||
|
||||
@RequiresPresenter(ReaderPresenter.class)
|
||||
@@ -37,7 +36,7 @@ public class ReaderActivity extends BaseRxActivity<ReaderPresenter> {
|
||||
|
||||
@Inject PreferencesHelper prefs;
|
||||
|
||||
private BaseViewer viewer;
|
||||
private BaseReader viewer;
|
||||
private boolean isFullscreen;
|
||||
|
||||
private static final int LEFT_TO_RIGHT = 1;
|
||||
@@ -146,16 +145,16 @@ public class ReaderActivity extends BaseRxActivity<ReaderPresenter> {
|
||||
enableFullScreen();
|
||||
}
|
||||
|
||||
private BaseViewer getViewer() {
|
||||
private BaseReader getViewer() {
|
||||
switch (prefs.getDefaultViewer()) {
|
||||
case LEFT_TO_RIGHT: default:
|
||||
return new LeftToRightViewer(this, container);
|
||||
return new LeftToRightReader(this, container);
|
||||
case RIGHT_TO_LEFT:
|
||||
return new RightToLeftViewer(this, container);
|
||||
return new RightToLeftReader(this, container);
|
||||
case VERTICAL:
|
||||
return new VerticalViewer(this, container);
|
||||
return new VerticalReader(this, container);
|
||||
case WEBTOON:
|
||||
return new WebtoonViewer(this, container);
|
||||
return new WebtoonReader(this, container);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
package eu.kanade.mangafeed.ui.reader;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import de.greenrobot.event.EventBus;
|
||||
import eu.kanade.mangafeed.data.helpers.DatabaseHelper;
|
||||
import eu.kanade.mangafeed.data.helpers.DownloadManager;
|
||||
import eu.kanade.mangafeed.data.helpers.PreferencesHelper;
|
||||
import eu.kanade.mangafeed.data.models.Chapter;
|
||||
import eu.kanade.mangafeed.data.models.Manga;
|
||||
import eu.kanade.mangafeed.data.models.Page;
|
||||
import eu.kanade.mangafeed.events.SourceMangaChapterEvent;
|
||||
import eu.kanade.mangafeed.sources.base.Source;
|
||||
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
||||
import eu.kanade.mangafeed.util.EventBusHook;
|
||||
import icepick.State;
|
||||
import rx.Observable;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class ReaderPresenter extends BasePresenter<ReaderActivity> {
|
||||
|
||||
@Inject PreferencesHelper prefs;
|
||||
@Inject DatabaseHelper db;
|
||||
@Inject DownloadManager downloadManager;
|
||||
|
||||
private Source source;
|
||||
private Manga manga;
|
||||
private Chapter chapter;
|
||||
private List<Page> pageList;
|
||||
private boolean isDownloaded;
|
||||
@State int currentPage;
|
||||
|
||||
private static final int GET_PAGE_LIST = 1;
|
||||
private static final int GET_PAGE_IMAGES = 2;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
|
||||
restartableLatestCache(GET_PAGE_LIST,
|
||||
() -> getPageListObservable()
|
||||
.doOnNext(pages -> pageList = pages)
|
||||
.doOnCompleted( () -> start(GET_PAGE_IMAGES) ),
|
||||
(view, pages) -> {
|
||||
view.onPageListReady(pages);
|
||||
if (currentPage != 0)
|
||||
view.setSelectedPage(currentPage);
|
||||
},
|
||||
(view, error) -> Timber.e("An error occurred while downloading page list"));
|
||||
|
||||
restartableReplay(GET_PAGE_IMAGES,
|
||||
this::getPageImagesObservable,
|
||||
(view, page) -> {},
|
||||
(view, error) -> Timber.e("An error occurred while downloading an image"));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTakeView(ReaderActivity view) {
|
||||
super.onTakeView(view);
|
||||
registerForStickyEvents();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDropView() {
|
||||
unregisterForEvents();
|
||||
super.onDropView();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
if (!isDownloaded)
|
||||
source.savePageList(chapter.url, pageList);
|
||||
saveChapterProgress();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@EventBusHook
|
||||
public void onEventMainThread(SourceMangaChapterEvent event) {
|
||||
source = event.getSource();
|
||||
manga = event.getManga();
|
||||
chapter = event.getChapter();
|
||||
isDownloaded = chapter.downloaded == Chapter.DOWNLOADED;
|
||||
if (chapter.last_page_read != 0 && !chapter.read)
|
||||
currentPage = chapter.last_page_read;
|
||||
|
||||
start(GET_PAGE_LIST);
|
||||
|
||||
EventBus.getDefault().removeStickyEvent(SourceMangaChapterEvent.class);
|
||||
}
|
||||
|
||||
private Observable<List<Page>> getPageListObservable() {
|
||||
if (!isDownloaded)
|
||||
return source.getCachedPageListOrPullFromNetwork(chapter.url)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread());
|
||||
else
|
||||
return Observable.just(downloadManager.getSavedPageList(source, manga, chapter));
|
||||
}
|
||||
|
||||
private Observable<Page> getPageImagesObservable() {
|
||||
Observable<Page> pages;
|
||||
|
||||
if (!isDownloaded) {
|
||||
pages = Observable
|
||||
.merge(Observable.from(pageList).filter(page -> page.getImageUrl() != null),
|
||||
source.getRemainingImageUrlsFromPageList(pageList))
|
||||
.flatMap(source::getCachedImage);
|
||||
} else {
|
||||
File chapterDir = downloadManager.getAbsoluteChapterDirectory(source, manga, chapter);
|
||||
|
||||
pages = Observable.from(pageList)
|
||||
.flatMap(page -> downloadManager.getDownloadedImage(page, source, chapterDir))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread());
|
||||
}
|
||||
return pages
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread());
|
||||
}
|
||||
|
||||
public void setCurrentPage(int currentPage) {
|
||||
this.currentPage = currentPage;
|
||||
}
|
||||
|
||||
private void saveChapterProgress() {
|
||||
chapter.last_page_read = currentPage;
|
||||
if (currentPage == pageList.size() - 1) {
|
||||
chapter.read = true;
|
||||
}
|
||||
db.insertChapter(chapter).executeAsBlocking();
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.viewer.base;
|
||||
package eu.kanade.mangafeed.ui.reader.viewer.base;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.FrameLayout;
|
||||
@@ -6,15 +6,15 @@ import android.widget.FrameLayout;
|
||||
import java.util.List;
|
||||
|
||||
import eu.kanade.mangafeed.data.models.Page;
|
||||
import eu.kanade.mangafeed.ui.activity.ReaderActivity;
|
||||
import eu.kanade.mangafeed.ui.reader.ReaderActivity;
|
||||
|
||||
public abstract class BaseViewer {
|
||||
public abstract class BaseReader {
|
||||
|
||||
protected ReaderActivity activity;
|
||||
protected FrameLayout container;
|
||||
protected int currentPosition;
|
||||
|
||||
public BaseViewer(ReaderActivity activity, FrameLayout container) {
|
||||
public BaseReader(ReaderActivity activity, FrameLayout container) {
|
||||
this.activity = activity;
|
||||
this.container = container;
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.adapter;
|
||||
package eu.kanade.mangafeed.ui.reader.viewer.common;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
+4
-5
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.adapter;
|
||||
package eu.kanade.mangafeed.ui.reader.viewer.common;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
@@ -6,13 +6,12 @@ import android.support.v4.app.FragmentManager;
|
||||
import java.util.List;
|
||||
|
||||
import eu.kanade.mangafeed.data.models.Page;
|
||||
import eu.kanade.mangafeed.ui.fragment.ReaderPageFragment;
|
||||
|
||||
public class ViewerPagerAdapter extends SmartFragmentStatePagerAdapter {
|
||||
public class ViewPagerReaderAdapter extends SmartFragmentStatePagerAdapter {
|
||||
|
||||
private List<Page> pages;
|
||||
|
||||
public ViewerPagerAdapter(FragmentManager fragmentManager) {
|
||||
public ViewPagerReaderAdapter(FragmentManager fragmentManager) {
|
||||
super(fragmentManager);
|
||||
}
|
||||
|
||||
@@ -26,7 +25,7 @@ public class ViewerPagerAdapter extends SmartFragmentStatePagerAdapter {
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
return ReaderPageFragment.newInstance(pages.get(position));
|
||||
return ViewPagerReaderFragment.newInstance(pages.get(position));
|
||||
}
|
||||
|
||||
public List<Page> getPages() {
|
||||
+6
-6
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.fragment;
|
||||
package eu.kanade.mangafeed.ui.reader.viewer.common;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
@@ -19,15 +19,15 @@ import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.models.Page;
|
||||
import eu.kanade.mangafeed.ui.activity.ReaderActivity;
|
||||
import eu.kanade.mangafeed.ui.fragment.base.BaseFragment;
|
||||
import eu.kanade.mangafeed.ui.base.fragment.BaseFragment;
|
||||
import eu.kanade.mangafeed.ui.reader.ReaderActivity;
|
||||
import rx.Observable;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
import rx.subjects.PublishSubject;
|
||||
|
||||
public class ReaderPageFragment extends BaseFragment {
|
||||
public class ViewPagerReaderFragment extends BaseFragment {
|
||||
|
||||
@Bind(R.id.page_image_view) SubsamplingScaleImageView imageView;
|
||||
@Bind(R.id.progress_container) LinearLayout progressContainer;
|
||||
@@ -39,8 +39,8 @@ public class ReaderPageFragment extends BaseFragment {
|
||||
private Subscription progressSubscription;
|
||||
private Subscription statusSubscription;
|
||||
|
||||
public static ReaderPageFragment newInstance(Page page) {
|
||||
ReaderPageFragment fragment = new ReaderPageFragment();
|
||||
public static ViewPagerReaderFragment newInstance(Page page) {
|
||||
ViewPagerReaderFragment fragment = new ViewPagerReaderFragment();
|
||||
fragment.setPage(page);
|
||||
return fragment;
|
||||
}
|
||||
+12
-25
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.viewer.base;
|
||||
package eu.kanade.mangafeed.ui.reader.viewer.horizontal;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.FrameLayout;
|
||||
@@ -9,39 +9,30 @@ import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.models.Page;
|
||||
import eu.kanade.mangafeed.ui.activity.ReaderActivity;
|
||||
import eu.kanade.mangafeed.ui.adapter.ViewerPagerAdapter;
|
||||
import eu.kanade.mangafeed.widget.HorizontalViewPager;
|
||||
import eu.kanade.mangafeed.ui.reader.ReaderActivity;
|
||||
import eu.kanade.mangafeed.ui.reader.viewer.base.BaseReader;
|
||||
import eu.kanade.mangafeed.ui.reader.viewer.common.ViewPagerReaderAdapter;
|
||||
|
||||
public abstract class ViewPagerViewer extends BaseViewer {
|
||||
public abstract class HorizontalReader extends BaseReader {
|
||||
|
||||
@Bind(R.id.view_pager) HorizontalViewPager viewPager;
|
||||
protected ViewerPagerAdapter adapter;
|
||||
|
||||
public ViewPagerViewer(ReaderActivity activity, FrameLayout container) {
|
||||
protected ViewPagerReaderAdapter adapter;
|
||||
|
||||
public HorizontalReader(ReaderActivity activity, FrameLayout container) {
|
||||
super(activity, container);
|
||||
activity.getLayoutInflater().inflate(R.layout.viewer_viewpager, container);
|
||||
activity.getLayoutInflater().inflate(R.layout.reader_horizontal, container);
|
||||
ButterKnife.bind(this, container);
|
||||
|
||||
adapter = new ViewerPagerAdapter(activity.getSupportFragmentManager());
|
||||
adapter = new ViewPagerReaderAdapter(activity.getSupportFragmentManager());
|
||||
viewPager.setAdapter(adapter);
|
||||
viewPager.setOffscreenPageLimit(3);
|
||||
viewPager.addOnPageChangeListener(new HorizontalViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
||||
}
|
||||
|
||||
viewPager.addOnPageChangeListener(new HorizontalViewPager.SimpleOnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
currentPosition = position;
|
||||
updatePageNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
});
|
||||
viewPager.setOnChapterBoundariesOutListener(new HorizontalViewPager.OnChapterBoundariesOutListener() {
|
||||
@Override
|
||||
@@ -56,11 +47,7 @@ public abstract class ViewPagerViewer extends BaseViewer {
|
||||
});
|
||||
viewPager.setOnChapterSingleTapListener(activity::onCenterSingleTap);
|
||||
}
|
||||
|
||||
public HorizontalViewPager getViewPager() {
|
||||
return viewPager;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getTotalPages() {
|
||||
return adapter.getCount();
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
package eu.kanade.mangafeed.ui.reader.viewer.horizontal;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public class HorizontalViewPager extends ViewPager {
|
||||
|
||||
private GestureDetector gestureDetector;
|
||||
|
||||
private OnChapterBoundariesOutListener mOnChapterBoundariesOutListener;
|
||||
private OnChapterSingleTapListener mOnChapterSingleTapListener;
|
||||
|
||||
private static final float LEFT_REGION = 0.33f;
|
||||
private static final float RIGHT_REGION = 0.66f;
|
||||
private static final float SWIPE_TOLERANCE = 0.25f;
|
||||
private float startDragX;
|
||||
|
||||
public HorizontalViewPager(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
gestureDetector = new GestureDetector(getContext(), new ReaderViewGestureListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
try {
|
||||
gestureDetector.onTouchEvent(ev);
|
||||
|
||||
if ((ev.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
|
||||
if (this.getCurrentItem() == 0 || this.getCurrentItem() == this.getAdapter().getCount() - 1) {
|
||||
startDragX = ev.getX();
|
||||
}
|
||||
}
|
||||
|
||||
return super.onInterceptTouchEvent(ev);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Do Nothing.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
try {
|
||||
if (mOnChapterBoundariesOutListener != null) {
|
||||
if (this.getCurrentItem() == 0) {
|
||||
if ((ev.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) {
|
||||
float displacement = ev.getX() - startDragX;
|
||||
|
||||
if (ev.getX() > startDragX && displacement > getWidth() * SWIPE_TOLERANCE) {
|
||||
mOnChapterBoundariesOutListener.onFirstPageOutEvent();
|
||||
return true;
|
||||
}
|
||||
|
||||
startDragX = 0;
|
||||
}
|
||||
} else if (this.getCurrentItem() == this.getAdapter().getCount() - 1) {
|
||||
if ((ev.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) {
|
||||
float displacement = startDragX - ev.getX();
|
||||
|
||||
if (ev.getX() < startDragX && displacement > getWidth() * SWIPE_TOLERANCE) {
|
||||
mOnChapterBoundariesOutListener.onLastPageOutEvent();
|
||||
return true;
|
||||
}
|
||||
|
||||
startDragX = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.onTouchEvent(ev);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Do Nothing.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onImageTouch(MotionEvent event) {
|
||||
return gestureDetector.onTouchEvent(event);
|
||||
}
|
||||
|
||||
public interface OnChapterBoundariesOutListener {
|
||||
void onFirstPageOutEvent();
|
||||
|
||||
void onLastPageOutEvent();
|
||||
}
|
||||
|
||||
public interface OnChapterSingleTapListener {
|
||||
void onSingleTap();
|
||||
}
|
||||
|
||||
public void setOnChapterBoundariesOutListener(OnChapterBoundariesOutListener onChapterBoundariesOutListener) {
|
||||
mOnChapterBoundariesOutListener = onChapterBoundariesOutListener;
|
||||
}
|
||||
|
||||
public void setOnChapterSingleTapListener(OnChapterSingleTapListener onChapterSingleTapListener) {
|
||||
mOnChapterSingleTapListener = onChapterSingleTapListener;
|
||||
}
|
||||
|
||||
|
||||
private class ReaderViewGestureListener extends GestureDetector.SimpleOnGestureListener {
|
||||
|
||||
@Override
|
||||
public boolean onSingleTapConfirmed(MotionEvent e) {
|
||||
final int position = getCurrentItem();
|
||||
final float positionX = e.getX();
|
||||
|
||||
if (positionX < getWidth() * LEFT_REGION) {
|
||||
if (position != 0) {
|
||||
setCurrentItem(position - 1, true);
|
||||
} else {
|
||||
if (mOnChapterBoundariesOutListener != null) {
|
||||
mOnChapterBoundariesOutListener.onFirstPageOutEvent();
|
||||
}
|
||||
}
|
||||
} else if (positionX > getWidth() * RIGHT_REGION) {
|
||||
if (position != getAdapter().getCount() - 1) {
|
||||
setCurrentItem(position + 1, true);
|
||||
} else {
|
||||
if (mOnChapterBoundariesOutListener != null) {
|
||||
mOnChapterBoundariesOutListener.onLastPageOutEvent();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mOnChapterSingleTapListener != null) {
|
||||
mOnChapterSingleTapListener.onSingleTap();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package eu.kanade.mangafeed.ui.reader.viewer.horizontal;
|
||||
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import eu.kanade.mangafeed.ui.reader.ReaderActivity;
|
||||
|
||||
public class LeftToRightReader extends HorizontalReader {
|
||||
|
||||
public LeftToRightReader(ReaderActivity activity, FrameLayout container) {
|
||||
super(activity, container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFirstPageOut() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLastPageOut() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
}
|
||||
+7
-8
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.viewer;
|
||||
package eu.kanade.mangafeed.ui.reader.viewer.horizontal;
|
||||
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
@@ -7,12 +7,11 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import eu.kanade.mangafeed.data.models.Page;
|
||||
import eu.kanade.mangafeed.ui.activity.ReaderActivity;
|
||||
import eu.kanade.mangafeed.ui.viewer.base.ViewPagerViewer;
|
||||
import eu.kanade.mangafeed.ui.reader.ReaderActivity;
|
||||
|
||||
public class RightToLeftViewer extends ViewPagerViewer {
|
||||
public class RightToLeftReader extends HorizontalReader {
|
||||
|
||||
public RightToLeftViewer(ReaderActivity activity, FrameLayout container) {
|
||||
public RightToLeftReader(ReaderActivity activity, FrameLayout container) {
|
||||
super(activity, container);
|
||||
}
|
||||
|
||||
@@ -21,7 +20,7 @@ public class RightToLeftViewer extends ViewPagerViewer {
|
||||
ArrayList<Page> inversedPages = new ArrayList<>(pages);
|
||||
Collections.reverse(inversedPages);
|
||||
adapter.setPages(inversedPages);
|
||||
getViewPager().setCurrentItem(adapter.getCount()-1, false);
|
||||
viewPager.setCurrentItem(adapter.getCount()-1, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -31,12 +30,12 @@ public class RightToLeftViewer extends ViewPagerViewer {
|
||||
|
||||
@Override
|
||||
public void onFirstPageOut() {
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLastPageOut() {
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
}
|
||||
+11
-21
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.viewer;
|
||||
package eu.kanade.mangafeed.ui.reader.viewer.vertical;
|
||||
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.view.MotionEvent;
|
||||
@@ -10,40 +10,30 @@ import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.models.Page;
|
||||
import eu.kanade.mangafeed.ui.activity.ReaderActivity;
|
||||
import eu.kanade.mangafeed.ui.adapter.ViewerPagerAdapter;
|
||||
import eu.kanade.mangafeed.ui.viewer.base.BaseViewer;
|
||||
import fr.castorflex.android.verticalviewpager.VerticalViewPager;
|
||||
import eu.kanade.mangafeed.ui.reader.ReaderActivity;
|
||||
import eu.kanade.mangafeed.ui.reader.viewer.base.BaseReader;
|
||||
import eu.kanade.mangafeed.ui.reader.viewer.common.ViewPagerReaderAdapter;
|
||||
|
||||
public class VerticalViewer extends BaseViewer {
|
||||
public class VerticalReader extends BaseReader {
|
||||
|
||||
@Bind(R.id.view_pager) VerticalViewPager viewPager;
|
||||
private ViewerPagerAdapter adapter;
|
||||
|
||||
public VerticalViewer(ReaderActivity activity, FrameLayout container) {
|
||||
private ViewPagerReaderAdapter adapter;
|
||||
|
||||
public VerticalReader(ReaderActivity activity, FrameLayout container) {
|
||||
super(activity, container);
|
||||
activity.getLayoutInflater().inflate(R.layout.viewer_verticalviewpager, container);
|
||||
activity.getLayoutInflater().inflate(R.layout.reader_vertical, container);
|
||||
ButterKnife.bind(this, container);
|
||||
|
||||
adapter = new ViewerPagerAdapter(activity.getSupportFragmentManager());
|
||||
adapter = new ViewPagerReaderAdapter(activity.getSupportFragmentManager());
|
||||
viewPager.setAdapter(adapter);
|
||||
viewPager.setOffscreenPageLimit(3);
|
||||
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
||||
}
|
||||
|
||||
viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
currentPosition = position;
|
||||
updatePageNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package eu.kanade.mangafeed.ui.reader.viewer.vertical;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.GestureDetector;
|
||||
|
||||
public class VerticalViewPager extends fr.castorflex.android.verticalviewpager.VerticalViewPager {
|
||||
|
||||
private GestureDetector gestureDetector;
|
||||
|
||||
public VerticalViewPager(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
gestureDetector = new GestureDetector(getContext(), new ReaderViewGestureListener());
|
||||
}
|
||||
|
||||
private class ReaderViewGestureListener extends GestureDetector.SimpleOnGestureListener {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.adapter;
|
||||
package eu.kanade.mangafeed.ui.reader.viewer.webtoon;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
@@ -47,7 +47,7 @@ public class WebtoonAdapter extends BaseEasyRecyclerAdapter<Page> {
|
||||
notifyItemChanged(page.getPageNumber());
|
||||
}
|
||||
|
||||
@LayoutId(R.layout.item_webtoon_viewer)
|
||||
@LayoutId(R.layout.item_webtoon_reader)
|
||||
static class ImageViewHolder extends ItemViewHolder<Page> {
|
||||
|
||||
@ViewId(R.id.page_image_view) SubsamplingScaleImageView imageView;
|
||||
+5
-6
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.mangafeed.ui.viewer;
|
||||
package eu.kanade.mangafeed.ui.reader.viewer.webtoon;
|
||||
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
@@ -8,14 +8,13 @@ import android.widget.FrameLayout;
|
||||
import java.util.List;
|
||||
|
||||
import eu.kanade.mangafeed.data.models.Page;
|
||||
import eu.kanade.mangafeed.ui.activity.ReaderActivity;
|
||||
import eu.kanade.mangafeed.ui.adapter.WebtoonAdapter;
|
||||
import eu.kanade.mangafeed.ui.viewer.base.BaseViewer;
|
||||
import eu.kanade.mangafeed.ui.reader.ReaderActivity;
|
||||
import eu.kanade.mangafeed.ui.reader.viewer.base.BaseReader;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.subjects.PublishSubject;
|
||||
|
||||
public class WebtoonViewer extends BaseViewer {
|
||||
public class WebtoonReader extends BaseReader {
|
||||
|
||||
private RecyclerView recycler;
|
||||
private LinearLayoutManager layoutManager;
|
||||
@@ -23,7 +22,7 @@ public class WebtoonViewer extends BaseViewer {
|
||||
private List<Page> pages;
|
||||
private Subscription subscription;
|
||||
|
||||
public WebtoonViewer(ReaderActivity activity, FrameLayout container) {
|
||||
public WebtoonReader(ReaderActivity activity, FrameLayout container) {
|
||||
super(activity, container);
|
||||
|
||||
recycler = new RecyclerView(activity);
|
||||
@@ -1,24 +0,0 @@
|
||||
package eu.kanade.mangafeed.ui.viewer;
|
||||
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import eu.kanade.mangafeed.ui.activity.ReaderActivity;
|
||||
import eu.kanade.mangafeed.ui.viewer.base.ViewPagerViewer;
|
||||
|
||||
public class LeftToRightViewer extends ViewPagerViewer {
|
||||
|
||||
public LeftToRightViewer(ReaderActivity activity, FrameLayout container) {
|
||||
super(activity, container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFirstPageOut() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLastPageOut() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user