From 674a1804e6a78f5726346ecc8c478ac32fc865bf Mon Sep 17 00:00:00 2001 From: Floens Date: Sat, 9 Apr 2016 19:24:33 +0200 Subject: [PATCH] Add bookmark clearing --- .../chan/core/manager/WatchManager.java | 56 +++++++++++++++++- .../java/org/floens/chan/core/model/Pin.java | 15 +++++ .../floens/chan/ui/adapter/PinAdapter.java | 57 +++++++++++++++---- .../chan/ui/controller/DrawerController.java | 33 +++++++++-- .../app/src/main/res/layout/cell_header.xml | 12 +++- Clover/app/src/main/res/values/strings.xml | 8 +++ 6 files changed, 163 insertions(+), 18 deletions(-) diff --git a/Clover/app/src/main/java/org/floens/chan/core/manager/WatchManager.java b/Clover/app/src/main/java/org/floens/chan/core/manager/WatchManager.java index 1352f0ef..3a7aa6cc 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/manager/WatchManager.java +++ b/Clover/app/src/main/java/org/floens/chan/core/manager/WatchManager.java @@ -168,8 +168,11 @@ public class WatchManager { } } - pin.order = pins.size(); + if (pin.order < 0) { + pin.order = pins.size(); + } pins.add(pin); + applyOrder(); databaseManager.runTaskSync(databasePinManager.createPin(pin)); updateState(); @@ -186,6 +189,7 @@ public class WatchManager { databaseManager.runTaskSync(databasePinManager.deletePin(pin)); // Update the new orders + applyOrder(); updatePinsInDatabase(); updateState(); @@ -223,6 +227,14 @@ public class WatchManager { return null; } + public void reorder(List pins) { + for (int i = 0; i < pins.size(); i++) { + Pin pin = pins.get(i); + pin.order = i; + } + updatePinsInDatabase(); + } + public List getAllPins() { return pins; } @@ -305,6 +317,40 @@ public class WatchManager { } } + // Clear all non watching pins or all pins + // Returns a list of pins that can later be given to addAll + // to undo the clearing + public List clearPins(boolean all) { + List toRemove = new ArrayList<>(); + for (int i = 0; i < pins.size(); i++) { + Pin pin = pins.get(i); + if (all || !pin.watching) { + toRemove.add(pin); + } + } + + List undo = new ArrayList<>(toRemove.size()); + for (int i = 0; i < toRemove.size(); i++) { + Pin pin = toRemove.get(i); + undo.add(pin.copy()); + } + + for (int i = 0; i < toRemove.size(); i++) { + Pin pin = toRemove.get(i); + deletePin(pin); + } + + return undo; + } + + public void addAll(List pins) { + Collections.sort(pins, SORT_PINS); + for (int i = 0; i < pins.size(); i++) { + Pin pin = pins.get(i); + createPin(pin); + } + } + // Called when the user changes the watch enabled preference public void onWatchEnabledChanged(boolean watchEnabled) { updateState(watchEnabled, isBackgroundWatchingSettingEnabled()); @@ -329,6 +375,14 @@ public class WatchManager { return pinWatchers.get(pin); } + private void applyOrder() { + Collections.sort(pins, SORT_PINS); + for (int i = 0; i < pins.size(); i++) { + Pin pin = pins.get(i); + pin.order = i; + } + } + private boolean createPinWatcher(Pin pin) { if (!pinWatchers.containsKey(pin)) { pinWatchers.put(pin, new PinWatcher(pin)); diff --git a/Clover/app/src/main/java/org/floens/chan/core/model/Pin.java b/Clover/app/src/main/java/org/floens/chan/core/model/Pin.java index 4e4b985f..78ed3223 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/model/Pin.java +++ b/Clover/app/src/main/java/org/floens/chan/core/model/Pin.java @@ -70,4 +70,19 @@ public class Pin { return Math.max(0, quoteNewCount - quoteLastCount); } } + + public Pin copy() { + Pin copy = new Pin(); + copy.loadable = loadable; + copy.watching = watching; + copy.watchLastCount = watchLastCount; + copy.watchNewCount = watchNewCount; + copy.quoteLastCount = quoteLastCount; + copy.quoteNewCount = quoteNewCount; + copy.isError = isError; + copy.thumbnailUrl = thumbnailUrl; + copy.order = order; + copy.archived = archived; + return copy; + } } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/adapter/PinAdapter.java b/Clover/app/src/main/java/org/floens/chan/ui/adapter/PinAdapter.java index 37f157a4..0d8b33c8 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/adapter/PinAdapter.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/adapter/PinAdapter.java @@ -26,7 +26,9 @@ import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; +import org.floens.chan.Chan; import org.floens.chan.R; +import org.floens.chan.core.manager.WatchManager; import org.floens.chan.core.model.Pin; import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.ui.helper.PostHelper; @@ -34,6 +36,8 @@ import org.floens.chan.ui.view.ThumbnailView; import org.floens.chan.utils.AndroidUtils; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; import static org.floens.chan.ui.theme.ThemeHelper.theme; @@ -44,6 +48,10 @@ import static org.floens.chan.utils.AndroidUtils.setRoundItemBackground; import static org.floens.chan.utils.AndroidUtils.sp; public class PinAdapter extends RecyclerView.Adapter { + public enum HeaderAction { + SETTINGS, CLEAR, CLEAR_ALL + } + private static final int PIN_OFFSET = 3; private static final int TYPE_HEADER = 0; @@ -51,11 +59,20 @@ public class PinAdapter extends RecyclerView.Adapter { private static final int TYPE_LINK = 2; private static final int TYPE_DIVIDER = 3; + private static final Comparator SORT_PINS = new Comparator() { + @Override + public int compare(Pin lhs, Pin rhs) { + return lhs.order - rhs.order; + } + }; + + private final WatchManager watchManager; private final Callback callback; private List pins = new ArrayList<>(); private Pin highlighted; public PinAdapter(Callback callback) { + watchManager = Chan.getWatchManager(); this.callback = callback; setHasStableIds(true); } @@ -120,7 +137,8 @@ public class PinAdapter extends RecyclerView.Adapter { case TYPE_HEADER: HeaderHolder headerHolder = (HeaderHolder) holder; headerHolder.text.setText(R.string.drawer_pinned); - theme().settingsDrawable.apply(headerHolder.image); + theme().clearDrawable.apply(headerHolder.clear); + theme().settingsDrawable.apply(headerHolder.settings); break; case TYPE_PIN: @@ -179,16 +197,19 @@ public class PinAdapter extends RecyclerView.Adapter { public void onPinsChanged(List pins) { this.pins.clear(); this.pins.addAll(pins); + Collections.sort(pins, SORT_PINS); notifyDataSetChanged(); } public void onPinAdded(Pin pin) { pins.add(pin); + Collections.sort(pins, SORT_PINS); notifyDataSetChanged(); } public void onPinRemoved(Pin pin) { pins.remove(pin); + Collections.sort(pins, SORT_PINS); notifyDataSetChanged(); } @@ -264,10 +285,8 @@ public class PinAdapter extends RecyclerView.Adapter { } private void applyOrder() { - for (int i = 0; i < pins.size(); i++) { - Pin pin = pins.get(i); - pin.order = i; - } + watchManager.reorder(pins); + notifyDataSetChanged(); } public class PinViewHolder extends RecyclerView.ViewHolder { @@ -323,18 +342,34 @@ public class PinAdapter extends RecyclerView.Adapter { public class HeaderHolder extends RecyclerView.ViewHolder { private TextView text; - private ImageView image; + private ImageView clear; + private ImageView settings; public HeaderHolder(View itemView) { super(itemView); text = (TextView) itemView.findViewById(R.id.text); text.setTypeface(ROBOTO_MEDIUM); - image = (ImageView) itemView.findViewById(R.id.image); - setRoundItemBackground(image); - image.setOnClickListener(new View.OnClickListener() { + clear = (ImageView) itemView.findViewById(R.id.clear); + setRoundItemBackground(clear); + clear.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + callback.onHeaderClicked(HeaderHolder.this, HeaderAction.CLEAR); + } + }); + clear.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + callback.onHeaderClicked(HeaderHolder.this, HeaderAction.CLEAR_ALL); + return true; + } + }); + settings = (ImageView) itemView.findViewById(R.id.settings); + setRoundItemBackground(settings); + settings.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - callback.onHeaderClicked(HeaderHolder.this); + callback.onHeaderClicked(HeaderHolder.this, HeaderAction.SETTINGS); } }); } @@ -392,7 +427,7 @@ public class PinAdapter extends RecyclerView.Adapter { void onWatchCountClicked(Pin pin); - void onHeaderClicked(HeaderHolder holder); + void onHeaderClicked(HeaderHolder holder, HeaderAction headerAction); void onPinRemoved(Pin pin); diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/DrawerController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/DrawerController.java index 3c4e4a41..bedae192 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/DrawerController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/DrawerController.java @@ -151,20 +151,43 @@ public class DrawerController extends Controller implements PinAdapter.Callback, } @Override - public void onHeaderClicked(PinAdapter.HeaderHolder holder) { - openController(new WatchSettingsController(context)); + public void onHeaderClicked(PinAdapter.HeaderHolder holder, PinAdapter.HeaderAction headerAction) { + if (headerAction == PinAdapter.HeaderAction.SETTINGS) { + openController(new WatchSettingsController(context)); + } else if (headerAction == PinAdapter.HeaderAction.CLEAR || headerAction == PinAdapter.HeaderAction.CLEAR_ALL) { + boolean all = headerAction == PinAdapter.HeaderAction.CLEAR_ALL; + final List pins = watchManager.clearPins(all); + if (!pins.isEmpty()) { + String text = context.getResources().getQuantityString(R.plurals.bookmark, pins.size(), pins.size()); + //noinspection WrongConstant + Snackbar snackbar = Snackbar.make(drawerLayout, context.getString(R.string.drawer_pins_cleared, text), 4000); + fixSnackbarText(context, snackbar); + snackbar.setAction(R.string.undo, new View.OnClickListener() { + @Override + public void onClick(View v) { + watchManager.addAll(pins); + } + }); + snackbar.show(); + } else { + int text = watchManager.getAllPins().isEmpty() ? R.string.drawer_pins_non_cleared : R.string.drawer_pins_non_cleared_try_all; + Snackbar snackbar = Snackbar.make(drawerLayout, text, Snackbar.LENGTH_LONG); + fixSnackbarText(context, snackbar); + snackbar.show(); + } + } } @Override - public void onPinRemoved(final Pin pin) { + public void onPinRemoved(Pin pin) { + final Pin undoPin = pin.copy(); watchManager.deletePin(pin); - Snackbar snackbar = Snackbar.make(drawerLayout, context.getString(R.string.drawer_pin_removed, pin.loadable.title), Snackbar.LENGTH_LONG); fixSnackbarText(context, snackbar); snackbar.setAction(R.string.undo, new View.OnClickListener() { @Override public void onClick(View v) { - watchManager.createPin(pin); + watchManager.createPin(undoPin); } }); snackbar.show(); diff --git a/Clover/app/src/main/res/layout/cell_header.xml b/Clover/app/src/main/res/layout/cell_header.xml index e2770c41..79359cda 100644 --- a/Clover/app/src/main/res/layout/cell_header.xml +++ b/Clover/app/src/main/res/layout/cell_header.xml @@ -35,7 +35,17 @@ along with this program. If not, see . android:textSize="14sp" /> + + . %d boards + + %d bookmark + %d bookmarks + + %1$dR %2$dI View album @@ -236,6 +241,9 @@ along with this program. If not, see . Catalog Bookmarked threads Removed \'%1$s\' + %1$s cleared + No bookmarks cleared. + No bookmarks cleared. Hold to remove all. Highlight ID Highlight tripcode