Load catalogue with thumbnails
This commit is contained in:
parent
c88d8f0ded
commit
ed76520ebc
7 changed files with 173 additions and 37 deletions
|
@ -3,6 +3,7 @@ package eu.kanade.mangafeed.presenter;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -38,6 +39,7 @@ public class CatalogueListPresenter extends BasePresenter {
|
||||||
private Subscription mMangaFetchSubscription;
|
private Subscription mMangaFetchSubscription;
|
||||||
private Subscription mMangaSearchSubscription;
|
private Subscription mMangaSearchSubscription;
|
||||||
private Subscription mSearchViewSubscription;
|
private Subscription mSearchViewSubscription;
|
||||||
|
private Subscription mMangaDetailFetchSubscription;
|
||||||
private PublishSubject<Observable<String>> mSearchViewPublishSubject;
|
private PublishSubject<Observable<String>> mSearchViewPublishSubject;
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,7 +71,10 @@ public class CatalogueListPresenter extends BasePresenter {
|
||||||
.flatMap(Observable::from)
|
.flatMap(Observable::from)
|
||||||
.map(this::networkToLocalManga)
|
.map(this::networkToLocalManga)
|
||||||
.toList()
|
.toList()
|
||||||
.subscribe(adapter::addItems);
|
.subscribe(newMangas -> {
|
||||||
|
adapter.addItems(newMangas);
|
||||||
|
getMangaDetails(newMangas);
|
||||||
|
});
|
||||||
|
|
||||||
subscriptions.add(mMangaFetchSubscription);
|
subscriptions.add(mMangaFetchSubscription);
|
||||||
}
|
}
|
||||||
|
@ -83,7 +88,10 @@ public class CatalogueListPresenter extends BasePresenter {
|
||||||
.flatMap(Observable::from)
|
.flatMap(Observable::from)
|
||||||
.map(this::networkToLocalManga)
|
.map(this::networkToLocalManga)
|
||||||
.toList()
|
.toList()
|
||||||
.subscribe(adapter::addItems);
|
.subscribe(newMangas -> {
|
||||||
|
adapter.addItems(newMangas);
|
||||||
|
getMangaDetails(newMangas);
|
||||||
|
});
|
||||||
|
|
||||||
subscriptions.add(mMangaSearchSubscription);
|
subscriptions.add(mMangaSearchSubscription);
|
||||||
}
|
}
|
||||||
|
@ -97,23 +105,40 @@ public class CatalogueListPresenter extends BasePresenter {
|
||||||
return localManga;
|
return localManga;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Observable<Manga> getMangaDetails(Manga manga) {
|
private void getMangaDetails(List<Manga> mangas) {
|
||||||
Observable<Manga> mangaObs = Observable.just(manga);
|
subscriptions.remove(mMangaDetailFetchSubscription);
|
||||||
if (!manga.initialized) {
|
|
||||||
return mangaObs
|
mMangaDetailFetchSubscription = Observable.from(mangas)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.flatMap(localManga -> {
|
.filter(manga -> !manga.initialized)
|
||||||
Timber.e("Request " + localManga.url);
|
.buffer(3)
|
||||||
return selectedSource.pullMangaFromNetwork(localManga.url);
|
.concatMap(localMangas -> {
|
||||||
})
|
List<Observable<Manga>> mangaObservables = new ArrayList<>();
|
||||||
.flatMap(networkManga -> {
|
for (Manga manga : localMangas) {
|
||||||
Manga.copyFromNetwork(manga, networkManga);
|
Observable<Manga> tempObs = selectedSource.pullMangaFromNetwork(manga.url)
|
||||||
Timber.w("Net manga " + manga.thumbnail_url);
|
.flatMap(networkManga -> {
|
||||||
db.insertMangaBlock(manga);
|
Manga.copyFromNetwork(manga, networkManga);
|
||||||
return Observable.just(manga);
|
db.insertMangaBlock(manga);
|
||||||
});
|
return Observable.just(manga);
|
||||||
}
|
})
|
||||||
return mangaObs;
|
.subscribeOn(Schedulers.io());
|
||||||
|
mangaObservables.add(tempObs);
|
||||||
|
}
|
||||||
|
return Observable.merge(mangaObservables);
|
||||||
|
})
|
||||||
|
.filter(manga -> manga.initialized)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(manga -> {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < adapter.getCount(); i++) {
|
||||||
|
if (manga.id == adapter.getItem(i).id) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
view.updateImage(i, manga.thumbnail_url);
|
||||||
|
});
|
||||||
|
|
||||||
|
subscriptions.add(mMangaDetailFetchSubscription);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onQueryTextChange(String query) {
|
public void onQueryTextChange(String query) {
|
||||||
|
@ -152,8 +177,8 @@ public class CatalogueListPresenter extends BasePresenter {
|
||||||
|
|
||||||
mSearchName = query;
|
mSearchName = query;
|
||||||
adapter.getItems().clear();
|
adapter.getItems().clear();
|
||||||
|
view.resetScrollListener();
|
||||||
loadMoreMangas(1);
|
loadMoreMangas(1);
|
||||||
view.setScrollListener();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadMoreMangas(int page) {
|
public void loadMoreMangas(int page) {
|
||||||
|
|
|
@ -4,7 +4,11 @@ import android.os.Bundle;
|
||||||
import android.support.v7.widget.SearchView;
|
import android.support.v7.widget.SearchView;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.widget.ListView;
|
import android.view.View;
|
||||||
|
import android.widget.GridView;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
|
|
||||||
import butterknife.Bind;
|
import butterknife.Bind;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
|
@ -19,11 +23,13 @@ public class CatalogueListActivity extends BaseActivity implements CatalogueList
|
||||||
@Bind(R.id.toolbar)
|
@Bind(R.id.toolbar)
|
||||||
Toolbar toolbar;
|
Toolbar toolbar;
|
||||||
|
|
||||||
@Bind(R.id.catalogue_manga_list)
|
@Bind(R.id.gridView)
|
||||||
ListView manga_list;
|
GridView manga_list;
|
||||||
|
|
||||||
private CatalogueListPresenter presenter;
|
private CatalogueListPresenter presenter;
|
||||||
|
|
||||||
|
private EndlessScrollListener scrollListener;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
@ -75,13 +81,34 @@ public class CatalogueListActivity extends BaseActivity implements CatalogueList
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setScrollListener() {
|
public void setScrollListener() {
|
||||||
manga_list.setOnScrollListener(new EndlessScrollListener() {
|
scrollListener = new EndlessScrollListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onLoadMore(int page, int totalItemsCount) {
|
public boolean onLoadMore(int page, int totalItemsCount) {
|
||||||
presenter.loadMoreMangas(page);
|
presenter.loadMoreMangas(page);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
manga_list.setOnScrollListener(scrollListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void resetScrollListener() {
|
||||||
|
scrollListener.resetScroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateImage(int position, String thumbnail) {
|
||||||
|
View v = manga_list.getChildAt(position -
|
||||||
|
manga_list.getFirstVisiblePosition());
|
||||||
|
|
||||||
|
if(v == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImageView imageView = (ImageView) v.findViewById(R.id.catalogue_thumbnail);
|
||||||
|
|
||||||
|
Glide.with(getActivity())
|
||||||
|
.load(thumbnail)
|
||||||
|
.centerCrop()
|
||||||
|
.into(imageView);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
package eu.kanade.mangafeed.ui.adapter;
|
package eu.kanade.mangafeed.ui.adapter;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
|
|
||||||
import eu.kanade.mangafeed.R;
|
import eu.kanade.mangafeed.R;
|
||||||
import eu.kanade.mangafeed.data.models.Manga;
|
import eu.kanade.mangafeed.data.models.Manga;
|
||||||
import uk.co.ribot.easyadapter.ItemViewHolder;
|
import uk.co.ribot.easyadapter.ItemViewHolder;
|
||||||
|
@ -16,6 +20,9 @@ public class CatalogueListHolder extends ItemViewHolder<Manga> {
|
||||||
@ViewId(R.id.catalogue_title)
|
@ViewId(R.id.catalogue_title)
|
||||||
TextView title;
|
TextView title;
|
||||||
|
|
||||||
|
@ViewId(R.id.catalogue_thumbnail)
|
||||||
|
ImageView image;
|
||||||
|
|
||||||
public CatalogueListHolder(View view) {
|
public CatalogueListHolder(View view) {
|
||||||
super(view);
|
super(view);
|
||||||
}
|
}
|
||||||
|
@ -23,5 +30,17 @@ public class CatalogueListHolder extends ItemViewHolder<Manga> {
|
||||||
@Override
|
@Override
|
||||||
public void onSetValues(Manga manga, PositionInfo positionInfo) {
|
public void onSetValues(Manga manga, PositionInfo positionInfo) {
|
||||||
title.setText(manga.title);
|
title.setText(manga.title);
|
||||||
|
|
||||||
|
String thumbnail;
|
||||||
|
if (manga.thumbnail_url != null)
|
||||||
|
thumbnail = manga.thumbnail_url;
|
||||||
|
else
|
||||||
|
thumbnail = "http://img1.wikia.nocookie.net/__cb20090524204255/starwars/images/thumb/1/1a/R2d2.jpg/400px-R2d2.jpg";
|
||||||
|
|
||||||
|
Glide.with(getContext())
|
||||||
|
.load(thumbnail)
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.RESULT)
|
||||||
|
.centerCrop()
|
||||||
|
.into(image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,4 +10,6 @@ public interface CatalogueListView extends BaseView {
|
||||||
void setSourceTitle(String title);
|
void setSourceTitle(String title);
|
||||||
void setAdapter(EasyAdapter adapter);
|
void setAdapter(EasyAdapter adapter);
|
||||||
void setScrollListener();
|
void setScrollListener();
|
||||||
|
void resetScrollListener();
|
||||||
|
void updateImage(int position, String thumbnail);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,12 @@ public abstract class EndlessScrollListener implements AbsListView.OnScrollListe
|
||||||
this.currentPage = startPage;
|
this.currentPage = startPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void resetScroll() {
|
||||||
|
this.currentPage = 0;
|
||||||
|
this.startingPageIndex = 0;
|
||||||
|
this.loading = true;
|
||||||
|
}
|
||||||
|
|
||||||
// This happens many times a second during a scroll, so be wary of the code you place here.
|
// This happens many times a second during a scroll, so be wary of the code you place here.
|
||||||
// We are given a few useful parameters to help us work out if we need to load some more data,
|
// We are given a few useful parameters to help us work out if we need to load some more data,
|
||||||
// but first we check if we are waiting for the previous load to finish.
|
// but first we check if we are waiting for the previous load to finish.
|
||||||
|
|
|
@ -11,11 +11,18 @@
|
||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
layout="@layout/toolbar"/>
|
layout="@layout/toolbar"/>
|
||||||
|
|
||||||
<ListView
|
<GridView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:id="@+id/catalogue_manga_list"
|
android:id="@+id/gridView"
|
||||||
tools:listitem="@layout/item_catalogue"
|
android:padding="10dp"
|
||||||
/>
|
android:clipToPadding="false"
|
||||||
|
android:verticalSpacing="8dp"
|
||||||
|
android:horizontalSpacing="8dp"
|
||||||
|
android:columnWidth="96dp"
|
||||||
|
android:numColumns="auto_fit"
|
||||||
|
android:stretchMode="columnWidth"
|
||||||
|
android:fastScrollEnabled="true"
|
||||||
|
tools:listitem="@layout/item_catalogue" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -1,14 +1,64 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:background="@drawable/library_item_background"
|
||||||
|
>
|
||||||
|
|
||||||
<TextView
|
<FrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="40dp"
|
android:layout_height="wrap_content">
|
||||||
tools:text="New Text"
|
|
||||||
android:gravity="center_vertical"
|
<ImageView
|
||||||
android:id="@+id/catalogue_title" />
|
android:layout_width="match_parent"
|
||||||
</LinearLayout>
|
android:layout_height="144dp"
|
||||||
|
android:id="@+id/catalogue_thumbnail"
|
||||||
|
tools:src="@mipmap/ic_launcher"
|
||||||
|
tools:background="@color/md_red_100"/>
|
||||||
|
|
||||||
|
<eu.kanade.mangafeed.widget.PTSansTextView
|
||||||
|
android:id="@+id/unreadText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="123"
|
||||||
|
app:typeface="ptsansNarrowBold"
|
||||||
|
android:background="@color/md_red_300"
|
||||||
|
android:layout_gravity="right"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:paddingLeft="3dp"
|
||||||
|
android:paddingRight="3dp"
|
||||||
|
android:paddingTop="1dp"
|
||||||
|
android:paddingBottom="1dp" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="36dp"
|
||||||
|
android:id="@+id/footerLinearLayout"
|
||||||
|
>
|
||||||
|
|
||||||
|
<eu.kanade.mangafeed.widget.PTSansTextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
app:typeface="ptsansNarrowBold"
|
||||||
|
android:ellipsize="middle"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:textColor="@color/black_87pc"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:id="@+id/catalogue_title"
|
||||||
|
android:paddingRight="8dp"
|
||||||
|
android:paddingLeft="8dp"
|
||||||
|
tools:text="Sample name"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
Reference in a new issue