mirror of https://github.com/tasks/tasks
Animate filter recycler view changes
parent
c2c78512dc
commit
1a05278ab0
@ -0,0 +1,19 @@
|
|||||||
|
package com.todoroo.astrid.core;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.DiffUtil;
|
||||||
|
|
||||||
|
public class CriterionDiffCallback extends DiffUtil.ItemCallback<CriterionInstance> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areItemsTheSame(
|
||||||
|
@NonNull CriterionInstance oldItem, @NonNull CriterionInstance newItem) {
|
||||||
|
return oldItem.getId().equals(newItem.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areContentsTheSame(
|
||||||
|
@NonNull CriterionInstance oldItem, @NonNull CriterionInstance newItem) {
|
||||||
|
return oldItem.equals(newItem);
|
||||||
|
}
|
||||||
|
}
|
@ -1,135 +1,56 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2012 Todoroo Inc
|
|
||||||
*
|
|
||||||
* See the file "LICENSE" for the full license governing this code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.todoroo.astrid.core;
|
package com.todoroo.astrid.core;
|
||||||
|
|
||||||
import static com.google.common.collect.Lists.transform;
|
import static com.google.common.collect.Lists.transform;
|
||||||
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.AsyncListDiffer;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.todoroo.andlib.sql.UnaryCriterion;
|
|
||||||
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
|
|
||||||
import com.todoroo.astrid.data.Task;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import org.tasks.Callback;
|
import org.tasks.Callback;
|
||||||
import org.tasks.R;
|
import org.tasks.R;
|
||||||
import org.tasks.locale.Locale;
|
import org.tasks.locale.Locale;
|
||||||
|
|
||||||
public class CustomFilterAdapter extends RecyclerView.Adapter<CriterionViewHolder> {
|
public class CustomFilterAdapter extends RecyclerView.Adapter<CriterionViewHolder> {
|
||||||
|
|
||||||
private final Callback<CriterionInstance> onClick;
|
private final Callback<String> onClick;
|
||||||
private final List<CriterionInstance> objects;
|
|
||||||
private final Locale locale;
|
private final Locale locale;
|
||||||
|
private final AsyncListDiffer<CriterionInstance> differ;
|
||||||
|
|
||||||
public CustomFilterAdapter(
|
public CustomFilterAdapter(
|
||||||
List<CriterionInstance> objects,
|
List<CriterionInstance> objects, Locale locale, Callback<String> onClick) {
|
||||||
Locale locale,
|
|
||||||
Callback<CriterionInstance> onClick) {
|
|
||||||
this.objects = objects;
|
|
||||||
this.locale = locale;
|
this.locale = locale;
|
||||||
this.onClick = onClick;
|
this.onClick = onClick;
|
||||||
|
differ = new AsyncListDiffer<>(this, new CriterionDiffCallback());
|
||||||
|
submitList(objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public CriterionViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public CriterionViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
View view =
|
||||||
return new CriterionViewHolder(
|
LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_filter_row, parent, false);
|
||||||
inflater.inflate(R.layout.custom_filter_row, parent, false), locale, onClick);
|
return new CriterionViewHolder(view, locale, onClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull CriterionViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull CriterionViewHolder holder, int position) {
|
||||||
holder.bind(getItem(position));
|
holder.bind(getItems().get(position));
|
||||||
}
|
|
||||||
|
|
||||||
public List<CriterionInstance> getItems() {
|
|
||||||
return objects;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return objects.size();
|
return getItems().size();
|
||||||
}
|
|
||||||
|
|
||||||
private String getValue(CriterionInstance instance) {
|
|
||||||
String value = instance.getValueFromCriterion();
|
|
||||||
if (value == null && instance.criterion.sql != null && instance.criterion.sql.contains("?")) {
|
|
||||||
value = "";
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSql() {
|
|
||||||
StringBuilder sql = new StringBuilder(" WHERE ");
|
|
||||||
for (CriterionInstance instance : objects) {
|
|
||||||
String value = getValue(instance);
|
|
||||||
|
|
||||||
switch (instance.type) {
|
|
||||||
case CriterionInstance.TYPE_ADD:
|
|
||||||
sql.append("OR ");
|
|
||||||
break;
|
|
||||||
case CriterionInstance.TYPE_SUBTRACT:
|
|
||||||
sql.append("AND NOT ");
|
|
||||||
break;
|
|
||||||
case CriterionInstance.TYPE_INTERSECT:
|
|
||||||
sql.append("AND ");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// special code for all tasks universe
|
|
||||||
if (instance.type == CriterionInstance.TYPE_UNIVERSE || instance.criterion.sql == null) {
|
|
||||||
sql.append(TaskCriteria.activeAndVisible()).append(' ');
|
|
||||||
} else {
|
|
||||||
String subSql = instance.criterion.sql.replace("?", UnaryCriterion.sanitize(value));
|
|
||||||
sql.append(Task.ID).append(" IN (").append(subSql).append(") ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sql.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Object> getValues() {
|
|
||||||
Map<String, Object> values = new HashMap<>();
|
|
||||||
for (CriterionInstance instance : objects) {
|
|
||||||
String value = getValue(instance);
|
|
||||||
|
|
||||||
if (instance.criterion.valuesForNewTasks != null
|
|
||||||
&& instance.type == CriterionInstance.TYPE_INTERSECT) {
|
|
||||||
for (Entry<String, Object> entry : instance.criterion.valuesForNewTasks.entrySet()) {
|
|
||||||
values.put(
|
|
||||||
entry.getKey().replace("?", value), entry.getValue().toString().replace("?", value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCriterion() {
|
|
||||||
return Joiner.on("\n").join(transform(objects, CriterionInstance::serialize));
|
|
||||||
}
|
|
||||||
|
|
||||||
public CriterionInstance getItem(int position) {
|
|
||||||
return objects.get(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void remove(CriterionInstance criterionInstance) {
|
|
||||||
objects.remove(criterionInstance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void replace(CriterionInstance replace, CriterionInstance instance) {
|
public void submitList(List<CriterionInstance> criteria) {
|
||||||
objects.set(objects.indexOf(replace), instance);
|
differ.submitList(ImmutableList.copyOf(transform(criteria, CriterionInstance::new)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(CriterionInstance instance) {
|
private List<CriterionInstance> getItems() {
|
||||||
objects.add(instance);
|
return differ.getCurrentList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue