Move FilterProvider to kmp

pull/2945/head
Alex Baker 4 months ago
parent 83e43ba72c
commit a067651c23

@ -178,6 +178,7 @@ dependencies {
ksp(libs.androidx.hilt.compiler) ksp(libs.androidx.hilt.compiler)
implementation(libs.androidx.hilt.work) implementation(libs.androidx.hilt.work)
implementation(libs.androidx.datastore)
implementation(libs.androidx.fragment.ktx) implementation(libs.androidx.fragment.ktx)
implementation(libs.androidx.lifecycle.runtime) implementation(libs.androidx.lifecycle.runtime)
implementation(libs.androidx.lifecycle.runtime.compose) implementation(libs.androidx.lifecycle.runtime.compose)

@ -3,6 +3,7 @@ package com.todoroo.astrid.activity
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
@ -32,8 +33,8 @@ import org.tasks.filters.Filter
import org.tasks.filters.FilterProvider import org.tasks.filters.FilterProvider
import org.tasks.filters.NavigationDrawerSubheader import org.tasks.filters.NavigationDrawerSubheader
import org.tasks.filters.getIcon import org.tasks.filters.getIcon
import org.tasks.preferences.TasksPreferences
import org.tasks.preferences.DefaultFilterProvider import org.tasks.preferences.DefaultFilterProvider
import org.tasks.preferences.Preferences
import org.tasks.themes.ColorProvider import org.tasks.themes.ColorProvider
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -48,7 +49,7 @@ class MainActivityViewModel @Inject constructor(
private val inventory: Inventory, private val inventory: Inventory,
private val colorProvider: ColorProvider, private val colorProvider: ColorProvider,
private val caldavDao: CaldavDao, private val caldavDao: CaldavDao,
private val preferences: Preferences, private val tasksPreferences: TasksPreferences,
) : ViewModel() { ) : ViewModel() {
data class State( data class State(
@ -193,7 +194,7 @@ class MainActivityViewModel @Inject constructor(
val collapsed = !subheader.isCollapsed val collapsed = !subheader.isCollapsed
when (subheader.subheaderType) { when (subheader.subheaderType) {
NavigationDrawerSubheader.SubheaderType.PREFERENCE -> { NavigationDrawerSubheader.SubheaderType.PREFERENCE -> {
preferences.setBoolean(subheader.id.toInt(), collapsed) tasksPreferences.set(booleanPreferencesKey(subheader.id), collapsed)
localBroadcastManager.broadcastRefreshList() localBroadcastManager.broadcastRefreshList()
} }
NavigationDrawerSubheader.SubheaderType.GOOGLE_TASKS, NavigationDrawerSubheader.SubheaderType.GOOGLE_TASKS,

@ -3,6 +3,7 @@ package com.todoroo.astrid.adapter
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
@ -21,15 +22,15 @@ import org.tasks.filters.NavigationDrawerSubheader.SubheaderType.CALDAV
import org.tasks.filters.NavigationDrawerSubheader.SubheaderType.GOOGLE_TASKS import org.tasks.filters.NavigationDrawerSubheader.SubheaderType.GOOGLE_TASKS
import org.tasks.filters.NavigationDrawerSubheader.SubheaderType.PREFERENCE import org.tasks.filters.NavigationDrawerSubheader.SubheaderType.PREFERENCE
import org.tasks.filters.NavigationDrawerSubheader.SubheaderType.TASKS import org.tasks.filters.NavigationDrawerSubheader.SubheaderType.TASKS
import org.tasks.preferences.TasksPreferences
import org.tasks.location.LocationPickerActivity import org.tasks.location.LocationPickerActivity
import org.tasks.preferences.MainPreferences import org.tasks.preferences.MainPreferences
import org.tasks.preferences.Preferences
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
class SubheaderClickHandler @Inject constructor( class SubheaderClickHandler @Inject constructor(
private val activity: Activity, private val activity: Activity,
private val preferences: Preferences, private val tasksPreferences: TasksPreferences,
private val caldavDao: CaldavDao, private val caldavDao: CaldavDao,
private val localBroadcastManager: LocalBroadcastManager, private val localBroadcastManager: LocalBroadcastManager,
): SubheaderViewHolder.ClickHandler { ): SubheaderViewHolder.ClickHandler {
@ -37,7 +38,7 @@ class SubheaderClickHandler @Inject constructor(
(activity as AppCompatActivity).lifecycleScope.launch { (activity as AppCompatActivity).lifecycleScope.launch {
val collapsed = !subheader.isCollapsed val collapsed = !subheader.isCollapsed
when (subheader.subheaderType) { when (subheader.subheaderType) {
PREFERENCE -> preferences.setBoolean(subheader.id.toInt(), collapsed) PREFERENCE -> tasksPreferences.set(booleanPreferencesKey(subheader.id), collapsed)
GOOGLE_TASKS, GOOGLE_TASKS,
CALDAV, CALDAV,
TASKS -> caldavDao.setCollapsed(subheader.id, collapsed) TASKS -> caldavDao.setCollapsed(subheader.id, collapsed)

@ -1,42 +0,0 @@
/*
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.core
import org.tasks.R
import org.tasks.data.dao.TaskDao
import org.tasks.filters.Filter
import org.tasks.filters.NotificationsFilter
import org.tasks.filters.RecentlyModifiedFilter
import org.tasks.filters.SnoozedFilter
import org.tasks.filters.TimerFilter
import org.tasks.filters.TodayFilter
import org.tasks.preferences.Preferences
import javax.inject.Inject
class BuiltInFilterExposer @Inject constructor(
private val preferences: Preferences,
private val taskDao: TaskDao
) {
suspend fun filters(): List<Filter> {
val filters: MutableList<Filter> = ArrayList()
if (preferences.getBoolean(R.string.p_show_today_filter, true)) {
filters.add(TodayFilter.create())
}
if (preferences.getBoolean(R.string.p_show_recently_modified_filter, true)) {
filters.add(RecentlyModifiedFilter.create())
}
if (taskDao.snoozedReminders() > 0) {
filters.add(SnoozedFilter.create())
}
if (taskDao.activeTimers() > 0) {
filters.add(TimerFilter.create())
}
if (taskDao.hasNotifications() > 0) {
filters.add(NotificationsFilter.create())
}
return filters
}
}

@ -0,0 +1,33 @@
package org.tasks.filters
import org.tasks.R
import org.tasks.compose.drawer.DrawerConfiguration
import org.tasks.preferences.Preferences
class PreferenceDrawerConfiguration(
private val preferences: Preferences
) : DrawerConfiguration {
override val filtersEnabled: Boolean
get() = preferences.getBoolean(R.string.p_filters_enabled, super.filtersEnabled)
override val placesEnabled: Boolean
get() = preferences.getBoolean(R.string.p_places_enabled, super.placesEnabled)
override val hideUnusedPlaces: Boolean
get() = preferences.getBoolean(R.string.p_places_hide_unused, super.hideUnusedPlaces)
override val tagsEnabled: Boolean
get() = preferences.getBoolean(R.string.p_tags_enabled, super.tagsEnabled)
override val hideUnusedTags: Boolean
get() = preferences.getBoolean(R.string.p_tags_hide_unused, super.hideUnusedTags)
override val todayFilter: Boolean
get() = preferences.getBoolean(R.string.p_show_today_filter, super.todayFilter)
override val recentlyModifiedFilter: Boolean
get() = preferences.getBoolean(R.string.p_show_recently_modified_filter, super.recentlyModifiedFilter)
override val localListsEnabled: Boolean
get() = preferences.getBoolean(R.string.p_lists_enabled, super.localListsEnabled)
}

@ -3,7 +3,6 @@ package org.tasks.injection
import android.app.NotificationManager import android.app.NotificationManager
import android.content.Context import android.content.Context
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import org.tasks.data.db.Database
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
@ -17,21 +16,28 @@ import org.tasks.billing.BillingClient
import org.tasks.billing.BillingClientImpl import org.tasks.billing.BillingClientImpl
import org.tasks.billing.Inventory import org.tasks.billing.Inventory
import org.tasks.data.dao.AlarmDao import org.tasks.data.dao.AlarmDao
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.Astrid2ContentProviderDao import org.tasks.data.dao.Astrid2ContentProviderDao
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.DeletionDao import org.tasks.data.dao.DeletionDao
import org.tasks.data.dao.FilterDao import org.tasks.data.dao.FilterDao
import org.tasks.data.dao.GoogleTaskDao import org.tasks.data.dao.GoogleTaskDao
import org.tasks.data.dao.GoogleTaskListDao import org.tasks.data.dao.GoogleTaskListDao
import org.tasks.data.dao.LocationDao import org.tasks.data.dao.LocationDao
import org.tasks.data.dao.NotificationDao
import org.tasks.data.dao.TagDao import org.tasks.data.dao.TagDao
import org.tasks.data.dao.TagDataDao import org.tasks.data.dao.TagDataDao
import org.tasks.data.dao.TaskAttachmentDao import org.tasks.data.dao.TaskAttachmentDao
import org.tasks.data.dao.TaskDao import org.tasks.data.dao.TaskDao
import org.tasks.data.dao.TaskListMetadataDao import org.tasks.data.dao.TaskListMetadataDao
import org.tasks.data.dao.UserActivityDao import org.tasks.data.dao.UserActivityDao
import org.tasks.data.db.Database
import org.tasks.filters.PreferenceDrawerConfiguration
import org.tasks.jobs.WorkManager import org.tasks.jobs.WorkManager
import org.tasks.data.dao.NotificationDao import org.tasks.kmp.createDataStore
import org.tasks.compose.drawer.DrawerConfiguration
import org.tasks.filters.FilterProvider
import org.tasks.preferences.TasksPreferences
import org.tasks.preferences.Preferences
import java.util.Locale import java.util.Locale
import javax.inject.Singleton import javax.inject.Singleton
@ -134,4 +140,34 @@ class ApplicationModule {
@Provides @Provides
fun providesNotificationManager(@ApplicationContext context: Context) = fun providesNotificationManager(@ApplicationContext context: Context) =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
@Singleton
@Provides
fun providesTasksPreferences(@ApplicationContext context: Context) =
TasksPreferences(createDataStore(context))
@Provides
fun providesDrawerConfiguration(preferences: Preferences): DrawerConfiguration =
PreferenceDrawerConfiguration(preferences)
@Provides
fun providesFilterProvider(
filterDao: FilterDao,
tagDataDao: TagDataDao,
googleTaskListDao: GoogleTaskListDao,
caldavDao: CaldavDao,
drawerConfiguration: DrawerConfiguration,
locationDao: LocationDao,
taskDao: TaskDao,
tasksPreferences: TasksPreferences,
) = FilterProvider(
filterDao = filterDao,
tagDataDao = tagDataDao,
googleTaskListDao = googleTaskListDao,
caldavDao = caldavDao,
configuration = drawerConfiguration,
locationDao = locationDao,
taskDao = taskDao,
tasksPreferences = tasksPreferences,
)
} }

@ -390,10 +390,6 @@
<string name="p_list_chips">chips_list</string> <string name="p_list_chips">chips_list</string>
<string name="p_tag_chips">chips_tag</string> <string name="p_tag_chips">chips_tag</string>
<string name="p_desaturate_colors">desaturate_colors</string> <string name="p_desaturate_colors">desaturate_colors</string>
<string name="p_collapse_filters">collapse_filters</string>
<string name="p_collapse_debug">collapse_debug</string>
<string name="p_collapse_tags">collapse_tags</string>
<string name="p_collapse_locations">collapse_locations</string>
<string name="p_auto_dismiss_datetime_edit_screen">auto_dismiss_datetime_edit_screen</string> <string name="p_auto_dismiss_datetime_edit_screen">auto_dismiss_datetime_edit_screen</string>
<string name="p_auto_dismiss_datetime_list_screen">auto_dismiss_datetime_list_screen</string> <string name="p_auto_dismiss_datetime_list_screen">auto_dismiss_datetime_list_screen</string>
<string name="p_auto_dismiss_datetime_widget">auto_dismiss_datetime_widget</string> <string name="p_auto_dismiss_datetime_widget">auto_dismiss_datetime_widget</string>

@ -55,7 +55,7 @@ abstract class CaldavDao(private val database: Database) {
abstract suspend fun getAccount(type: Int, username: String): CaldavAccount? abstract suspend fun getAccount(type: Int, username: String): CaldavAccount?
@Query("SELECT * FROM caldav_accounts WHERE cda_id = :id") @Query("SELECT * FROM caldav_accounts WHERE cda_id = :id")
abstract suspend fun getAccount(id: Long): CaldavAccount? abstract suspend fun getAccount(id: String): CaldavAccount?
@Query("SELECT * FROM caldav_accounts WHERE cda_id = :id") @Query("SELECT * FROM caldav_accounts WHERE cda_id = :id")
abstract fun watchAccount(id: Long): Flow<CaldavAccount?> abstract fun watchAccount(id: Long): Flow<CaldavAccount?>
@ -83,7 +83,7 @@ ORDER BY CASE cda_account_type
abstract suspend fun getAccounts(): List<CaldavAccount> abstract suspend fun getAccounts(): List<CaldavAccount>
@Query("UPDATE caldav_accounts SET cda_collapsed = :collapsed WHERE cda_id = :id") @Query("UPDATE caldav_accounts SET cda_collapsed = :collapsed WHERE cda_id = :id")
abstract suspend fun setCollapsed(id: Long, collapsed: Boolean) abstract suspend fun setCollapsed(id: String, collapsed: Boolean)
@Insert @Insert
abstract suspend fun insert(caldavAccount: CaldavAccount): Long abstract suspend fun insert(caldavAccount: CaldavAccount): Long

@ -611,6 +611,56 @@
+| | +--- androidx.compose.material:material-icons-core:1.6.8 (c) +| | +--- androidx.compose.material:material-icons-core:1.6.8 (c)
+| | \--- androidx.compose.material:material-ripple:1.6.8 (c) +| | \--- androidx.compose.material:material-ripple:1.6.8 (c)
+| +--- org.jetbrains.compose.runtime:runtime:1.6.11 (*) +| +--- org.jetbrains.compose.runtime:runtime:1.6.11 (*)
+| +--- androidx.datastore:datastore-preferences:1.1.1
+| | \--- androidx.datastore:datastore-preferences-android:1.1.1
+| | +--- androidx.datastore:datastore:1.1.1
+| | | \--- androidx.datastore:datastore-android:1.1.1
+| | | +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*)
+| | | +--- androidx.datastore:datastore-core:1.1.1
+| | | | \--- androidx.datastore:datastore-core-android:1.1.1
+| | | | +--- androidx.annotation:annotation:1.7.0 -> 1.8.0 (*)
+| | | | +--- org.jetbrains.kotlin:kotlin-parcelize-runtime:1.9.22 -> 2.0.0 (*)
+| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 2.0.0 (*)
+| | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.0 (*)
+| | | | +--- androidx.datastore:datastore:1.1.1 (c)
+| | | | +--- androidx.datastore:datastore-core-okio:1.1.1 (c)
+| | | | +--- androidx.datastore:datastore-preferences:1.1.1 (c)
+| | | | \--- androidx.datastore:datastore-preferences-core:1.1.1 (c)
+| | | +--- androidx.datastore:datastore-core-okio:1.1.1
+| | | | \--- androidx.datastore:datastore-core-okio-jvm:1.1.1
+| | | | +--- androidx.datastore:datastore-core:1.1.1 (*)
+| | | | +--- com.squareup.okio:okio:3.4.0 -> 3.8.0
+| | | | | \--- com.squareup.okio:okio-jvm:3.8.0
+| | | | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.21 -> 2.0.0 (*)
+| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 2.0.0 (*)
+| | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.0 (*)
+| | | | +--- androidx.datastore:datastore:1.1.1 (c)
+| | | | +--- androidx.datastore:datastore-core:1.1.1 (c)
+| | | | +--- androidx.datastore:datastore-preferences:1.1.1 (c)
+| | | | \--- androidx.datastore:datastore-preferences-core:1.1.1 (c)
+| | | +--- com.squareup.okio:okio:3.4.0 -> 3.8.0 (*)
+| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 2.0.0 (*)
+| | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.0 (*)
+| | | +--- androidx.datastore:datastore-core:1.1.1 (c)
+| | | +--- androidx.datastore:datastore-core-okio:1.1.1 (c)
+| | | +--- androidx.datastore:datastore-preferences:1.1.1 (c)
+| | | \--- androidx.datastore:datastore-preferences-core:1.1.1 (c)
+| | +--- androidx.datastore:datastore-preferences-core:1.1.1
+| | | \--- androidx.datastore:datastore-preferences-core-jvm:1.1.1
+| | | +--- androidx.datastore:datastore-core:1.1.1 (*)
+| | | +--- androidx.datastore:datastore-core-okio:1.1.1 (*)
+| | | +--- com.squareup.okio:okio:3.4.0 -> 3.8.0 (*)
+| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 2.0.0 (*)
+| | | +--- androidx.datastore:datastore:1.1.1 (c)
+| | | +--- androidx.datastore:datastore-core:1.1.1 (c)
+| | | +--- androidx.datastore:datastore-core-okio:1.1.1 (c)
+| | | \--- androidx.datastore:datastore-preferences:1.1.1 (c)
+| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 2.0.0 (*)
+| | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.0 (*)
+| | +--- androidx.datastore:datastore:1.1.1 (c)
+| | +--- androidx.datastore:datastore-preferences-core:1.1.1 (c)
+| | +--- androidx.datastore:datastore-core:1.1.1 (c)
+| | \--- androidx.datastore:datastore-core-okio:1.1.1 (c)
+| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.2 +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.2
+| | \--- androidx.lifecycle:lifecycle-viewmodel-compose-android:2.8.2 +| | \--- androidx.lifecycle:lifecycle-viewmodel-compose-android:2.8.2
+| | +--- androidx.annotation:annotation:1.8.0 (*) +| | +--- androidx.annotation:annotation:1.8.0 (*)
@ -720,9 +770,7 @@
+| +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.20 -> 2.0.0 (*) +| +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.20 -> 2.0.0 (*)
+| +--- org.apache.commons:commons-lang3:3.8.1 -> 3.12.0 +| +--- org.apache.commons:commons-lang3:3.8.1 -> 3.12.0
+| \--- com.squareup.okhttp3:okhttp:4.10.0 -> 4.12.0 +| \--- com.squareup.okhttp3:okhttp:4.10.0 -> 4.12.0
+| +--- com.squareup.okio:okio:3.6.0 -> 3.8.0 +| +--- com.squareup.okio:okio:3.6.0 -> 3.8.0 (*)
+| | \--- com.squareup.okio:okio-jvm:3.8.0
+| | \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.21 -> 2.0.0 (*)
+| \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.21 -> 2.0.0 (*) +| \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.21 -> 2.0.0 (*)
++--- com.github.tasks:ical4android:12fe73a ++--- com.github.tasks:ical4android:12fe73a
+| +--- org.mnode.ical4j:ical4j:3.2.7 +| +--- org.mnode.ical4j:ical4j:3.2.7
@ -886,6 +934,7 @@
+| | +--- com.google.guava:listenablefuture:1.0 -> 9999.0-empty-to-avoid-conflict-with-guava +| | +--- com.google.guava:listenablefuture:1.0 -> 9999.0-empty-to-avoid-conflict-with-guava
+| | \--- org.jetbrains.kotlin:kotlin-stdlib:1.7.21 -> 2.0.0 (*) +| | \--- org.jetbrains.kotlin:kotlin-stdlib:1.7.21 -> 2.0.0 (*)
+| \--- com.google.dagger:hilt-android:2.49 -> 2.50 (*) +| \--- com.google.dagger:hilt-android:2.49 -> 2.50 (*)
++--- androidx.datastore:datastore-preferences:1.1.1 (*)
++--- androidx.fragment:fragment-ktx:1.8.0 ++--- androidx.fragment:fragment-ktx:1.8.0
+| +--- androidx.activity:activity-ktx:1.8.1 -> 1.9.0 (*) +| +--- androidx.activity:activity-ktx:1.8.1 -> 1.9.0 (*)
+| +--- androidx.collection:collection-ktx:1.1.0 -> 1.4.0 (*) +| +--- androidx.collection:collection-ktx:1.1.0 -> 1.4.0 (*)

@ -375,19 +375,59 @@
+| | | | +--- com.google.firebase:firebase-encoders-json:18.0.0 -> 18.0.1 (*) +| | | | +--- com.google.firebase:firebase-encoders-json:18.0.0 -> 18.0.1 (*)
+| | | | \--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | \--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*)
+| | | \--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | \--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*)
+| | +--- androidx.datastore:datastore-preferences:1.0.0 +| | +--- androidx.datastore:datastore-preferences:1.0.0 -> 1.1.1
+| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.5.10 -> 2.0.0 (*) +| | | \--- androidx.datastore:datastore-preferences-android:1.1.1
+| | | +--- androidx.datastore:datastore:1.0.0 +| | | +--- androidx.datastore:datastore:1.1.1
+| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.5.10 -> 2.0.0 (*) +| | | | \--- androidx.datastore:datastore-android:1.1.1
+| | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0 -> 1.8.0 (*) +| | | | +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*)
+| | | | +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| | | | +--- androidx.datastore:datastore-core:1.1.1
+| | | | \--- androidx.datastore:datastore-core:1.0.0 +| | | | | \--- androidx.datastore:datastore-core-android:1.1.1
+| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.5.10 -> 2.0.0 (*) +| | | | | +--- androidx.annotation:annotation:1.7.0 -> 1.8.0 (*)
+| | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0 -> 1.8.0 (*) +| | | | | +--- org.jetbrains.kotlin:kotlin-parcelize-runtime:1.9.22 -> 2.0.0
+| | | | \--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 (*)
+| | | \--- androidx.datastore:datastore-preferences-core:1.0.0 +| | | | | | \--- org.jetbrains.kotlin:kotlin-android-extensions-runtime:2.0.0
+| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.5.10 -> 2.0.0 (*) +| | | | | | \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 (*)
+| | | \--- androidx.datastore:datastore-core:1.0.0 (*) +| | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 2.0.0 (*)
+| | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.0 (*)
+| | | | | +--- androidx.datastore:datastore:1.1.1 (c)
+| | | | | +--- androidx.datastore:datastore-core-okio:1.1.1 (c)
+| | | | | +--- androidx.datastore:datastore-preferences:1.1.1 (c)
+| | | | | \--- androidx.datastore:datastore-preferences-core:1.1.1 (c)
+| | | | +--- androidx.datastore:datastore-core-okio:1.1.1
+| | | | | \--- androidx.datastore:datastore-core-okio-jvm:1.1.1
+| | | | | +--- androidx.datastore:datastore-core:1.1.1 (*)
+| | | | | +--- com.squareup.okio:okio:3.4.0 -> 3.8.0
+| | | | | | \--- com.squareup.okio:okio-jvm:3.8.0
+| | | | | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.21 -> 2.0.0 (*)
+| | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 2.0.0 (*)
+| | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.0 (*)
+| | | | | +--- androidx.datastore:datastore:1.1.1 (c)
+| | | | | +--- androidx.datastore:datastore-core:1.1.1 (c)
+| | | | | +--- androidx.datastore:datastore-preferences:1.1.1 (c)
+| | | | | \--- androidx.datastore:datastore-preferences-core:1.1.1 (c)
+| | | | +--- com.squareup.okio:okio:3.4.0 -> 3.8.0 (*)
+| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 2.0.0 (*)
+| | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.0 (*)
+| | | | +--- androidx.datastore:datastore-core:1.1.1 (c)
+| | | | +--- androidx.datastore:datastore-core-okio:1.1.1 (c)
+| | | | +--- androidx.datastore:datastore-preferences:1.1.1 (c)
+| | | | \--- androidx.datastore:datastore-preferences-core:1.1.1 (c)
+| | | +--- androidx.datastore:datastore-preferences-core:1.1.1
+| | | | \--- androidx.datastore:datastore-preferences-core-jvm:1.1.1
+| | | | +--- androidx.datastore:datastore-core:1.1.1 (*)
+| | | | +--- androidx.datastore:datastore-core-okio:1.1.1 (*)
+| | | | +--- com.squareup.okio:okio:3.4.0 -> 3.8.0 (*)
+| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 2.0.0 (*)
+| | | | +--- androidx.datastore:datastore:1.1.1 (c)
+| | | | +--- androidx.datastore:datastore-core:1.1.1 (c)
+| | | | +--- androidx.datastore:datastore-core-okio:1.1.1 (c)
+| | | | \--- androidx.datastore:datastore-preferences:1.1.1 (c)
+| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 2.0.0 (*)
+| | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.0 (*)
+| | | +--- androidx.datastore:datastore:1.1.1 (c)
+| | | +--- androidx.datastore:datastore-preferences-core:1.1.1 (c)
+| | | +--- androidx.datastore:datastore-core:1.1.1 (c)
+| | | \--- androidx.datastore:datastore-core-okio:1.1.1 (c)
+| | +--- com.google.android.datatransport:transport-api:3.0.0 (*) +| | +--- com.google.android.datatransport:transport-api:3.0.0 (*)
+| | \--- androidx.annotation:annotation:1.5.0 -> 1.8.0 (*) +| | \--- androidx.annotation:annotation:1.5.0 -> 1.8.0 (*)
+| +--- com.google.android.gms:play-services-tasks:18.0.1 -> 18.2.0 (*) +| +--- com.google.android.gms:play-services-tasks:18.0.1 -> 18.2.0 (*)
@ -590,10 +630,7 @@
+| +--- com.google.android.gms:play-services-base:18.5.0 (*) +| +--- com.google.android.gms:play-services-base:18.5.0 (*)
+| +--- com.google.android.gms:play-services-basement:18.4.0 (*) +| +--- com.google.android.gms:play-services-basement:18.4.0 (*)
+| \--- com.google.android.gms:play-services-tasks:18.2.0 (*) +| \--- com.google.android.gms:play-services-tasks:18.2.0 (*)
++--- org.jetbrains.kotlin:kotlin-parcelize-runtime:2.0.0 ++--- org.jetbrains.kotlin:kotlin-parcelize-runtime:2.0.0 (*)
+| +--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 (*)
+| \--- org.jetbrains.kotlin:kotlin-android-extensions-runtime:2.0.0
+| \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 (*)
++--- project :data ++--- project :data
+| +--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 (*) +| +--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 (*)
+| +--- androidx.room:room-runtime:2.7.0-alpha04 +| +--- androidx.room:room-runtime:2.7.0-alpha04
@ -920,6 +957,7 @@
+| | +--- androidx.compose.material:material-icons-core:1.6.8 (c) +| | +--- androidx.compose.material:material-icons-core:1.6.8 (c)
+| | \--- androidx.compose.material:material-ripple:1.6.8 (c) +| | \--- androidx.compose.material:material-ripple:1.6.8 (c)
+| +--- org.jetbrains.compose.runtime:runtime:1.6.11 (*) +| +--- org.jetbrains.compose.runtime:runtime:1.6.11 (*)
+| +--- androidx.datastore:datastore-preferences:1.1.1 (*)
+| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.2 +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.2
+| | \--- androidx.lifecycle:lifecycle-viewmodel-compose-android:2.8.2 +| | \--- androidx.lifecycle:lifecycle-viewmodel-compose-android:2.8.2
+| | +--- androidx.annotation:annotation:1.8.0 (*) +| | +--- androidx.annotation:annotation:1.8.0 (*)
@ -965,9 +1003,7 @@
+| +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.20 -> 2.0.0 (*) +| +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.20 -> 2.0.0 (*)
+| +--- org.apache.commons:commons-lang3:3.8.1 -> 3.12.0 +| +--- org.apache.commons:commons-lang3:3.8.1 -> 3.12.0
+| \--- com.squareup.okhttp3:okhttp:4.10.0 -> 4.12.0 +| \--- com.squareup.okhttp3:okhttp:4.10.0 -> 4.12.0
+| +--- com.squareup.okio:okio:3.6.0 -> 3.8.0 +| +--- com.squareup.okio:okio:3.6.0 -> 3.8.0 (*)
+| | \--- com.squareup.okio:okio-jvm:3.8.0
+| | \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.21 -> 2.0.0 (*)
+| \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.21 -> 2.0.0 (*) +| \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.21 -> 2.0.0 (*)
++--- com.github.tasks:ical4android:12fe73a ++--- com.github.tasks:ical4android:12fe73a
+| +--- org.mnode.ical4j:ical4j:3.2.7 +| +--- org.mnode.ical4j:ical4j:3.2.7
@ -1122,6 +1158,7 @@
+| | +--- com.google.guava:listenablefuture:1.0 -> 9999.0-empty-to-avoid-conflict-with-guava +| | +--- com.google.guava:listenablefuture:1.0 -> 9999.0-empty-to-avoid-conflict-with-guava
+| | \--- org.jetbrains.kotlin:kotlin-stdlib:1.7.21 -> 2.0.0 (*) +| | \--- org.jetbrains.kotlin:kotlin-stdlib:1.7.21 -> 2.0.0 (*)
+| \--- com.google.dagger:hilt-android:2.49 -> 2.50 (*) +| \--- com.google.dagger:hilt-android:2.49 -> 2.50 (*)
++--- androidx.datastore:datastore-preferences:1.1.1 (*)
++--- androidx.fragment:fragment-ktx:1.8.0 ++--- androidx.fragment:fragment-ktx:1.8.0
+| +--- androidx.activity:activity-ktx:1.8.1 -> 1.9.0 (*) +| +--- androidx.activity:activity-ktx:1.8.1 -> 1.9.0 (*)
+| +--- androidx.collection:collection-ktx:1.1.0 -> 1.4.0 (*) +| +--- androidx.collection:collection-ktx:1.1.0 -> 1.4.0 (*)

@ -72,6 +72,7 @@ androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "a
androidx-compose = { module = "androidx.compose:compose-bom", version.ref = "compose" } androidx-compose = { module = "androidx.compose:compose-bom", version.ref = "compose" }
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" } androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" } androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" }
androidx-datastore = { module = "androidx.datastore:datastore-preferences", version = "1.1.1" }
androidx-fragment-ktx = { module = "androidx.fragment:fragment-ktx", version.ref = "fragment-ktx" } androidx-fragment-ktx = { module = "androidx.fragment:fragment-ktx", version.ref = "fragment-ktx" }
androidx-hilt-compiler = { module = "androidx.hilt:hilt-compiler", version.ref = "hilt" } androidx-hilt-compiler = { module = "androidx.hilt:hilt-compiler", version.ref = "hilt" }
androidx-hilt-work = { module = "androidx.hilt:hilt-work", version.ref = "hilt" } androidx-hilt-work = { module = "androidx.hilt:hilt-work", version.ref = "hilt" }

@ -32,6 +32,7 @@ kotlin {
implementation(compose.material3) implementation(compose.material3)
implementation(compose.materialIconsExtended) implementation(compose.materialIconsExtended)
implementation(compose.runtime) implementation(compose.runtime)
implementation(libs.androidx.datastore)
implementation(libs.androidx.lifecycle.viewmodel.compose) implementation(libs.androidx.lifecycle.viewmodel.compose)
implementation(libs.kermit) implementation(libs.kermit)
implementation(libs.kotlinx.datetime) implementation(libs.kotlinx.datetime)

@ -1,6 +1,16 @@
package org.tasks.kmp package org.tasks.kmp
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import org.tasks.data.BuildConfig
import org.tasks.extensions.formatNumber import org.tasks.extensions.formatNumber
import java.util.Locale import java.util.Locale
actual fun formatNumber(number: Int) = Locale.getDefault().formatNumber(number) actual fun formatNumber(number: Int) = Locale.getDefault().formatNumber(number)
fun createDataStore(context: Context): DataStore<Preferences> = createDataStore(
producePath = { context.filesDir.resolve(dataStoreFileName).absolutePath }
)
actual val IS_DEBUG = BuildConfig.DEBUG

@ -34,7 +34,7 @@ fun MenuPreview() {
false, false,
false, false,
NavigationDrawerSubheader.SubheaderType.PREFERENCE, NavigationDrawerSubheader.SubheaderType.PREFERENCE,
0L, "",
), ),
) )
), ),

@ -26,7 +26,7 @@ fun FilterPickerPreview() {
false, false,
false, false,
NavigationDrawerSubheader.SubheaderType.PREFERENCE, NavigationDrawerSubheader.SubheaderType.PREFERENCE,
0L, "",
), ),
), ),
query = "", query = "",

@ -14,4 +14,8 @@
<string name="default_list">Default list</string> <string name="default_list">Default list</string>
<string name="help_and_feedback">Help &amp; feedback</string> <string name="help_and_feedback">Help &amp; feedback</string>
<string name="settings">Settings</string> <string name="settings">Settings</string>
<string name="drawer_filters">Filters</string>
<string name="drawer_tags">Tags</string>
<string name="drawer_places">Places</string>
<string name="drawer_local_lists">Local lists</string>
</resources> </resources>

@ -1,3 +1,17 @@
package org.tasks.kmp package org.tasks.kmp
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.Preferences
import okio.Path.Companion.toPath
expect fun formatNumber(number: Int): String expect fun formatNumber(number: Int): String
expect val IS_DEBUG: Boolean
fun createDataStore(producePath: () -> String): DataStore<Preferences> =
PreferenceDataStoreFactory.createWithPath(
produceFile = { producePath().toPath() }
)
const val dataStoreFileName = "tasks.preferences_pb"

@ -0,0 +1,27 @@
package org.tasks.compose.drawer
interface DrawerConfiguration {
val filtersEnabled: Boolean
get() = true
val placesEnabled: Boolean
get() = true
val hideUnusedPlaces: Boolean
get() = false
val tagsEnabled: Boolean
get() = true
val hideUnusedTags: Boolean
get() = false
val todayFilter: Boolean
get() = true
val recentlyModifiedFilter: Boolean
get() = true
val localListsEnabled: Boolean
get() = true
}

@ -1,10 +1,6 @@
package org.tasks.filters package org.tasks.filters
import android.content.Context import org.jetbrains.compose.resources.getString
import com.todoroo.astrid.core.BuiltInFilterExposer
import dagger.hilt.android.qualifiers.ApplicationContext
import org.tasks.BuildConfig
import org.tasks.R
import org.tasks.data.GoogleTaskFilters import org.tasks.data.GoogleTaskFilters
import org.tasks.data.LocationFilters import org.tasks.data.LocationFilters
import org.tasks.data.NO_ORDER import org.tasks.data.NO_ORDER
@ -14,26 +10,37 @@ import org.tasks.data.dao.FilterDao
import org.tasks.data.dao.GoogleTaskListDao import org.tasks.data.dao.GoogleTaskListDao
import org.tasks.data.dao.LocationDao import org.tasks.data.dao.LocationDao
import org.tasks.data.dao.TagDataDao import org.tasks.data.dao.TagDataDao
import org.tasks.data.dao.TaskDao
import org.tasks.data.entity.CaldavAccount import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavAccount.Companion.TYPE_LOCAL import org.tasks.data.entity.CaldavAccount.Companion.TYPE_LOCAL
import org.tasks.data.entity.CaldavAccount.Companion.TYPE_OPENTASKS import org.tasks.data.entity.CaldavAccount.Companion.TYPE_OPENTASKS
import org.tasks.data.setupLocalAccount import org.tasks.data.setupLocalAccount
import org.tasks.data.toGtasksFilter import org.tasks.data.toGtasksFilter
import org.tasks.filters.NavigationDrawerSubheader.SubheaderType
import org.tasks.kmp.IS_DEBUG
import org.tasks.compose.drawer.DrawerConfiguration
import org.tasks.data.toLocationFilter import org.tasks.data.toLocationFilter
import org.tasks.data.toTagFilter import org.tasks.data.toTagFilter
import org.tasks.filters.NavigationDrawerSubheader.SubheaderType import org.tasks.preferences.TasksPreferences
import org.tasks.preferences.Preferences import org.tasks.preferences.TasksPreferences.Companion.collapseDebug
import javax.inject.Inject import org.tasks.preferences.TasksPreferences.Companion.collapseFilters
import org.tasks.preferences.TasksPreferences.Companion.collapsePlaces
import org.tasks.preferences.TasksPreferences.Companion.collapseTags
import tasks.kmp.generated.resources.Res
import tasks.kmp.generated.resources.drawer_filters
import tasks.kmp.generated.resources.drawer_local_lists
import tasks.kmp.generated.resources.drawer_places
import tasks.kmp.generated.resources.drawer_tags
class FilterProvider @Inject constructor( class FilterProvider(
@param:ApplicationContext private val context: Context,
private val builtInFilterExposer: BuiltInFilterExposer,
private val filterDao: FilterDao, private val filterDao: FilterDao,
private val tagDataDao: TagDataDao, private val tagDataDao: TagDataDao,
private val googleTaskListDao: GoogleTaskListDao, private val googleTaskListDao: GoogleTaskListDao,
private val caldavDao: CaldavDao, private val caldavDao: CaldavDao,
private val preferences: Preferences, private val configuration: DrawerConfiguration,
private val locationDao: LocationDao private val locationDao: LocationDao,
private val taskDao: TaskDao,
private val tasksPreferences: TasksPreferences,
) { ) {
suspend fun listPickerItems(): List<FilterListItem> = suspend fun listPickerItems(): List<FilterListItem> =
caldavFilters(showCreate = false, forceExpand = false) caldavFilters(showCreate = false, forceExpand = false)
@ -41,7 +48,6 @@ class FilterProvider @Inject constructor(
suspend fun drawerItems(): List<FilterListItem> = suspend fun drawerItems(): List<FilterListItem> =
getAllFilters(showCreate = true, hideUnused = true) getAllFilters(showCreate = true, hideUnused = true)
suspend fun allLists(): List<Filter> = suspend fun allLists(): List<Filter> =
caldavFilters(showCreate = false, forceExpand = true) caldavFilters(showCreate = false, forceExpand = true)
.filterIsInstance<Filter>() .filterIsInstance<Filter>()
@ -56,27 +62,27 @@ class FilterProvider @Inject constructor(
suspend fun drawerCustomizationItems(): List<FilterListItem> = suspend fun drawerCustomizationItems(): List<FilterListItem> =
getAllFilters(showBuiltIn = false, showCreate = true) getAllFilters(showBuiltIn = false, showCreate = true)
private fun getDebugFilters(): List<FilterListItem> = private suspend fun getDebugFilters(): List<FilterListItem> =
if (BuildConfig.DEBUG) { if (IS_DEBUG) {
val collapsed = preferences.getBoolean(R.string.p_collapse_debug, false) val collapsed = tasksPreferences.get(collapseDebug, false)
listOf( listOf(
NavigationDrawerSubheader( NavigationDrawerSubheader(
context.getString(R.string.debug), "Debug",
false, false,
collapsed, collapsed,
SubheaderType.PREFERENCE, SubheaderType.PREFERENCE,
R.string.p_collapse_debug.toLong(), collapseDebug.name,
) )
) )
.apply { if (collapsed) return this } .apply { if (collapsed) return this }
.plus(listOf( .plus(listOf(
DebugFilters.getNoListFilter(), DebugFilters.getNoListFilter(),
DebugFilters.getNoTitleFilter(), DebugFilters.getNoTitleFilter(),
DebugFilters.getMissingListFilter(), DebugFilters.getMissingListFilter(),
DebugFilters.getMissingAccountFilter(), DebugFilters.getMissingAccountFilter(),
DebugFilters.getNoCreateDateFilter(), DebugFilters.getNoCreateDateFilter(),
DebugFilters.getNoModificationDateFilter(), DebugFilters.getNoModificationDateFilter(),
DebugFilters.getDeleted() DebugFilters.getDeleted()
)) ))
} else { } else {
@ -88,23 +94,23 @@ class FilterProvider @Inject constructor(
showBuiltIn: Boolean, showBuiltIn: Boolean,
forceExpand: Boolean, forceExpand: Boolean,
): List<FilterListItem> = ): List<FilterListItem> =
if (!preferences.getBoolean(R.string.p_filters_enabled, true)) { if (!configuration.filtersEnabled) {
emptyList() emptyList()
} else { } else {
val collapsed = !forceExpand && preferences.getBoolean(R.string.p_collapse_filters, false) val collapsed = !forceExpand && tasksPreferences.get(collapseFilters, false)
listOf( listOf(
NavigationDrawerSubheader( NavigationDrawerSubheader(
context.getString(R.string.filters), getString(Res.string.drawer_filters),
false, false,
collapsed, collapsed,
SubheaderType.PREFERENCE, SubheaderType.PREFERENCE,
R.string.p_collapse_filters.toLong(), collapseFilters.name,
if (showCreate) REQUEST_NEW_FILTER else 0, if (showCreate) REQUEST_NEW_FILTER else 0,
) )
) )
.apply { if (collapsed) return this } .apply { if (collapsed) return this }
.plusAllIf(showBuiltIn) { .plusAllIf(showBuiltIn) {
builtInFilterExposer.filters() builtInFilters()
} }
.plus(filterDao.getFilters().map(::CustomFilter).sort()) .plus(filterDao.getFilters().map(::CustomFilter).sort())
} }
@ -114,23 +120,23 @@ class FilterProvider @Inject constructor(
hideUnused: Boolean, hideUnused: Boolean,
forceExpand: Boolean, forceExpand: Boolean,
): List<FilterListItem> = ): List<FilterListItem> =
if (!preferences.getBoolean(R.string.p_tags_enabled, true)) { if (!configuration.tagsEnabled) {
emptyList() emptyList()
} else { } else {
val collapsed = !forceExpand && preferences.getBoolean(R.string.p_collapse_tags, false) val collapsed = !forceExpand && tasksPreferences.get(collapseTags, false)
listOf( listOf(
NavigationDrawerSubheader( NavigationDrawerSubheader(
context.getString(R.string.tags), getString(Res.string.drawer_tags),
false, false,
collapsed, collapsed,
SubheaderType.PREFERENCE, SubheaderType.PREFERENCE,
R.string.p_collapse_tags.toLong(), collapseTags.name,
if (showCreate) REQUEST_NEW_TAGS else 0, if (showCreate) REQUEST_NEW_TAGS else 0,
) )
) )
.apply { if (collapsed) return this } .apply { if (collapsed) return this }
.plus(tagDataDao.getTagFilters() .plus(tagDataDao.getTagFilters()
.filterIf(hideUnused && preferences.getBoolean(R.string.p_tags_hide_unused, false)) { .filterIf(hideUnused && configuration.hideUnusedTags) {
it.count > 0 it.count > 0
} }
.map(TagFilters::toTagFilter) .map(TagFilters::toTagFilter)
@ -142,23 +148,23 @@ class FilterProvider @Inject constructor(
hideUnused: Boolean, hideUnused: Boolean,
forceExpand: Boolean, forceExpand: Boolean,
): List<FilterListItem> = ): List<FilterListItem> =
if (!preferences.getBoolean(R.string.p_places_enabled, true)) { if (!configuration.placesEnabled) {
emptyList() emptyList()
} else { } else {
val collapsed = !forceExpand && preferences.getBoolean(R.string.p_collapse_locations, false) val collapsed = !forceExpand && tasksPreferences.get(collapsePlaces, false)
listOf( listOf(
NavigationDrawerSubheader( NavigationDrawerSubheader(
context.getString(R.string.places), getString(Res.string.drawer_places),
false, false,
collapsed, collapsed,
SubheaderType.PREFERENCE, SubheaderType.PREFERENCE,
R.string.p_collapse_locations.toLong(), collapsePlaces.name,
if (showCreate) REQUEST_NEW_PLACE else 0, if (showCreate) REQUEST_NEW_PLACE else 0,
) )
) )
.apply { if (collapsed) return this } .apply { if (collapsed) return this }
.plus(locationDao.getPlaceFilters() .plus(locationDao.getPlaceFilters()
.filterIf(hideUnused && preferences.getBoolean(R.string.p_places_hide_unused, false)) { .filterIf(hideUnused && configuration.hideUnusedPlaces) {
it.count > 0 it.count > 0
} }
.map(LocationFilters::toLocationFilter) .map(LocationFilters::toLocationFilter)
@ -182,7 +188,7 @@ class FilterProvider @Inject constructor(
.plus(addPlaces(showCreate, hideUnused, forceExpand)) .plus(addPlaces(showCreate, hideUnused, forceExpand))
.plus(caldavFilters(showCreate, forceExpand)) .plus(caldavFilters(showCreate, forceExpand))
.toList() .toList()
.plusAllIf(BuildConfig.DEBUG) { getDebugFilters() } .plusAllIf(IS_DEBUG) { getDebugFilters() }
private suspend fun googleTaskFilter( private suspend fun googleTaskFilter(
account: CaldavAccount, account: CaldavAccount,
@ -196,7 +202,7 @@ class FilterProvider @Inject constructor(
account.error?.isNotBlank() ?: false, account.error?.isNotBlank() ?: false,
collapsed, collapsed,
SubheaderType.GOOGLE_TASKS, SubheaderType.GOOGLE_TASKS,
account.id, account.id.toString(),
if (showCreate) REQUEST_NEW_LIST else 0, if (showCreate) REQUEST_NEW_LIST else 0,
) )
) )
@ -215,7 +221,7 @@ class FilterProvider @Inject constructor(
): List<FilterListItem> = ): List<FilterListItem> =
caldavDao.getAccounts() caldavDao.getAccounts()
.ifEmpty { listOf(caldavDao.setupLocalAccount()) } .ifEmpty { listOf(caldavDao.setupLocalAccount()) }
.filter { it.accountType != TYPE_LOCAL || preferences.getBoolean(R.string.p_lists_enabled, true) } .filter { it.accountType != TYPE_LOCAL || configuration.localListsEnabled }
.flatMap { .flatMap {
if (it.isGoogleTasks) { if (it.isGoogleTasks) {
googleTaskFilter(it, showCreate, forceExpand) googleTaskFilter(it, showCreate, forceExpand)
@ -237,7 +243,7 @@ class FilterProvider @Inject constructor(
return listOf( return listOf(
NavigationDrawerSubheader( NavigationDrawerSubheader(
if (account.accountType == TYPE_LOCAL) { if (account.accountType == TYPE_LOCAL) {
context.getString(R.string.local_lists) getString(Res.string.drawer_local_lists)
} else { } else {
account.name account.name
}, },
@ -247,7 +253,7 @@ class FilterProvider @Inject constructor(
account.isTasksOrg -> SubheaderType.TASKS account.isTasksOrg -> SubheaderType.TASKS
else -> SubheaderType.CALDAV else -> SubheaderType.CALDAV
}, },
account.id, account.id.toString(),
if (showCreate) REQUEST_NEW_LIST else 0, if (showCreate) REQUEST_NEW_LIST else 0,
) )
) )
@ -264,6 +270,26 @@ class FilterProvider @Inject constructor(
.sort()) .sort())
} }
private suspend fun builtInFilters(): List<Filter> {
val filters: MutableList<Filter> = ArrayList()
if (configuration.todayFilter) {
filters.add(TodayFilter.create())
}
if (configuration.recentlyModifiedFilter) {
filters.add(RecentlyModifiedFilter.create())
}
if (taskDao.snoozedReminders() > 0) {
filters.add(SnoozedFilter.create())
}
if (taskDao.activeTimers() > 0) {
filters.add(TimerFilter.create())
}
if (taskDao.hasNotifications() > 0) {
filters.add(NotificationsFilter.create())
}
return filters
}
companion object { companion object {
const val REQUEST_NEW_LIST = 10100 const val REQUEST_NEW_LIST = 10100
const val REQUEST_NEW_TAGS = 10101 const val REQUEST_NEW_TAGS = 10101

@ -5,7 +5,7 @@ data class NavigationDrawerSubheader(
val error: Boolean, val error: Boolean,
val isCollapsed: Boolean, val isCollapsed: Boolean,
val subheaderType: SubheaderType, val subheaderType: SubheaderType,
val id: Long, val id: String,
val addIntentRc: Int = 0, val addIntentRc: Int = 0,
) : FilterListItem { ) : FilterListItem {
override fun areItemsTheSame(other: FilterListItem): Boolean { override fun areItemsTheSame(other: FilterListItem): Boolean {

@ -0,0 +1,29 @@
package org.tasks.preferences
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.map
class TasksPreferences(private val dataStore: DataStore<Preferences>) {
suspend fun <T> get(key: Preferences.Key<T>, defaultValue: T): T =
dataStore.data.map { it[key] }.firstOrNull() ?: defaultValue
fun <T> flow(key: Preferences.Key<T>, defaultValue: T): Flow<T> =
dataStore.data.map { it[key] ?: defaultValue }
suspend fun <T> set(key: Preferences.Key<T>, value: T) {
dataStore.edit { it[key] = value }
}
companion object {
val collapseFilters = booleanPreferencesKey("drawer_collapse_filters")
val collapseTags = booleanPreferencesKey("drawer_collapse_tags")
val collapseDebug = booleanPreferencesKey("drawer_collapse_debug")
val collapsePlaces = booleanPreferencesKey("drawer_collapse_places")
}
}

@ -1,3 +1,5 @@
package org.tasks.kmp package org.tasks.kmp
actual fun formatNumber(number: Int) = number.toString() actual fun formatNumber(number: Int) = number.toString()
actual val IS_DEBUG = true
Loading…
Cancel
Save