diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsActivity.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsActivity.java index f5d54179f..e6b379435 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsActivity.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsActivity.java @@ -87,6 +87,5 @@ public class ListHabitsActivity extends BaseActivity protected void onResume() { super.onResume(); - adapter.refresh(); } } diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsController.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsController.java index 063f31ca1..1382012ec 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsController.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsController.java @@ -179,7 +179,7 @@ public class ListHabitsController public void onToggle(@NonNull Habit habit, long timestamp) { commandRunner.execute(new ToggleRepetitionCommand(habit, timestamp), - null); + habit.getId()); } private void onFirstRun() diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsMenu.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsMenu.java index d4017e366..51d7f2584 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsMenu.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsMenu.java @@ -137,5 +137,6 @@ public class ListHabitsMenu extends BaseMenu .setArchivedAllowed(showArchived) .setCompletedAllowed(showCompleted) .build()); + adapter.refresh(); } } diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsRootView.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsRootView.java index 4ff891f36..41cf97d2c 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsRootView.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsRootView.java @@ -20,7 +20,6 @@ package org.isoron.uhabits.ui.habits.list; import android.content.*; -import android.content.res.*; import android.support.annotation.*; import android.support.v7.widget.Toolbar; import android.view.*; @@ -84,11 +83,13 @@ public class ListHabitsRootView extends BaseRootView public static int getCheckmarkCount(View v) { - Resources res = v.getResources(); - float labelWidth = res.getDimension(R.dimen.habitNameWidth); - float buttonWidth = res.getDimension(R.dimen.checkmarkWidth); - return Math.min(MAX_CHECKMARK_COUNT, Math.max(0, - (int) ((v.getMeasuredWidth() - labelWidth) / buttonWidth))); +// Resources res = v.getResources(); +// float labelWidth = res.getDimension(R.dimen.habitNameWidth); +// float buttonWidth = res.getDimension(R.dimen.checkmarkWidth); +// return Math.min(MAX_CHECKMARK_COUNT, Math.max(0, +// (int) ((v.getMeasuredWidth() - labelWidth) / buttonWidth))); + + return 5; // TODO: Fix this. } @Override diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/model/HabitCardListAdapter.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/model/HabitCardListAdapter.java index 8fce97143..2d73bacc7 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/model/HabitCardListAdapter.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/model/HabitCardListAdapter.java @@ -21,6 +21,7 @@ package org.isoron.uhabits.ui.habits.list.model; import android.support.annotation.*; import android.support.v7.widget.*; +import android.util.*; import android.view.*; import org.isoron.uhabits.*; @@ -80,12 +81,6 @@ public class HabitCardListAdapter notifyDataSetChanged(); } - @Override - public int getItemCount() - { - return cache.getHabitCount(); - } - /** * Returns the item that occupies a certain position on the list * @@ -101,28 +96,9 @@ public class HabitCardListAdapter } @Override - public HabitCardViewHolder onCreateViewHolder(ViewGroup parent, - int viewType) - { - if(listView == null) return null; - View view = listView.createCardView(); - return new HabitCardViewHolder(view); - } - - @Override - public void onBindViewHolder(@Nullable HabitCardViewHolder holder, int position) + public int getItemCount() { - if(holder == null) return; - if(listView == null) return; - - Habit habit = cache.getHabitByPosition(position); - int score = cache.getScore(habit.getId()); - int checkmarks[] = cache.getCheckmarks(habit.getId()); - boolean selected = this.selected.contains(habit); - - HabitCardView cardView = (HabitCardView) holder.itemView; - listView.bindCardView(cardView, habit, score, checkmarks, selected, - position); + return cache.getHabitCount(); } @Override @@ -143,6 +119,24 @@ public class HabitCardListAdapter return new LinkedList<>(selected); } + /** + * Returns whether list of selected items is empty. + * + * @return true if selection is empty, false otherwise + */ + public boolean isSelectionEmpty() + { + return selected.isEmpty(); + } + + /** + * Notify the adapter that it has been attached to a ListView. + */ + public void onAttached() + { + cache.onAttached(); + } + // @Override // public View getView(int position, // @Nullable View view, @@ -159,29 +153,34 @@ public class HabitCardListAdapter // checkmarks, selected); // } - /** - * Returns whether list of selected items is empty. - * - * @return true if selection is empty, false otherwise - */ - public boolean isSelectionEmpty() + @Override + public void onBindViewHolder(@Nullable HabitCardViewHolder holder, + int position) { - return selected.isEmpty(); - } + if (holder == null) return; + if (listView == null) return; - /** - * Notify the adapter that it has been attached to a ListView. - */ - public void onAttached() - { - cache.onAttached(); + Habit habit = cache.getHabitByPosition(position); + int score = cache.getScore(habit.getId()); + int checkmarks[] = cache.getCheckmarks(habit.getId()); + boolean selected = this.selected.contains(habit); + + Log.d("HabitCardListView", + String.format("bind pos=%d itemId=%d, habit=%d:%s", position, + holder.getItemId(), habit.getId(), habit.getName())); + + HabitCardView cardView = (HabitCardView) holder.itemView; + listView.bindCardView(cardView, habit, score, checkmarks, selected, + position); } @Override - public void onCacheRefresh() + public HabitCardViewHolder onCreateViewHolder(ViewGroup parent, + int viewType) { - notifyDataSetChanged(); - observable.notifyListeners(); + if (listView == null) return null; + View view = listView.createCardView(); + return new HabitCardViewHolder(view); } /** @@ -192,6 +191,34 @@ public class HabitCardListAdapter cache.onDetached(); } + @Override + public void onItemChanged(int position) + { + notifyItemChanged(position); + observable.notifyListeners(); + } + + @Override + public void onItemInserted(int position) + { + notifyItemInserted(position); + observable.notifyListeners(); + } + + @Override + public void onItemMoved(int fromPosition, int toPosition) + { + notifyItemMoved(fromPosition, toPosition); + observable.notifyListeners(); + } + + @Override + public void onItemRemoved(int position) + { + notifyItemRemoved(position); + observable.notifyListeners(); + } + public void refresh() { cache.refreshAllHabits(true); @@ -212,6 +239,7 @@ public class HabitCardListAdapter public void reorder(int from, int to) { cache.reorder(from, to); + notifyItemMoved(from, to); } public void setFilter(HabitMatcher matcher) @@ -242,6 +270,6 @@ public class HabitCardListAdapter int k = selected.indexOf(h); if (k < 0) selected.add(h); else selected.remove(h); - notifyDataSetChanged(); + notifyItemChanged(position); } } diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/model/HabitCardListCache.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/model/HabitCardListCache.java index e20d52653..4d03f0e3e 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/model/HabitCardListCache.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/model/HabitCardListCache.java @@ -42,8 +42,6 @@ import javax.inject.*; */ public class HabitCardListCache implements CommandRunner.Listener { - boolean includeArchived; - private int checkmarkCount; private BaseTask currentFetchTask; @@ -116,7 +114,6 @@ public class HabitCardListCache implements CommandRunner.Listener public void onAttached() { refreshAllHabits(true); - if (lastLoadTimestamp == null) refreshAllHabits(true); commandRunner.addListener(this); } @@ -151,7 +148,8 @@ public class HabitCardListCache implements CommandRunner.Listener Habit fromHabit = data.habits.get(from); data.habits.remove(from); data.habits.add(to, fromHabit); - if (listener != null) listener.onCacheRefresh(); + if(listener != null) + listener.onItemMoved(from, to); } public void setCheckmarkCount(int checkmarkCount) @@ -162,7 +160,6 @@ public class HabitCardListCache implements CommandRunner.Listener public void setFilter(HabitMatcher matcher) { filteredHabits = allHabits.getFiltered(matcher); - refreshAllHabits(true); } public void setListener(@Nullable Listener listener) @@ -176,16 +173,19 @@ public class HabitCardListCache implements CommandRunner.Listener */ public interface Listener { - /** - * Called when the data on the cache has been modified. - */ - void onCacheRefresh(); + void onItemChanged(int position); + + void onItemInserted(int position); + + void onItemMoved(int oldPosition, int newPosition); + + void onItemRemoved(int position); } private class CacheData { @NonNull - public HashMap map; + public HashMap id_to_habit; @NonNull public List habits; @@ -201,7 +201,7 @@ public class HabitCardListCache implements CommandRunner.Listener */ public CacheData() { - map = new HashMap<>(); + id_to_habit = new HashMap<>(); habits = new LinkedList<>(); checkmarks = new HashMap<>(); scores = new HashMap<>(); @@ -211,7 +211,7 @@ public class HabitCardListCache implements CommandRunner.Listener { int[] empty = new int[checkmarkCount]; - for (Long id : map.keySet()) + for (Long id : id_to_habit.keySet()) { if (oldData.checkmarks.containsKey(id)) checkmarks.put(id, oldData.checkmarks.get(id)); @@ -221,7 +221,7 @@ public class HabitCardListCache implements CommandRunner.Listener public void copyScoresFrom(@NonNull CacheData oldData) { - for (Long id : map.keySet()) + for (Long id : id_to_habit.keySet()) { if (oldData.scores.containsKey(id)) scores.put(id, oldData.scores.get(id)); @@ -234,7 +234,7 @@ public class HabitCardListCache implements CommandRunner.Listener for (Habit h : filteredHabits) { habits.add(h); - map.put(h.getId(), h); + id_to_habit.put(h.getId(), h); } } } @@ -259,65 +259,83 @@ public class HabitCardListCache implements CommandRunner.Listener newData.copyScoresFrom(data); newData.copyCheckmarksFrom(data); -// sleep(1000); - commit(); - - if (!refreshScoresAndCheckmarks) return; - long dateTo = DateUtils.getStartOfDay(DateUtils.getLocalTime()); - long dateFrom = - dateTo - (checkmarkCount - 1) * DateUtils.millisecondsInOneDay; + long day = DateUtils.millisecondsInOneDay; + long dateFrom = dateTo - (checkmarkCount - 1) * day; - int current = 0; - for (Habit h : newData.habits) + for(Habit h : newData.habits) { - if (isCancelled()) return; - Long id = h.getId(); newData.scores.put(id, h.getScores().getTodayValue()); newData.checkmarks.put(id, h.getCheckmarks().getValues(dateFrom, dateTo)); - -// sleep(1000); - publishProgress(current++, newData.map.size()); } + + publishProgress(0); } @Override protected void onPostExecute(Void aVoid) { - if (isCancelled()) return; - lastLoadTimestamp = DateUtils.getStartOfToday(); currentFetchTask = null; - - if (listener != null) listener.onCacheRefresh(); super.onPostExecute(null); } @Override protected void onProgressUpdate(Integer... values) { - if (listener != null) listener.onCacheRefresh(); - } + if(listener == null) throw new RuntimeException( + "listener should have been attached"); - private void commit() - { - data = newData; - } + Set before = data.id_to_habit.keySet(); + Set after = newData.id_to_habit.keySet(); - private void sleep(int time) - { - try + Set removed = new TreeSet<>(before); + removed.removeAll(after); + + for(Long id : removed) { - Thread.sleep(time); + Habit h = data.id_to_habit.get(id); + int position = data.habits.indexOf(h); + data.habits.remove(position); + data.id_to_habit.remove(id); + data.checkmarks.remove(id); + data.scores.remove(id); + listener.onItemRemoved(position); + Log.d("HabitCardListCache", String.format("removed %d", + position)); } - catch (InterruptedException e) + + for(int k = 0; k < newData.habits.size(); k++) { - e.printStackTrace(); + Habit h = newData.habits.get(k); + Long id = h.getId(); + + Habit prevHabit = data.id_to_habit.get(id); + int prevPosition = data.habits.indexOf(prevHabit); + if(prevPosition == k) continue; + + if(prevPosition < 0) + { + data.habits.add(k, h); + data.id_to_habit.put(id, h); + data.scores.put(id, newData.scores.get(id)); + data.checkmarks.put(id, newData.checkmarks.get(id)); + listener.onItemInserted(k); + Log.d("HabitCardListCache", String.format("inserted %d", + k)); + } + else + { + data.habits.remove(prevPosition); + data.habits.add(k, h); + listener.onItemMoved(prevPosition, k); + Log.d("HabitCardListCache", String.format("moved %d %d", + prevPosition, k)); + } } } - } private class RefreshHabitTask extends BaseTask @@ -333,13 +351,12 @@ public class HabitCardListCache implements CommandRunner.Listener protected void doInBackground() { long dateTo = DateUtils.getStartOfDay(DateUtils.getLocalTime()); - long dateFrom = - dateTo - (checkmarkCount - 1) * DateUtils.millisecondsInOneDay; + long day = DateUtils.millisecondsInOneDay; + long dateFrom = dateTo - (checkmarkCount - 1) * day; Habit h = allHabits.getById(id); if (h == null) return; - data.map.put(id, h); data.scores.put(id, h.getScores().getTodayValue()); data.checkmarks.put(id, h.getCheckmarks().getValues(dateFrom, dateTo)); @@ -348,7 +365,13 @@ public class HabitCardListCache implements CommandRunner.Listener @Override protected void onPostExecute(Void aVoid) { - if (listener != null) listener.onCacheRefresh(); + if (listener != null) + { + Habit h = data.id_to_habit.get(id); + int position = data.habits.indexOf(h); + listener.onItemChanged(position); + } + super.onPostExecute(null); } } diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/views/CheckmarkButtonView.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/views/CheckmarkButtonView.java index ef6f7f2ca..2fcd34406 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/views/CheckmarkButtonView.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/views/CheckmarkButtonView.java @@ -68,8 +68,8 @@ public class CheckmarkButtonView extends FrameLayout public void toggle() { -// value = (value == Checkmark.CHECKED_EXPLICITLY ? Checkmark.UNCHECKED : -// Checkmark.CHECKED_EXPLICITLY); + value = (value == Checkmark.CHECKED_EXPLICITLY ? Checkmark.UNCHECKED : + Checkmark.CHECKED_EXPLICITLY); performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); postInvalidate(); diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/views/HabitCardListView.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/views/HabitCardListView.java index 0eb898e46..236eceaea 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/views/HabitCardListView.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/views/HabitCardListView.java @@ -42,11 +42,10 @@ public class HabitCardListView extends RecyclerView { super(context, attrs); setLongClickable(true); - setHasFixedSize(true); setLayoutManager(new LinearLayoutManager(getContext())); - TouchHelperCallback callback = new TouchHelperCallback(); - new ItemTouchHelper(callback).attachToRecyclerView(this); +// TouchHelperCallback callback = new TouchHelperCallback(); +// new ItemTouchHelper(callback).attachToRecyclerView(this); } /**