mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-21 20:47:03 -05:00
Allow to create/remove categories. Some refactoring.
This commit is contained in:
parent
3dff7f90e7
commit
e548cbf171
31 changed files with 539 additions and 75 deletions
|
@ -113,6 +113,7 @@ dependencies {
|
|||
compile 'com.github.dmytrodanylyk.android-process-button:library:1.0.4'
|
||||
compile 'eu.davidea:flexible-adapter:4.2.0@aar'
|
||||
compile 'com.nononsenseapps:filepicker:2.5.0'
|
||||
compile 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
|
||||
|
||||
compile "com.google.dagger:dagger:$DAGGER_VERSION"
|
||||
apt "com.google.dagger:dagger-compiler:$DAGGER_VERSION"
|
||||
|
|
|
@ -367,6 +367,12 @@ public class DatabaseHelper {
|
|||
.prepare();
|
||||
}
|
||||
|
||||
public PreparedDeleteCollectionOfObjects<Category> deleteCategories(List<Category> categories) {
|
||||
return db.delete()
|
||||
.objects(categories)
|
||||
.prepare();
|
||||
}
|
||||
|
||||
public PreparedPutObject<MangaCategory> insertMangaCategory(MangaCategory mangaCategory) {
|
||||
return db.put()
|
||||
.object(mangaCategory)
|
||||
|
|
|
@ -71,7 +71,7 @@ public class DownloadManager {
|
|||
if (threadsNumberSubscription != null && !threadsNumberSubscription.isUnsubscribed())
|
||||
threadsNumberSubscription.unsubscribe();
|
||||
|
||||
threadsNumberSubscription = preferences.getDownloadTheadsObservable()
|
||||
threadsNumberSubscription = preferences.downloadThreads().asObservable()
|
||||
.subscribe(threadsNumber::onNext);
|
||||
|
||||
downloadsSubscription = downloadsQueueSubject
|
||||
|
|
|
@ -13,7 +13,6 @@ import java.io.File;
|
|||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.mangasync.base.MangaSyncService;
|
||||
import eu.kanade.mangafeed.data.source.base.Source;
|
||||
import rx.Observable;
|
||||
|
||||
public class PreferencesHelper {
|
||||
|
||||
|
@ -138,12 +137,8 @@ public class PreferencesHelper {
|
|||
prefs.edit().putString(getKey(R.string.pref_download_directory_key), path).apply();
|
||||
}
|
||||
|
||||
public int getDownloadThreads() {
|
||||
return prefs.getInt(getKey(R.string.pref_download_slots_key), 1);
|
||||
}
|
||||
|
||||
public Observable<Integer> getDownloadTheadsObservable() {
|
||||
return rxPrefs.getInteger(getKey(R.string.pref_download_slots_key), 1).asObservable();
|
||||
public Preference<Integer> downloadThreads() {
|
||||
return rxPrefs.getInteger(getKey(R.string.pref_download_slots_key), 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import eu.kanade.mangafeed.injection.module.AppModule;
|
|||
import eu.kanade.mangafeed.injection.module.DataModule;
|
||||
import eu.kanade.mangafeed.ui.catalogue.CataloguePresenter;
|
||||
import eu.kanade.mangafeed.ui.download.DownloadPresenter;
|
||||
import eu.kanade.mangafeed.ui.library.LibraryCategoryFragment;
|
||||
import eu.kanade.mangafeed.ui.library.category.CategoryPresenter;
|
||||
import eu.kanade.mangafeed.ui.library.LibraryPresenter;
|
||||
import eu.kanade.mangafeed.ui.manga.MangaActivity;
|
||||
import eu.kanade.mangafeed.ui.manga.MangaPresenter;
|
||||
|
@ -43,14 +43,13 @@ public interface AppComponent {
|
|||
void inject(ReaderPresenter readerPresenter);
|
||||
void inject(DownloadPresenter downloadPresenter);
|
||||
void inject(MyAnimeListPresenter myAnimeListPresenter);
|
||||
void inject(CategoryPresenter categoryPresenter);
|
||||
|
||||
void inject(ReaderActivity readerActivity);
|
||||
void inject(MangaActivity mangaActivity);
|
||||
void inject(SettingsAccountsFragment settingsAccountsFragment);
|
||||
void inject(SettingsActivity settingsActivity);
|
||||
|
||||
void inject(LibraryCategoryFragment libraryCategoryFragment);
|
||||
|
||||
void inject(Source source);
|
||||
|
||||
void inject(MyAnimeList myAnimeList);
|
||||
|
|
|
@ -1,14 +1,27 @@
|
|||
package eu.kanade.mangafeed.ui.base.activity;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import de.greenrobot.event.EventBus;
|
||||
import icepick.Icepick;
|
||||
|
||||
public class BaseActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
Icepick.restoreInstanceState(this, savedState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
Icepick.saveInstanceState(this, outState);
|
||||
}
|
||||
|
||||
protected void setupToolbar(Toolbar toolbar) {
|
||||
setSupportActionBar(toolbar);
|
||||
if (getSupportActionBar() != null)
|
||||
|
@ -35,10 +48,6 @@ public class BaseActivity extends AppCompatActivity {
|
|||
getSupportActionBar().setSubtitle(getString(titleResource));
|
||||
}
|
||||
|
||||
public Context getActivity() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
|
|
|
@ -33,8 +33,8 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onDrawOver(Canvas c, RecyclerView parent) {
|
||||
if (mDivider == null) { super.onDrawOver(c, parent); return; }
|
||||
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
|
||||
if (mDivider == null) { super.onDrawOver(c, parent, state); return; }
|
||||
|
||||
if (getOrientation(parent) == LinearLayoutManager.VERTICAL) {
|
||||
final int left = parent.getPaddingLeft();
|
||||
|
|
|
@ -14,15 +14,11 @@ import com.f2prateek.rx.preferences.Preference;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.kanade.mangafeed.App;
|
||||
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.preference.PreferencesHelper;
|
||||
import eu.kanade.mangafeed.event.LibraryMangasEvent;
|
||||
import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
|
||||
import eu.kanade.mangafeed.ui.base.adapter.FlexibleViewHolder;
|
||||
|
@ -37,8 +33,6 @@ import rx.Subscription;
|
|||
public class LibraryCategoryFragment extends BaseFragment implements
|
||||
ActionMode.Callback, FlexibleViewHolder.OnListItemClickListener {
|
||||
|
||||
@Inject PreferencesHelper preferences;
|
||||
|
||||
@Bind(R.id.library_mangas) AutofitRecyclerView recycler;
|
||||
|
||||
@State Category category;
|
||||
|
@ -47,20 +41,12 @@ public class LibraryCategoryFragment extends BaseFragment implements
|
|||
|
||||
private Subscription numColumnsSubscription;
|
||||
|
||||
private static final int INVALID_POSITION = -1;
|
||||
|
||||
public static LibraryCategoryFragment newInstance(Category category) {
|
||||
LibraryCategoryFragment fragment = new LibraryCategoryFragment();
|
||||
fragment.category = category;
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
App.get(getActivity()).getComponent().inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
|
||||
// Inflate the layout for this fragment
|
||||
|
@ -75,8 +61,8 @@ public class LibraryCategoryFragment extends BaseFragment implements
|
|||
|
||||
Preference<Integer> columnsPref = getResources().getConfiguration()
|
||||
.orientation == Configuration.ORIENTATION_PORTRAIT ?
|
||||
preferences.portraitColumns() :
|
||||
preferences.landscapeColumns();
|
||||
getLibraryPresenter().preferences.portraitColumns() :
|
||||
getLibraryPresenter().preferences.landscapeColumns();
|
||||
|
||||
numColumnsSubscription = columnsPref.asObservable()
|
||||
.subscribe(recycler::setSpanCount);
|
||||
|
@ -110,6 +96,7 @@ public class LibraryCategoryFragment extends BaseFragment implements
|
|||
|
||||
@EventBusHook
|
||||
public void onEventMainThread(LibraryMangasEvent event) {
|
||||
destroyActionModeIfNeeded();
|
||||
setMangas(event.getMangas().get(category.id));
|
||||
}
|
||||
|
||||
|
@ -128,7 +115,7 @@ public class LibraryCategoryFragment extends BaseFragment implements
|
|||
|
||||
@Override
|
||||
public boolean onListItemClick(int position) {
|
||||
if (actionMode != null && position != INVALID_POSITION) {
|
||||
if (actionMode != null && position != -1) {
|
||||
toggleSelection(position);
|
||||
return true;
|
||||
} else {
|
||||
|
@ -145,6 +132,22 @@ public class LibraryCategoryFragment extends BaseFragment implements
|
|||
toggleSelection(position);
|
||||
}
|
||||
|
||||
private void toggleSelection(int position) {
|
||||
adapter.toggleSelection(position, false);
|
||||
|
||||
int count = adapter.getSelectedItemCount();
|
||||
if (count == 0) {
|
||||
actionMode.finish();
|
||||
} else {
|
||||
setContextTitle(count);
|
||||
actionMode.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private 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);
|
||||
|
@ -169,19 +172,17 @@ public class LibraryCategoryFragment extends BaseFragment implements
|
|||
actionMode = null;
|
||||
}
|
||||
|
||||
private void toggleSelection(int position) {
|
||||
adapter.toggleSelection(position, false);
|
||||
|
||||
int count = adapter.getSelectedItemCount();
|
||||
if (count == 0) {
|
||||
public void destroyActionModeIfNeeded() {
|
||||
if (actionMode != null) {
|
||||
actionMode.finish();
|
||||
} else {
|
||||
setContextTitle(count);
|
||||
actionMode.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private void setContextTitle(int count) {
|
||||
actionMode.setTitle(getString(R.string.selected_chapters_title, count));
|
||||
private LibraryFragment getLibraryFragment() {
|
||||
return (LibraryFragment) getParentFragment();
|
||||
}
|
||||
|
||||
private LibraryPresenter getLibraryPresenter() {
|
||||
return getLibraryFragment().getPresenter();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Intent;
|
|||
import android.os.Bundle;
|
||||
import android.support.design.widget.AppBarLayout;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
|
@ -21,6 +22,7 @@ import eu.kanade.mangafeed.R;
|
|||
import eu.kanade.mangafeed.data.database.models.Category;
|
||||
import eu.kanade.mangafeed.data.sync.LibraryUpdateService;
|
||||
import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment;
|
||||
import eu.kanade.mangafeed.ui.library.category.CategoryFragment;
|
||||
import eu.kanade.mangafeed.ui.main.MainActivity;
|
||||
import nucleus.factory.RequiresPresenter;
|
||||
|
||||
|
@ -82,12 +84,20 @@ public class LibraryFragment extends BaseRxFragment<LibraryPresenter> {
|
|||
getActivity().startService(intent);
|
||||
}
|
||||
|
||||
return true;
|
||||
case R.id.action_edit_categories:
|
||||
onEditCategories();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void onEditCategories() {
|
||||
Fragment fragment = CategoryFragment.newInstance();
|
||||
((MainActivity) getActivity()).pushFragment(fragment);
|
||||
}
|
||||
|
||||
public void onNextCategories(List<Category> categories) {
|
||||
List<Category> actualCategories = new ArrayList<>();
|
||||
|
||||
|
|
|
@ -11,21 +11,25 @@ import javax.inject.Inject;
|
|||
import de.greenrobot.event.EventBus;
|
||||
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;
|
||||
import eu.kanade.mangafeed.event.LibraryMangasEvent;
|
||||
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
||||
import rx.Observable;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
public class LibraryPresenter extends BasePresenter<LibraryFragment> {
|
||||
|
||||
@Inject DatabaseHelper db;
|
||||
@Inject PreferencesHelper prefs;
|
||||
@Inject PreferencesHelper preferences;
|
||||
@Inject CoverCache coverCache;
|
||||
@Inject SourceManager sourceManager;
|
||||
|
||||
protected List<Category> categories;
|
||||
|
||||
private static final int GET_CATEGORIES = 1;
|
||||
|
||||
@Override
|
||||
|
@ -33,7 +37,7 @@ public class LibraryPresenter extends BasePresenter<LibraryFragment> {
|
|||
super.onCreate(savedState);
|
||||
|
||||
restartableLatestCache(GET_CATEGORIES,
|
||||
() -> db.getCategories().createObservable(),
|
||||
this::getCategoriesObservable,
|
||||
LibraryFragment::onNextCategories);
|
||||
|
||||
start(GET_CATEGORIES);
|
||||
|
@ -41,9 +45,16 @@ public class LibraryPresenter extends BasePresenter<LibraryFragment> {
|
|||
add(getLibraryMangasObservable()
|
||||
.subscribe(mangas ->
|
||||
EventBus.getDefault().postSticky(new LibraryMangasEvent(mangas))));
|
||||
|
||||
}
|
||||
|
||||
public Observable<Map<Integer, List<Manga>>> getLibraryMangasObservable() {
|
||||
public Observable<List<Category>> getCategoriesObservable() {
|
||||
return db.getCategories().createObservable()
|
||||
.doOnNext(categories -> this.categories = categories)
|
||||
.observeOn(AndroidSchedulers.mainThread());
|
||||
}
|
||||
|
||||
private Observable<Map<Integer, List<Manga>>> getLibraryMangasObservable() {
|
||||
return db.getLibraryMangas().createObservable()
|
||||
.flatMap(mangas -> Observable.from(mangas)
|
||||
.groupBy(manga -> manga.category)
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package eu.kanade.mangafeed.ui.library.category;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.amulyakhare.textdrawable.util.ColorGenerator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.database.models.Category;
|
||||
|
||||
public class CategoryAdapter extends FlexibleAdapter<CategoryHolder, Category> {
|
||||
|
||||
private CategoryFragment fragment;
|
||||
private ColorGenerator generator;
|
||||
|
||||
public CategoryAdapter(CategoryFragment fragment) {
|
||||
this.fragment = fragment;
|
||||
setHasStableIds(true);
|
||||
generator = ColorGenerator.DEFAULT;
|
||||
}
|
||||
|
||||
public void setItems(List<Category> items) {
|
||||
mItems = items;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return mItems.get(position).id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDataSet(String param) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CategoryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
LayoutInflater inflater = LayoutInflater.from(fragment.getActivity());
|
||||
View v = inflater.inflate(R.layout.item_edit_categories, parent, false);
|
||||
return new CategoryHolder(v, this, fragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(CategoryHolder holder, int position) {
|
||||
final Category category = getItem(position);
|
||||
holder.onSetValues(category, generator);
|
||||
|
||||
//When user scrolls this bind the correct selection status
|
||||
holder.itemView.setActivated(isSelected(position));
|
||||
}
|
||||
|
||||
public ColorGenerator getColorGenerator() {
|
||||
return generator;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
package eu.kanade.mangafeed.ui.library.category;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.content.res.ResourcesCompat;
|
||||
import android.support.v7.view.ActionMode;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.database.models.Category;
|
||||
import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
|
||||
import eu.kanade.mangafeed.ui.base.adapter.FlexibleViewHolder;
|
||||
import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment;
|
||||
import eu.kanade.mangafeed.ui.decoration.DividerItemDecoration;
|
||||
import eu.kanade.mangafeed.ui.library.LibraryCategoryAdapter;
|
||||
import nucleus.factory.RequiresPresenter;
|
||||
import rx.Observable;
|
||||
|
||||
@RequiresPresenter(CategoryPresenter.class)
|
||||
public class CategoryFragment extends BaseRxFragment<CategoryPresenter>
|
||||
implements ActionMode.Callback, FlexibleViewHolder.OnListItemClickListener {
|
||||
|
||||
@Bind(R.id.categories_list) RecyclerView recycler;
|
||||
@Bind(R.id.fab) FloatingActionButton fab;
|
||||
|
||||
private CategoryAdapter adapter;
|
||||
private ActionMode actionMode;
|
||||
|
||||
public static CategoryFragment newInstance() {
|
||||
return new CategoryFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
|
||||
View view = inflater.inflate(R.layout.fragment_edit_categories, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
|
||||
setToolbarTitle(R.string.action_edit_categories);
|
||||
|
||||
adapter = new CategoryAdapter(this);
|
||||
recycler.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||
recycler.setHasFixedSize(true);
|
||||
recycler.setAdapter(adapter);
|
||||
recycler.addItemDecoration(new DividerItemDecoration(
|
||||
ResourcesCompat.getDrawable(getResources(), R.drawable.line_divider, null)));
|
||||
|
||||
fab.setOnClickListener(v -> {
|
||||
new MaterialDialog.Builder(getActivity())
|
||||
.title(R.string.action_add_category)
|
||||
.input(R.string.name, 0, false, (dialog, input) -> {
|
||||
getPresenter().createCategory(input.toString());
|
||||
}).show();
|
||||
});
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
public void setCategories(List<Category> categories) {
|
||||
destroyActionModeIfNeeded();
|
||||
adapter.setItems(categories);
|
||||
}
|
||||
|
||||
private List<Category> getSelectedCategories() {
|
||||
// Create a blocking copy of the selected categories
|
||||
return Observable.from(adapter.getSelectedItems())
|
||||
.map(adapter::getItem).toList().toBlocking().single();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onListItemClick(int position) {
|
||||
if (actionMode != null && position != -1) {
|
||||
toggleSelection(position);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListItemLongClick(int position) {
|
||||
if (actionMode == null)
|
||||
actionMode = ((BaseActivity) getActivity()).startSupportActionMode(this);
|
||||
|
||||
toggleSelection(position);
|
||||
}
|
||||
|
||||
private void toggleSelection(int position) {
|
||||
adapter.toggleSelection(position, false);
|
||||
|
||||
int count = adapter.getSelectedItemCount();
|
||||
if (count == 0) {
|
||||
actionMode.finish();
|
||||
} else {
|
||||
setContextTitle(count);
|
||||
actionMode.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private 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.category_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) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_delete:
|
||||
getPresenter().deleteCategories(getSelectedCategories());
|
||||
return true;
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package eu.kanade.mangafeed.ui.library.category;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.amulyakhare.textdrawable.TextDrawable;
|
||||
import com.amulyakhare.textdrawable.util.ColorGenerator;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.database.models.Category;
|
||||
import eu.kanade.mangafeed.ui.base.adapter.FlexibleViewHolder;
|
||||
|
||||
public class CategoryHolder extends FlexibleViewHolder {
|
||||
|
||||
private View view;
|
||||
|
||||
@Bind(R.id.image) ImageView image;
|
||||
@Bind(R.id.title) TextView title;
|
||||
|
||||
public CategoryHolder(View view, CategoryAdapter adapter, OnListItemClickListener listener) {
|
||||
super(view, adapter, listener);
|
||||
ButterKnife.bind(this, view);
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
public void onSetValues(Category category, ColorGenerator generator) {
|
||||
title.setText(category.name);
|
||||
image.setImageDrawable(getRound(category.name.substring(0, 1), generator));
|
||||
}
|
||||
|
||||
private TextDrawable getRound(String text, ColorGenerator generator) {
|
||||
return TextDrawable.builder().buildRound(text, generator.getColor(text));
|
||||
}
|
||||
|
||||
@OnClick(R.id.image)
|
||||
void onImageClick() {
|
||||
// Simulate long click on this view to enter selection mode
|
||||
onLongClick(view);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package eu.kanade.mangafeed.ui.library.category;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import eu.kanade.mangafeed.data.database.DatabaseHelper;
|
||||
import eu.kanade.mangafeed.data.database.models.Category;
|
||||
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
|
||||
public class CategoryPresenter extends BasePresenter<CategoryFragment> {
|
||||
|
||||
@Inject DatabaseHelper db;
|
||||
|
||||
private static final int GET_CATEGORIES = 1;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
|
||||
restartableLatestCache(GET_CATEGORIES,
|
||||
() -> db.getCategories().createObservable()
|
||||
.observeOn(AndroidSchedulers.mainThread()),
|
||||
CategoryFragment::setCategories);
|
||||
|
||||
start(GET_CATEGORIES);
|
||||
}
|
||||
|
||||
public void createCategory(String name) {
|
||||
db.insertCategory(Category.create(name)).createObservable().subscribe();
|
||||
}
|
||||
|
||||
public void deleteCategories(List<Category> categories) {
|
||||
db.deleteCategories(categories).createObservable().subscribe();
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import android.content.Intent;
|
|||
import android.os.Bundle;
|
||||
import android.support.design.widget.AppBarLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
|
@ -19,23 +20,23 @@ import eu.kanade.mangafeed.ui.catalogue.CatalogueFragment;
|
|||
import eu.kanade.mangafeed.ui.download.DownloadFragment;
|
||||
import eu.kanade.mangafeed.ui.library.LibraryFragment;
|
||||
import eu.kanade.mangafeed.ui.setting.SettingsActivity;
|
||||
import icepick.State;
|
||||
import nucleus.view.ViewWithPresenter;
|
||||
|
||||
public class MainActivity extends BaseActivity {
|
||||
|
||||
@Bind(R.id.appbar) AppBarLayout appBar;
|
||||
@Bind(R.id.toolbar) Toolbar toolbar;
|
||||
|
||||
@Bind(R.id.drawer_container) FrameLayout container;
|
||||
|
||||
private Drawer drawer;
|
||||
private FragmentStack fragmentStack;
|
||||
|
||||
private final static String SELECTED_ITEM = "selected_item";
|
||||
@State int selectedItem;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
protected void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
setContentView(R.layout.activity_main);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
|
@ -52,6 +53,13 @@ public class MainActivity extends BaseActivity {
|
|||
.withRootView(container)
|
||||
.withToolbar(toolbar)
|
||||
.withActionBarDrawerToggleAnimated(true)
|
||||
.withOnDrawerNavigationListener(view -> {
|
||||
if (fragmentStack.size() > 1) {
|
||||
onBackPressed();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.addDrawerItems(
|
||||
new PrimaryDrawerItem()
|
||||
.withName(R.string.label_library)
|
||||
|
@ -70,7 +78,7 @@ public class MainActivity extends BaseActivity {
|
|||
.withIdentifier(R.id.nav_drawer_settings)
|
||||
.withSelectable(false)
|
||||
)
|
||||
.withSavedInstance(savedInstanceState)
|
||||
.withSavedInstance(savedState)
|
||||
.withOnDrawerItemClickListener(
|
||||
(view, position, drawerItem) -> {
|
||||
if (drawerItem != null) {
|
||||
|
@ -97,15 +105,23 @@ public class MainActivity extends BaseActivity {
|
|||
)
|
||||
.build();
|
||||
|
||||
if (savedInstanceState == null)
|
||||
if (savedState != null) {
|
||||
// Recover icon state after rotation
|
||||
if (fragmentStack.size() > 1) {
|
||||
showBackArrow();
|
||||
}
|
||||
|
||||
// Set saved selection
|
||||
drawer.setSelection(selectedItem, false);
|
||||
} else {
|
||||
// Set default selection
|
||||
drawer.setSelection(R.id.nav_drawer_library);
|
||||
else
|
||||
drawer.setSelection(savedInstanceState.getInt(SELECTED_ITEM), false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
outState.putInt(SELECTED_ITEM, drawer.getCurrentSelection());
|
||||
selectedItem = drawer.getCurrentSelection();
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
|
@ -113,8 +129,37 @@ public class MainActivity extends BaseActivity {
|
|||
fragmentStack.replace(fragment);
|
||||
}
|
||||
|
||||
public Fragment getActiveFragment() {
|
||||
return fragmentStack.peek();
|
||||
public void pushFragment(Fragment fragment) {
|
||||
fragmentStack.push(fragment);
|
||||
if (fragmentStack.size() > 1) {
|
||||
showBackArrow();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (!fragmentStack.pop()) {
|
||||
super.onBackPressed();
|
||||
} else if (fragmentStack.size() == 1) {
|
||||
showHamburgerIcon();
|
||||
drawer.getActionBarDrawerToggle().syncState();
|
||||
}
|
||||
}
|
||||
|
||||
private void showHamburgerIcon() {
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
|
||||
drawer.getActionBarDrawerToggle().setDrawerIndicatorEnabled(true);
|
||||
drawer.getDrawerLayout().setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
|
||||
}
|
||||
}
|
||||
|
||||
private void showBackArrow() {
|
||||
if (getSupportActionBar() != null) {
|
||||
drawer.getActionBarDrawerToggle().setDrawerIndicatorEnabled(false);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
drawer.getDrawerLayout().setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
|
||||
}
|
||||
}
|
||||
|
||||
public Toolbar getToolbar() {
|
||||
|
|
|
@ -49,8 +49,8 @@ public class MangaActivity extends BaseRxActivity<MangaPresenter> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
protected void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
App.get(this).getComponent().inject(this);
|
||||
setContentView(R.layout.activity_manga);
|
||||
ButterKnife.bind(this);
|
||||
|
@ -64,14 +64,12 @@ public class MangaActivity extends BaseRxActivity<MangaPresenter> {
|
|||
|
||||
setupViewPager();
|
||||
|
||||
if (savedInstanceState == null)
|
||||
if (savedState == null)
|
||||
getPresenter().queryManga(manga_id);
|
||||
}
|
||||
|
||||
private void setupViewPager() {
|
||||
adapter = new MangaDetailAdapter(
|
||||
getSupportFragmentManager(),
|
||||
getActivity());
|
||||
adapter = new MangaDetailAdapter(getSupportFragmentManager(), this);
|
||||
|
||||
view_pager.setAdapter(adapter);
|
||||
tabs.setupWithViewPager(view_pager);
|
||||
|
|
|
@ -145,7 +145,7 @@ public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implemen
|
|||
if (getPresenter().getChapters().isEmpty())
|
||||
initialFetchChapters();
|
||||
|
||||
closeActionMode();
|
||||
destroyActionModeIfNeeded();
|
||||
adapter.setItems(chapters);
|
||||
}
|
||||
|
||||
|
@ -254,7 +254,7 @@ public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implemen
|
|||
return Observable.from(chapters);
|
||||
}
|
||||
|
||||
public void closeActionMode() {
|
||||
public void destroyActionModeIfNeeded() {
|
||||
if (actionMode != null) {
|
||||
actionMode.finish();
|
||||
}
|
||||
|
@ -283,7 +283,7 @@ public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implemen
|
|||
.doOnCompleted(adapter::notifyDataSetChanged);
|
||||
|
||||
getPresenter().downloadChapters(observable);
|
||||
closeActionMode();
|
||||
destroyActionModeIfNeeded();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -311,7 +311,7 @@ public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implemen
|
|||
.finallyDo(dialog::dismiss);
|
||||
|
||||
getPresenter().deleteChapters(observable);
|
||||
closeActionMode();
|
||||
destroyActionModeIfNeeded();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -347,7 +347,7 @@ public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implemen
|
|||
}
|
||||
|
||||
private void setContextTitle(int count) {
|
||||
actionMode.setTitle(getString(R.string.selected_chapters_title, count));
|
||||
actionMode.setTitle(getString(R.string.label_selected, count));
|
||||
}
|
||||
|
||||
public void setSortIcon() {
|
||||
|
|
|
@ -22,15 +22,15 @@ public class SettingsActivity extends BaseActivity {
|
|||
@Bind(R.id.toolbar) Toolbar toolbar;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
protected void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
App.get(this).getComponent().inject(this);
|
||||
setContentView(R.layout.activity_preferences);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
setupToolbar(toolbar);
|
||||
|
||||
if (savedInstanceState == null)
|
||||
if (savedState == null)
|
||||
getFragmentManager().beginTransaction().replace(R.id.settings_content,
|
||||
new SettingsMainFragment())
|
||||
.commit();
|
||||
|
|
BIN
app/src/main/res/drawable-hdpi/ic_action_add_18dp.png
Normal file
BIN
app/src/main/res/drawable-hdpi/ic_action_add_18dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 134 B |
BIN
app/src/main/res/drawable-ldpi/ic_action_add_18dp.png
Normal file
BIN
app/src/main/res/drawable-ldpi/ic_action_add_18dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 119 B |
BIN
app/src/main/res/drawable-mdpi/ic_action_add_18dp.png
Normal file
BIN
app/src/main/res/drawable-mdpi/ic_action_add_18dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 116 B |
BIN
app/src/main/res/drawable-xhdpi/ic_action_add_18dp.png
Normal file
BIN
app/src/main/res/drawable-xhdpi/ic_action_add_18dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 168 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_action_add_18dp.png
Normal file
BIN
app/src/main/res/drawable-xxhdpi/ic_action_add_18dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 242 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_action_add_18dp.png
Normal file
BIN
app/src/main/res/drawable-xxxhdpi/ic_action_add_18dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 500 B |
26
app/src/main/res/layout/fragment_edit_categories.xml
Normal file
26
app/src/main/res/layout/fragment_edit_categories.xml
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.design.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/categories_list"
|
||||
android:choiceMode="multipleChoice"
|
||||
android:listSelector="@color/list_choice_pressed_bg_light" />
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="end|bottom"
|
||||
android:layout_margin="@dimen/fab_margin"
|
||||
android:clickable="true"
|
||||
android:src="@drawable/ic_action_add_18dp"
|
||||
app:borderWidth="0dp"/>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
39
app/src/main/res/layout/item_edit_categories.xml
Normal file
39
app/src/main/res/layout/item_edit_categories.xml
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?android:attr/listPreferredItemHeightLarge"
|
||||
android:paddingTop="@dimen/margin_top"
|
||||
android:paddingBottom="@dimen/margin_bottom"
|
||||
android:background="@drawable/selector_chapter_light">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerInParent="true"
|
||||
android:elevation="4dp"
|
||||
android:clickable="true"
|
||||
android:layout_marginLeft="@dimen/margin_left"
|
||||
android:layout_marginStart="@dimen/margin_left"
|
||||
android:layout_marginRight="@dimen/margin_right"
|
||||
android:layout_marginEnd="@dimen/margin_right"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="@dimen/margin_right"
|
||||
android:layout_marginEnd="@dimen/margin_right"
|
||||
android:layout_toRightOf="@id/image"
|
||||
android:layout_toEndOf="@id/image"
|
||||
android:layout_centerInParent="true"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
||||
android:textColor="@color/primary_text"
|
||||
tools:text="Title"/>
|
||||
|
||||
</RelativeLayout>
|
12
app/src/main/res/menu/category_selection.xml
Normal file
12
app/src/main/res/menu/category_selection.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item android:id="@+id/action_delete"
|
||||
android:title="@string/action_delete"
|
||||
android:icon="@drawable/ic_action_delete"
|
||||
android:orderInCategory="1"
|
||||
app:showAsAction="always"/>
|
||||
|
||||
</menu>
|
|
@ -1,17 +1,25 @@
|
|||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_search"
|
||||
android:title="@string/action_search"
|
||||
android:icon="@drawable/ic_action_search"
|
||||
android:orderInCategory="100"
|
||||
app:showAsAction="collapseActionView|ifRoom"
|
||||
app:actionViewClass="android.support.v7.widget.SearchView"/>
|
||||
app:actionViewClass="android.support.v7.widget.SearchView" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_refresh"
|
||||
android:title="@string/action_refresh"
|
||||
android:icon="@drawable/ic_action_refresh"
|
||||
android:orderInCategory="1"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_edit_categories"
|
||||
android:title="@string/action_edit_categories"
|
||||
app:showAsAction="never" />
|
||||
|
||||
</menu>
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
<dimen name="margin_top">16dp</dimen>
|
||||
<dimen name="margin_bottom">16dp</dimen>
|
||||
<dimen name="margin_left">16dp</dimen>
|
||||
<dimen name="margin_right">16dp</dimen>
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
|
||||
<dimen name="text_headline">24sp</dimen>
|
||||
<dimen name="text_large_title">22sp</dimen>
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
<resources>
|
||||
<string name="app_name">Mangafeed</string>
|
||||
|
||||
<string name="name">Name</string>
|
||||
|
||||
<!-- Activities and fragments labels (toolbar title) -->
|
||||
<string name="label_settings">Settings</string>
|
||||
<string name="label_download_queue">Download queue</string>
|
||||
<string name="label_library">My library</string>
|
||||
<string name="label_recent_updates">Recent updates</string>
|
||||
<string name="label_catalogues">Catalogues</string>
|
||||
<string name="label_selected">Selected: %1$d</string>
|
||||
|
||||
<!-- Actions -->
|
||||
<string name="action_settings">Settings</string>
|
||||
|
@ -19,6 +22,8 @@
|
|||
<string name="action_delete">Delete</string>
|
||||
<string name="action_update">Update</string>
|
||||
<string name="action_edit">Edit</string>
|
||||
<string name="action_add_category">Add category</string>
|
||||
<string name="action_edit_categories">Edit categories</string>
|
||||
<string name="action_sort_up">Sort up</string>
|
||||
<string name="action_sort_down">Sort down</string>
|
||||
<string name="action_show_unread">Unread</string>
|
||||
|
@ -118,7 +123,6 @@
|
|||
|
||||
<!-- Manga chapters fragment -->
|
||||
<string name="manga_chapters_tab">Chapters</string>
|
||||
<string name="selected_chapters_title">Selected: %1$d</string>
|
||||
<string name="manga_chapter_no_title">No title</string>
|
||||
<string name="chapter_downloaded">Downloaded</string>
|
||||
<string name="chapter_queued">Queued</string>
|
||||
|
|
|
@ -22,5 +22,6 @@ allprojects {
|
|||
maven { url "https://clojars.org/repo/" }
|
||||
maven { url "http://dl.bintray.com/davideas/maven" }
|
||||
maven { url "https://jitpack.io" }
|
||||
maven { url 'http://dl.bintray.com/amulyakhare/maven' }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue