Move built-in filters to kmp

pull/2945/head
Alex Baker 4 months ago
parent 33798b3255
commit 95bc9aa6f2

@ -2,9 +2,7 @@ package com.todoroo.astrid.adapter
import com.natpryce.makeiteasy.MakeItEasy.with import com.natpryce.makeiteasy.MakeItEasy.with
import com.natpryce.makeiteasy.PropertyValue import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.astrid.core.BuiltInFilterExposer
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import org.tasks.data.entity.Task
import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -13,7 +11,9 @@ import org.junit.Before
import org.junit.Ignore import org.junit.Ignore
import org.junit.Test import org.junit.Test
import org.tasks.data.TaskListQuery.getQuery import org.tasks.data.TaskListQuery.getQuery
import org.tasks.data.entity.Task
import org.tasks.date.DateTimeUtils.newDateTime import org.tasks.date.DateTimeUtils.newDateTime
import org.tasks.filters.TodayFilter
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule import org.tasks.injection.ProductionModule
import org.tasks.makers.TaskMaker.DUE_DATE import org.tasks.makers.TaskMaker.DUE_DATE
@ -76,7 +76,7 @@ class RecursiveLoopTest : InjectingTestCase() {
} }
private suspend fun getTasks() = taskDao.fetchTasks { private suspend fun getTasks() = taskDao.fetchTasks {
getQuery(preferences, BuiltInFilterExposer.getTodayFilter(context.resources)) getQuery(preferences, TodayFilter.create())
} }
private suspend fun addTask(vararg properties: PropertyValue<in Task?, *>): Long { private suspend fun addTask(vararg properties: PropertyValue<in Task?, *>): Long {

@ -62,7 +62,6 @@ import com.todoroo.astrid.adapter.TaskAdapterProvider
import com.todoroo.astrid.api.AstridApiConstants.EXTRAS_OLD_DUE_DATE import com.todoroo.astrid.api.AstridApiConstants.EXTRAS_OLD_DUE_DATE
import com.todoroo.astrid.api.AstridApiConstants.EXTRAS_TASK_ID import com.todoroo.astrid.api.AstridApiConstants.EXTRAS_TASK_ID
import com.todoroo.astrid.api.CustomFilter import com.todoroo.astrid.api.CustomFilter
import com.todoroo.astrid.core.BuiltInFilterExposer
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.repeats.RepeatTaskHelper import com.todoroo.astrid.repeats.RepeatTaskHelper
import com.todoroo.astrid.service.TaskCompleter import com.todoroo.astrid.service.TaskCompleter
@ -123,6 +122,7 @@ import org.tasks.filters.CaldavFilter
import org.tasks.filters.Filter import org.tasks.filters.Filter
import org.tasks.filters.FilterImpl import org.tasks.filters.FilterImpl
import org.tasks.filters.GtasksFilter import org.tasks.filters.GtasksFilter
import org.tasks.filters.MyTasksFilter
import org.tasks.filters.PlaceFilter import org.tasks.filters.PlaceFilter
import org.tasks.filters.TagFilter import org.tasks.filters.TagFilter
import org.tasks.markdown.MarkdownProvider import org.tasks.markdown.MarkdownProvider
@ -220,8 +220,9 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
if (result.resultCode != RESULT_OK) return@registerForActivityResult if (result.resultCode != RESULT_OK) return@registerForActivityResult
val data = result.data ?: return@registerForActivityResult val data = result.data ?: return@registerForActivityResult
when (data.action) { when (data.action) {
ACTION_DELETED -> ACTION_DELETED -> lifecycleScope.launch {
mainViewModel.setFilter(BuiltInFilterExposer.getMyTasksFilter(resources)) mainViewModel.setFilter(MyTasksFilter.create())
}
ACTION_RELOAD -> ACTION_RELOAD ->
IntentCompat.getParcelableExtra(data, MainActivity.OPEN_FILTER, Filter::class.java)?.let { IntentCompat.getParcelableExtra(data, MainActivity.OPEN_FILTER, Filter::class.java)?.let {
mainViewModel.setFilter(it) mainViewModel.setFilter(it)

@ -1,10 +1,6 @@
package com.todoroo.astrid.adapter package com.todoroo.astrid.adapter
import android.content.Context import android.content.Context
import org.tasks.filters.CaldavFilter
import org.tasks.filters.GtasksFilter
import org.tasks.filters.TagFilter
import com.todoroo.astrid.core.BuiltInFilterExposer
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.service.TaskMover import com.todoroo.astrid.service.TaskMover
import com.todoroo.astrid.subtasks.SubtasksFilterUpdater import com.todoroo.astrid.subtasks.SubtasksFilterUpdater
@ -19,7 +15,12 @@ import org.tasks.data.dao.TaskListMetadataDao
import org.tasks.data.entity.Task.Companion.isUuidEmpty import org.tasks.data.entity.Task.Companion.isUuidEmpty
import org.tasks.data.entity.TaskListMetadata import org.tasks.data.entity.TaskListMetadata
import org.tasks.filters.AstridOrderingFilter import org.tasks.filters.AstridOrderingFilter
import org.tasks.filters.CaldavFilter
import org.tasks.filters.Filter import org.tasks.filters.Filter
import org.tasks.filters.GtasksFilter
import org.tasks.filters.MyTasksFilter
import org.tasks.filters.TagFilter
import org.tasks.filters.TodayFilter
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import javax.inject.Inject import javax.inject.Inject
@ -71,10 +72,10 @@ class TaskAdapterProvider @Inject constructor(
private fun createManualFilterTaskAdapter(filter: AstridOrderingFilter): TaskAdapter? = runBlocking { private fun createManualFilterTaskAdapter(filter: AstridOrderingFilter): TaskAdapter? = runBlocking {
var filterId: String? = null var filterId: String? = null
var prefId: String? = null var prefId: String? = null
if (BuiltInFilterExposer.isInbox(context, filter)) { if (filter is MyTasksFilter) {
filterId = TaskListMetadata.FILTER_ID_ALL filterId = TaskListMetadata.FILTER_ID_ALL
prefId = SubtasksFilterUpdater.ACTIVE_TASKS_ORDER prefId = SubtasksFilterUpdater.ACTIVE_TASKS_ORDER
} else if (BuiltInFilterExposer.isTodayFilter(context, filter)) { } else if (filter is TodayFilter) {
filterId = TaskListMetadata.FILTER_ID_TODAY filterId = TaskListMetadata.FILTER_ID_TODAY
prefId = SubtasksFilterUpdater.TODAY_TASKS_ORDER prefId = SubtasksFilterUpdater.TODAY_TASKS_ORDER
} }

@ -5,164 +5,38 @@
*/ */
package com.todoroo.astrid.core package com.todoroo.astrid.core
import android.content.Context
import android.content.res.Resources
import dagger.hilt.android.qualifiers.ApplicationContext
import org.tasks.R import org.tasks.R
import org.tasks.data.dao.TaskDao import org.tasks.data.dao.TaskDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.entity.CaldavTask
import org.tasks.data.entity.Task
import org.tasks.data.sql.Criterion.Companion.and
import org.tasks.data.sql.Criterion.Companion.or
import org.tasks.data.sql.Join
import org.tasks.data.sql.QueryTemplate
import org.tasks.filters.Filter import org.tasks.filters.Filter
import org.tasks.filters.FilterImpl
import org.tasks.filters.MyTasksFilter
import org.tasks.filters.NotificationsFilter import org.tasks.filters.NotificationsFilter
import org.tasks.filters.RecentlyModifiedFilter import org.tasks.filters.RecentlyModifiedFilter
import org.tasks.filters.SnoozedFilter import org.tasks.filters.SnoozedFilter
import org.tasks.filters.TimerFilter import org.tasks.filters.TimerFilter
import org.tasks.filters.TodayFilter import org.tasks.filters.TodayFilter
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import org.tasks.themes.TasksIcons
import javax.inject.Inject import javax.inject.Inject
class BuiltInFilterExposer @Inject constructor( class BuiltInFilterExposer @Inject constructor(
@param:ApplicationContext private val context: Context,
private val preferences: Preferences, private val preferences: Preferences,
private val taskDao: TaskDao private val taskDao: TaskDao
) { ) {
val myTasksFilter: Filter
get() = getMyTasksFilter(context.resources)
suspend fun filters(): List<Filter> { suspend fun filters(): List<Filter> {
val r = context.resources
val filters: MutableList<Filter> = ArrayList() val filters: MutableList<Filter> = ArrayList()
if (preferences.getBoolean(R.string.p_show_today_filter, true)) { if (preferences.getBoolean(R.string.p_show_today_filter, true)) {
filters.add(getTodayFilter(r)) filters.add(TodayFilter.create())
} }
if (preferences.getBoolean(R.string.p_show_recently_modified_filter, true)) { if (preferences.getBoolean(R.string.p_show_recently_modified_filter, true)) {
filters.add(getRecentlyModifiedFilter(r)) filters.add(RecentlyModifiedFilter.create())
} }
if (taskDao.snoozedReminders() > 0) { if (taskDao.snoozedReminders() > 0) {
filters.add(getSnoozedFilter(r)) filters.add(SnoozedFilter.create())
} }
if (taskDao.activeTimers() > 0) { if (taskDao.activeTimers() > 0) {
filters.add(getTimerFilter(r)) filters.add(TimerFilter.create())
} }
if (taskDao.hasNotifications() > 0) { if (taskDao.hasNotifications() > 0) {
filters.add(getNotificationsFilter(context)) filters.add(NotificationsFilter.create())
} }
return filters return filters
} }
companion object {
fun getMyTasksFilter(r: Resources) = MyTasksFilter(r.getString(R.string.BFE_Active))
fun getTodayFilter(r: Resources): Filter {
return TodayFilter(r.getString(R.string.today))
}
fun getNoListFilter() =
FilterImpl(
title = "No list",
sql = QueryTemplate()
.join(Join.left(CaldavTask.TABLE, CaldavTask.TASK.eq(Task.ID)))
.where(CaldavTask.ID.eq(null))
.toString(),
icon = TasksIcons.CLOUD_OFF,
)
fun getDeleted() =
FilterImpl(
title = "Deleted",
sql = QueryTemplate().where(Task.DELETION_DATE.gt(0)).toString(),
icon = TasksIcons.DELETE,
)
fun getMissingListFilter() =
FilterImpl(
title = "Missing list",
sql = QueryTemplate()
.join(Join.left(CaldavTask.TABLE, CaldavTask.TASK.eq(Task.ID)))
.join(
Join.left(
CaldavCalendar.TABLE,
CaldavCalendar.UUID.eq(CaldavTask.CALENDAR)
)
)
.where(and(CaldavTask.ID.gt(0), CaldavCalendar.UUID.eq(null)))
.toString(),
icon = TasksIcons.CLOUD_OFF,
)
fun getMissingAccountFilter() =
FilterImpl(
title = "Missing account",
sql = QueryTemplate()
.join(
Join.left(CaldavTask.TABLE, and(CaldavTask.TASK.eq(Task.ID)))
).join(
Join.left(CaldavCalendar.TABLE, CaldavCalendar.UUID.eq(CaldavTask.CALENDAR))
).join(
Join.left(
CaldavAccount.TABLE, CaldavAccount.UUID.eq(CaldavCalendar.ACCOUNT)
)
)
.where(and(CaldavTask.ID.gt(0), CaldavAccount.UUID.eq(null)))
.toString(),
icon = TasksIcons.CLOUD_OFF,
)
fun getNoTitleFilter() =
FilterImpl(
title = "No title",
sql = QueryTemplate().where(or(Task.TITLE.eq(null), Task.TITLE.eq(""))).toString(),
icon = TasksIcons.CLEAR,
)
fun getNoCreateDateFilter() =
FilterImpl(
title = "No create time",
sql = QueryTemplate().where(Task.CREATION_DATE.eq(0)).toString(),
icon = TasksIcons.ADD,
)
fun getNoModificationDateFilter() =
FilterImpl(
title = "No modify time",
sql = QueryTemplate().where(Task.MODIFICATION_DATE.eq(0)).toString(),
icon = TasksIcons.EDIT,
)
fun getRecentlyModifiedFilter(r: Resources) =
RecentlyModifiedFilter(r.getString(R.string.BFE_Recent))
fun getSnoozedFilter(r: Resources) = SnoozedFilter(r.getString(R.string.filter_snoozed))
fun getTimerFilter(r: Resources) = TimerFilter(r.getString(R.string.TFE_workingOn))
fun getNotificationsFilter(context: Context) = NotificationsFilter(context.getString(R.string.notifications))
@JvmStatic
fun isInbox(context: Context, filter: Filter?) =
filter == getMyTasksFilter(context.resources)
@JvmStatic
fun isTodayFilter(context: Context, filter: Filter?) =
filter == getTodayFilter(context.resources)
fun isRecentlyModifiedFilter(context: Context, filter: Filter?) =
filter == getRecentlyModifiedFilter(context.resources)
fun isSnoozedFilter(context: Context, filter: Filter?) =
filter == getSnoozedFilter(context.resources)
fun isNotificationsFilter(context: Context, filter: Filter?) =
filter == getNotificationsFilter(context)
}
} }

@ -1,8 +1,6 @@
package com.todoroo.astrid.subtasks package com.todoroo.astrid.subtasks
import android.content.Context import android.content.Context
import com.todoroo.astrid.core.BuiltInFilterExposer.Companion.isInbox
import com.todoroo.astrid.core.BuiltInFilterExposer.Companion.isTodayFilter
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.subtasks.SubtasksFilterUpdater.Companion.buildOrderString import com.todoroo.astrid.subtasks.SubtasksFilterUpdater.Companion.buildOrderString
import com.todoroo.astrid.subtasks.SubtasksFilterUpdater.Companion.buildTreeModel import com.todoroo.astrid.subtasks.SubtasksFilterUpdater.Companion.buildTreeModel
@ -17,6 +15,8 @@ import org.tasks.data.entity.TaskListMetadata
import org.tasks.db.QueryUtils.showHiddenAndCompleted import org.tasks.db.QueryUtils.showHiddenAndCompleted
import org.tasks.filters.AstridOrderingFilter import org.tasks.filters.AstridOrderingFilter
import org.tasks.filters.Filter import org.tasks.filters.Filter
import org.tasks.filters.MyTasksFilter
import org.tasks.filters.TodayFilter
import org.tasks.preferences.QueryPreferences import org.tasks.preferences.QueryPreferences
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -38,9 +38,9 @@ class SubtasksHelper @Inject constructor(
val tlm = when { val tlm = when {
tagData != null -> tagData != null ->
taskListMetadataDao.fetchByTagOrFilter(tagData.remoteId!!) taskListMetadataDao.fetchByTagOrFilter(tagData.remoteId!!)
isInbox(context, filter) -> filter is MyTasksFilter ->
taskListMetadataDao.fetchByTagOrFilter(TaskListMetadata.FILTER_ID_ALL) taskListMetadataDao.fetchByTagOrFilter(TaskListMetadata.FILTER_ID_ALL)
isTodayFilter(context, filter) -> filter is TodayFilter ->
taskListMetadataDao.fetchByTagOrFilter(TaskListMetadata.FILTER_ID_TODAY) taskListMetadataDao.fetchByTagOrFilter(TaskListMetadata.FILTER_ID_TODAY)
else -> null else -> null
} }

@ -73,13 +73,13 @@ class FilterProvider @Inject constructor(
) )
.apply { if (collapsed) return this } .apply { if (collapsed) return this }
.plus(listOf( .plus(listOf(
BuiltInFilterExposer.getNoListFilter(), DebugFilters.getNoListFilter(),
BuiltInFilterExposer.getNoTitleFilter(), DebugFilters.getNoTitleFilter(),
BuiltInFilterExposer.getMissingListFilter(), DebugFilters.getMissingListFilter(),
BuiltInFilterExposer.getMissingAccountFilter(), DebugFilters.getMissingAccountFilter(),
BuiltInFilterExposer.getNoCreateDateFilter(), DebugFilters.getNoCreateDateFilter(),
BuiltInFilterExposer.getNoModificationDateFilter(), DebugFilters.getNoModificationDateFilter(),
BuiltInFilterExposer.getDeleted() DebugFilters.getDeleted()
)) ))
} else { } else {
@ -175,7 +175,7 @@ class FilterProvider @Inject constructor(
forceExpand: Boolean = false, forceExpand: Boolean = false,
): List<FilterListItem> = ): List<FilterListItem> =
if (showBuiltIn) { if (showBuiltIn) {
arrayListOf(builtInFilterExposer.myTasksFilter) arrayListOf(MyTasksFilter.create())
} else { } else {
ArrayList<FilterListItem>() ArrayList<FilterListItem>()
} }

@ -8,7 +8,6 @@ import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat.InterruptionFilter import androidx.core.app.NotificationManagerCompat.InterruptionFilter
import com.todoroo.andlib.utility.AndroidUtilities import com.todoroo.andlib.utility.AndroidUtilities
import com.todoroo.andlib.utility.AndroidUtilities.preUpsideDownCake import com.todoroo.andlib.utility.AndroidUtilities.preUpsideDownCake
import com.todoroo.astrid.core.BuiltInFilterExposer
import com.todoroo.astrid.utility.Constants import com.todoroo.astrid.utility.Constants
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
@ -19,6 +18,8 @@ import org.tasks.data.dao.TaskDao
import org.tasks.data.displayName import org.tasks.data.displayName
import org.tasks.data.entity.Alarm import org.tasks.data.entity.Alarm
import org.tasks.data.entity.Notification import org.tasks.data.entity.Notification
import org.tasks.filters.NotificationsFilter
import org.tasks.filters.TimerFilter
import org.tasks.intents.TaskIntents import org.tasks.intents.TaskIntents
import org.tasks.markdown.MarkdownProvider import org.tasks.markdown.MarkdownProvider
import org.tasks.preferences.PermissionChecker import org.tasks.preferences.PermissionChecker
@ -267,7 +268,7 @@ class NotificationManager @Inject constructor(
PendingIntent.getActivity( PendingIntent.getActivity(
context, context,
0, 0,
TaskIntents.getTaskListIntent(context, BuiltInFilterExposer.getNotificationsFilter(context)), TaskIntents.getTaskListIntent(context, NotificationsFilter.create()),
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
) )
) )
@ -401,7 +402,7 @@ class NotificationManager @Inject constructor(
if (count == 0) { if (count == 0) {
cancel(Constants.NOTIFICATION_TIMER.toLong()) cancel(Constants.NOTIFICATION_TIMER.toLong())
} else { } else {
val filter = BuiltInFilterExposer.getTimerFilter(context.resources) val filter = TimerFilter.create()
val notifyIntent = TaskIntents.getTaskListIntent(context, filter) val notifyIntent = TaskIntents.getTaskListIntent(context, filter)
val pendingIntent = PendingIntent.getActivity( val pendingIntent = PendingIntent.getActivity(
context, context,
@ -412,8 +413,10 @@ class NotificationManager @Inject constructor(
val r = context.resources val r = context.resources
val appName = r.getString(R.string.app_name) val appName = r.getString(R.string.app_name)
val text = r.getString( val text = r.getString(
R.string.TPl_notification, r.getQuantityString(R.plurals.Ntasks, count, count)) R.string.TPl_notification, r.getQuantityString(R.plurals.Ntasks, count, count)
val builder = NotificationCompat.Builder(context, NotificationManager.NOTIFICATION_CHANNEL_TIMERS) )
val builder =
NotificationCompat.Builder(context, NotificationManager.NOTIFICATION_CHANNEL_TIMERS)
.setContentIntent(pendingIntent) .setContentIntent(pendingIntent)
.setContentTitle(appName) .setContentTitle(appName)
.setContentText(text) .setContentText(text)
@ -426,7 +429,8 @@ class NotificationManager @Inject constructor(
builder, builder,
alert = false, alert = false,
nonstop = false, nonstop = false,
fiveTimes = false) fiveTimes = false
)
} }
} }

@ -1,12 +1,7 @@
package org.tasks.preferences package org.tasks.preferences
import android.content.Context import android.content.Context
import org.tasks.filters.CaldavFilter
import com.todoroo.astrid.api.CustomFilter import com.todoroo.astrid.api.CustomFilter
import org.tasks.filters.GtasksFilter
import org.tasks.filters.TagFilter
import com.todoroo.astrid.core.BuiltInFilterExposer
import com.todoroo.astrid.core.BuiltInFilterExposer.Companion.getMyTasksFilter
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.tasks.R import org.tasks.R
@ -22,8 +17,16 @@ import org.tasks.data.entity.CaldavCalendar.Companion.ACCESS_READ_ONLY
import org.tasks.data.entity.CaldavTask import org.tasks.data.entity.CaldavTask
import org.tasks.data.entity.Task import org.tasks.data.entity.Task
import org.tasks.data.getLocalList import org.tasks.data.getLocalList
import org.tasks.filters.CaldavFilter
import org.tasks.filters.Filter import org.tasks.filters.Filter
import org.tasks.filters.GtasksFilter
import org.tasks.filters.MyTasksFilter
import org.tasks.filters.NotificationsFilter
import org.tasks.filters.PlaceFilter import org.tasks.filters.PlaceFilter
import org.tasks.filters.RecentlyModifiedFilter
import org.tasks.filters.SnoozedFilter
import org.tasks.filters.TagFilter
import org.tasks.filters.TodayFilter
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -85,7 +88,7 @@ class DefaultFilterProvider @Inject constructor(
getFilterFromPreference(preferences.getStringValue(resId)) getFilterFromPreference(preferences.getStringValue(resId))
suspend fun getFilterFromPreference(prefString: String?): Filter = suspend fun getFilterFromPreference(prefString: String?): Filter =
getFilterFromPreference(prefString, getMyTasksFilter(context.resources))!! getFilterFromPreference(prefString, MyTasksFilter.create())!!
private suspend fun getAnyList(): Filter { private suspend fun getAnyList(): Filter {
val filter = caldavDao.getGoogleTaskLists().getOrNull(0)?.let(::GtasksFilter) val filter = caldavDao.getGoogleTaskLists().getOrNull(0)?.let(::GtasksFilter)
@ -142,12 +145,12 @@ class DefaultFilterProvider @Inject constructor(
else -> TYPE_FILTER else -> TYPE_FILTER
} }
private fun getBuiltInFilter(id: Int): Filter = when (id) { private suspend fun getBuiltInFilter(id: Int): Filter = when (id) {
FILTER_TODAY -> BuiltInFilterExposer.getTodayFilter(context.resources) FILTER_TODAY -> TodayFilter.create()
FILTER_RECENTLY_MODIFIED -> BuiltInFilterExposer.getRecentlyModifiedFilter(context.resources) FILTER_RECENTLY_MODIFIED -> RecentlyModifiedFilter.create()
FILTER_SNOOZED -> BuiltInFilterExposer.getSnoozedFilter(context.resources) FILTER_SNOOZED -> SnoozedFilter.create()
FILTER_NOTIFICATIONS -> BuiltInFilterExposer.getNotificationsFilter(context) FILTER_NOTIFICATIONS -> NotificationsFilter.create()
else -> getMyTasksFilter(context.resources) else -> MyTasksFilter.create()
} }
private fun getBuiltInFilterId(filter: Filter) = with(filter) { private fun getBuiltInFilterId(filter: Filter) = with(filter) {
@ -194,17 +197,13 @@ class DefaultFilterProvider @Inject constructor(
return originalList ?: getDefaultList() return originalList ?: getDefaultList()
} }
private fun Filter.isToday() = private fun Filter.isToday() = this is TodayFilter
BuiltInFilterExposer.isTodayFilter(context, this)
private fun Filter.isRecentlyModified() = private fun Filter.isRecentlyModified() = this is RecentlyModifiedFilter
BuiltInFilterExposer.isRecentlyModifiedFilter(context, this)
private fun Filter.isSnoozed() = private fun Filter.isSnoozed() = this is SnoozedFilter
BuiltInFilterExposer.isSnoozedFilter(context, this)
private fun Filter.isNotifications() = private fun Filter.isNotifications() = this is NotificationsFilter
BuiltInFilterExposer.isNotificationsFilter(context, this)
companion object { companion object {
private const val TYPE_FILTER = 0 private const val TYPE_FILTER = 0

@ -6,7 +6,6 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.todoroo.astrid.core.BuiltInFilterExposer
import com.todoroo.astrid.service.TaskDeleter import com.todoroo.astrid.service.TaskDeleter
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
@ -36,6 +35,7 @@ import org.tasks.filters.AstridOrderingFilter
import org.tasks.filters.EmptyFilter import org.tasks.filters.EmptyFilter
import org.tasks.filters.Filter import org.tasks.filters.Filter
import org.tasks.filters.FilterImpl import org.tasks.filters.FilterImpl
import org.tasks.filters.MyTasksFilter
import org.tasks.filters.SearchFilter import org.tasks.filters.SearchFilter
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import org.tasks.preferences.QueryPreferences import org.tasks.preferences.QueryPreferences
@ -147,7 +147,7 @@ class TaskListViewModel @Inject constructor(
.map { .map {
val filter = when { val filter = when {
it.searchQuery == null -> it.filter it.searchQuery == null -> it.filter
it.searchQuery.isBlank() -> BuiltInFilterExposer.getMyTasksFilter(context.resources) it.searchQuery.isBlank() -> MyTasksFilter.create()
else -> context.createSearchQuery(it.searchQuery) else -> context.createSearchQuery(it.searchQuery)
} }
taskDao.fetchTasks { getQuery(preferences, filter) } taskDao.fetchTasks { getQuery(preferences, filter) }

@ -3,6 +3,7 @@
package org.tasks package org.tasks
import android.os.Parcelable import android.os.Parcelable
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.RawValue import kotlinx.parcelize.RawValue
import org.tasks.data.BuildConfig import org.tasks.data.BuildConfig
import java.util.Date import java.util.Date
@ -11,6 +12,8 @@ actual typealias CommonParcelable = Parcelable
actual typealias CommonRawValue = RawValue actual typealias CommonRawValue = RawValue
actual typealias CommonIgnoredOnParcel = IgnoredOnParcel
actual val IS_DEBUG = BuildConfig.DEBUG actual val IS_DEBUG = BuildConfig.DEBUG
actual fun Long.printTimestamp(): String = Date(this).toString() actual fun Long.printTimestamp(): String = Date(this).toString()

@ -10,6 +10,10 @@ annotation class CommonParcelize
@Retention(AnnotationRetention.BINARY) @Retention(AnnotationRetention.BINARY)
expect annotation class CommonRawValue() expect annotation class CommonRawValue()
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.SOURCE)
expect annotation class CommonIgnoredOnParcel()
expect interface CommonParcelable expect interface CommonParcelable
expect val IS_DEBUG: Boolean expect val IS_DEBUG: Boolean

@ -8,8 +8,14 @@ actual interface CommonParcelable
@Retention(AnnotationRetention.BINARY) @Retention(AnnotationRetention.BINARY)
annotation class RawValue annotation class RawValue
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.SOURCE)
annotation class IgnoredOnParcel
actual typealias CommonRawValue = RawValue actual typealias CommonRawValue = RawValue
actual typealias CommonIgnoredOnParcel = IgnoredOnParcel
actual val IS_DEBUG = false actual val IS_DEBUG = false
actual fun Long.printTimestamp(): String = this.toString() actual fun Long.printTimestamp(): String = this.toString()

@ -42,6 +42,11 @@ kotlin {
task("testClasses") task("testClasses")
} }
compose.resources {
publicResClass = true
generateResClass = always
}
android { android {
namespace = "org.tasks.kmp" namespace = "org.tasks.kmp"
compileSdk = libs.versions.android.compileSdk.get().toInt() compileSdk = libs.versions.android.compileSdk.get().toInt()

@ -5,4 +5,10 @@
<string name="requires_pro_subscription">Pro feature</string> <string name="requires_pro_subscription">Pro feature</string>
<string name="subscription_required_description">Unlock all features for as little as $1 USD/year</string> <string name="subscription_required_description">Unlock all features for as little as $1 USD/year</string>
<string name="subscribe">Subscribe</string> <string name="subscribe">Subscribe</string>
<string name="filter_my_tasks">My Tasks</string>
<string name="filter_notifications">Notifications</string>
<string name="filter_snoozed">Snoozed</string>
<string name="filter_timer">Tasks Being Timed</string>
<string name="filter_today">Today</string>
<string name="filter_recently_modified">Recently modified</string>
</resources> </resources>

@ -0,0 +1,85 @@
package org.tasks.filters
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.entity.CaldavTask
import org.tasks.data.entity.Task
import org.tasks.data.sql.Criterion.Companion.and
import org.tasks.data.sql.Criterion.Companion.or
import org.tasks.data.sql.Join
import org.tasks.data.sql.QueryTemplate
import org.tasks.themes.TasksIcons
object DebugFilters {
fun getNoListFilter() =
FilterImpl(
title = "No list",
sql = QueryTemplate()
.join(Join.left(CaldavTask.TABLE, CaldavTask.TASK.eq(Task.ID)))
.where(CaldavTask.ID.eq(null))
.toString(),
icon = TasksIcons.CLOUD_OFF,
)
fun getDeleted() =
FilterImpl(
title = "Deleted",
sql = QueryTemplate().where(Task.DELETION_DATE.gt(0)).toString(),
icon = TasksIcons.DELETE,
)
fun getMissingListFilter() =
FilterImpl(
title = "Missing list",
sql = QueryTemplate()
.join(Join.left(CaldavTask.TABLE, CaldavTask.TASK.eq(Task.ID)))
.join(
Join.left(
CaldavCalendar.TABLE,
CaldavCalendar.UUID.eq(CaldavTask.CALENDAR)
)
)
.where(and(CaldavTask.ID.gt(0), CaldavCalendar.UUID.eq(null)))
.toString(),
icon = TasksIcons.CLOUD_OFF,
)
fun getMissingAccountFilter() =
FilterImpl(
title = "Missing account",
sql = QueryTemplate()
.join(
Join.left(CaldavTask.TABLE, and(CaldavTask.TASK.eq(Task.ID)))
).join(
Join.left(CaldavCalendar.TABLE, CaldavCalendar.UUID.eq(CaldavTask.CALENDAR))
).join(
Join.left(
CaldavAccount.TABLE, CaldavAccount.UUID.eq(CaldavCalendar.ACCOUNT)
)
)
.where(and(CaldavTask.ID.gt(0), CaldavAccount.UUID.eq(null)))
.toString(),
icon = TasksIcons.CLOUD_OFF,
)
fun getNoTitleFilter() =
FilterImpl(
title = "No title",
sql = QueryTemplate().where(or(Task.TITLE.eq(null), Task.TITLE.eq(""))).toString(),
icon = TasksIcons.CLEAR,
)
fun getNoCreateDateFilter() =
FilterImpl(
title = "No create time",
sql = QueryTemplate().where(Task.CREATION_DATE.eq(0)).toString(),
icon = TasksIcons.ADD,
)
fun getNoModificationDateFilter() =
FilterImpl(
title = "No modify time",
sql = QueryTemplate().where(Task.MODIFICATION_DATE.eq(0)).toString(),
icon = TasksIcons.EDIT,
)
}

@ -1,11 +1,14 @@
package org.tasks.filters package org.tasks.filters
import org.jetbrains.compose.resources.getString
import org.tasks.CommonParcelize import org.tasks.CommonParcelize
import org.tasks.data.dao.TaskDao import org.tasks.data.dao.TaskDao
import org.tasks.data.entity.Task import org.tasks.data.entity.Task
import org.tasks.data.sql.Criterion import org.tasks.data.sql.Criterion
import org.tasks.data.sql.QueryTemplate import org.tasks.data.sql.QueryTemplate
import org.tasks.themes.TasksIcons import org.tasks.themes.TasksIcons
import tasks.kmp.generated.resources.Res
import tasks.kmp.generated.resources.filter_my_tasks
@CommonParcelize @CommonParcelize
data class MyTasksFilter( data class MyTasksFilter(
@ -26,4 +29,8 @@ data class MyTasksFilter(
override fun areItemsTheSame(other: FilterListItem): Boolean { override fun areItemsTheSame(other: FilterListItem): Boolean {
return other is MyTasksFilter return other is MyTasksFilter
} }
companion object {
suspend fun create() = MyTasksFilter(getString(Res.string.filter_my_tasks))
}
} }

@ -1,13 +1,16 @@
package org.tasks.filters package org.tasks.filters
import kotlinx.parcelize.Parcelize import org.jetbrains.compose.resources.getString
import org.tasks.CommonParcelize
import org.tasks.data.entity.Notification import org.tasks.data.entity.Notification
import org.tasks.data.entity.Task import org.tasks.data.entity.Task
import org.tasks.data.sql.Join import org.tasks.data.sql.Join
import org.tasks.data.sql.QueryTemplate import org.tasks.data.sql.QueryTemplate
import org.tasks.themes.TasksIcons import org.tasks.themes.TasksIcons
import tasks.kmp.generated.resources.Res
import tasks.kmp.generated.resources.filter_notifications
@Parcelize @CommonParcelize
data class NotificationsFilter( data class NotificationsFilter(
override val title: String, override val title: String,
) : Filter { ) : Filter {
@ -24,4 +27,8 @@ data class NotificationsFilter(
override fun areItemsTheSame(other: FilterListItem): Boolean { override fun areItemsTheSame(other: FilterListItem): Boolean {
return other is NotificationsFilter return other is NotificationsFilter
} }
companion object {
suspend fun create() = NotificationsFilter(getString(Res.string.filter_notifications))
}
} }

@ -1,5 +1,6 @@
package org.tasks.filters package org.tasks.filters
import org.jetbrains.compose.resources.getString
import org.tasks.CommonParcelize import org.tasks.CommonParcelize
import org.tasks.data.entity.Task import org.tasks.data.entity.Task
import org.tasks.data.sql.Criterion.Companion.and import org.tasks.data.sql.Criterion.Companion.and
@ -9,6 +10,8 @@ import org.tasks.themes.TasksIcons
import org.tasks.time.DateTimeUtils2.currentTimeMillis import org.tasks.time.DateTimeUtils2.currentTimeMillis
import org.tasks.time.minusDays import org.tasks.time.minusDays
import org.tasks.time.startOfMinute import org.tasks.time.startOfMinute
import tasks.kmp.generated.resources.Res
import tasks.kmp.generated.resources.filter_recently_modified
@CommonParcelize @CommonParcelize
data class RecentlyModifiedFilter( data class RecentlyModifiedFilter(
@ -39,4 +42,9 @@ data class RecentlyModifiedFilter(
override fun areItemsTheSame(other: FilterListItem): Boolean { override fun areItemsTheSame(other: FilterListItem): Boolean {
return other is RecentlyModifiedFilter return other is RecentlyModifiedFilter
} }
companion object {
suspend fun create() =
RecentlyModifiedFilter(getString(Res.string.filter_recently_modified))
}
} }

@ -1,16 +1,19 @@
package org.tasks.filters package org.tasks.filters
import org.jetbrains.compose.resources.getString
import org.tasks.CommonParcelize
import org.tasks.data.dao.TaskDao.TaskCriteria.activeAndVisible
import org.tasks.data.entity.Alarm
import org.tasks.data.entity.Task
import org.tasks.data.sql.Criterion.Companion.and import org.tasks.data.sql.Criterion.Companion.and
import org.tasks.data.sql.Functions.now import org.tasks.data.sql.Functions.now
import org.tasks.data.sql.Join.Companion.inner import org.tasks.data.sql.Join.Companion.inner
import org.tasks.data.sql.QueryTemplate import org.tasks.data.sql.QueryTemplate
import org.tasks.data.entity.Task
import kotlinx.parcelize.Parcelize
import org.tasks.data.entity.Alarm
import org.tasks.data.dao.TaskDao.TaskCriteria.activeAndVisible
import org.tasks.themes.TasksIcons import org.tasks.themes.TasksIcons
import tasks.kmp.generated.resources.Res
import tasks.kmp.generated.resources.filter_snoozed
@Parcelize @CommonParcelize
data class SnoozedFilter( data class SnoozedFilter(
override val title: String, override val title: String,
) : Filter { ) : Filter {
@ -34,4 +37,8 @@ data class SnoozedFilter(
override fun areItemsTheSame(other: FilterListItem): Boolean { override fun areItemsTheSame(other: FilterListItem): Boolean {
return other is SnoozedFilter return other is SnoozedFilter
} }
companion object {
suspend fun create() = SnoozedFilter(getString(Res.string.filter_snoozed))
}
} }

@ -1,20 +1,20 @@
package org.tasks.filters package org.tasks.filters
import kotlinx.parcelize.IgnoredOnParcel import org.tasks.CommonIgnoredOnParcel
import kotlinx.parcelize.Parcelize import org.tasks.CommonParcelize
import org.tasks.data.dao.TaskDao import org.tasks.data.dao.TaskDao
import org.tasks.data.entity.Task import org.tasks.data.entity.Task
import org.tasks.data.sql.Criterion import org.tasks.data.sql.Criterion
import org.tasks.data.sql.QueryTemplate import org.tasks.data.sql.QueryTemplate
@Parcelize @CommonParcelize
data class SubtaskFilter( data class SubtaskFilter(
private val parent: Long, private val parent: Long,
) : Filter { ) : Filter {
@IgnoredOnParcel @CommonIgnoredOnParcel
override val title: String = "subtasks" override val title: String = "subtasks"
@IgnoredOnParcel @CommonIgnoredOnParcel
override val sql: String = override val sql: String =
QueryTemplate() QueryTemplate()
.where( .where(

@ -1,13 +1,16 @@
package org.tasks.filters package org.tasks.filters
import org.jetbrains.compose.resources.getString
import org.tasks.CommonParcelize
import org.tasks.data.entity.Task
import org.tasks.data.sql.Criterion import org.tasks.data.sql.Criterion
import org.tasks.data.sql.QueryTemplate import org.tasks.data.sql.QueryTemplate
import org.tasks.data.entity.Task
import kotlinx.parcelize.Parcelize
import org.tasks.themes.TasksIcons import org.tasks.themes.TasksIcons
import tasks.kmp.generated.resources.Res
import tasks.kmp.generated.resources.filter_timer
@Parcelize @CommonParcelize
data class TimerFilter(override val title: String?) : Filter { data class TimerFilter(override val title: String) : Filter {
override val icon override val icon
get() = TasksIcons.TIMER get() = TasksIcons.TIMER
@ -21,4 +24,8 @@ data class TimerFilter(override val title: String?) : Filter {
).toString() ).toString()
override fun areItemsTheSame(other: FilterListItem) = other is TimerFilter override fun areItemsTheSame(other: FilterListItem) = other is TimerFilter
companion object {
suspend fun create() = TimerFilter(getString(Res.string.filter_timer))
}
} }

@ -1,14 +1,17 @@
package org.tasks.filters package org.tasks.filters
import com.todoroo.astrid.api.PermaSql import com.todoroo.astrid.api.PermaSql
import kotlinx.parcelize.Parcelize import org.jetbrains.compose.resources.getString
import org.tasks.CommonParcelize
import org.tasks.data.dao.TaskDao import org.tasks.data.dao.TaskDao
import org.tasks.data.entity.Task import org.tasks.data.entity.Task
import org.tasks.data.sql.Criterion import org.tasks.data.sql.Criterion
import org.tasks.data.sql.QueryTemplate import org.tasks.data.sql.QueryTemplate
import org.tasks.themes.TasksIcons import org.tasks.themes.TasksIcons
import tasks.kmp.generated.resources.Res
import tasks.kmp.generated.resources.filter_today
@Parcelize @CommonParcelize
data class TodayFilter( data class TodayFilter(
override val title: String, override val title: String,
override var filterOverride: String? = null, override var filterOverride: String? = null,
@ -33,4 +36,8 @@ data class TodayFilter(
override fun areItemsTheSame(other: FilterListItem): Boolean { override fun areItemsTheSame(other: FilterListItem): Boolean {
return other is TodayFilter return other is TodayFilter
} }
companion object {
suspend fun create() = TodayFilter(getString(Res.string.filter_today))
}
} }
Loading…
Cancel
Save