Change mangas from categories (needs testing)
This commit is contained in:
parent
3f1f9ea9f2
commit
1360a90bf9
15 changed files with 245 additions and 69 deletions
|
@ -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>
|
||||||
|
|
Reference in a new issue