mirror of
https://github.com/mihonapp/mihon.git
synced 2025-06-25 10:37:51 +02:00
Add multiple chapters selection and allow to mark them as read/unread
This commit is contained in:
@ -18,6 +18,7 @@ import eu.kanade.mangafeed.ui.fragment.MangaChaptersFragment;
|
||||
import eu.kanade.mangafeed.util.EventBusHook;
|
||||
import eu.kanade.mangafeed.util.PostResult;
|
||||
import rx.Observable;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
@ -32,6 +33,8 @@ public class MangaChaptersPresenter extends BasePresenter<MangaChaptersFragment>
|
||||
private static final int DB_CHAPTERS = 1;
|
||||
private static final int ONLINE_CHAPTERS = 2;
|
||||
|
||||
private Subscription menuOperationSubscription;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
@ -106,4 +109,22 @@ public class MangaChaptersPresenter extends BasePresenter<MangaChaptersFragment>
|
||||
public void onChapterClicked(Chapter chapter) {
|
||||
EventBus.getDefault().postSticky(new SourceChapterEvent(source, chapter));
|
||||
}
|
||||
|
||||
public void markChaptersRead(Observable<Chapter> selectedChapters, boolean read) {
|
||||
if (menuOperationSubscription != null)
|
||||
remove(menuOperationSubscription);
|
||||
|
||||
add(menuOperationSubscription = selectedChapters
|
||||
.subscribeOn(Schedulers.io())
|
||||
.map(chapter -> {
|
||||
chapter.read = read;
|
||||
return chapter;
|
||||
})
|
||||
.toList()
|
||||
.flatMap(db::insertChapters)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(result -> {
|
||||
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,52 @@
|
||||
package eu.kanade.mangafeed.ui.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.models.Chapter;
|
||||
import eu.kanade.mangafeed.ui.fragment.base.BaseFragment;
|
||||
import eu.kanade.mangafeed.ui.holder.ChaptersHolder;
|
||||
|
||||
public class ChaptersAdapter extends FlexibleAdapter<ChaptersHolder, Chapter> {
|
||||
|
||||
private Context context;
|
||||
public OnItemClickListener clickListener;
|
||||
|
||||
public ChaptersAdapter(BaseFragment fragment) {
|
||||
this.context = fragment.getActivity();
|
||||
mItems = new ArrayList<>();
|
||||
clickListener = (OnItemClickListener) fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDataSet(String param) {}
|
||||
|
||||
@Override
|
||||
public ChaptersHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View v = LayoutInflater.from(context).inflate(R.layout.item_chapter, parent, false);
|
||||
return new ChaptersHolder(v, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ChaptersHolder holder, int position) {
|
||||
final Chapter chapter = getItem(position);
|
||||
holder.onSetValues(context, chapter);
|
||||
}
|
||||
|
||||
public void setItems(List<Chapter> chapters) {
|
||||
mItems = chapters;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public interface OnItemClickListener {
|
||||
boolean onListItemClick(int position);
|
||||
void onListItemLongClick(int position);
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.view.ActionMode;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
@ -22,18 +23,22 @@ import eu.kanade.mangafeed.data.models.Chapter;
|
||||
import eu.kanade.mangafeed.presenter.MangaChaptersPresenter;
|
||||
import eu.kanade.mangafeed.ui.activity.MangaDetailActivity;
|
||||
import eu.kanade.mangafeed.ui.activity.ReaderActivity;
|
||||
import eu.kanade.mangafeed.ui.holder.ChapterListHolder;
|
||||
import eu.kanade.mangafeed.ui.activity.base.BaseActivity;
|
||||
import eu.kanade.mangafeed.ui.adapter.ChaptersAdapter;
|
||||
import eu.kanade.mangafeed.ui.fragment.base.BaseRxFragment;
|
||||
import nucleus.factory.RequiresPresenter;
|
||||
import uk.co.ribot.easyadapter.EasyRecyclerAdapter;
|
||||
import rx.Observable;
|
||||
|
||||
@RequiresPresenter(MangaChaptersPresenter.class)
|
||||
public class MangaChaptersFragment extends BaseRxFragment<MangaChaptersPresenter> {
|
||||
public class MangaChaptersFragment extends BaseRxFragment<MangaChaptersPresenter> implements
|
||||
ActionMode.Callback, ChaptersAdapter.OnItemClickListener {
|
||||
|
||||
@Bind(R.id.chapter_list) RecyclerView chapters;
|
||||
@Bind(R.id.swipe_refresh) SwipeRefreshLayout swipeRefresh;
|
||||
|
||||
private EasyRecyclerAdapter<Chapter> adapter;
|
||||
private ChaptersAdapter adapter;
|
||||
|
||||
private ActionMode actionMode;
|
||||
|
||||
public static Fragment newInstance() {
|
||||
return new MangaChaptersFragment();
|
||||
@ -76,13 +81,7 @@ public class MangaChaptersFragment extends BaseRxFragment<MangaChaptersPresenter
|
||||
}
|
||||
|
||||
private void createAdapter() {
|
||||
ChapterListHolder.ChapterListener listener = chapter -> {
|
||||
getPresenter().onChapterClicked(chapter);
|
||||
Intent intent = ReaderActivity.newInstance(getActivity());
|
||||
startActivity(intent);
|
||||
};
|
||||
|
||||
adapter = new EasyRecyclerAdapter<>(getActivity(), ChapterListHolder.class, listener);
|
||||
adapter = new ChaptersAdapter(this);
|
||||
chapters.setAdapter(adapter);
|
||||
}
|
||||
|
||||
@ -92,6 +91,7 @@ public class MangaChaptersFragment extends BaseRxFragment<MangaChaptersPresenter
|
||||
|
||||
public void onNextChapters(List<Chapter> chapters) {
|
||||
adapter.setItems(chapters);
|
||||
closeActionMode();
|
||||
}
|
||||
|
||||
public void onNextOnlineChapters() {
|
||||
@ -105,4 +105,87 @@ public class MangaChaptersFragment extends BaseRxFragment<MangaChaptersPresenter
|
||||
public boolean isOnlineManga() {
|
||||
return ((MangaDetailActivity)getActivity()).isOnlineManga();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
mode.getMenuInflater().inflate(R.menu.chapter_selection, menu);
|
||||
adapter.setMode(ChaptersAdapter.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_select_all:
|
||||
adapter.selectAll();
|
||||
return true;
|
||||
case R.id.action_mark_as_read:
|
||||
getPresenter().markChaptersRead(getSelectedChapters(), true);
|
||||
return true;
|
||||
case R.id.action_mark_as_unread:
|
||||
getPresenter().markChaptersRead(getSelectedChapters(), false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode mode) {
|
||||
adapter.setMode(ChaptersAdapter.MODE_SINGLE);
|
||||
adapter.clearSelection();
|
||||
actionMode = null;
|
||||
}
|
||||
|
||||
private Observable<Chapter> getSelectedChapters() {
|
||||
return Observable.from(adapter.getSelectedItems())
|
||||
.map(adapter::getItem);
|
||||
}
|
||||
|
||||
public void closeActionMode() {
|
||||
if (actionMode != null)
|
||||
actionMode.finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onListItemClick(int position) {
|
||||
if (actionMode != null && adapter.getMode() == ChaptersAdapter.MODE_MULTI) {
|
||||
toggleSelection(position);
|
||||
return true;
|
||||
} else {
|
||||
getPresenter().onChapterClicked(adapter.getItem(position));
|
||||
Intent intent = ReaderActivity.newInstance(getActivity());
|
||||
startActivity(intent);
|
||||
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.selected_chapters_title, count));
|
||||
}
|
||||
}
|
||||
|
@ -1,60 +0,0 @@
|
||||
package eu.kanade.mangafeed.ui.holder;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.models.Chapter;
|
||||
import uk.co.ribot.easyadapter.ItemViewHolder;
|
||||
import uk.co.ribot.easyadapter.PositionInfo;
|
||||
import uk.co.ribot.easyadapter.annotations.LayoutId;
|
||||
import uk.co.ribot.easyadapter.annotations.ViewId;
|
||||
|
||||
@LayoutId(R.layout.item_chapter)
|
||||
public class ChapterListHolder extends ItemViewHolder<Chapter> {
|
||||
|
||||
@ViewId(R.id.chapter_title) TextView title;
|
||||
@ViewId(R.id.chapter_download_image) ImageView download_icon;
|
||||
@ViewId(R.id.chapter_pages) TextView pages;
|
||||
|
||||
View view;
|
||||
|
||||
public ChapterListHolder(View view) {
|
||||
super(view);
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
public void onSetValues(Chapter chapter, PositionInfo positionInfo) {
|
||||
title.setText(chapter.name);
|
||||
download_icon.setImageResource(R.drawable.ic_file_download_black_48dp);
|
||||
|
||||
if (chapter.read) {
|
||||
title.setTextColor(ContextCompat.getColor(getContext(), R.color.chapter_read_text));
|
||||
} else {
|
||||
title.setTextColor(Color.BLACK);
|
||||
}
|
||||
|
||||
if (chapter.last_page_read > 0 && !chapter.read) {
|
||||
pages.setText(getContext().getString(R.string.chapter_progress, chapter.last_page_read+1));
|
||||
} else {
|
||||
pages.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetListeners() {
|
||||
view.setOnClickListener(view -> {
|
||||
ChapterListener listener = getListener(ChapterListener.class);
|
||||
if (listener != null) {
|
||||
listener.onRowClicked(getItem());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public interface ChapterListener {
|
||||
void onRowClicked(Chapter chapter);
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package eu.kanade.mangafeed.ui.holder;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.kanade.mangafeed.R;
|
||||
import eu.kanade.mangafeed.data.models.Chapter;
|
||||
import eu.kanade.mangafeed.ui.adapter.ChaptersAdapter;
|
||||
|
||||
public class ChaptersHolder extends RecyclerView.ViewHolder implements
|
||||
View.OnClickListener, View.OnLongClickListener {
|
||||
|
||||
private ChaptersAdapter adapter;
|
||||
|
||||
@Bind(R.id.chapter_title) TextView title;
|
||||
@Bind(R.id.chapter_download_image) ImageView download_icon;
|
||||
@Bind(R.id.chapter_pages) TextView pages;
|
||||
|
||||
public ChaptersHolder(View view) {
|
||||
super(view);
|
||||
ButterKnife.bind(this, view);
|
||||
}
|
||||
|
||||
public ChaptersHolder(View view, final ChaptersAdapter adapter) {
|
||||
this(view);
|
||||
|
||||
this.adapter = adapter;
|
||||
itemView.setOnClickListener(this);
|
||||
itemView.setOnLongClickListener(this);
|
||||
}
|
||||
|
||||
public void onSetValues(Context context, Chapter chapter) {
|
||||
title.setText(chapter.name);
|
||||
download_icon.setImageResource(R.drawable.ic_file_download_black_48dp);
|
||||
|
||||
if (chapter.read) {
|
||||
title.setTextColor(ContextCompat.getColor(context, R.color.chapter_read_text));
|
||||
} else {
|
||||
title.setTextColor(Color.BLACK);
|
||||
}
|
||||
|
||||
if (chapter.last_page_read > 0 && !chapter.read) {
|
||||
pages.setText(context.getString(R.string.chapter_progress, chapter.last_page_read + 1));
|
||||
} else {
|
||||
pages.setText("");
|
||||
}
|
||||
|
||||
toggleActivation();
|
||||
}
|
||||
|
||||
private void toggleActivation() {
|
||||
itemView.setActivated(adapter.isSelected(getAdapterPosition()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (adapter.clickListener.onListItemClick(getAdapterPosition()))
|
||||
toggleActivation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
adapter.clickListener.onListItemLongClick(getAdapterPosition());
|
||||
toggleActivation();
|
||||
return true;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user