mirror of https://github.com/tasks/tasks
Convert more custom filter code to Kotlin
parent
e97e0d3a22
commit
6fd1cb3e44
@ -1,201 +0,0 @@
|
||||
package com.todoroo.astrid.core;
|
||||
|
||||
import static com.google.common.collect.Lists.transform;
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.tasks.Strings.isNullOrEmpty;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.todoroo.andlib.utility.AndroidUtilities;
|
||||
import com.todoroo.astrid.api.CustomFilterCriterion;
|
||||
import com.todoroo.astrid.api.MultipleSelectCriterion;
|
||||
import com.todoroo.astrid.api.TextInputCriterion;
|
||||
import com.todoroo.astrid.helper.UUIDHelper;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.tasks.filters.FilterCriteriaProvider;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class CriterionInstance {
|
||||
|
||||
public static final int TYPE_ADD = 0;
|
||||
public static final int TYPE_SUBTRACT = 1;
|
||||
public static final int TYPE_INTERSECT = 2;
|
||||
public static final int TYPE_UNIVERSE = 3;
|
||||
public CustomFilterCriterion criterion;
|
||||
public int selectedIndex = -1;
|
||||
public String selectedText = null;
|
||||
public int type = TYPE_INTERSECT;
|
||||
public int end;
|
||||
public int start;
|
||||
public int max;
|
||||
private String id = UUIDHelper.newUUID();
|
||||
|
||||
public CriterionInstance() {}
|
||||
|
||||
public CriterionInstance(CriterionInstance other) {
|
||||
id = other.id;
|
||||
criterion = other.criterion;
|
||||
selectedIndex = other.selectedIndex;
|
||||
selectedText = other.selectedText;
|
||||
type = other.type;
|
||||
end = other.end;
|
||||
start = other.start;
|
||||
max = other.max;
|
||||
}
|
||||
|
||||
public static List<CriterionInstance> fromString(
|
||||
FilterCriteriaProvider provider, String criterion) {
|
||||
if (isNullOrEmpty(criterion)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<CriterionInstance> entries = new ArrayList<>();
|
||||
for (String row : criterion.split("\n")) {
|
||||
List<String> split =
|
||||
transform(
|
||||
Splitter.on(AndroidUtilities.SERIALIZATION_SEPARATOR).splitToList(row),
|
||||
CriterionInstance::unescape);
|
||||
if (split.size() != 4 && split.size() != 5) {
|
||||
Timber.e("invalid row: %s", row);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
CriterionInstance entry = new CriterionInstance();
|
||||
entry.criterion = provider.getFilterCriteria(split.get(0));
|
||||
String value = split.get(1);
|
||||
if (entry.criterion instanceof TextInputCriterion) {
|
||||
entry.selectedText = value;
|
||||
} else if (entry.criterion instanceof MultipleSelectCriterion) {
|
||||
MultipleSelectCriterion multipleSelectCriterion = (MultipleSelectCriterion) entry.criterion;
|
||||
if (multipleSelectCriterion.entryValues != null) {
|
||||
entry.selectedIndex = asList(multipleSelectCriterion.entryValues).indexOf(value);
|
||||
}
|
||||
} else {
|
||||
Timber.d("Ignored value %s for %s", value, entry.criterion);
|
||||
}
|
||||
entry.type = Integer.parseInt(split.get(3));
|
||||
entry.criterion.sql = split.get(4);
|
||||
Timber.d("%s -> %s", row, entry);
|
||||
entries.add(entry);
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
private static String escape(String item) {
|
||||
if (item == null) {
|
||||
return ""; // $NON-NLS-1$
|
||||
}
|
||||
return item.replace(
|
||||
AndroidUtilities.SERIALIZATION_SEPARATOR, AndroidUtilities.SEPARATOR_ESCAPE);
|
||||
}
|
||||
|
||||
private static String unescape(String item) {
|
||||
if (isNullOrEmpty(item)) {
|
||||
return "";
|
||||
}
|
||||
return item.replace(
|
||||
AndroidUtilities.SEPARATOR_ESCAPE, AndroidUtilities.SERIALIZATION_SEPARATOR);
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getTitleFromCriterion() {
|
||||
if (criterion instanceof MultipleSelectCriterion) {
|
||||
if (selectedIndex >= 0
|
||||
&& ((MultipleSelectCriterion) criterion).entryTitles != null
|
||||
&& selectedIndex < ((MultipleSelectCriterion) criterion).entryTitles.length) {
|
||||
String title = ((MultipleSelectCriterion) criterion).entryTitles[selectedIndex];
|
||||
return criterion.text.replace("?", title);
|
||||
}
|
||||
return criterion.text;
|
||||
} else if (criterion instanceof TextInputCriterion) {
|
||||
if (selectedText == null) {
|
||||
return criterion.text;
|
||||
}
|
||||
return criterion.text.replace("?", selectedText);
|
||||
}
|
||||
throw new UnsupportedOperationException("Unknown criterion type"); // $NON-NLS-1$
|
||||
}
|
||||
|
||||
public String getValueFromCriterion() {
|
||||
if (type == TYPE_UNIVERSE) {
|
||||
return null;
|
||||
}
|
||||
if (criterion instanceof MultipleSelectCriterion) {
|
||||
if (selectedIndex >= 0
|
||||
&& ((MultipleSelectCriterion) criterion).entryValues != null
|
||||
&& selectedIndex < ((MultipleSelectCriterion) criterion).entryValues.length) {
|
||||
return ((MultipleSelectCriterion) criterion).entryValues[selectedIndex];
|
||||
}
|
||||
return criterion.text;
|
||||
} else if (criterion instanceof TextInputCriterion) {
|
||||
return selectedText;
|
||||
}
|
||||
throw new UnsupportedOperationException("Unknown criterion type"); // $NON-NLS-1$
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof CriterionInstance)) {
|
||||
return false;
|
||||
}
|
||||
CriterionInstance that = (CriterionInstance) o;
|
||||
return selectedIndex == that.selectedIndex
|
||||
&& type == that.type
|
||||
&& end == that.end
|
||||
&& start == that.start
|
||||
&& max == that.max
|
||||
&& Objects.equals(criterion, that.criterion)
|
||||
&& Objects.equals(selectedText, that.selectedText)
|
||||
&& Objects.equals(id, that.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(criterion, selectedIndex, selectedText, type, end, start, max, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CriterionInstance{"
|
||||
+ "criterion="
|
||||
+ criterion
|
||||
+ ", selectedIndex="
|
||||
+ selectedIndex
|
||||
+ ", selectedText='"
|
||||
+ selectedText
|
||||
+ '\''
|
||||
+ ", type="
|
||||
+ type
|
||||
+ ", end="
|
||||
+ end
|
||||
+ ", start="
|
||||
+ start
|
||||
+ ", max="
|
||||
+ max
|
||||
+ '}';
|
||||
}
|
||||
|
||||
public static String serialize(List<CriterionInstance> criterion) {
|
||||
return Joiner.on("\n").join(transform(criterion, CriterionInstance::serialize));
|
||||
}
|
||||
|
||||
private String serialize() {
|
||||
// criterion|entry|text|type|sql
|
||||
return Joiner.on(AndroidUtilities.SERIALIZATION_SEPARATOR)
|
||||
.join(
|
||||
asList(
|
||||
escape(criterion.identifier),
|
||||
escape(getValueFromCriterion()),
|
||||
escape(criterion.text),
|
||||
type,
|
||||
criterion.sql == null ? "" : criterion.sql));
|
||||
}
|
||||
}
|
@ -0,0 +1,174 @@
|
||||
package com.todoroo.astrid.core
|
||||
|
||||
import com.google.common.base.Joiner
|
||||
import com.google.common.base.Splitter
|
||||
import com.google.common.collect.Lists
|
||||
import com.todoroo.andlib.utility.AndroidUtilities
|
||||
import com.todoroo.astrid.api.CustomFilterCriterion
|
||||
import com.todoroo.astrid.api.MultipleSelectCriterion
|
||||
import com.todoroo.astrid.api.TextInputCriterion
|
||||
import com.todoroo.astrid.helper.UUIDHelper
|
||||
import org.tasks.Strings.isNullOrEmpty
|
||||
import org.tasks.filters.FilterCriteriaProvider
|
||||
import timber.log.Timber
|
||||
import java.util.*
|
||||
|
||||
class CriterionInstance {
|
||||
lateinit var criterion: CustomFilterCriterion
|
||||
var selectedIndex = -1
|
||||
var selectedText: String? = null
|
||||
var type = TYPE_INTERSECT
|
||||
var end = 0
|
||||
var start = 0
|
||||
var max = 0
|
||||
var id: String = UUIDHelper.newUUID()
|
||||
private set
|
||||
|
||||
constructor()
|
||||
|
||||
constructor(other: CriterionInstance) {
|
||||
id = other.id
|
||||
criterion = other.criterion
|
||||
selectedIndex = other.selectedIndex
|
||||
selectedText = other.selectedText
|
||||
type = other.type
|
||||
end = other.end
|
||||
start = other.start
|
||||
max = other.max
|
||||
}
|
||||
|
||||
// $NON-NLS-1$
|
||||
val titleFromCriterion: String
|
||||
get() {
|
||||
if (criterion is MultipleSelectCriterion) {
|
||||
if (selectedIndex >= 0 && (criterion as MultipleSelectCriterion).entryTitles != null && selectedIndex < (criterion as MultipleSelectCriterion).entryTitles.size) {
|
||||
val title = (criterion as MultipleSelectCriterion).entryTitles[selectedIndex]
|
||||
return criterion.text.replace("?", title)
|
||||
}
|
||||
return criterion.text
|
||||
} else if (criterion is TextInputCriterion) {
|
||||
return if (selectedText == null) {
|
||||
criterion.text
|
||||
} else criterion.text.replace("?", selectedText!!)
|
||||
}
|
||||
throw UnsupportedOperationException("Unknown criterion type") // $NON-NLS-1$
|
||||
}
|
||||
|
||||
// $NON-NLS-1$
|
||||
val valueFromCriterion: String?
|
||||
get() {
|
||||
if (type == TYPE_UNIVERSE) {
|
||||
return null
|
||||
}
|
||||
if (criterion is MultipleSelectCriterion) {
|
||||
return if (selectedIndex >= 0 && (criterion as MultipleSelectCriterion).entryValues != null && selectedIndex < (criterion as MultipleSelectCriterion).entryValues.size) {
|
||||
(criterion as MultipleSelectCriterion).entryValues[selectedIndex]
|
||||
} else criterion.text
|
||||
} else if (criterion is TextInputCriterion) {
|
||||
return selectedText
|
||||
}
|
||||
throw UnsupportedOperationException("Unknown criterion type") // $NON-NLS-1$
|
||||
}
|
||||
|
||||
private fun serialize(): String {
|
||||
// criterion|entry|text|type|sql
|
||||
return Joiner.on(AndroidUtilities.SERIALIZATION_SEPARATOR)
|
||||
.join(
|
||||
listOf(
|
||||
escape(criterion.identifier),
|
||||
escape(valueFromCriterion),
|
||||
escape(criterion.text),
|
||||
type,
|
||||
if (criterion.sql == null) "" else criterion.sql))
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "CriterionInstance(criterion=$criterion, selectedIndex=$selectedIndex, selectedText=$selectedText, type=$type, end=$end, start=$start, max=$max, id='$id')"
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is CriterionInstance) return false
|
||||
|
||||
if (criterion != other.criterion) return false
|
||||
if (selectedIndex != other.selectedIndex) return false
|
||||
if (selectedText != other.selectedText) return false
|
||||
if (type != other.type) return false
|
||||
if (end != other.end) return false
|
||||
if (start != other.start) return false
|
||||
if (max != other.max) return false
|
||||
if (id != other.id) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = criterion.hashCode()
|
||||
result = 31 * result + selectedIndex
|
||||
result = 31 * result + (selectedText?.hashCode() ?: 0)
|
||||
result = 31 * result + type
|
||||
result = 31 * result + end
|
||||
result = 31 * result + start
|
||||
result = 31 * result + max
|
||||
result = 31 * result + (id.hashCode() ?: 0)
|
||||
return result
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TYPE_ADD = 0
|
||||
const val TYPE_SUBTRACT = 1
|
||||
const val TYPE_INTERSECT = 2
|
||||
const val TYPE_UNIVERSE = 3
|
||||
|
||||
suspend fun fromString(
|
||||
provider: FilterCriteriaProvider, criterion: String): List<CriterionInstance> {
|
||||
if (isNullOrEmpty(criterion)) {
|
||||
return emptyList()
|
||||
}
|
||||
val entries: MutableList<CriterionInstance> = ArrayList()
|
||||
for (row in criterion.split("\n".toRegex()).toTypedArray()) {
|
||||
val split = Lists.transform(
|
||||
Splitter.on(AndroidUtilities.SERIALIZATION_SEPARATOR).splitToList(row)) { item: String? -> unescape(item) }
|
||||
if (split.size != 4 && split.size != 5) {
|
||||
Timber.e("invalid row: %s", row)
|
||||
return emptyList()
|
||||
}
|
||||
val entry = CriterionInstance()
|
||||
entry.criterion = provider.getFilterCriteria(split[0])
|
||||
val value = split[1]
|
||||
if (entry.criterion is TextInputCriterion) {
|
||||
entry.selectedText = value
|
||||
} else if (entry.criterion is MultipleSelectCriterion) {
|
||||
val multipleSelectCriterion = entry.criterion as MultipleSelectCriterion?
|
||||
if (multipleSelectCriterion!!.entryValues != null) {
|
||||
entry.selectedIndex = listOf(*multipleSelectCriterion.entryValues).indexOf(value)
|
||||
}
|
||||
} else {
|
||||
Timber.d("Ignored value %s for %s", value, entry.criterion)
|
||||
}
|
||||
entry.type = split[3].toInt()
|
||||
entry.criterion.sql = split[4]
|
||||
Timber.d("%s -> %s", row, entry)
|
||||
entries.add(entry)
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
private fun escape(item: String?): String {
|
||||
return item?.replace(
|
||||
AndroidUtilities.SERIALIZATION_SEPARATOR, AndroidUtilities.SEPARATOR_ESCAPE)
|
||||
?: "" // $NON-NLS-1$
|
||||
}
|
||||
|
||||
private fun unescape(item: String?): String {
|
||||
return if (isNullOrEmpty(item)) {
|
||||
""
|
||||
} else item!!.replace(
|
||||
AndroidUtilities.SEPARATOR_ESCAPE, AndroidUtilities.SERIALIZATION_SEPARATOR)
|
||||
}
|
||||
|
||||
fun serialize(criterion: List<CriterionInstance>?): String {
|
||||
return Joiner.on("\n").join(Lists.transform<CriterionInstance, String?>(criterion!!) { obj: CriterionInstance? -> obj!!.serialize() })
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package org.tasks.data
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import javax.inject.Inject
|
||||
|
||||
@Deprecated("use coroutines")
|
||||
class CaldavDaoBlocking @Inject constructor(private val dao: CaldavDao) {
|
||||
fun getCalendars(): List<CaldavCalendar> = runBlocking {
|
||||
dao.getCalendars()
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package org.tasks.data
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import javax.inject.Inject
|
||||
|
||||
@Deprecated("use coroutines")
|
||||
class TagDataDaoBlocking @Inject constructor(private val dao: TagDataDao) {
|
||||
fun tagDataOrderedByName(): List<TagData> = runBlocking {
|
||||
dao.tagDataOrderedByName()
|
||||
}
|
||||
}
|
@ -1,278 +0,0 @@
|
||||
package org.tasks.filters;
|
||||
|
||||
import static com.google.common.collect.Iterables.transform;
|
||||
import static com.google.common.collect.Sets.newLinkedHashSet;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import com.todoroo.andlib.sql.Criterion;
|
||||
import com.todoroo.andlib.sql.Field;
|
||||
import com.todoroo.andlib.sql.Join;
|
||||
import com.todoroo.andlib.sql.Query;
|
||||
import com.todoroo.astrid.api.CustomFilterCriterion;
|
||||
import com.todoroo.astrid.api.MultipleSelectCriterion;
|
||||
import com.todoroo.astrid.api.PermaSql;
|
||||
import com.todoroo.astrid.api.TextInputCriterion;
|
||||
import com.todoroo.astrid.data.Task;
|
||||
import com.todoroo.astrid.data.Task.Priority;
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.R;
|
||||
import org.tasks.data.CaldavCalendar;
|
||||
import org.tasks.data.CaldavDaoBlocking;
|
||||
import org.tasks.data.CaldavTask;
|
||||
import org.tasks.data.GoogleTask;
|
||||
import org.tasks.data.GoogleTaskList;
|
||||
import org.tasks.data.GoogleTaskListDaoBlocking;
|
||||
import org.tasks.data.Tag;
|
||||
import org.tasks.data.TagData;
|
||||
import org.tasks.data.TagDataDaoBlocking;
|
||||
import org.tasks.data.TaskDao;
|
||||
|
||||
public class FilterCriteriaProvider {
|
||||
|
||||
private static final String IDENTIFIER_UNIVERSE = "active";
|
||||
private static final String IDENTIFIER_TITLE = "title";
|
||||
private static final String IDENTIFIER_IMPORTANCE = "importance";
|
||||
private static final String IDENTIFIER_DUEDATE = "dueDate";
|
||||
private static final String IDENTIFIER_GTASKS = "gtaskslist";
|
||||
private static final String IDENTIFIER_CALDAV = "caldavlist";
|
||||
private static final String IDENTIFIER_TAG_IS = "tag_is";
|
||||
private static final String IDENTIFIER_TAG_CONTAINS = "tag_contains";
|
||||
|
||||
private final Context context;
|
||||
private final TagDataDaoBlocking tagDataDao;
|
||||
private final Resources r;
|
||||
private final GoogleTaskListDaoBlocking googleTaskListDao;
|
||||
private final CaldavDaoBlocking caldavDao;
|
||||
|
||||
@Inject
|
||||
public FilterCriteriaProvider(
|
||||
@ApplicationContext Context context,
|
||||
TagDataDaoBlocking tagDataDao,
|
||||
GoogleTaskListDaoBlocking googleTaskListDao,
|
||||
CaldavDaoBlocking caldavDao) {
|
||||
this.context = context;
|
||||
this.tagDataDao = tagDataDao;
|
||||
|
||||
r = context.getResources();
|
||||
this.googleTaskListDao = googleTaskListDao;
|
||||
this.caldavDao = caldavDao;
|
||||
}
|
||||
|
||||
public CustomFilterCriterion getFilterCriteria(String identifier) {
|
||||
switch (identifier) {
|
||||
case IDENTIFIER_UNIVERSE:
|
||||
return getStartingUniverse();
|
||||
case IDENTIFIER_TITLE:
|
||||
return getTaskTitleContainsFilter();
|
||||
case IDENTIFIER_IMPORTANCE:
|
||||
return getPriorityFilter();
|
||||
case IDENTIFIER_DUEDATE:
|
||||
return getDueDateFilter();
|
||||
case IDENTIFIER_GTASKS:
|
||||
return getGtasksFilterCriteria();
|
||||
case IDENTIFIER_CALDAV:
|
||||
return getCaldavFilterCriteria();
|
||||
case IDENTIFIER_TAG_IS:
|
||||
return getTagFilter();
|
||||
case IDENTIFIER_TAG_CONTAINS:
|
||||
return getTagNameContainsFilter();
|
||||
default:
|
||||
throw new RuntimeException("Unknown identifier: " + identifier);
|
||||
}
|
||||
}
|
||||
|
||||
public CustomFilterCriterion getStartingUniverse() {
|
||||
return new MultipleSelectCriterion(
|
||||
IDENTIFIER_UNIVERSE,
|
||||
context.getString(R.string.BFE_Active),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
public List<CustomFilterCriterion> getAll() {
|
||||
List<CustomFilterCriterion> result = new ArrayList<>();
|
||||
|
||||
result.add(getTagFilter());
|
||||
result.add(getTagNameContainsFilter());
|
||||
result.add(getDueDateFilter());
|
||||
result.add(getPriorityFilter());
|
||||
result.add(getTaskTitleContainsFilter());
|
||||
if (!googleTaskListDao.getAccounts().isEmpty()) {
|
||||
result.add(getGtasksFilterCriteria());
|
||||
}
|
||||
result.add(getCaldavFilterCriteria());
|
||||
return result;
|
||||
}
|
||||
|
||||
private CustomFilterCriterion getTagFilter() {
|
||||
// TODO: adding to hash set because duplicate tag name bug hasn't been fixed yet
|
||||
String[] tagNames =
|
||||
newLinkedHashSet(transform(tagDataDao.tagDataOrderedByName(), TagData::getName))
|
||||
.toArray(new String[0]);
|
||||
Map<String, Object> values = new HashMap<>();
|
||||
values.put(Tag.KEY, "?");
|
||||
return new MultipleSelectCriterion(
|
||||
IDENTIFIER_TAG_IS,
|
||||
context.getString(R.string.CFC_tag_text),
|
||||
Query.select(Tag.TASK)
|
||||
.from(Tag.TABLE)
|
||||
.join(Join.inner(Task.TABLE, Tag.TASK.eq(Task.ID)))
|
||||
.where(Criterion.and(TaskDao.TaskCriteria.activeAndVisible(), Tag.NAME.eq("?")))
|
||||
.toString(),
|
||||
values,
|
||||
tagNames,
|
||||
tagNames,
|
||||
context.getString(R.string.CFC_tag_name));
|
||||
}
|
||||
|
||||
public CustomFilterCriterion getTagNameContainsFilter() {
|
||||
return new TextInputCriterion(
|
||||
IDENTIFIER_TAG_CONTAINS,
|
||||
context.getString(R.string.CFC_tag_contains_text),
|
||||
Query.select(Tag.TASK)
|
||||
.from(Tag.TABLE)
|
||||
.join(Join.inner(Task.TABLE, Tag.TASK.eq(Task.ID)))
|
||||
.where(Criterion.and(TaskDao.TaskCriteria.activeAndVisible(), Tag.NAME.like("%?%")))
|
||||
.toString(),
|
||||
context.getString(R.string.CFC_tag_contains_name),
|
||||
"",
|
||||
context.getString(R.string.CFC_tag_contains_name));
|
||||
}
|
||||
|
||||
public CustomFilterCriterion getDueDateFilter() {
|
||||
String[] entryValues =
|
||||
new String[] {
|
||||
"0",
|
||||
PermaSql.VALUE_EOD_YESTERDAY,
|
||||
PermaSql.VALUE_EOD,
|
||||
PermaSql.VALUE_EOD_TOMORROW,
|
||||
PermaSql.VALUE_EOD_DAY_AFTER,
|
||||
PermaSql.VALUE_EOD_NEXT_WEEK,
|
||||
PermaSql.VALUE_EOD_NEXT_MONTH,
|
||||
};
|
||||
Map<String, Object> values = new HashMap<>();
|
||||
values.put(Task.DUE_DATE.name, "?");
|
||||
return new MultipleSelectCriterion(
|
||||
IDENTIFIER_DUEDATE,
|
||||
r.getString(R.string.CFC_dueBefore_text),
|
||||
Query.select(Task.ID)
|
||||
.from(Task.TABLE)
|
||||
.where(
|
||||
Criterion.and(
|
||||
TaskDao.TaskCriteria.activeAndVisible(),
|
||||
Criterion.or(Field.field("?").eq(0), Task.DUE_DATE.gt(0)),
|
||||
Task.DUE_DATE.lte("?")))
|
||||
.toString(),
|
||||
values,
|
||||
r.getStringArray(R.array.CFC_dueBefore_entries),
|
||||
entryValues,
|
||||
r.getString(R.string.CFC_dueBefore_name));
|
||||
}
|
||||
|
||||
public CustomFilterCriterion getPriorityFilter() {
|
||||
String[] entryValues =
|
||||
new String[] {
|
||||
Integer.toString(Priority.HIGH),
|
||||
Integer.toString(Priority.MEDIUM),
|
||||
Integer.toString(Priority.LOW),
|
||||
Integer.toString(Priority.NONE),
|
||||
};
|
||||
String[] entries = new String[] {"!!!", "!!", "!", "o"};
|
||||
Map<String, Object> values = new HashMap<>();
|
||||
values.put(Task.IMPORTANCE.name, "?");
|
||||
return new MultipleSelectCriterion(
|
||||
IDENTIFIER_IMPORTANCE,
|
||||
r.getString(R.string.CFC_importance_text),
|
||||
Query.select(Task.ID)
|
||||
.from(Task.TABLE)
|
||||
.where(Criterion.and(TaskDao.TaskCriteria.activeAndVisible(), Task.IMPORTANCE.lte("?")))
|
||||
.toString(),
|
||||
values,
|
||||
entries,
|
||||
entryValues,
|
||||
r.getString(R.string.CFC_importance_name));
|
||||
}
|
||||
|
||||
private CustomFilterCriterion getTaskTitleContainsFilter() {
|
||||
return new TextInputCriterion(
|
||||
IDENTIFIER_TITLE,
|
||||
r.getString(R.string.CFC_title_contains_text),
|
||||
Query.select(Task.ID)
|
||||
.from(Task.TABLE)
|
||||
.where(Criterion.and(TaskDao.TaskCriteria.activeAndVisible(), Task.TITLE.like("%?%")))
|
||||
.toString(),
|
||||
r.getString(R.string.CFC_title_contains_name),
|
||||
"",
|
||||
r.getString(R.string.CFC_title_contains_name));
|
||||
}
|
||||
|
||||
private CustomFilterCriterion getGtasksFilterCriteria() {
|
||||
List<GoogleTaskList> lists = googleTaskListDao.getAllLists();
|
||||
|
||||
String[] listNames = new String[lists.size()];
|
||||
String[] listIds = new String[lists.size()];
|
||||
for (int i = 0; i < lists.size(); i++) {
|
||||
listNames[i] = lists.get(i).getTitle();
|
||||
listIds[i] = lists.get(i).getRemoteId();
|
||||
}
|
||||
|
||||
Map<String, Object> values = new HashMap<>();
|
||||
values.put(GoogleTask.KEY, "?");
|
||||
|
||||
return new MultipleSelectCriterion(
|
||||
IDENTIFIER_GTASKS,
|
||||
context.getString(R.string.CFC_gtasks_list_text),
|
||||
Query.select(GoogleTask.TASK)
|
||||
.from(GoogleTask.TABLE)
|
||||
.join(Join.inner(Task.TABLE, GoogleTask.TASK.eq(Task.ID)))
|
||||
.where(
|
||||
Criterion.and(
|
||||
TaskDao.TaskCriteria.activeAndVisible(),
|
||||
GoogleTask.DELETED.eq(0),
|
||||
GoogleTask.LIST.eq("?")))
|
||||
.toString(),
|
||||
values,
|
||||
listNames,
|
||||
listIds,
|
||||
context.getString(R.string.CFC_gtasks_list_name));
|
||||
}
|
||||
|
||||
private CustomFilterCriterion getCaldavFilterCriteria() {
|
||||
List<CaldavCalendar> calendars = caldavDao.getCalendars();
|
||||
|
||||
String[] names = new String[calendars.size()];
|
||||
String[] ids = new String[calendars.size()];
|
||||
for (int i = 0; i < calendars.size(); i++) {
|
||||
names[i] = calendars.get(i).getName();
|
||||
ids[i] = calendars.get(i).getUuid();
|
||||
}
|
||||
Map<String, Object> values = new HashMap<>();
|
||||
values.put(CaldavTask.KEY, "?");
|
||||
|
||||
return new MultipleSelectCriterion(
|
||||
IDENTIFIER_CALDAV,
|
||||
context.getString(R.string.CFC_gtasks_list_text),
|
||||
Query.select(CaldavTask.TASK)
|
||||
.from(CaldavTask.TABLE)
|
||||
.join(Join.inner(Task.TABLE, CaldavTask.TASK.eq(Task.ID)))
|
||||
.where(
|
||||
Criterion.and(
|
||||
TaskDao.TaskCriteria.activeAndVisible(),
|
||||
CaldavTask.DELETED.eq(0),
|
||||
CaldavTask.CALENDAR.eq("?")))
|
||||
.toString(),
|
||||
values,
|
||||
names,
|
||||
ids,
|
||||
context.getString(R.string.CFC_list_name));
|
||||
}
|
||||
}
|
@ -0,0 +1,233 @@
|
||||
package org.tasks.filters
|
||||
|
||||
import android.content.Context
|
||||
import com.todoroo.andlib.sql.Criterion.Companion.and
|
||||
import com.todoroo.andlib.sql.Criterion.Companion.or
|
||||
import com.todoroo.andlib.sql.Field.Companion.field
|
||||
import com.todoroo.andlib.sql.Join.Companion.inner
|
||||
import com.todoroo.andlib.sql.Query.Companion.select
|
||||
import com.todoroo.astrid.api.CustomFilterCriterion
|
||||
import com.todoroo.astrid.api.MultipleSelectCriterion
|
||||
import com.todoroo.astrid.api.PermaSql
|
||||
import com.todoroo.astrid.api.TextInputCriterion
|
||||
import com.todoroo.astrid.data.Task
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import org.tasks.R
|
||||
import org.tasks.data.*
|
||||
import org.tasks.data.TaskDao.TaskCriteria.activeAndVisible
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class FilterCriteriaProvider @Inject constructor(
|
||||
@param:ApplicationContext private val context: Context,
|
||||
private val tagDataDao: TagDataDao,
|
||||
private val googleTaskListDao: GoogleTaskListDao,
|
||||
private val caldavDao: CaldavDao) {
|
||||
private val r = context.resources
|
||||
|
||||
suspend fun getFilterCriteria(identifier: String): CustomFilterCriterion {
|
||||
return when (identifier) {
|
||||
IDENTIFIER_UNIVERSE -> startingUniverse
|
||||
IDENTIFIER_TITLE -> taskTitleContainsFilter
|
||||
IDENTIFIER_IMPORTANCE -> priorityFilter
|
||||
IDENTIFIER_DUEDATE -> dueDateFilter
|
||||
IDENTIFIER_GTASKS -> gtasksFilterCriteria()
|
||||
IDENTIFIER_CALDAV -> caldavFilterCriteria()
|
||||
IDENTIFIER_TAG_IS -> tagFilter()
|
||||
IDENTIFIER_TAG_CONTAINS -> tagNameContainsFilter
|
||||
else -> throw RuntimeException("Unknown identifier: $identifier")
|
||||
}
|
||||
}
|
||||
|
||||
val startingUniverse: CustomFilterCriterion
|
||||
get() = MultipleSelectCriterion(
|
||||
IDENTIFIER_UNIVERSE,
|
||||
context.getString(R.string.BFE_Active),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null)
|
||||
|
||||
suspend fun all(): List<CustomFilterCriterion> {
|
||||
val result: MutableList<CustomFilterCriterion> = ArrayList()
|
||||
result.add(tagFilter())
|
||||
result.add(tagNameContainsFilter)
|
||||
result.add(dueDateFilter)
|
||||
result.add(priorityFilter)
|
||||
result.add(taskTitleContainsFilter)
|
||||
if (googleTaskListDao.getAccounts().isNotEmpty()) {
|
||||
result.add(gtasksFilterCriteria())
|
||||
}
|
||||
result.add(caldavFilterCriteria())
|
||||
return result
|
||||
}
|
||||
|
||||
// TODO: adding to hash set because duplicate tag name bug hasn't been fixed yet
|
||||
private suspend fun tagFilter(): CustomFilterCriterion {
|
||||
// TODO: adding to hash set because duplicate tag name bug hasn't been fixed yet
|
||||
val tagNames = tagDataDao
|
||||
.tagDataOrderedByName()
|
||||
.map(TagData::name)
|
||||
.distinct()
|
||||
.toTypedArray()
|
||||
val values: MutableMap<String, Any> = HashMap()
|
||||
values[Tag.KEY] = "?"
|
||||
return MultipleSelectCriterion(
|
||||
IDENTIFIER_TAG_IS,
|
||||
context.getString(R.string.CFC_tag_text),
|
||||
select(Tag.TASK)
|
||||
.from(Tag.TABLE)
|
||||
.join(inner(Task.TABLE, Tag.TASK.eq(Task.ID)))
|
||||
.where(and(activeAndVisible(), Tag.NAME.eq("?")))
|
||||
.toString(),
|
||||
values,
|
||||
tagNames,
|
||||
tagNames,
|
||||
context.getString(R.string.CFC_tag_name))
|
||||
}
|
||||
|
||||
val tagNameContainsFilter: CustomFilterCriterion
|
||||
get() = TextInputCriterion(
|
||||
IDENTIFIER_TAG_CONTAINS,
|
||||
context.getString(R.string.CFC_tag_contains_text),
|
||||
select(Tag.TASK)
|
||||
.from(Tag.TABLE)
|
||||
.join(inner(Task.TABLE, Tag.TASK.eq(Task.ID)))
|
||||
.where(and(activeAndVisible(), Tag.NAME.like("%?%")))
|
||||
.toString(),
|
||||
context.getString(R.string.CFC_tag_contains_name),
|
||||
"",
|
||||
context.getString(R.string.CFC_tag_contains_name))
|
||||
|
||||
val dueDateFilter: CustomFilterCriterion
|
||||
get() {
|
||||
val entryValues = arrayOf(
|
||||
"0",
|
||||
PermaSql.VALUE_EOD_YESTERDAY,
|
||||
PermaSql.VALUE_EOD,
|
||||
PermaSql.VALUE_EOD_TOMORROW,
|
||||
PermaSql.VALUE_EOD_DAY_AFTER,
|
||||
PermaSql.VALUE_EOD_NEXT_WEEK,
|
||||
PermaSql.VALUE_EOD_NEXT_MONTH)
|
||||
val values: MutableMap<String?, Any> = HashMap()
|
||||
values[Task.DUE_DATE.name] = "?"
|
||||
return MultipleSelectCriterion(
|
||||
IDENTIFIER_DUEDATE,
|
||||
r.getString(R.string.CFC_dueBefore_text),
|
||||
select(Task.ID)
|
||||
.from(Task.TABLE)
|
||||
.where(
|
||||
and(
|
||||
activeAndVisible(),
|
||||
or(field("?").eq(0), Task.DUE_DATE.gt(0)),
|
||||
Task.DUE_DATE.lte("?")))
|
||||
.toString(),
|
||||
values,
|
||||
r.getStringArray(R.array.CFC_dueBefore_entries),
|
||||
entryValues,
|
||||
r.getString(R.string.CFC_dueBefore_name))
|
||||
}
|
||||
|
||||
val priorityFilter: CustomFilterCriterion
|
||||
get() {
|
||||
val entryValues = arrayOf(
|
||||
Task.Priority.HIGH.toString(),
|
||||
Task.Priority.MEDIUM.toString(),
|
||||
Task.Priority.LOW.toString(),
|
||||
Task.Priority.NONE.toString())
|
||||
val entries = arrayOf("!!!", "!!", "!", "o")
|
||||
val values: MutableMap<String?, Any> = HashMap()
|
||||
values[Task.IMPORTANCE.name] = "?"
|
||||
return MultipleSelectCriterion(
|
||||
IDENTIFIER_IMPORTANCE,
|
||||
r.getString(R.string.CFC_importance_text),
|
||||
select(Task.ID)
|
||||
.from(Task.TABLE)
|
||||
.where(and(activeAndVisible(), Task.IMPORTANCE.lte("?")))
|
||||
.toString(),
|
||||
values,
|
||||
entries,
|
||||
entryValues,
|
||||
r.getString(R.string.CFC_importance_name))
|
||||
}
|
||||
|
||||
private val taskTitleContainsFilter: CustomFilterCriterion
|
||||
get() = TextInputCriterion(
|
||||
IDENTIFIER_TITLE,
|
||||
r.getString(R.string.CFC_title_contains_text),
|
||||
select(Task.ID)
|
||||
.from(Task.TABLE)
|
||||
.where(and(activeAndVisible(), Task.TITLE.like("%?%")))
|
||||
.toString(),
|
||||
r.getString(R.string.CFC_title_contains_name),
|
||||
"",
|
||||
r.getString(R.string.CFC_title_contains_name))
|
||||
|
||||
private suspend fun gtasksFilterCriteria(): CustomFilterCriterion {
|
||||
val lists = googleTaskListDao.getAllLists()
|
||||
val listNames = arrayOfNulls<String>(lists.size)
|
||||
val listIds = arrayOfNulls<String>(lists.size)
|
||||
for (i in lists.indices) {
|
||||
listNames[i] = lists[i].title
|
||||
listIds[i] = lists[i].remoteId
|
||||
}
|
||||
val values: MutableMap<String, Any> = HashMap()
|
||||
values[GoogleTask.KEY] = "?"
|
||||
return MultipleSelectCriterion(
|
||||
IDENTIFIER_GTASKS,
|
||||
context.getString(R.string.CFC_gtasks_list_text),
|
||||
select(GoogleTask.TASK)
|
||||
.from(GoogleTask.TABLE)
|
||||
.join(inner(Task.TABLE, GoogleTask.TASK.eq(Task.ID)))
|
||||
.where(
|
||||
and(
|
||||
activeAndVisible(),
|
||||
GoogleTask.DELETED.eq(0),
|
||||
GoogleTask.LIST.eq("?")))
|
||||
.toString(),
|
||||
values,
|
||||
listNames,
|
||||
listIds,
|
||||
context.getString(R.string.CFC_gtasks_list_name))
|
||||
}
|
||||
|
||||
private suspend fun caldavFilterCriteria(): CustomFilterCriterion {
|
||||
val calendars = caldavDao.getCalendars()
|
||||
val names = arrayOfNulls<String>(calendars.size)
|
||||
val ids = arrayOfNulls<String>(calendars.size)
|
||||
for (i in calendars.indices) {
|
||||
names[i] = calendars[i].name
|
||||
ids[i] = calendars[i].uuid
|
||||
}
|
||||
val values: MutableMap<String, Any> = HashMap()
|
||||
values[CaldavTask.KEY] = "?"
|
||||
return MultipleSelectCriterion(
|
||||
IDENTIFIER_CALDAV,
|
||||
context.getString(R.string.CFC_gtasks_list_text),
|
||||
select(CaldavTask.TASK)
|
||||
.from(CaldavTask.TABLE)
|
||||
.join(inner(Task.TABLE, CaldavTask.TASK.eq(Task.ID)))
|
||||
.where(
|
||||
and(
|
||||
activeAndVisible(),
|
||||
CaldavTask.DELETED.eq(0),
|
||||
CaldavTask.CALENDAR.eq("?")))
|
||||
.toString(),
|
||||
values,
|
||||
names,
|
||||
ids,
|
||||
context.getString(R.string.CFC_list_name))
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val IDENTIFIER_UNIVERSE = "active"
|
||||
private const val IDENTIFIER_TITLE = "title"
|
||||
private const val IDENTIFIER_IMPORTANCE = "importance"
|
||||
private const val IDENTIFIER_DUEDATE = "dueDate"
|
||||
private const val IDENTIFIER_GTASKS = "gtaskslist"
|
||||
private const val IDENTIFIER_CALDAV = "caldavlist"
|
||||
private const val IDENTIFIER_TAG_IS = "tag_is"
|
||||
private const val IDENTIFIER_TAG_CONTAINS = "tag_contains"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue