From bfddc42f5ee0a940665cd6193b5341cae6c1e40c Mon Sep 17 00:00:00 2001 From: Quentin Hibon Date: Fri, 20 Nov 2020 02:05:21 +0100 Subject: [PATCH] Allow user to sort by status (#660) --- .../activities/habits/list/ListHabitsMenu.kt | 5 + .../list/views/HabitCardListAdapter.java | 23 ++-- .../src/main/res/menu/list_habits.xml | 4 + .../src/main/res/values/strings.xml | 1 + .../isoron/uhabits/core/models/Checkmark.java | 5 + .../isoron/uhabits/core/models/HabitList.java | 19 +++- .../core/models/memory/MemoryHabitList.java | 104 ++++++++++++------ .../core/models/sqlite/SQLiteHabitList.java | 21 +++- .../uhabits/core/preferences/Preferences.java | 25 ++++- .../habits/list/HabitCardListCache.java | 23 +++- .../habits/list/ListHabitsMenuBehavior.java | 45 +++++--- .../core/io/HabitsCSVExporterTest.java | 10 +- .../isoron/uhabits/core/io/ImportTest.java | 6 +- .../uhabits/core/models/HabitListTest.java | 31 +++--- .../core/preferences/PreferencesTest.java | 8 +- .../list/ListHabitsMenuBehaviorTest.java | 35 +++++- 16 files changed, 260 insertions(+), 105 deletions(-) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.kt index 74f2f0d89..c9d40f1c0 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.kt @@ -104,6 +104,11 @@ class ListHabitsMenu @Inject constructor( return true } + R.id.actionSortStatus -> { + behavior.onSortByStatus() + return true + } + else -> return false } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListAdapter.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListAdapter.java index 62394690e..95bffc3ae 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListAdapter.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListAdapter.java @@ -21,7 +21,7 @@ package org.isoron.uhabits.activities.habits.list.views; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.widget.*; + import android.view.*; import androidx.recyclerview.widget.RecyclerView; @@ -83,7 +83,8 @@ public class HabitCardListAdapter cache.setListener(this); cache.setCheckmarkCount( ListHabitsRootViewKt.MAX_CHECKMARK_COUNT); - cache.setOrder(preferences.getDefaultOrder()); + cache.setSecondaryOrder(preferences.getDefaultSecondaryOrder()); + cache.setPrimaryOrder(preferences.getDefaultPrimaryOrder()); setHasStableIds(true); } @@ -160,7 +161,7 @@ public class HabitCardListAdapter public boolean isSortable() { - return cache.getOrder() == HabitList.Order.BY_POSITION; + return cache.getPrimaryOrder() == HabitList.Order.BY_POSITION; } /** @@ -313,16 +314,22 @@ public class HabitCardListAdapter } @Override - public void setOrder(HabitList.Order order) + public void setPrimaryOrder(HabitList.Order order) { - cache.setOrder(order); - preferences.setDefaultOrder(order); + cache.setPrimaryOrder(order); + preferences.setDefaultPrimaryOrder(order); + } + + @Override + public void setSecondaryOrder(HabitList.Order order) { + cache.setSecondaryOrder(order); + preferences.setDefaultSecondaryOrder(order); } @Override - public HabitList.Order getOrder() + public HabitList.Order getPrimaryOrder() { - return cache.getOrder(); + return cache.getPrimaryOrder(); } /** diff --git a/android/uhabits-android/src/main/res/menu/list_habits.xml b/android/uhabits-android/src/main/res/menu/list_habits.xml index f74b910e2..9514c7a28 100644 --- a/android/uhabits-android/src/main/res/menu/list_habits.xml +++ b/android/uhabits-android/src/main/res/menu/list_habits.xml @@ -65,6 +65,10 @@ + + diff --git a/android/uhabits-android/src/main/res/values/strings.xml b/android/uhabits-android/src/main/res/values/strings.xml index 4e1fd75d9..7f807dccd 100644 --- a/android/uhabits-android/src/main/res/values/strings.xml +++ b/android/uhabits-android/src/main/res/values/strings.xml @@ -159,6 +159,7 @@ By name By color By score + By status Export Press-and-hold to change the value Change value diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Checkmark.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Checkmark.java index a3150e150..88bc0ae05 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Checkmark.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Checkmark.java @@ -31,6 +31,11 @@ import static org.isoron.uhabits.core.utils.StringUtils.defaultToStringStyle; * While repetitions simply record that the habit was performed at a given date, * a checkmark provides more information, such as whether a repetition was * expected at that day or not. + *

+ *

+ * Note that the status comparator in + * {@link org.isoron.uhabits.core.models.memory.MemoryHabitList} + * relies on SKIP > YES_MANUAL > YES_AUTO > NO. *

* Checkmarks are computed automatically from the list of repetitions. */ diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/HabitList.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/HabitList.java index 436016664..8f19258d0 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/HabitList.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/HabitList.java @@ -107,14 +107,23 @@ public abstract class HabitList implements Iterable return observable; } - public abstract Order getOrder(); + public abstract Order getPrimaryOrder(); + + public abstract Order getSecondaryOrder(); /** * Changes the order of the elements on the list. * - * @param order the new order criterea + * @param order the new order criterion */ - public abstract void setOrder(@NonNull Order order); + public abstract void setPrimaryOrder(@NonNull Order order); + + /** + * Changes the previous order of the elements on the list. + * + * @param order the new order criterion + */ + public abstract void setSecondaryOrder(@NonNull Order order); /** * Returns the index of the given habit in the list, or -1 if the list does @@ -242,6 +251,8 @@ public abstract class HabitList implements Iterable csv.close(); } + + public enum Order { BY_NAME_ASC, @@ -250,6 +261,8 @@ public abstract class HabitList implements Iterable BY_COLOR_DESC, BY_SCORE_ASC, BY_SCORE_DESC, + BY_STATUS_ASC, + BY_STATUS_DESC, BY_POSITION } } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryHabitList.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryHabitList.java index 60f05ee3a..84716e771 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryHabitList.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryHabitList.java @@ -35,10 +35,13 @@ public class MemoryHabitList extends HabitList @NonNull private LinkedList list = new LinkedList<>(); - private Comparator comparator = null; + @NonNull + private Order primaryOrder = Order.BY_POSITION; @NonNull - private Order order = Order.BY_POSITION; + private Order secondaryOrder = Order.BY_NAME_ASC; + + private Comparator comparator = getComposedComparatorByOrder(primaryOrder, secondaryOrder); @Nullable private MemoryHabitList parent = null; @@ -55,7 +58,8 @@ public class MemoryHabitList extends HabitList super(matcher); this.parent = parent; this.comparator = comparator; - this.order = parent.order; + this.primaryOrder = parent.primaryOrder; + this.secondaryOrder = parent.secondaryOrder; parent.getObservable().addListener(this::loadFromParent); loadFromParent(); } @@ -105,58 +109,88 @@ public class MemoryHabitList extends HabitList } @Override - public synchronized Order getOrder() + public synchronized Order getPrimaryOrder() { - return order; + return primaryOrder; } @Override - public synchronized void setOrder(@NonNull Order order) + public synchronized Order getSecondaryOrder() { - this.order = order; - this.comparator = getComparatorByOrder(order); + return secondaryOrder; + } + + @Override + public synchronized void setPrimaryOrder(@NonNull Order order) + { + this.primaryOrder = order; + this.comparator = getComposedComparatorByOrder(this.primaryOrder, this.secondaryOrder); resort(); getObservable().notifyListeners(); } - private Comparator getComparatorByOrder(Order order) + @Override + public void setSecondaryOrder(@NonNull Order order) { - Comparator nameComparatorAsc = - (h1, h2) -> h1.getName().compareTo(h2.getName()); + this.secondaryOrder = order; + this.comparator = getComposedComparatorByOrder(this.primaryOrder, this.secondaryOrder); + resort(); + getObservable().notifyListeners(); + } - Comparator nameComparatorDesc = - (h1, h2) -> nameComparatorAsc.compare(h2, h1); + private Comparator getComposedComparatorByOrder(Order firstOrder, Order secondOrder) + { + return (h1, h2) -> { + int firstResult = getComparatorByOrder(firstOrder).compare(h1, h2); - Comparator colorComparatorAsc = (h1, h2) -> - { - Integer c1 = h1.getColor(); - Integer c2 = h2.getColor(); - if (c1.equals(c2)) return nameComparatorAsc.compare(h1, h2); - else return c1.compareTo(c2); + if (firstResult != 0 || secondOrder == null) { + return firstResult; + } + + return getComparatorByOrder(secondOrder).compare(h1, h2); }; + } - Comparator colorComparatorDesc = - (h1, h2) -> colorComparatorAsc.compare(h2, h1); + private Comparator getComparatorByOrder(Order order) { + Comparator nameComparatorAsc = (h1, h2) -> + h1.getName().compareTo(h2.getName()); + + Comparator nameComparatorDesc = (h1, h2) -> + nameComparatorAsc.compare(h2, h1); + + Comparator colorComparatorAsc = (h1, h2) -> + h1.getColor().compareTo(h2.getColor()); + + Comparator colorComparatorDesc = (h1, h2) -> + colorComparatorAsc.compare(h2, h1); Comparator scoreComparatorDesc = (h1, h2) -> - { - Double s1 = h1.getScores().getTodayValue(); - Double s2 = h2.getScores().getTodayValue(); - if (s1.equals(s2)) return nameComparatorAsc.compare(h1, h2); - else return s2.compareTo(s1); - }; + Double.compare(h1.getScores().getTodayValue(), h2.getScores().getTodayValue()); - Comparator scoreComparatorAsc = - (h1, h2) -> scoreComparatorDesc.compare(h2, h1); + Comparator scoreComparatorAsc = (h1, h2) -> + scoreComparatorDesc.compare(h2, h1); Comparator positionComparator = (h1, h2) -> + h1.getPosition().compareTo(h2.getPosition()); + + Comparator statusComparatorDesc = (h1, h2) -> { - Integer p1 = h1.getPosition(); - Integer p2 = h2.getPosition(); - if (p1.equals(p2)) return nameComparatorAsc.compare(h1, h2); - else return p1.compareTo(p2); + if (h1.isCompletedToday() != h2.isCompletedToday()) { + return h1.isCompletedToday() ? -1 : 1; + } + + if (h1.isNumerical() != h2.isNumerical()) { + return h1.isNumerical() ? -1 : 1; + } + + Integer v1 = Objects.requireNonNull(h1.getCheckmarks().getToday()).getValue(); + Integer v2 = Objects.requireNonNull(h2.getCheckmarks().getToday()).getValue(); + + return v2.compareTo(v1); }; + Comparator statusComparatorAsc = (h1, h2) -> statusComparatorDesc.compare(h2, h1); + if (order == BY_POSITION) return positionComparator; if (order == BY_NAME_ASC) return nameComparatorAsc; if (order == BY_NAME_DESC) return nameComparatorDesc; @@ -164,6 +198,8 @@ public class MemoryHabitList extends HabitList if (order == BY_COLOR_DESC) return colorComparatorDesc; if (order == BY_SCORE_DESC) return scoreComparatorDesc; if (order == BY_SCORE_ASC) return scoreComparatorAsc; + if (order == BY_STATUS_DESC) return statusComparatorDesc; + if (order == BY_STATUS_ASC) return statusComparatorAsc; throw new IllegalStateException(); } @@ -192,7 +228,7 @@ public class MemoryHabitList extends HabitList public synchronized void reorder(@NonNull Habit from, @NonNull Habit to) { throwIfHasParent(); - if (order != BY_POSITION) throw new IllegalStateException( + if (primaryOrder != BY_POSITION) throw new IllegalStateException( "cannot reorder automatically sorted list"); if (indexOf(from) < 0) throw new IllegalArgumentException( diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitList.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitList.java index a60f5613d..1ba429bfd 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitList.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitList.java @@ -116,15 +116,28 @@ public class SQLiteHabitList extends HabitList @Override @NonNull - public Order getOrder() + public Order getPrimaryOrder() { - return list.getOrder(); + return list.getPrimaryOrder(); } @Override - public synchronized void setOrder(@NonNull Order order) + public Order getSecondaryOrder() { - list.setOrder(order); + return list.getSecondaryOrder(); + } + + @Override + public synchronized void setPrimaryOrder(@NonNull Order order) + { + list.setPrimaryOrder(order); + getObservable().notifyListeners(); + } + + @Override + public synchronized void setSecondaryOrder(@NonNull Order order) + { + list.setSecondaryOrder(order); getObservable().notifyListeners(); } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java index 6cca0ae24..857989aea 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java @@ -60,7 +60,7 @@ public class Preferences fallbackColor); } - public HabitList.Order getDefaultOrder() + public HabitList.Order getDefaultPrimaryOrder() { String name = storage.getString("pref_default_order", "BY_POSITION"); @@ -70,16 +70,35 @@ public class Preferences } catch (IllegalArgumentException e) { - setDefaultOrder(HabitList.Order.BY_POSITION); + setDefaultPrimaryOrder(HabitList.Order.BY_POSITION); return HabitList.Order.BY_POSITION; } } - public void setDefaultOrder(HabitList.Order order) + public HabitList.Order getDefaultSecondaryOrder() { + String name = storage.getString("pref_default_secondary_order", "BY_NAME_ASC"); + + try + { + return HabitList.Order.valueOf(name); + } + catch (IllegalArgumentException e) + { + setDefaultSecondaryOrder(HabitList.Order.BY_NAME_ASC); + return HabitList.Order.BY_POSITION; + } + } + + public void setDefaultPrimaryOrder(HabitList.Order order) { storage.putString("pref_default_order", order.name()); } + public void setDefaultSecondaryOrder(HabitList.Order order) + { + storage.putString("pref_default_secondary_order", order.name()); + } + public int getDefaultScoreSpinnerPosition() { int defaultScoreInterval = diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCache.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCache.java index 86f67c29d..2533270ec 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCache.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCache.java @@ -116,9 +116,14 @@ public class HabitCardListCache implements CommandRunner.Listener return data.habits.size(); } - public synchronized HabitList.Order getOrder() + public synchronized HabitList.Order getPrimaryOrder() { - return filteredHabits.getOrder(); + return filteredHabits.getPrimaryOrder(); + } + + public synchronized HabitList.Order getSecondaryOrder() + { + return filteredHabits.getSecondaryOrder(); } public synchronized double getScore(long habitId) @@ -196,14 +201,22 @@ public class HabitCardListCache implements CommandRunner.Listener this.listener = listener; } - public synchronized void setOrder(@NonNull HabitList.Order order) + public synchronized void setPrimaryOrder(@NonNull HabitList.Order order) { if (order == null) throw new NullPointerException(); - allHabits.setOrder(order); - filteredHabits.setOrder(order); + allHabits.setPrimaryOrder(order); + filteredHabits.setPrimaryOrder(order); + refreshAllHabits(); + } + + public synchronized void setSecondaryOrder(@NonNull HabitList.Order order) + { + allHabits.setSecondaryOrder(order); + filteredHabits.setSecondaryOrder(order); refreshAllHabits(); } + /** * Interface definition for a callback to be invoked when the data on the * cache has been modified. diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsMenuBehavior.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsMenuBehavior.java index ad0607a4c..c166cdb2e 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsMenuBehavior.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsMenuBehavior.java @@ -95,36 +95,43 @@ public class ListHabitsMenuBehavior updateAdapterFilter(); } - public void onSortByColor() + public void onSortByManually() { - if (adapter.getOrder() != HabitList.Order.BY_COLOR_ASC) { - adapter.setOrder(HabitList.Order.BY_COLOR_ASC); - } else { - adapter.setOrder(HabitList.Order.BY_COLOR_DESC); - } + adapter.setPrimaryOrder(HabitList.Order.BY_POSITION); } - public void onSortByManually() + public void onSortByColor() { - adapter.setOrder(HabitList.Order.BY_POSITION); + onSortToggleBy(HabitList.Order.BY_COLOR_ASC, HabitList.Order.BY_COLOR_DESC); } + public void onSortByScore() { - if (adapter.getOrder() != HabitList.Order.BY_SCORE_DESC) { - adapter.setOrder(HabitList.Order.BY_SCORE_DESC); - } else { - adapter.setOrder(HabitList.Order.BY_SCORE_ASC); - } + onSortToggleBy(HabitList.Order.BY_SCORE_DESC, HabitList.Order.BY_SCORE_ASC); } public void onSortByName() { - if (adapter.getOrder() != HabitList.Order.BY_NAME_ASC) { - adapter.setOrder(HabitList.Order.BY_NAME_ASC); + onSortToggleBy(HabitList.Order.BY_NAME_ASC, HabitList.Order.BY_NAME_DESC); + } + + public void onSortByStatus() + { + onSortToggleBy(HabitList.Order.BY_STATUS_ASC, HabitList.Order.BY_STATUS_DESC); + } + + private void onSortToggleBy(HabitList.Order defaultOrder, HabitList.Order reversedOrder) + { + if (adapter.getPrimaryOrder() != defaultOrder) { + if (adapter.getPrimaryOrder() != reversedOrder) { + adapter.setSecondaryOrder(adapter.getPrimaryOrder()); + } + adapter.setPrimaryOrder(defaultOrder); } else { - adapter.setOrder(HabitList.Order.BY_NAME_DESC); + adapter.setPrimaryOrder(reversedOrder); } + } public void onToggleNightMode() @@ -148,9 +155,11 @@ public class ListHabitsMenuBehavior void setFilter(HabitMatcher build); - void setOrder(HabitList.Order order); + void setPrimaryOrder(HabitList.Order order); + + void setSecondaryOrder(HabitList.Order order); - HabitList.Order getOrder(); + HabitList.Order getPrimaryOrder(); } public interface Screen diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/io/HabitsCSVExporterTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/io/HabitsCSVExporterTest.java index 758a70220..ec9e56f28 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/io/HabitsCSVExporterTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/io/HabitsCSVExporterTest.java @@ -68,11 +68,11 @@ public class HabitsCSVExporterTest extends BaseUnitTest unzip(archive); assertPathExists("Habits.csv"); - assertPathExists("001 Wake up early"); - assertPathExists("001 Wake up early/Checkmarks.csv"); - assertPathExists("001 Wake up early/Scores.csv"); - assertPathExists("002 Meditate/Checkmarks.csv"); - assertPathExists("002 Meditate/Scores.csv"); + assertPathExists("001 Meditate/Checkmarks.csv"); + assertPathExists("001 Meditate/Scores.csv"); + assertPathExists("002 Wake up early"); + assertPathExists("002 Wake up early/Checkmarks.csv"); + assertPathExists("002 Wake up early/Scores.csv"); assertPathExists("Checkmarks.csv"); assertPathExists("Scores.csv"); } diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/io/ImportTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/io/ImportTest.java index 73671d7e7..1fa3ba513 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/io/ImportTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/io/ImportTest.java @@ -81,7 +81,7 @@ public class ImportTest extends BaseUnitTest assertThat(habitList.size(), equalTo(3)); - Habit habit = habitList.getByPosition(0); + Habit habit = habitList.getByPosition(1); assertThat(habit.getName(), equalTo("Wake up early")); assertThat(habit.getFrequency(), equalTo(THREE_TIMES_PER_WEEK)); assertFalse(habit.hasReminder()); @@ -90,7 +90,7 @@ public class ImportTest extends BaseUnitTest assertTrue(containsRepetition(habit, 2016, 1, 28)); assertFalse(containsRepetition(habit, 2016, 3, 10)); - habit = habitList.getByPosition(1); + habit = habitList.getByPosition(2); assertThat(habit.getName(), equalTo("brush teeth")); assertThat(habit.getFrequency(), equalTo(THREE_TIMES_PER_WEEK)); assertThat(habit.hasReminder(), equalTo(true)); @@ -109,7 +109,7 @@ public class ImportTest extends BaseUnitTest assertThat(habitList.size(), equalTo(3)); - Habit h = habitList.getByPosition(0); + Habit h = habitList.getByPosition(2); assertThat(h.getName(), equalTo("Vegan")); assertTrue(containsRepetition(h, 2016, 1, 24)); assertTrue(containsRepetition(h, 2016, 2, 5)); diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/HabitListTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/HabitListTest.java index d5fdc448a..2057562c0 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/HabitListTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/HabitListTest.java @@ -111,7 +111,6 @@ public class HabitListTest extends BaseUnitTest @Test public void testOrdering() { - HabitList list = modelFactory.buildHabitList(); Habit h1 = fixtures.createEmptyHabit(); h1.setName("A Habit"); h1.setColor(2); @@ -132,46 +131,51 @@ public class HabitListTest extends BaseUnitTest h4.setColor(1); h4.setPosition(2); + HabitList list = modelFactory.buildHabitList(); + list.add(h3); list.add(h1); list.add(h4); list.add(h2); - list.setOrder(BY_POSITION); + list.setPrimaryOrder(BY_POSITION); assertThat(list.getByPosition(0), equalTo(h3)); assertThat(list.getByPosition(1), equalTo(h1)); assertThat(list.getByPosition(2), equalTo(h4)); assertThat(list.getByPosition(3), equalTo(h2)); - list.setOrder(BY_NAME_DESC); + list.setPrimaryOrder(BY_NAME_DESC); assertThat(list.getByPosition(0), equalTo(h4)); assertThat(list.getByPosition(1), equalTo(h3)); assertThat(list.getByPosition(2), equalTo(h2)); assertThat(list.getByPosition(3), equalTo(h1)); - list.setOrder(BY_NAME_ASC); + list.setPrimaryOrder(BY_NAME_ASC); assertThat(list.getByPosition(0), equalTo(h1)); assertThat(list.getByPosition(1), equalTo(h2)); assertThat(list.getByPosition(2), equalTo(h3)); assertThat(list.getByPosition(3), equalTo(h4)); + list.setPrimaryOrder(BY_NAME_ASC); list.remove(h1); list.add(h1); assertThat(list.getByPosition(0), equalTo(h1)); - list.setOrder(BY_COLOR_ASC); + list.setPrimaryOrder(BY_COLOR_ASC); + list.setSecondaryOrder(BY_NAME_ASC); assertThat(list.getByPosition(0), equalTo(h3)); assertThat(list.getByPosition(1), equalTo(h4)); assertThat(list.getByPosition(2), equalTo(h1)); assertThat(list.getByPosition(3), equalTo(h2)); - list.setOrder(BY_COLOR_DESC); - assertThat(list.getByPosition(0), equalTo(h2)); - assertThat(list.getByPosition(1), equalTo(h1)); + list.setPrimaryOrder(BY_COLOR_DESC); + list.setSecondaryOrder(BY_NAME_ASC); + assertThat(list.getByPosition(0), equalTo(h1)); + assertThat(list.getByPosition(1), equalTo(h2)); assertThat(list.getByPosition(2), equalTo(h4)); assertThat(list.getByPosition(3), equalTo(h3)); - list.setOrder(BY_POSITION); + list.setPrimaryOrder(BY_POSITION); assertThat(list.getByPosition(0), equalTo(h3)); assertThat(list.getByPosition(1), equalTo(h1)); assertThat(list.getByPosition(2), equalTo(h4)); @@ -179,8 +183,7 @@ public class HabitListTest extends BaseUnitTest } @Test - public void testReorder() - { + public void testReorder() { int operations[][] = { { 5, 2 }, { 3, 7 }, { 4, 4 }, { 8, 3 } }; @@ -225,12 +228,12 @@ public class HabitListTest extends BaseUnitTest @Test public void testOrder_inherit() { - habitList.setOrder(BY_COLOR_ASC); + habitList.setPrimaryOrder(BY_COLOR_ASC); HabitList filteredList = habitList.getFiltered(new HabitMatcherBuilder() .setArchivedAllowed(false) .setCompletedAllowed(false) .build()); - assertEquals(filteredList.getOrder(), BY_COLOR_ASC); + assertEquals(filteredList.getPrimaryOrder(), BY_COLOR_ASC); } @Test @@ -306,7 +309,7 @@ public class HabitListTest extends BaseUnitTest @Test public void testReorder_onSortedList() throws Exception { - habitList.setOrder(BY_SCORE_DESC); + habitList.setPrimaryOrder(BY_SCORE_DESC); Habit h1 = habitsArray.get(1); Habit h2 = habitsArray.get(2); thrown.expect(IllegalStateException.class); diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/preferences/PreferencesTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/preferences/PreferencesTest.java index f1011f583..409a9fa9e 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/preferences/PreferencesTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/preferences/PreferencesTest.java @@ -75,13 +75,13 @@ public class PreferencesTest extends BaseUnitTest @Test public void testDefaultOrder() throws Exception { - assertThat(prefs.getDefaultOrder(), equalTo(HabitList.Order.BY_POSITION)); + assertThat(prefs.getDefaultPrimaryOrder(), equalTo(HabitList.Order.BY_POSITION)); - prefs.setDefaultOrder(HabitList.Order.BY_SCORE_DESC); - assertThat(prefs.getDefaultOrder(), equalTo(HabitList.Order.BY_SCORE_DESC)); + prefs.setDefaultPrimaryOrder(HabitList.Order.BY_SCORE_DESC); + assertThat(prefs.getDefaultPrimaryOrder(), equalTo(HabitList.Order.BY_SCORE_DESC)); storage.putString("pref_default_order", "BOGUS"); - assertThat(prefs.getDefaultOrder(), equalTo(HabitList.Order.BY_POSITION)); + assertThat(prefs.getDefaultPrimaryOrder(), equalTo(HabitList.Order.BY_POSITION)); assertThat(storage.getString("pref_default_order", ""), equalTo("BY_POSITION")); } diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsMenuBehaviorTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsMenuBehaviorTest.java index a6191933d..8751d2d1d 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsMenuBehaviorTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsMenuBehaviorTest.java @@ -54,6 +54,9 @@ public class ListHabitsMenuBehaviorTest extends BaseUnitTest @Captor private ArgumentCaptor orderCaptor; + @Captor + private ArgumentCaptor secondaryOrderCaptor; + @Override public void setUp() throws Exception { @@ -103,7 +106,7 @@ public class ListHabitsMenuBehaviorTest extends BaseUnitTest public void testOnSortByColor() { behavior.onSortByColor(); - verify(adapter).setOrder(orderCaptor.capture()); + verify(adapter).setPrimaryOrder(orderCaptor.capture()); assertThat(orderCaptor.getValue(), equalTo(BY_COLOR_ASC)); } @@ -111,7 +114,7 @@ public class ListHabitsMenuBehaviorTest extends BaseUnitTest public void testOnSortManually() { behavior.onSortByManually(); - verify(adapter).setOrder(orderCaptor.capture()); + verify(adapter).setPrimaryOrder(orderCaptor.capture()); assertThat(orderCaptor.getValue(), equalTo(BY_POSITION)); } @@ -119,7 +122,7 @@ public class ListHabitsMenuBehaviorTest extends BaseUnitTest public void testOnSortScore() { behavior.onSortByScore(); - verify(adapter).setOrder(orderCaptor.capture()); + verify(adapter).setPrimaryOrder(orderCaptor.capture()); assertThat(orderCaptor.getValue(), equalTo(BY_SCORE_DESC)); } @@ -127,10 +130,34 @@ public class ListHabitsMenuBehaviorTest extends BaseUnitTest public void testOnSortName() { behavior.onSortByName(); - verify(adapter).setOrder(orderCaptor.capture()); + verify(adapter).setPrimaryOrder(orderCaptor.capture()); assertThat(orderCaptor.getValue(), equalTo(BY_NAME_ASC)); } + @Test + public void testOnSortStatus() + { + when(adapter.getPrimaryOrder()).thenReturn(BY_NAME_ASC); + + behavior.onSortByStatus(); + verify(adapter).setPrimaryOrder(orderCaptor.capture()); + verify(adapter).setSecondaryOrder(secondaryOrderCaptor.capture()); + assertThat(orderCaptor.getValue(), equalTo(BY_STATUS_ASC)); + assertThat(secondaryOrderCaptor.getValue(), equalTo(BY_NAME_ASC)); + } + + @Test + public void testOnSortStatusToggle() + { + when(adapter.getPrimaryOrder()).thenReturn(BY_STATUS_ASC); + + behavior.onSortByStatus(); + + verify(adapter).setPrimaryOrder(orderCaptor.capture()); + verify(adapter, never()).setSecondaryOrder(any()); + assertThat(orderCaptor.getValue(), equalTo(BY_STATUS_DESC)); + } + @Test public void testOnToggleShowArchived() {