diff --git a/app/src/main/java/eu/kanade/mangafeed/data/database/DatabaseHelper.java b/app/src/main/java/eu/kanade/mangafeed/data/database/DatabaseHelper.java index 66b906908d..31deeda4fb 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/database/DatabaseHelper.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/database/DatabaseHelper.java @@ -39,6 +39,7 @@ import eu.kanade.mangafeed.data.database.models.MangaSyncStorIOSQLitePutResolver import eu.kanade.mangafeed.data.database.resolvers.LibraryMangaGetResolver; import eu.kanade.mangafeed.data.database.tables.CategoryTable; import eu.kanade.mangafeed.data.database.tables.ChapterTable; +import eu.kanade.mangafeed.data.database.tables.MangaCategoryTable; import eu.kanade.mangafeed.data.database.tables.MangaSyncTable; import eu.kanade.mangafeed.data.database.tables.MangaTable; import eu.kanade.mangafeed.data.mangasync.base.MangaSyncService; @@ -98,7 +99,7 @@ public class DatabaseHelper { .listOfObjects(Manga.class) .withQuery(RawQuery.builder() .query(LibraryMangaGetResolver.QUERY) - .observesTables(MangaTable.TABLE, ChapterTable.TABLE, CategoryTable.TABLE) + .observesTables(MangaTable.TABLE, ChapterTable.TABLE, MangaCategoryTable.TABLE) .build()) .withGetResolver(LibraryMangaGetResolver.INSTANCE) .prepare(); diff --git a/app/src/main/java/eu/kanade/mangafeed/data/database/models/Category.java b/app/src/main/java/eu/kanade/mangafeed/data/database/models/Category.java index 135942c76e..a06882af59 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/database/models/Category.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/database/models/Category.java @@ -11,7 +11,7 @@ import eu.kanade.mangafeed.data.database.tables.CategoryTable; public class Category implements Serializable { @StorIOSQLiteColumn(name = CategoryTable.COLUMN_ID, key = true) - public Long id; + public Integer id; @StorIOSQLiteColumn(name = CategoryTable.COLUMN_NAME) public String name; diff --git a/app/src/main/java/eu/kanade/mangafeed/data/database/models/Manga.java b/app/src/main/java/eu/kanade/mangafeed/data/database/models/Manga.java index 340f3f3cca..d76c60c940 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/database/models/Manga.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/database/models/Manga.java @@ -58,7 +58,7 @@ public class Manga implements Serializable { public int unread; - public long category; + public int category; public Manga() {} diff --git a/app/src/main/java/eu/kanade/mangafeed/data/database/models/MangaCategory.java b/app/src/main/java/eu/kanade/mangafeed/data/database/models/MangaCategory.java index 5877f644d5..802e0dac30 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/database/models/MangaCategory.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/database/models/MangaCategory.java @@ -15,7 +15,7 @@ public class MangaCategory { public long manga_id; @StorIOSQLiteColumn(name = MangaCategoryTable.COLUMN_CATEGORY_ID) - public long category_id; + public int category_id; public MangaCategory() {} diff --git a/app/src/main/java/eu/kanade/mangafeed/data/database/resolvers/LibraryMangaGetResolver.java b/app/src/main/java/eu/kanade/mangafeed/data/database/resolvers/LibraryMangaGetResolver.java index 848829ffc6..0044644926 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/database/resolvers/LibraryMangaGetResolver.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/database/resolvers/LibraryMangaGetResolver.java @@ -53,7 +53,7 @@ public class LibraryMangaGetResolver extends MangaStorIOSQLiteGetResolver { manga.unread = cursor.getInt(unreadColumn); int categoryColumn = cursor.getColumnIndex(MangaTable.COLUMN_CATEGORY); - manga.category = cursor.getLong(categoryColumn); + manga.category = cursor.getInt(categoryColumn); return manga; } diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryCategoryAdapter.java b/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryCategoryAdapter.java new file mode 100644 index 0000000000..c2227bcb34 --- /dev/null +++ b/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryCategoryAdapter.java @@ -0,0 +1,69 @@ +package eu.kanade.mangafeed.ui.library; + +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; + +import java.util.List; +import java.util.Map; + +import eu.kanade.mangafeed.data.database.models.Category; +import eu.kanade.mangafeed.data.database.models.Manga; +import eu.kanade.mangafeed.ui.reader.viewer.common.SmartFragmentStatePagerAdapter; + +class LibraryCategoryAdapter extends SmartFragmentStatePagerAdapter { + + private LibraryFragment fragment; + private List categories; + private Map> mangas; + + public LibraryCategoryAdapter(LibraryFragment fragment, FragmentManager fm) { + super(fm); + this.fragment = fragment; + } + + @Override + public Fragment getItem(int position) { + Category category = categories.get(position); + return LibraryCategoryFragment.newInstance(fragment, category, + mangas != null ? mangas.get(category.id) : null); + } + + @Override + public int getCount() { + return categories == null ? 0 : categories.size(); + } + + @Override + public CharSequence getPageTitle(int position) { + return categories.get(position).name; + } + + public void setCategories(List categories) { + this.categories = categories; + notifyDataSetChanged(); + } + + public void setMangasOnCategories(Map> mangas) { + this.mangas = mangas; + for (Map.Entry> entry : mangas.entrySet()) { + LibraryCategoryFragment fragment = getFragment(entry.getKey()); + if (fragment != null) { + fragment.setMangas(entry.getValue()); + } + } + } + + @Nullable + public LibraryCategoryFragment getFragment(int categoryId) { + if (categories != null) { + for (int i = 0; i < categories.size(); i++) { + if (categories.get(i).id == categoryId) { + return (LibraryCategoryFragment) getRegisteredFragment(i); + } + } + } + return null; + } + +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryCategoryFragment.java b/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryCategoryFragment.java new file mode 100644 index 0000000000..59fd7dd006 --- /dev/null +++ b/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryCategoryFragment.java @@ -0,0 +1,75 @@ +package eu.kanade.mangafeed.ui.library; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +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.database.models.Category; +import eu.kanade.mangafeed.data.database.models.Manga; +import eu.kanade.mangafeed.ui.base.fragment.BaseFragment; +import eu.kanade.mangafeed.ui.manga.MangaActivity; + +public class LibraryCategoryFragment extends BaseFragment { + + @Bind(R.id.gridView) GridView grid; + + private LibraryFragment parent; + private LibraryAdapter adapter; + private Category category; + private List mangas; + + public static LibraryCategoryFragment newInstance(LibraryFragment parent, Category category, + List mangas) { + LibraryCategoryFragment fragment = new LibraryCategoryFragment(); + fragment.initialize(parent, category, mangas); + return fragment; + } + + private void initialize(LibraryFragment parent, Category category, List mangas) { + this.parent = parent; + this.category = category; + this.mangas = mangas; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View view = inflater.inflate(R.layout.fragment_library_category, container, false); + ButterKnife.bind(this, view); + + adapter = new LibraryAdapter(parent); + grid.setAdapter(adapter); + + if (mangas != null) { + setMangas(mangas); + } + + return view; + } + + @OnItemClick(R.id.gridView) + protected void onMangaClick(int position) { + Intent intent = MangaActivity.newIntent( + getActivity(), + adapter.getItem(position) + ); + parent.getPresenter().onOpenManga(); + getActivity().startActivity(intent); + } + + public void setMangas(List mangas) { + adapter.setNewItems(mangas); + } + +} diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryFragment.java b/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryFragment.java index 57757a2938..6b3cd743b3 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryFragment.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryFragment.java @@ -2,35 +2,34 @@ package eu.kanade.mangafeed.ui.library; import android.content.Intent; import android.os.Bundle; -import android.support.v7.widget.SearchView; -import android.util.SparseBooleanArray; -import android.view.ActionMode; +import android.support.design.widget.TabLayout; +import android.support.v4.view.ViewPager; 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.ArrayList; import java.util.List; +import java.util.Map; import butterknife.Bind; import butterknife.ButterKnife; -import butterknife.OnItemClick; import eu.kanade.mangafeed.R; +import eu.kanade.mangafeed.data.database.models.Category; import eu.kanade.mangafeed.data.database.models.Manga; import eu.kanade.mangafeed.data.sync.LibraryUpdateService; import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment; -import eu.kanade.mangafeed.ui.manga.MangaActivity; import nucleus.factory.RequiresPresenter; -import rx.Observable; @RequiresPresenter(LibraryPresenter.class) public class LibraryFragment extends BaseRxFragment { - @Bind(R.id.gridView) GridView grid; - private LibraryAdapter adapter; + @Bind(R.id.tabs) TabLayout tabs; + @Bind(R.id.view_pager) ViewPager categoriesPager; + private LibraryCategoryAdapter adapter; public static LibraryFragment newInstance() { return new LibraryFragment(); @@ -50,8 +49,8 @@ public class LibraryFragment extends BaseRxFragment { setToolbarTitle(getString(R.string.label_library)); ButterKnife.bind(this, view); - createAdapter(); - setMangaLongClickListener(); + adapter = new LibraryCategoryAdapter(this, getChildFragmentManager()); + categoriesPager.setAdapter(adapter); return view; } @@ -59,7 +58,6 @@ public class LibraryFragment extends BaseRxFragment { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.library, menu); - initializeSearch(menu); } @Override @@ -77,83 +75,21 @@ public class LibraryFragment extends BaseRxFragment { 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; - } - }); + public void onNextMangas(Map> mangas) { + adapter.setMangasOnCategories(mangas); } - private void createAdapter() { - adapter = new LibraryAdapter(this); - grid.setAdapter(adapter); - } + public void onNextCategories(List categories) { + List actualCategories = new ArrayList<>(); - public void onNextMangas(List mangas) { - adapter.setNewItems(mangas); - } + // TODO should we always add this? + Category defaultCat = Category.create("Default"); + defaultCat.id = 0; + actualCategories.add(defaultCat); - @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().deleteMangas(getSelectedMangas()); - mode.finish(); - return true; - } - return false; - } - - @Override - public void onDestroyActionMode(ActionMode mode) { - - } - }); - } - - private Observable getSelectedMangas() { - SparseBooleanArray checkedItems = grid.getCheckedItemPositions(); - return Observable.range(0, checkedItems.size()) - .map(checkedItems::keyAt) - .map(adapter::getItem); + actualCategories.addAll(categories); + adapter.setCategories(actualCategories); + tabs.setupWithViewPager(categoriesPager); } } diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryPresenter.java b/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryPresenter.java index 6d5d499865..7336920bb0 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryPresenter.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryPresenter.java @@ -10,6 +10,7 @@ import javax.inject.Inject; import eu.kanade.mangafeed.data.cache.CoverCache; import eu.kanade.mangafeed.data.database.DatabaseHelper; +import eu.kanade.mangafeed.data.database.models.Category; import eu.kanade.mangafeed.data.database.models.Manga; import eu.kanade.mangafeed.data.preference.PreferencesHelper; import eu.kanade.mangafeed.data.source.SourceManager; @@ -25,18 +26,31 @@ public class LibraryPresenter extends BasePresenter { @Inject CoverCache coverCache; @Inject SourceManager sourceManager; - private static final int GET_MANGAS = 1; + private static final int GET_CATEGORIES = 1; + private static final int GET_MANGAS = 2; @Override protected void onCreate(Bundle savedState) { super.onCreate(savedState); + restartableLatestCache(GET_CATEGORIES, + () -> db.getCategories().createObservable(), + LibraryFragment::onNextCategories); + restartableLatestCache(GET_MANGAS, - () -> db.getLibraryMangas().createObservable() - .observeOn(AndroidSchedulers.mainThread()), + this::getLibraryMangasObservable, LibraryFragment::onNextMangas); - start(GET_MANGAS); + start(GET_CATEGORIES); + } + + @Override + protected void onTakeView(LibraryFragment view) { + super.onTakeView(view); + + if (!isSubscribed(GET_MANGAS)) { + start(GET_MANGAS); + } } public void deleteMangas(Observable selectedMangas) { @@ -48,12 +62,17 @@ public class LibraryPresenter extends BasePresenter { .subscribe()); } - public Observable>> getLibraryMangasObservable() { + public Observable>> getLibraryMangasObservable() { return db.getLibraryMangas().createObservable() .flatMap(mangas -> Observable.from(mangas) .groupBy(manga -> manga.category) - .flatMap(group -> group.toList().map(list -> new Pair<>(group.getKey(), list))) - .toMap(pair -> pair.first, pair -> pair.second)); + .flatMap(group -> group.toList() + .map(list -> Pair.create(group.getKey(), list))) + .toMap(pair -> pair.first, pair -> pair.second)) + .observeOn(AndroidSchedulers.mainThread()); } + public void onOpenManga() { + stop(GET_MANGAS); + } } diff --git a/app/src/main/res/layout/fragment_library.xml b/app/src/main/res/layout/fragment_library.xml index 7739f760e4..f5db4a4fc2 100644 --- a/app/src/main/res/layout/fragment_library.xml +++ b/app/src/main/res/layout/fragment_library.xml @@ -1,13 +1,32 @@ - + - + - + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_library_category.xml b/app/src/main/res/layout/fragment_library_category.xml new file mode 100644 index 0000000000..173caa14b3 --- /dev/null +++ b/app/src/main/res/layout/fragment_library_category.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file