Organize ui by feature instead of layer

This commit is contained in:
inorichi
2015-11-14 17:10:55 +01:00
parent e74f81d41a
commit 4f604e828b
61 changed files with 245 additions and 276 deletions
@@ -0,0 +1,66 @@
package eu.kanade.mangafeed.ui.library;
import android.content.Context;
import android.widget.Filter;
import android.widget.Filterable;
import java.util.List;
import eu.kanade.mangafeed.data.models.Manga;
import eu.kanade.mangafeed.ui.library.LibraryHolder;
import rx.Observable;
import uk.co.ribot.easyadapter.EasyAdapter;
public class LibraryAdapter extends EasyAdapter<Manga> implements Filterable {
List<Manga> mangas;
Filter filter;
public LibraryAdapter(Context context) {
super(context, LibraryHolder.class);
filter = new LibraryFilter();
}
public void setNewItems(List<Manga> list) {
super.setItems(list);
mangas = list;
}
@Override
public Filter getFilter() {
return filter;
}
private class LibraryFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
FilterResults results = new FilterResults();
String query = charSequence.toString().toLowerCase();
if (query.length() == 0) {
results.values = mangas;
results.count = mangas.size();
} else {
List<Manga> filteredMangas = Observable.from(mangas)
.filter(x ->
(x.title != null && x.title.toLowerCase().contains(query)) ||
(x.author != null && x.author.toLowerCase().contains(query)) ||
(x.artist != null && x.artist.toLowerCase().contains(query)))
.toList()
.toBlocking()
.single();
results.values = filteredMangas;
results.count = filteredMangas.size();
}
return results;
}
@Override
public void publishResults(CharSequence constraint, FilterResults results) {
setItems((List<Manga >) results.values);
}
}
}
@@ -0,0 +1,153 @@
package eu.kanade.mangafeed.ui.library;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.SearchView;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
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.ui.manga.MangaActivity;
import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment;
import nucleus.factory.RequiresPresenter;
@RequiresPresenter(LibraryPresenter.class)
public class LibraryFragment extends BaseRxFragment<LibraryPresenter> {
@Bind(R.id.gridView) GridView grid;
private LibraryAdapter adapter;
public static LibraryFragment newInstance() {
LibraryFragment fragment = new LibraryFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_library, container, false);
setToolbarTitle(getString(R.string.library_title));
ButterKnife.bind(this, view);
createAdapter();
setMangaLongClickListener();
return view;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.library, menu);
initializeSearch(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_refresh:
if (!LibraryUpdateService.isRunning(getActivity())) {
Intent intent = LibraryUpdateService.getStartIntent(getActivity());
getActivity().startService(intent);
}
return true;
}
return super.onOptionsItemSelected(item);
}
private void initializeSearch(Menu menu) {
final SearchView sv = (SearchView) menu.findItem(R.id.action_search).getActionView();
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return true;
}
});
}
private void createAdapter() {
adapter = new LibraryAdapter(getActivity());
grid.setAdapter(adapter);
}
public void onNextMangas(List<Manga> mangas) {
adapter.setNewItems(mangas);
}
@OnItemClick(R.id.gridView)
protected void onMangaClick(int position) {
Intent intent = MangaActivity.newIntent(
getActivity(),
adapter.getItem(position)
);
getActivity().startActivity(intent);
}
private void setMangaLongClickListener() {
grid.setMultiChoiceModeListener(new GridView.MultiChoiceModeListener() {
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
mode.setTitle(getResources().getString(R.string.library_selection_title)
+ ": " + grid.getCheckedItemCount());
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.library_selection, menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.action_delete:
getPresenter().onDelete(grid.getCheckedItemPositions(), adapter);
mode.finish();
return true;
}
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
}
});
}
}
@@ -0,0 +1,57 @@
package eu.kanade.mangafeed.ui.library;
import android.view.View;
import android.widget.ImageView;
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.data.models.Manga;
import uk.co.ribot.easyadapter.ItemViewHolder;
import uk.co.ribot.easyadapter.PositionInfo;
import uk.co.ribot.easyadapter.annotations.LayoutId;
import uk.co.ribot.easyadapter.annotations.ViewId;
@LayoutId(R.layout.item_library)
public class LibraryHolder extends ItemViewHolder<Manga> {
@ViewId(R.id.thumbnailImage)
ImageView mThumbImage;
@ViewId(R.id.titleText)
TextView mTitleText;
@ViewId(R.id.unreadText)
TextView mUnreadText;
public LibraryHolder(View view) {
super(view);
}
public void onSetValues(Manga manga, PositionInfo positionInfo) {
mTitleText.setText(manga.title);
if (manga.unread > 0) {
mUnreadText.setVisibility(View.VISIBLE);
mUnreadText.setText(Integer.toString(manga.unread));
}
else {
mUnreadText.setVisibility(View.GONE);
}
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(mThumbImage);
}
}
@@ -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());
}
}