Dbrant has uploaded a new change for review. (
https://gerrit.wikimedia.org/r/349963 )
Change subject: Enable multi-selection in History fragment.
......................................................................
Enable multi-selection in History fragment.
TODO in next patch: swipe to delete.
Bug: T162280
Change-Id: Ifc97f253538281a7d1903e255f2b916db52fc45c
---
M app/src/main/java/org/wikipedia/history/HistoryFragment.java
M app/src/main/res/values-qq/strings.xml
M app/src/main/res/values/strings.xml
3 files changed, 163 insertions(+), 23 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/apps/android/wikipedia
refs/changes/63/349963/1
diff --git a/app/src/main/java/org/wikipedia/history/HistoryFragment.java
b/app/src/main/java/org/wikipedia/history/HistoryFragment.java
index dd0473e..3f35142 100644
--- a/app/src/main/java/org/wikipedia/history/HistoryFragment.java
+++ b/app/src/main/java/org/wikipedia/history/HistoryFragment.java
@@ -6,6 +6,7 @@
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
@@ -27,14 +28,20 @@
import org.wikipedia.R;
import org.wikipedia.WikipediaApp;
import org.wikipedia.activity.FragmentUtil;
+import org.wikipedia.database.DatabaseClient;
import org.wikipedia.database.contract.PageHistoryContract;
import org.wikipedia.page.PageTitle;
+import org.wikipedia.util.FeedbackUtil;
import org.wikipedia.views.DefaultViewHolder;
+import org.wikipedia.views.MultiSelectActionModeCallback;
import org.wikipedia.views.PageItemView;
import org.wikipedia.views.SearchEmptyView;
import java.text.DateFormat;
+import java.util.ArrayList;
import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
@@ -62,6 +69,8 @@
private ItemCallback itemCallback = new ItemCallback();
private ActionMode actionMode;
private SearchActionModeCallback searchActionModeCallback = new
HistorySearchCallback();
+ private MultiSelectCallback multiSelectCallback = new
MultiSelectCallback();
+ private HashSet<Integer> selectedIndices = new HashSet<>();
@NonNull public static HistoryFragment newInstance() {
return new HistoryFragment();
@@ -182,10 +191,6 @@
}
}
- private void setActionModeIntTitle(int count, ActionMode mode) {
- mode.setTitle(getString(R.string.multi_select_items_selected, count));
- }
-
private void onPageClick(PageTitle title, HistoryEntry entry) {
Callback callback = callback();
if (callback != null) {
@@ -198,6 +203,79 @@
if (callback != null) {
callback.onClearHistory();
}
+ }
+
+ private void finishActionMode() {
+ if (actionMode != null) {
+ actionMode.finish();
+ }
+ }
+
+ private void beginMultiSelect() {
+ if (HistorySearchCallback.is(actionMode)) {
+ finishActionMode();
+ }
+ if (!MultiSelectCallback.is(actionMode)) {
+ ((AppCompatActivity)
getActivity()).startSupportActionMode(multiSelectCallback);
+ }
+ }
+
+ private void toggleSelectPage(@Nullable IndexedHistoryEntry indexedEntry) {
+ if (indexedEntry == null) {
+ return;
+ }
+ if (selectedIndices.contains(indexedEntry.getIndex())) {
+ selectedIndices.remove(indexedEntry.getIndex());
+ } else {
+ selectedIndices.add(indexedEntry.getIndex());
+ }
+ int selectedCount = selectedIndices.size();
+ if (selectedCount == 0) {
+ finishActionMode();
+ } else if (actionMode != null) {
+
actionMode.setTitle(getString(R.string.multi_select_items_selected,
selectedCount));
+ }
+ adapter.notifyDataSetChanged();
+ }
+
+ private void unselectAllPages() {
+ selectedIndices.clear();
+ adapter.notifyDataSetChanged();
+ }
+
+ private void deleteSelectedPages() {
+ List<HistoryEntry> selectedEntries = new ArrayList<>();
+ for (int index : selectedIndices) {
+ HistoryEntry entry = adapter.getItem(index);
+ if (entry != null) {
+ selectedEntries.add(entry);
+ app.getDatabaseClient(HistoryEntry.class).delete(entry,
+ PageHistoryContract.PageWithImage.SELECTION);
+ }
+ }
+ if (!selectedEntries.isEmpty()) {
+ showDeleteItemsUndoSnackbar(selectedEntries);
+ adapter.notifyDataSetChanged();
+ }
+ }
+
+ private void showDeleteItemsUndoSnackbar(final List<HistoryEntry> entries)
{
+ String message = entries.size() == 1
+ ? String.format(getString(R.string.history_item_deleted),
entries.get(0).getTitle().getDisplayText())
+ : String.format(getString(R.string.history_items_deleted),
entries.size());
+ Snackbar snackbar = FeedbackUtil.makeSnackbar(getActivity(), message,
+ FeedbackUtil.LENGTH_DEFAULT);
+ snackbar.setAction(R.string.history_item_delete_undo, new
View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ DatabaseClient<HistoryEntry> client =
app.getDatabaseClient(HistoryEntry.class);
+ for (HistoryEntry entry : entries) {
+ client.upsert(entry,
PageHistoryContract.PageWithImage.SELECTION);
+ }
+ adapter.notifyDataSetChanged();
+ }
+ });
+ snackbar.show();
}
private void restartLoader() {
@@ -240,24 +318,43 @@
}
}
- private class HistoryEntryItemHolder extends
DefaultViewHolder<PageItemView<HistoryEntry>> {
- private HistoryEntry entry;
+ private static class IndexedHistoryEntry {
+ private final int index;
+ @NonNull private final HistoryEntry entry;
- HistoryEntryItemHolder(PageItemView<HistoryEntry> itemView) {
+ IndexedHistoryEntry(@NonNull HistoryEntry entry, int index) {
+ this.entry = entry;
+ this.index = index;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ @NonNull public HistoryEntry getEntry() {
+ return entry;
+ }
+ }
+
+ private class HistoryEntryItemHolder extends
DefaultViewHolder<PageItemView<IndexedHistoryEntry>> {
+ HistoryEntryItemHolder(PageItemView<IndexedHistoryEntry> itemView) {
super(itemView);
}
void bindItem(@NonNull Cursor cursor) {
- entry = HistoryEntry.DATABASE_TABLE.fromCursor(cursor);
- getView().setItem(entry);
- getView().setTitle(entry.getTitle().getDisplayText());
- getView().setDescription(entry.getTitle().getDescription());
+ IndexedHistoryEntry indexedEntry
+ = new
IndexedHistoryEntry(HistoryEntry.DATABASE_TABLE.fromCursor(cursor),
+ cursor.getPosition());
+ getView().setItem(indexedEntry);
+
getView().setTitle(indexedEntry.getEntry().getTitle().getDisplayText());
+
getView().setDescription(indexedEntry.getEntry().getTitle().getDescription());
getView().setImageUrl(PageHistoryContract.PageWithImage.IMAGE_NAME.val(cursor));
+
getView().setSelected(selectedIndices.contains(indexedEntry.getIndex()));
// Check the previous item, see if the times differ enough
// If they do, display the section header.
// Always do it this is the first item.
- String curTime = getDateString(entry.getTimestamp());
+ String curTime =
getDateString(indexedEntry.getEntry().getTimestamp());
String prevTime = "";
if (cursor.getPosition() != 0) {
cursor.moveToPrevious();
@@ -285,6 +382,17 @@
return getItemCount() == 0;
}
+ @Nullable public HistoryEntry getItem(int position) {
+ if (cursor == null) {
+ return null;
+ }
+ int prevPosition = cursor.getPosition();
+ cursor.moveToPosition(position);
+ HistoryEntry entry =
HistoryEntry.DATABASE_TABLE.fromCursor(cursor);
+ cursor.moveToPosition(prevPosition);
+ return entry;
+ }
+
public void setCursor(@Nullable Cursor newCursor) {
if (cursor == newCursor) {
return;
@@ -298,7 +406,7 @@
@Override
public HistoryEntryItemHolder onCreateViewHolder(ViewGroup parent, int
type) {
- return new HistoryEntryItemHolder(new
PageItemView<HistoryEntry>(getContext()));
+ return new HistoryEntryItemHolder(new
PageItemView<IndexedHistoryEntry>(getContext()));
}
@Override
@@ -321,28 +429,31 @@
}
}
- private class ItemCallback implements PageItemView.Callback<HistoryEntry> {
+ private class ItemCallback implements
PageItemView.Callback<IndexedHistoryEntry> {
@Override
- public void onClick(@Nullable HistoryEntry entry) {
- if (entry != null) {
- HistoryEntry newEntry = new HistoryEntry(entry.getTitle(),
HistoryEntry.SOURCE_HISTORY);
- onPageClick(entry.getTitle(), newEntry);
+ public void onClick(@Nullable IndexedHistoryEntry indexedEntry) {
+ if (MultiSelectCallback.is(actionMode)) {
+ toggleSelectPage(indexedEntry);
+ } else if (indexedEntry != null) {
+ HistoryEntry newEntry = new
HistoryEntry(indexedEntry.getEntry().getTitle(), HistoryEntry.SOURCE_HISTORY);
+ onPageClick(indexedEntry.getEntry().getTitle(), newEntry);
}
}
@Override
- public boolean onLongClick(@Nullable HistoryEntry entry) {
- // TODO: multi-select
+ public boolean onLongClick(@Nullable IndexedHistoryEntry indexedEntry)
{
+ beginMultiSelect();
+ toggleSelectPage(indexedEntry);
return true;
}
@Override
- public void onThumbClick(@Nullable HistoryEntry entry) {
- onClick(entry);
+ public void onThumbClick(@Nullable IndexedHistoryEntry indexedEntry) {
+ onClick(indexedEntry);
}
@Override
- public void onActionClick(@Nullable HistoryEntry entry, @NonNull
PageItemView view) {
+ public void onActionClick(@Nullable IndexedHistoryEntry entry,
@NonNull PageItemView view) {
}
}
@@ -375,6 +486,28 @@
}
}
+ private class MultiSelectCallback extends MultiSelectActionModeCallback {
+ @Override
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ actionMode = mode;
+ selectedIndices.clear();
+ return super.onCreateActionMode(mode, menu);
+ }
+
+ @Override
+ protected void onDelete() {
+ deleteSelectedPages();
+ finishActionMode();
+ }
+
+ @Override
+ public void onDestroyActionMode(ActionMode mode) {
+ unselectAllPages();
+ actionMode = null;
+ super.onDestroyActionMode(mode);
+ }
+ }
+
@Nullable private Callback callback() {
return FragmentUtil.getCallback(this, Callback.class);
}
diff --git a/app/src/main/res/values-qq/strings.xml
b/app/src/main/res/values-qq/strings.xml
index 92d644f..ba795cf 100644
--- a/app/src/main/res/values-qq/strings.xml
+++ b/app/src/main/res/values-qq/strings.xml
@@ -24,6 +24,10 @@
{{Identical|Go back}}</string>
<string name="menu_clear_all_history">Menu item text for clearing your
reading history.
{{Identical|Clear history}}</string>
+ <string name="history_item_deleted">Message shown when an article is removed
from the browsing history. The \"%s\" symbol is replaced with the name of the
article.</string>
+ <string name="history_items_deleted">Message shown when multiple articles
are removed from the browsing history. The \"%d\" symbol is replaced with the
number of articles removed.</string>
+ <string name="history_item_delete_undo">Button label to undo the operation
of deleting an item from the browsing history.
+{{Identical|Undo}}</string>
<string name="page_does_not_exist_error">Text shown when the requested page
does not exist</string>
<string name="dialog_title_clear_history">Title for dialog box asking if you
want to clear your reading history.</string>
<string name="dialog_message_clear_history">Message for the dialog box that
asks if the user wants to clear their browsing history, as well close any tabs
that are open.</string>
diff --git a/app/src/main/res/values/strings.xml
b/app/src/main/res/values/strings.xml
index a9662b7..a6ed98e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -18,6 +18,9 @@
<string name="page_error_retry">Retry</string>
<string name="page_error_back_to_main">Go back</string>
<string name="menu_clear_all_history">Clear history</string>
+ <string name="history_item_deleted">%s removed from history</string>
+ <string name="history_items_deleted">%d articles removed from
history</string>
+ <string name="history_item_delete_undo">Undo</string>
<string name="page_does_not_exist_error">This page does not exist.</string>
<!-- Saved pages -->
--
To view, visit https://gerrit.wikimedia.org/r/349963
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ifc97f253538281a7d1903e255f2b916db52fc45c
Gerrit-PatchSet: 1
Gerrit-Project: apps/android/wikipedia
Gerrit-Branch: master
Gerrit-Owner: Dbrant <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits