Change mangas from categories (needs testing)
This commit is contained in:
		
							parent
							
								
									3f1f9ea9f2
								
							
						
					
					
						commit
						1360a90bf9
					
				| @ -2,15 +2,18 @@ package eu.kanade.mangafeed.data.database; | |||||||
| 
 | 
 | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| 
 | 
 | ||||||
|  | import com.pushtorefresh.storio.Queries; | ||||||
| import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping; | import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping; | ||||||
| import com.pushtorefresh.storio.sqlite.StorIOSQLite; | import com.pushtorefresh.storio.sqlite.StorIOSQLite; | ||||||
| import com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite; | import com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite; | ||||||
|  | import com.pushtorefresh.storio.sqlite.operations.delete.PreparedDeleteByQuery; | ||||||
| import com.pushtorefresh.storio.sqlite.operations.delete.PreparedDeleteCollectionOfObjects; | import com.pushtorefresh.storio.sqlite.operations.delete.PreparedDeleteCollectionOfObjects; | ||||||
| import com.pushtorefresh.storio.sqlite.operations.delete.PreparedDeleteObject; | import com.pushtorefresh.storio.sqlite.operations.delete.PreparedDeleteObject; | ||||||
| import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetListOfObjects; | import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetListOfObjects; | ||||||
| import com.pushtorefresh.storio.sqlite.operations.put.PreparedPutCollectionOfObjects; | import com.pushtorefresh.storio.sqlite.operations.put.PreparedPutCollectionOfObjects; | ||||||
| import com.pushtorefresh.storio.sqlite.operations.put.PreparedPutObject; | import com.pushtorefresh.storio.sqlite.operations.put.PreparedPutObject; | ||||||
| import com.pushtorefresh.storio.sqlite.operations.put.PutResults; | import com.pushtorefresh.storio.sqlite.operations.put.PutResults; | ||||||
|  | import com.pushtorefresh.storio.sqlite.queries.DeleteQuery; | ||||||
| import com.pushtorefresh.storio.sqlite.queries.Query; | import com.pushtorefresh.storio.sqlite.queries.Query; | ||||||
| import com.pushtorefresh.storio.sqlite.queries.RawQuery; | import com.pushtorefresh.storio.sqlite.queries.RawQuery; | ||||||
| 
 | 
 | ||||||
| @ -386,9 +389,36 @@ public class DatabaseHelper { | |||||||
|                 .prepare(); |                 .prepare(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public PreparedPutCollectionOfObjects<MangaCategory> insertMangasCategory(List<MangaCategory> mangasCategory) { |     public PreparedPutCollectionOfObjects<MangaCategory> insertMangasCategories(List<MangaCategory> mangasCategories) { | ||||||
|         return db.put() |         return db.put() | ||||||
|                 .objects(mangasCategory) |                 .objects(mangasCategories) | ||||||
|                 .prepare(); |                 .prepare(); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     public PreparedDeleteByQuery deleteOldMangasCategories(List<Manga> mangas) { | ||||||
|  |         List<Long> mangaIds = Observable.from(mangas) | ||||||
|  |                 .map(manga -> manga.id) | ||||||
|  |                 .toList().toBlocking().single(); | ||||||
|  | 
 | ||||||
|  |         return db.delete() | ||||||
|  |                 .byQuery(DeleteQuery.builder() | ||||||
|  |                         .table(MangaCategoryTable.TABLE) | ||||||
|  |                         .where(MangaCategoryTable.COLUMN_MANGA_ID + " IN (" | ||||||
|  |                                 + Queries.placeholders(mangas.size()) + ")") | ||||||
|  |                         .whereArgs(mangaIds.toArray()) | ||||||
|  |                         .build()) | ||||||
|  |                 .prepare(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setMangaCategories(List<MangaCategory> mangasCategories, List<Manga> mangas) { | ||||||
|  |         db.internal().beginTransaction(); | ||||||
|  |         try { | ||||||
|  |             deleteOldMangasCategories(mangas).executeAsBlocking(); | ||||||
|  |             insertMangasCategories(mangasCategories).executeAsBlocking(); | ||||||
|  |             db.internal().setTransactionSuccessful(); | ||||||
|  |         } finally { | ||||||
|  |             db.internal().endTransaction(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| package eu.kanade.mangafeed.ui.reader.viewer.common; | package eu.kanade.mangafeed.ui.base.adapter; | ||||||
| 
 | 
 | ||||||
| import android.support.v4.app.Fragment; | import android.support.v4.app.Fragment; | ||||||
| import android.support.v4.app.FragmentManager; | import android.support.v4.app.FragmentManager; | ||||||
| @ -6,6 +6,9 @@ import android.support.v4.app.FragmentStatePagerAdapter; | |||||||
| import android.util.SparseArray; | import android.util.SparseArray; | ||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
| 
 | 
 | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
| public abstract class SmartFragmentStatePagerAdapter extends FragmentStatePagerAdapter { | public abstract class SmartFragmentStatePagerAdapter extends FragmentStatePagerAdapter { | ||||||
|     // Sparse array to keep track of registered fragments in memory |     // Sparse array to keep track of registered fragments in memory | ||||||
|     private SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>(); |     private SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>(); | ||||||
| @ -33,4 +36,13 @@ public abstract class SmartFragmentStatePagerAdapter extends FragmentStatePagerA | |||||||
|     public Fragment getRegisteredFragment(int position) { |     public Fragment getRegisteredFragment(int position) { | ||||||
|         return registeredFragments.get(position); |         return registeredFragments.get(position); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     public List<Fragment> getRegisteredFragments() { | ||||||
|  |         ArrayList<Fragment> fragments = new ArrayList<>(); | ||||||
|  |         for (int i = 0; i < registeredFragments.size(); i++) { | ||||||
|  |             fragments.add(registeredFragments.valueAt(i)); | ||||||
|  |         } | ||||||
|  |         return fragments; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| @ -2,15 +2,15 @@ package eu.kanade.mangafeed.ui.library; | |||||||
| 
 | 
 | ||||||
| import android.support.v4.app.Fragment; | import android.support.v4.app.Fragment; | ||||||
| import android.support.v4.app.FragmentManager; | import android.support.v4.app.FragmentManager; | ||||||
| import android.support.v4.app.FragmentStatePagerAdapter; |  | ||||||
| 
 | 
 | ||||||
| import java.util.List; | import java.util.List; | ||||||
| 
 | 
 | ||||||
| import eu.kanade.mangafeed.data.database.models.Category; | import eu.kanade.mangafeed.data.database.models.Category; | ||||||
|  | import eu.kanade.mangafeed.ui.base.adapter.SmartFragmentStatePagerAdapter; | ||||||
| 
 | 
 | ||||||
| class LibraryAdapter extends FragmentStatePagerAdapter { | public class LibraryAdapter extends SmartFragmentStatePagerAdapter { | ||||||
| 
 | 
 | ||||||
|     private List<Category> categories; |     protected List<Category> categories; | ||||||
| 
 | 
 | ||||||
|     public LibraryAdapter(FragmentManager fm) { |     public LibraryAdapter(FragmentManager fm) { | ||||||
|         super(fm); |         super(fm); | ||||||
| @ -18,8 +18,7 @@ class LibraryAdapter extends FragmentStatePagerAdapter { | |||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Fragment getItem(int position) { |     public Fragment getItem(int position) { | ||||||
|         Category category = categories.get(position); |         return LibraryCategoryFragment.newInstance(position); | ||||||
|         return LibraryCategoryFragment.newInstance(category); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
| @ -37,4 +36,10 @@ class LibraryAdapter extends FragmentStatePagerAdapter { | |||||||
|         notifyDataSetChanged(); |         notifyDataSetChanged(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public void setSelectionMode(int mode) { | ||||||
|  |         for (Fragment fragment : getRegisteredFragments()) { | ||||||
|  |             ((LibraryCategoryFragment) fragment).setMode(mode); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| @ -3,24 +3,22 @@ package eu.kanade.mangafeed.ui.library; | |||||||
| import android.content.Intent; | import android.content.Intent; | ||||||
| import android.content.res.Configuration; | import android.content.res.Configuration; | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| import android.support.v7.view.ActionMode; |  | ||||||
| import android.view.LayoutInflater; | import android.view.LayoutInflater; | ||||||
| import android.view.Menu; |  | ||||||
| import android.view.MenuItem; |  | ||||||
| import android.view.View; | import android.view.View; | ||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
| 
 | 
 | ||||||
| import com.f2prateek.rx.preferences.Preference; | import com.f2prateek.rx.preferences.Preference; | ||||||
| 
 | 
 | ||||||
|  | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| 
 | 
 | ||||||
| import butterknife.Bind; | import butterknife.Bind; | ||||||
| import butterknife.ButterKnife; | import butterknife.ButterKnife; | ||||||
|  | import eu.davidea.flexibleadapter.FlexibleAdapter; | ||||||
| import eu.kanade.mangafeed.R; | import eu.kanade.mangafeed.R; | ||||||
| import eu.kanade.mangafeed.data.database.models.Category; | import eu.kanade.mangafeed.data.database.models.Category; | ||||||
| import eu.kanade.mangafeed.data.database.models.Manga; | import eu.kanade.mangafeed.data.database.models.Manga; | ||||||
| import eu.kanade.mangafeed.event.LibraryMangasEvent; | import eu.kanade.mangafeed.event.LibraryMangasEvent; | ||||||
| import eu.kanade.mangafeed.ui.base.activity.BaseActivity; |  | ||||||
| import eu.kanade.mangafeed.ui.base.adapter.FlexibleViewHolder; | import eu.kanade.mangafeed.ui.base.adapter.FlexibleViewHolder; | ||||||
| import eu.kanade.mangafeed.ui.base.fragment.BaseFragment; | import eu.kanade.mangafeed.ui.base.fragment.BaseFragment; | ||||||
| import eu.kanade.mangafeed.ui.manga.MangaActivity; | import eu.kanade.mangafeed.ui.manga.MangaActivity; | ||||||
| @ -30,20 +28,19 @@ import icepick.Icepick; | |||||||
| import icepick.State; | import icepick.State; | ||||||
| import rx.Subscription; | import rx.Subscription; | ||||||
| 
 | 
 | ||||||
| public class LibraryCategoryFragment extends BaseFragment implements | public class LibraryCategoryFragment extends BaseFragment | ||||||
|         ActionMode.Callback, FlexibleViewHolder.OnListItemClickListener { |         implements FlexibleViewHolder.OnListItemClickListener { | ||||||
| 
 | 
 | ||||||
|     @Bind(R.id.library_mangas) AutofitRecyclerView recycler; |     @Bind(R.id.library_mangas) AutofitRecyclerView recycler; | ||||||
| 
 | 
 | ||||||
|     @State Category category; |     @State int position; | ||||||
|     private LibraryCategoryAdapter adapter; |     private LibraryCategoryAdapter adapter; | ||||||
|     private ActionMode actionMode; |  | ||||||
| 
 | 
 | ||||||
|     private Subscription numColumnsSubscription; |     private Subscription numColumnsSubscription; | ||||||
| 
 | 
 | ||||||
|     public static LibraryCategoryFragment newInstance(Category category) { |     public static LibraryCategoryFragment newInstance(int position) { | ||||||
|         LibraryCategoryFragment fragment = new LibraryCategoryFragment(); |         LibraryCategoryFragment fragment = new LibraryCategoryFragment(); | ||||||
|         fragment.category = category; |         fragment.position = position; | ||||||
|         return fragment; |         return fragment; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -54,11 +51,14 @@ public class LibraryCategoryFragment extends BaseFragment implements | |||||||
|         ButterKnife.bind(this, view); |         ButterKnife.bind(this, view); | ||||||
|         Icepick.restoreInstanceState(this, savedState); |         Icepick.restoreInstanceState(this, savedState); | ||||||
| 
 | 
 | ||||||
|         recycler.setHasFixedSize(true); |  | ||||||
| 
 |  | ||||||
|         adapter = new LibraryCategoryAdapter(this); |         adapter = new LibraryCategoryAdapter(this); | ||||||
|  |         recycler.setHasFixedSize(true); | ||||||
|         recycler.setAdapter(adapter); |         recycler.setAdapter(adapter); | ||||||
| 
 | 
 | ||||||
|  |         if (getLibraryFragment().getActionMode() != null) { | ||||||
|  |             setMode(FlexibleAdapter.MODE_MULTI); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         Preference<Integer> columnsPref = getResources().getConfiguration() |         Preference<Integer> columnsPref = getResources().getConfiguration() | ||||||
|                 .orientation == Configuration.ORIENTATION_PORTRAIT ? |                 .orientation == Configuration.ORIENTATION_PORTRAIT ? | ||||||
|                 getLibraryPresenter().preferences.portraitColumns() : |                 getLibraryPresenter().preferences.portraitColumns() : | ||||||
| @ -67,6 +67,14 @@ public class LibraryCategoryFragment extends BaseFragment implements | |||||||
|         numColumnsSubscription = columnsPref.asObservable() |         numColumnsSubscription = columnsPref.asObservable() | ||||||
|                 .subscribe(recycler::setSpanCount); |                 .subscribe(recycler::setSpanCount); | ||||||
| 
 | 
 | ||||||
|  |         if (savedState != null) { | ||||||
|  |             adapter.onRestoreInstanceState(savedState); | ||||||
|  | 
 | ||||||
|  |             if (adapter.getMode() == FlexibleAdapter.MODE_SINGLE) { | ||||||
|  |                 adapter.clearSelection(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         return view; |         return view; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -91,13 +99,23 @@ public class LibraryCategoryFragment extends BaseFragment implements | |||||||
|     @Override |     @Override | ||||||
|     public void onSaveInstanceState(Bundle outState) { |     public void onSaveInstanceState(Bundle outState) { | ||||||
|         Icepick.saveInstanceState(this, outState); |         Icepick.saveInstanceState(this, outState); | ||||||
|  |         adapter.onSaveInstanceState(outState); | ||||||
|         super.onSaveInstanceState(outState); |         super.onSaveInstanceState(outState); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @EventBusHook |     @EventBusHook | ||||||
|     public void onEventMainThread(LibraryMangasEvent event) { |     public void onEventMainThread(LibraryMangasEvent event) { | ||||||
|         destroyActionModeIfNeeded(); |         List<Category> categories = getLibraryFragment().getAdapter().categories; | ||||||
|         setMangas(event.getMangas().get(category.id)); |         // When a category is deleted, the index can be greater than the number of categories | ||||||
|  |         if (position >= categories.size()) | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|  |         Category category = categories.get(position); | ||||||
|  |         List<Manga> mangas = event.getMangas().get(category.id); | ||||||
|  |         if (mangas == null) { | ||||||
|  |             mangas = new ArrayList<>(); | ||||||
|  |         } | ||||||
|  |         setMangas(mangas); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     protected void openManga(Manga manga) { |     protected void openManga(Manga manga) { | ||||||
| @ -115,7 +133,7 @@ public class LibraryCategoryFragment extends BaseFragment implements | |||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public boolean onListItemClick(int position) { |     public boolean onListItemClick(int position) { | ||||||
|         if (actionMode != null && position != -1) { |         if (getLibraryFragment().getActionMode() != null && position != -1) { | ||||||
|             toggleSelection(position); |             toggleSelection(position); | ||||||
|             return true; |             return true; | ||||||
|         } else { |         } else { | ||||||
| @ -126,55 +144,29 @@ public class LibraryCategoryFragment extends BaseFragment implements | |||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void onListItemLongClick(int position) { |     public void onListItemLongClick(int position) { | ||||||
|         if (actionMode == null) |         getLibraryFragment().createActionModeIfNeeded(); | ||||||
|             actionMode = ((BaseActivity) getActivity()).startSupportActionMode(this); |  | ||||||
| 
 |  | ||||||
|         toggleSelection(position); |         toggleSelection(position); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void toggleSelection(int position) { |     private void toggleSelection(int position) { | ||||||
|         adapter.toggleSelection(position, false); |         LibraryFragment f = getLibraryFragment(); | ||||||
| 
 | 
 | ||||||
|         int count = adapter.getSelectedItemCount(); |         adapter.toggleSelection(position, false); | ||||||
|  |         f.getPresenter().setSelection(adapter.getItem(position), adapter.isSelected(position)); | ||||||
|  | 
 | ||||||
|  |         int count = f.getPresenter().selectedMangas.size(); | ||||||
|         if (count == 0) { |         if (count == 0) { | ||||||
|             actionMode.finish(); |             f.destroyActionModeIfNeeded(); | ||||||
|         } else { |         } else { | ||||||
|             setContextTitle(count); |             f.setContextTitle(count); | ||||||
|             actionMode.invalidate(); |             f.invalidateActionMode(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void setContextTitle(int count) { |     public void setMode(int mode) { | ||||||
|         actionMode.setTitle(getString(R.string.label_selected, count)); |         adapter.setMode(mode); | ||||||
|     } |         if (mode == FlexibleAdapter.MODE_SINGLE) { | ||||||
| 
 |             adapter.clearSelection(); | ||||||
|     @Override |  | ||||||
|     public boolean onCreateActionMode(ActionMode mode, Menu menu) { |  | ||||||
|         mode.getMenuInflater().inflate(R.menu.library_selection, menu); |  | ||||||
|         adapter.setMode(LibraryCategoryAdapter.MODE_MULTI); |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public boolean onPrepareActionMode(ActionMode mode, Menu menu) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public boolean onActionItemClicked(ActionMode mode, MenuItem item) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public void onDestroyActionMode(ActionMode mode) { |  | ||||||
|         adapter.setMode(LibraryCategoryAdapter.MODE_SINGLE); |  | ||||||
|         adapter.clearSelection(); |  | ||||||
|         actionMode = null; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public void destroyActionModeIfNeeded() { |  | ||||||
|         if (actionMode != null) { |  | ||||||
|             actionMode.finish(); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,10 +2,12 @@ package eu.kanade.mangafeed.ui.library; | |||||||
| 
 | 
 | ||||||
| import android.content.Intent; | import android.content.Intent; | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
|  | import android.support.annotation.Nullable; | ||||||
| import android.support.design.widget.AppBarLayout; | import android.support.design.widget.AppBarLayout; | ||||||
| import android.support.design.widget.TabLayout; | import android.support.design.widget.TabLayout; | ||||||
| import android.support.v4.app.Fragment; | import android.support.v4.app.Fragment; | ||||||
| import android.support.v4.view.ViewPager; | import android.support.v4.view.ViewPager; | ||||||
|  | import android.support.v7.view.ActionMode; | ||||||
| import android.view.LayoutInflater; | import android.view.LayoutInflater; | ||||||
| import android.view.Menu; | import android.view.Menu; | ||||||
| import android.view.MenuInflater; | import android.view.MenuInflater; | ||||||
| @ -13,21 +15,27 @@ import android.view.MenuItem; | |||||||
| import android.view.View; | import android.view.View; | ||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
| 
 | 
 | ||||||
|  | import com.afollestad.materialdialogs.MaterialDialog; | ||||||
|  | 
 | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| 
 | 
 | ||||||
| import butterknife.Bind; | import butterknife.Bind; | ||||||
| import butterknife.ButterKnife; | import butterknife.ButterKnife; | ||||||
|  | import eu.davidea.flexibleadapter.FlexibleAdapter; | ||||||
| import eu.kanade.mangafeed.R; | import eu.kanade.mangafeed.R; | ||||||
| import eu.kanade.mangafeed.data.database.models.Category; | 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.data.sync.LibraryUpdateService; | ||||||
|  | import eu.kanade.mangafeed.ui.base.activity.BaseActivity; | ||||||
| import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment; | import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment; | ||||||
| import eu.kanade.mangafeed.ui.library.category.CategoryFragment; | import eu.kanade.mangafeed.ui.library.category.CategoryFragment; | ||||||
| import eu.kanade.mangafeed.ui.main.MainActivity; | import eu.kanade.mangafeed.ui.main.MainActivity; | ||||||
| import nucleus.factory.RequiresPresenter; | import nucleus.factory.RequiresPresenter; | ||||||
| 
 | 
 | ||||||
| @RequiresPresenter(LibraryPresenter.class) | @RequiresPresenter(LibraryPresenter.class) | ||||||
| public class LibraryFragment extends BaseRxFragment<LibraryPresenter> { | public class LibraryFragment extends BaseRxFragment<LibraryPresenter> | ||||||
|  |         implements ActionMode.Callback { | ||||||
| 
 | 
 | ||||||
|     TabLayout tabs; |     TabLayout tabs; | ||||||
|     AppBarLayout appBar; |     AppBarLayout appBar; | ||||||
| @ -35,6 +43,8 @@ public class LibraryFragment extends BaseRxFragment<LibraryPresenter> { | |||||||
|     @Bind(R.id.view_pager) ViewPager categoriesPager; |     @Bind(R.id.view_pager) ViewPager categoriesPager; | ||||||
|     protected LibraryAdapter adapter; |     protected LibraryAdapter adapter; | ||||||
| 
 | 
 | ||||||
|  |     private ActionMode actionMode; | ||||||
|  | 
 | ||||||
|     public static LibraryFragment newInstance() { |     public static LibraryFragment newInstance() { | ||||||
|         return new LibraryFragment(); |         return new LibraryFragment(); | ||||||
|     } |     } | ||||||
| @ -83,7 +93,6 @@ public class LibraryFragment extends BaseRxFragment<LibraryPresenter> { | |||||||
|                     Intent intent = LibraryUpdateService.getStartIntent(getActivity()); |                     Intent intent = LibraryUpdateService.getStartIntent(getActivity()); | ||||||
|                     getActivity().startService(intent); |                     getActivity().startService(intent); | ||||||
|                 } |                 } | ||||||
| 
 |  | ||||||
|                 return true; |                 return true; | ||||||
|             case R.id.action_edit_categories: |             case R.id.action_edit_categories: | ||||||
|                 onEditCategories(); |                 onEditCategories(); | ||||||
| @ -112,4 +121,77 @@ public class LibraryFragment extends BaseRxFragment<LibraryPresenter> { | |||||||
|         tabs.setVisibility(actualCategories.size() == 1 ? View.GONE : View.VISIBLE); |         tabs.setVisibility(actualCategories.size() == 1 ? View.GONE : View.VISIBLE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public void setContextTitle(int count) { | ||||||
|  |         actionMode.setTitle(getString(R.string.label_selected, count)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public boolean onCreateActionMode(ActionMode mode, Menu menu) { | ||||||
|  |         mode.getMenuInflater().inflate(R.menu.library_selection, menu); | ||||||
|  |         adapter.setSelectionMode(FlexibleAdapter.MODE_MULTI); | ||||||
|  |         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_move_to_category: | ||||||
|  |                 moveMangasToCategories(getPresenter().selectedMangas); | ||||||
|  |                 return true; | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void onDestroyActionMode(ActionMode mode) { | ||||||
|  |         adapter.setSelectionMode(FlexibleAdapter.MODE_SINGLE); | ||||||
|  |         getPresenter().selectedMangas.clear(); | ||||||
|  |         actionMode = null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void destroyActionModeIfNeeded() { | ||||||
|  |         if (actionMode != null) { | ||||||
|  |             actionMode.finish(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void moveMangasToCategories(List<Manga> mangas) { | ||||||
|  |         new MaterialDialog.Builder(getActivity()) | ||||||
|  |                 .title(R.string.action_move_category) | ||||||
|  |                 .items(getPresenter().getCategoriesNames()) | ||||||
|  |                 .itemsCallbackMultiChoice(null, (dialog, which, text) -> { | ||||||
|  |                     getPresenter().moveMangasToCategories(which, mangas); | ||||||
|  |                     destroyActionModeIfNeeded(); | ||||||
|  |                     return true; | ||||||
|  |                 }) | ||||||
|  |                 .positiveText(R.string.button_ok) | ||||||
|  |                 .negativeText(R.string.button_cancel) | ||||||
|  |                 .show(); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Nullable | ||||||
|  |     public ActionMode getActionMode() { | ||||||
|  |         return actionMode; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public LibraryAdapter getAdapter() { | ||||||
|  |         return adapter; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void createActionModeIfNeeded() { | ||||||
|  |         if (actionMode == null) { | ||||||
|  |             actionMode = ((BaseActivity) getActivity()).startSupportActionMode(this); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void invalidateActionMode() { | ||||||
|  |         actionMode.invalidate(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ package eu.kanade.mangafeed.ui.library; | |||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| import android.util.Pair; | import android.util.Pair; | ||||||
| 
 | 
 | ||||||
|  | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| 
 | 
 | ||||||
| @ -13,6 +14,7 @@ import eu.kanade.mangafeed.data.cache.CoverCache; | |||||||
| import eu.kanade.mangafeed.data.database.DatabaseHelper; | import eu.kanade.mangafeed.data.database.DatabaseHelper; | ||||||
| import eu.kanade.mangafeed.data.database.models.Category; | import eu.kanade.mangafeed.data.database.models.Category; | ||||||
| import eu.kanade.mangafeed.data.database.models.Manga; | import eu.kanade.mangafeed.data.database.models.Manga; | ||||||
|  | import eu.kanade.mangafeed.data.database.models.MangaCategory; | ||||||
| import eu.kanade.mangafeed.data.preference.PreferencesHelper; | import eu.kanade.mangafeed.data.preference.PreferencesHelper; | ||||||
| import eu.kanade.mangafeed.data.source.SourceManager; | import eu.kanade.mangafeed.data.source.SourceManager; | ||||||
| import eu.kanade.mangafeed.event.LibraryMangasEvent; | import eu.kanade.mangafeed.event.LibraryMangasEvent; | ||||||
| @ -29,6 +31,7 @@ public class LibraryPresenter extends BasePresenter<LibraryFragment> { | |||||||
|     @Inject SourceManager sourceManager; |     @Inject SourceManager sourceManager; | ||||||
| 
 | 
 | ||||||
|     protected List<Category> categories; |     protected List<Category> categories; | ||||||
|  |     protected List<Manga> selectedMangas; | ||||||
| 
 | 
 | ||||||
|     private static final int GET_CATEGORIES = 1; |     private static final int GET_CATEGORIES = 1; | ||||||
| 
 | 
 | ||||||
| @ -36,6 +39,8 @@ public class LibraryPresenter extends BasePresenter<LibraryFragment> { | |||||||
|     protected void onCreate(Bundle savedState) { |     protected void onCreate(Bundle savedState) { | ||||||
|         super.onCreate(savedState); |         super.onCreate(savedState); | ||||||
| 
 | 
 | ||||||
|  |         selectedMangas = new ArrayList<>(); | ||||||
|  | 
 | ||||||
|         restartableLatestCache(GET_CATEGORIES, |         restartableLatestCache(GET_CATEGORIES, | ||||||
|                 this::getCategoriesObservable, |                 this::getCategoriesObservable, | ||||||
|                 LibraryFragment::onNextCategories); |                 LibraryFragment::onNextCategories); | ||||||
| @ -48,6 +53,12 @@ public class LibraryPresenter extends BasePresenter<LibraryFragment> { | |||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|  |     protected void onDestroy() { | ||||||
|  |         EventBus.getDefault().removeStickyEvent(LibraryMangasEvent.class); | ||||||
|  |         super.onDestroy(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public Observable<List<Category>> getCategoriesObservable() { |     public Observable<List<Category>> getCategoriesObservable() { | ||||||
|         return db.getCategories().createObservable() |         return db.getCategories().createObservable() | ||||||
|                 .doOnNext(categories -> this.categories = categories) |                 .doOnNext(categories -> this.categories = categories) | ||||||
| @ -72,5 +83,43 @@ public class LibraryPresenter extends BasePresenter<LibraryFragment> { | |||||||
|                 .subscribe()); |                 .subscribe()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public void setSelection(Manga manga, boolean selected) { | ||||||
|  |         if (selected) { | ||||||
|  |             selectedMangas.add(manga); | ||||||
|  |         } else { | ||||||
|  |             selectedMangas.remove(manga); | ||||||
|  |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|  |     public String[] getCategoriesNames() { | ||||||
|  |         int count = categories.size(); | ||||||
|  |         String[] names = new String[count]; | ||||||
|  | 
 | ||||||
|  |         for (int i = 0; i < count; i++) { | ||||||
|  |             names[i] = categories.get(i).name; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return names; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void moveMangasToCategories(Integer[] positions, List<Manga> mangas) { | ||||||
|  |         List<Category> categoriesToAdd = new ArrayList<>(); | ||||||
|  |         for (Integer index : positions) { | ||||||
|  |             categoriesToAdd.add(categories.get(index)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         moveMangasToCategories(categoriesToAdd, mangas); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void moveMangasToCategories(List<Category> categories, List<Manga> mangas) { | ||||||
|  |         List<MangaCategory> mc = new ArrayList<>(); | ||||||
|  | 
 | ||||||
|  |         for (Manga manga : mangas) { | ||||||
|  |             for (Category cat : categories) { | ||||||
|  |                 mc.add(MangaCategory.create(manga, cat)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         db.setMangaCategories(mc, mangas); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ import android.support.v4.app.FragmentManager; | |||||||
| import java.util.List; | import java.util.List; | ||||||
| 
 | 
 | ||||||
| import eu.kanade.mangafeed.data.source.model.Page; | import eu.kanade.mangafeed.data.source.model.Page; | ||||||
|  | import eu.kanade.mangafeed.ui.base.adapter.SmartFragmentStatePagerAdapter; | ||||||
| 
 | 
 | ||||||
| public class ViewPagerReaderAdapter extends SmartFragmentStatePagerAdapter { | public class ViewPagerReaderAdapter extends SmartFragmentStatePagerAdapter { | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-hdpi/ic_label.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable-hdpi/ic_label.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 244 B | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-ldpi/ic_label.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable-ldpi/ic_label.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 205 B | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-mdpi/ic_label.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable-mdpi/ic_label.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 177 B | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xhdpi/ic_label.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xhdpi/ic_label.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 295 B | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xxhdpi/ic_label.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xxhdpi/ic_label.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 404 B | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xxxhdpi/ic_label.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xxxhdpi/ic_label.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 525 B | 
| @ -1,12 +1,16 @@ | |||||||
| <?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||||||
| 
 | 
 | ||||||
| <menu xmlns:android="http://schemas.android.com/apk/res/android" | <menu xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|     xmlns:app="http://schemas.android.com/apk/res-auto"> |       xmlns:app="http://schemas.android.com/apk/res-auto"> | ||||||
|  | 
 | ||||||
|  |     <item android:id="@+id/action_move_to_category" | ||||||
|  |           android:title="@string/action_move_category" | ||||||
|  |           android:icon="@drawable/ic_label" | ||||||
|  |           app:showAsAction="ifRoom"/> | ||||||
| 
 | 
 | ||||||
|     <item android:id="@+id/action_delete" |     <item android:id="@+id/action_delete" | ||||||
|         android:title="@string/action_delete" |           android:title="@string/action_delete" | ||||||
|         android:icon="@drawable/ic_action_delete" |           android:icon="@drawable/ic_action_delete" | ||||||
|         android:orderInCategory="1" |           app:showAsAction="ifRoom"/> | ||||||
|         app:showAsAction="always"/> |  | ||||||
| 
 | 
 | ||||||
| </menu> | </menu> | ||||||
| @ -25,6 +25,7 @@ | |||||||
|     <string name="action_add_category">Add category</string> |     <string name="action_add_category">Add category</string> | ||||||
|     <string name="action_edit_categories">Edit categories</string> |     <string name="action_edit_categories">Edit categories</string> | ||||||
|     <string name="action_rename_category">Rename category</string> |     <string name="action_rename_category">Rename category</string> | ||||||
|  |     <string name="action_move_category">Move to categories</string> | ||||||
|     <string name="action_sort_up">Sort up</string> |     <string name="action_sort_up">Sort up</string> | ||||||
|     <string name="action_sort_down">Sort down</string> |     <string name="action_sort_down">Sort down</string> | ||||||
|     <string name="action_show_unread">Unread</string> |     <string name="action_show_unread">Unread</string> | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 inorichi
						inorichi