diff --git a/app/src/main/java/com/todoroo/andlib/sql/Criterion.kt b/app/src/main/java/com/todoroo/andlib/sql/Criterion.kt index 83a00123a..a574c0741 100644 --- a/app/src/main/java/com/todoroo/andlib/sql/Criterion.kt +++ b/app/src/main/java/com/todoroo/andlib/sql/Criterion.kt @@ -19,6 +19,12 @@ abstract class Criterion(val operator: Operator) { } } + fun exists(query: Query): Criterion { + return object : Criterion(Operator.exists) { + override fun populate() = "EXISTS ($query)" + } + } + operator fun T.plus(tail: Array): List { val list = ArrayList(1 + tail.size) diff --git a/app/src/main/java/com/todoroo/andlib/sql/Operator.kt b/app/src/main/java/com/todoroo/andlib/sql/Operator.kt index 5f38ddd45..e64b4ca5f 100644 --- a/app/src/main/java/com/todoroo/andlib/sql/Operator.kt +++ b/app/src/main/java/com/todoroo/andlib/sql/Operator.kt @@ -12,6 +12,7 @@ class Operator private constructor(private val operator: String) { val not = Operator("NOT") val like = Operator("LIKE") val `in` = Operator("IN") + val exists = Operator("EXISTS") val gt = Operator(">") val gte = Operator(">=") val lt = Operator("<") diff --git a/app/src/main/java/org/tasks/data/Alarm.kt b/app/src/main/java/org/tasks/data/Alarm.kt index 56d9fa97b..9bf745487 100644 --- a/app/src/main/java/org/tasks/data/Alarm.kt +++ b/app/src/main/java/org/tasks/data/Alarm.kt @@ -6,10 +6,11 @@ import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.Ignore import androidx.room.PrimaryKey +import com.todoroo.andlib.data.Table import org.tasks.time.DateTimeUtils.printTimestamp import java.util.concurrent.TimeUnit -@Entity(tableName = "alarms") +@Entity(tableName = Alarm.TABLE_NAME) class Alarm : Parcelable { @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "_id") @@ -96,6 +97,9 @@ class Alarm : Parcelable { } companion object { + const val TABLE_NAME = "alarms" + val TABLE = Table(TABLE_NAME) + val TASK = TABLE.column("task") const val TYPE_DATE_TIME = 0 const val TYPE_REL_START = 1 const val TYPE_REL_END = 2 diff --git a/app/src/main/java/org/tasks/filters/FilterCriteriaProvider.kt b/app/src/main/java/org/tasks/filters/FilterCriteriaProvider.kt index e0711741d..c2689cebb 100644 --- a/app/src/main/java/org/tasks/filters/FilterCriteriaProvider.kt +++ b/app/src/main/java/org/tasks/filters/FilterCriteriaProvider.kt @@ -2,19 +2,30 @@ package org.tasks.filters import android.content.Context import com.todoroo.andlib.sql.Criterion.Companion.and +import com.todoroo.andlib.sql.Criterion.Companion.exists 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.Join.Companion.left import com.todoroo.andlib.sql.Query.Companion.select import com.todoroo.andlib.sql.UnaryCriterion.Companion.isNotNull -import com.todoroo.astrid.api.* +import com.todoroo.astrid.api.BooleanCriterion +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.Alarm +import org.tasks.data.CaldavDao +import org.tasks.data.CaldavTask +import org.tasks.data.GoogleTask +import org.tasks.data.GoogleTaskListDao +import org.tasks.data.Tag +import org.tasks.data.TagData +import org.tasks.data.TagDataDao import org.tasks.data.TaskDao.TaskCriteria.activeAndVisible -import java.util.* import javax.inject.Inject class FilterCriteriaProvider @Inject constructor( @@ -39,6 +50,7 @@ class FilterCriteriaProvider @Inject constructor( IDENTIFIER_HIDDEN -> hiddenFilter IDENTIFIER_PARENT -> parentFilter IDENTIFIER_SUBTASK -> subtaskFilter + IDENTIFIER_REMINDERS -> reminderFilter else -> throw RuntimeException("Unknown identifier: $identifier") } @@ -70,6 +82,7 @@ class FilterCriteriaProvider @Inject constructor( add(hiddenFilter) add(parentFilter) add(subtaskFilter) + add(reminderFilter) } return result } @@ -157,6 +170,18 @@ class FilterCriteriaProvider @Inject constructor( .toString() ) + private val reminderFilter: CustomFilterCriterion + get() { + return BooleanCriterion( + IDENTIFIER_REMINDERS, + context.getString(R.string.custom_filter_has_reminders), + select(Task.ID) + .from(Task.TABLE) + .where(exists(select(ONE).from(Alarm.TABLE).where(Alarm.TASK.eq(Task.ID)))) + .toString() + ) + } + val tagNameContainsFilter: CustomFilterCriterion get() = TextInputCriterion( IDENTIFIER_TAG_CONTAINS, @@ -342,5 +367,8 @@ class FilterCriteriaProvider @Inject constructor( private const val IDENTIFIER_HIDDEN = "hidden" private const val IDENTIFIER_PARENT = "parent" private const val IDENTIFIER_SUBTASK = "subtask" + private const val IDENTIFIER_REMINDERS = "reminders" + + private val ONE = field("1") } } \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ec1732e41..91e7d2e6f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -636,6 +636,7 @@ File %1$s contained %2$s.\n\n Delete this comment? Has subtasks Is subtask + Has reminders Your subscription has expired. Subscribe now to resume service. Insufficient subscription level. Please upgrade your subscription to resume service. No eligible GitHub sponsorship found