Convert FilterListItem to interface

pull/2553/head
Alex Baker 8 months ago
parent a32d35720a
commit ee3d3fa4f5

@ -265,7 +265,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
fab.isVisible = filter.isWritable
}
themeColor = if (filter.tint != 0) colorProvider.getThemeColor(filter.tint, true) else defaultThemeColor
filter.setFilterQueryOverride(null)
filter.filterOverride = null
// set up list adapters
taskAdapter = taskAdapterProvider.createTaskAdapter(filter)

@ -5,14 +5,15 @@ import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.todoroo.astrid.api.FilterListItem
import org.tasks.databinding.FilterAdapterActionBinding
import org.tasks.filters.NavigationDrawerAction
import org.tasks.themes.DrawableUtil
class ActionViewHolder internal constructor(
private val context: Context,
itemView: View,
private val onClick: ((FilterListItem?) -> Unit)?) : RecyclerView.ViewHolder(itemView) {
private val onClick: (NavigationDrawerAction) -> Unit
) : RecyclerView.ViewHolder(itemView) {
private val row: View
private val text: TextView
@ -26,13 +27,11 @@ class ActionViewHolder internal constructor(
}
}
fun bind(filter: FilterListItem) {
fun bind(filter: NavigationDrawerAction) {
text.text = filter.listingTitle
icon.setImageDrawable(DrawableUtil.getWrapped(context, filter.icon))
if (onClick != null) {
row.setOnClickListener {
onClick.invoke(filter)
}
row.setOnClickListener {
onClick.invoke(filter)
}
}
}

@ -7,7 +7,11 @@ import android.widget.ImageView
import android.widget.TextView
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import com.todoroo.astrid.api.*
import com.todoroo.astrid.api.CaldavFilter
import com.todoroo.astrid.api.CustomFilter
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.api.TagFilter
import org.tasks.R
import org.tasks.billing.Inventory
import org.tasks.databinding.FilterAdapterRowBinding
@ -16,7 +20,7 @@ import org.tasks.filters.PlaceFilter
import org.tasks.themes.ColorProvider
import org.tasks.themes.CustomIcons.getIconResId
import org.tasks.themes.DrawableUtil
import java.util.*
import java.util.Locale
class FilterViewHolder internal constructor(
itemView: View,
@ -25,7 +29,7 @@ class FilterViewHolder internal constructor(
private val context: Context,
private val inventory: Inventory,
private val colorProvider: ColorProvider,
private val onClick: ((FilterListItem?) -> Unit)?
private val onClick: (Filter) -> Unit,
) : RecyclerView.ViewHolder(itemView) {
private val row: View
@ -34,7 +38,7 @@ class FilterViewHolder internal constructor(
private val size: TextView
private val shareIndicator: ImageView
lateinit var filter: FilterListItem
lateinit var filter: Filter
init {
FilterAdapterRowBinding.bind(itemView).let {
@ -53,7 +57,7 @@ class FilterViewHolder internal constructor(
itemView.isSelected = moving
}
fun bind(filter: FilterListItem, selected: Boolean, count: Int?) {
fun bind(filter: Filter, selected: Boolean, count: Int?) {
this.filter = filter
if (navigationDrawer) {
itemView.isSelected = selected
@ -71,21 +75,20 @@ class FilterViewHolder internal constructor(
size.visibility = View.VISIBLE
}
shareIndicator.apply {
isVisible = filter.principals > 0
isVisible = filter is CaldavFilter && filter.principals > 0
setImageResource(when {
filter !is CaldavFilter -> 0
filter.principals <= 0 -> 0
filter.principals == 1 -> R.drawable.ic_outline_perm_identity_24px
else -> R.drawable.ic_outline_people_outline_24
})
}
if (onClick != null) {
row.setOnClickListener {
onClick.invoke(filter)
}
row.setOnClickListener {
onClick.invoke(filter)
}
}
private fun getColor(filter: FilterListItem): Int {
private fun getColor(filter: Filter): Int {
if (filter.tint != 0) {
val color = colorProvider.getThemeColor(filter.tint, true)
if (color.isFree || inventory.purchasedThemes()) {
@ -95,7 +98,7 @@ class FilterViewHolder internal constructor(
return context.getColor(R.color.text_primary)
}
private fun getIcon(filter: FilterListItem): Int {
private fun getIcon(filter: Filter): Int {
if (filter.icon < 1000 || inventory.hasPro) {
val icon = getIconResId(filter.icon)
if (icon != null) {

@ -18,9 +18,12 @@ import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.channels.Channel
import org.tasks.activities.DragAndDropDiffer
import org.tasks.billing.Inventory
import org.tasks.filters.NavigationDrawerAction
import org.tasks.filters.NavigationDrawerSubheader
import org.tasks.themes.ColorProvider
import java.util.*
import java.util.LinkedList
import java.util.Locale
import java.util.Queue
import java.util.concurrent.Executors
import javax.inject.Inject
import kotlin.math.max
@ -79,8 +82,8 @@ class NavigationDrawerAdapter @Inject constructor(
val item = getItem(position)
when (item.itemType) {
FilterListItem.Type.ITEM ->
(holder as FilterViewHolder).bind(item, item == selected, max(item.count, 0))
FilterListItem.Type.ACTION -> (holder as ActionViewHolder).bind(item)
(holder as FilterViewHolder).bind(item as Filter, item == selected, max(item.count, 0))
FilterListItem.Type.ACTION -> (holder as ActionViewHolder).bind(item as NavigationDrawerAction)
FilterListItem.Type.SUBHEADER ->
(holder as SubheaderViewHolder).bind((item as NavigationDrawerSubheader))
else -> {}

@ -9,7 +9,11 @@ import org.tasks.LocalBroadcastManager
import org.tasks.data.CaldavDao
import org.tasks.dialogs.NewFilterDialog
import org.tasks.filters.NavigationDrawerSubheader
import org.tasks.filters.NavigationDrawerSubheader.SubheaderType.*
import org.tasks.filters.NavigationDrawerSubheader.SubheaderType.CALDAV
import org.tasks.filters.NavigationDrawerSubheader.SubheaderType.ETESYNC
import org.tasks.filters.NavigationDrawerSubheader.SubheaderType.GOOGLE_TASKS
import org.tasks.filters.NavigationDrawerSubheader.SubheaderType.PREFERENCE
import org.tasks.filters.NavigationDrawerSubheader.SubheaderType.TASKS
import org.tasks.preferences.MainPreferences
import org.tasks.preferences.Preferences
import org.tasks.ui.NavigationDrawerFragment
@ -30,6 +34,7 @@ class SubheaderClickHandler @Inject constructor(
CALDAV,
TASKS,
ETESYNC -> caldavDao.setCollapsed(subheader.id, collapsed)
else -> throw IllegalArgumentException()
}
localBroadcastManager.broadcastRefreshList()
}

@ -16,6 +16,8 @@ internal class SubheaderViewHolder(
private val clickHandler: ClickHandler,
): RecyclerView.ViewHolder(itemView) {
var listingTitle: String? = null
interface ClickHandler {
fun onClick(subheader: NavigationDrawerSubheader)
fun onAdd(subheader: NavigationDrawerSubheader)

@ -14,7 +14,8 @@ import org.tasks.data.CaldavTask
import org.tasks.data.TaskDao.TaskCriteria.activeAndVisible
class CaldavFilter(
val calendar: CaldavCalendar
val calendar: CaldavCalendar,
val principals: Int = 0,
) : Filter(calendar.name, queryTemplate(calendar), getValuesForNewTask(calendar)) {
init {
@ -41,7 +42,7 @@ class CaldavFilter(
override val menu = R.menu.menu_caldav_list_fragment
override fun areContentsTheSame(other: FilterListItem): Boolean {
return super.areContentsTheSame(other) && calendar == (other as CaldavFilter).calendar
return super.areContentsTheSame(other) && calendar == (other as CaldavFilter).calendar && principals == other.principals
}
companion object {

@ -36,7 +36,7 @@ class CustomFilter : Filter {
}
override val menu: Int
get() = if (getId() > 0) R.menu.menu_custom_filter else 0
get() = if (id > 0) R.menu.menu_custom_filter else 0
override fun areContentsTheSame(other: FilterListItem): Boolean {
return super.areContentsTheSame(other) && criterion == (other as CustomFilter).criterion

@ -6,35 +6,15 @@ import androidx.annotation.MenuRes
import com.todoroo.andlib.sql.QueryTemplate
open class Filter : FilterListItem {
/**
* Values to apply to a task when quick-adding a task from this filter. For example, when a user
* views tasks tagged 'ABC', the tasks they create should also be tagged 'ABC'. If set to null, no
* additional values will be stored for a task. Can use [PermaSql]
*/
val valuesForNewTasks: MutableMap<String, Any> = HashMap()
/**
* [PermaSql] query for this filter. The query will be appended to the select statement
* after "`SELECT fields FROM table %s`". It is recommended that you use a [ ] to construct your query.
*
*
* Examples:
*
*
* * `"WHERE completionDate = 0"`
* * `"INNER JOIN " +
* Constants.TABLE_METADATA + " ON metadata.task = tasks.id WHERE
* metadata.namespace = " + NAMESPACE + " AND metadata.key = 'a' AND
* metadata.value = 'b' GROUP BY tasks.id ORDER BY tasks.title"`
*
*/
var originalSqlQuery: String? = null
/**
* Field for holding a modified sqlQuery based on sqlQuery. Useful for adjusting query for
* sort/subtasks without breaking the equality checking based on sqlQuery.
*/
private var filterOverride: String? = null
@Deprecated("for astrid manual order") var filterOverride: String? = null
var id = 0L
var icon = -1
var listingTitle: String? = null
var tint = 0
var count = -1
var order = NO_ORDER
constructor(listingTitle: String?, sqlQuery: QueryTemplate?) : this(
listingTitle,
@ -77,85 +57,45 @@ open class Filter : FilterListItem {
return filterOverride ?: originalSqlQuery!!
}
// --- parcelable
fun setFilterQueryOverride(filterOverride: String?) {
this.filterOverride = filterOverride
}
override fun hashCode(): Int {
val prime = 31
var result = 1
result = prime * result + if (originalSqlQuery == null) 0 else originalSqlQuery.hashCode()
result = prime * result + if (listingTitle == null) 0 else listingTitle.hashCode()
return result
}
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
}
if (other == null) {
return false
}
if (javaClass != other.javaClass) {
return false
}
val filter = other as Filter
if (originalSqlQuery == null) {
if (filter.originalSqlQuery != null) {
return false
}
} else if (originalSqlQuery != filter.originalSqlQuery) {
return false
}
return if (listingTitle == null) {
filter.listingTitle == null
} else listingTitle == filter.listingTitle
}
override fun getItemType(): Type {
return Type.ITEM
}
override val itemType = FilterListItem.Type.ITEM
/** {@inheritDoc} */
override fun writeToParcel(dest: Parcel, flags: Int) {
super.writeToParcel(dest, flags)
dest.writeString("") // old title
dest.writeLong(id)
dest.writeInt(icon)
dest.writeString(listingTitle)
dest.writeInt(tint)
dest.writeInt(count)
dest.writeInt(order)
dest.writeString(originalSqlQuery)
dest.writeMap(valuesForNewTasks)
}
override fun readFromParcel(source: Parcel) {
super.readFromParcel(source)
source.readString() // old title
open fun readFromParcel(source: Parcel) {
id = source.readLong()
icon = source.readInt()
listingTitle = source.readString()
tint = source.readInt()
count = source.readInt()
order = source.readInt()
originalSqlQuery = source.readString()
source.readMap(valuesForNewTasks, javaClass.classLoader)
}
open fun supportsAstridSorting(): Boolean {
return false
}
open fun supportsAstridSorting() = false
open fun supportsManualSort(): Boolean {
return false
}
open fun supportsManualSort() = false
open fun supportsHiddenTasks(): Boolean {
return true
}
open fun supportsHiddenTasks() = true
open fun supportsSubtasks(): Boolean {
return true
}
open fun supportsSubtasks() = true
open fun supportsSorting(): Boolean {
return true
}
open fun supportsSorting() = true
open val isReadOnly: Boolean = false
val isWritable: Boolean
get() = !isReadOnly
open val isReadOnly: Boolean
get() = false
fun hasBeginningMenu(): Boolean {
return beginningMenu != 0
@ -173,28 +113,55 @@ open class Filter : FilterListItem {
open val menu: Int
get() = 0
override fun toString(): String {
return ("Filter{"
+ "sqlQuery='"
+ originalSqlQuery
+ '\''
+ ", filterOverride='"
+ filterOverride
+ '\''
+ ", valuesForNewTasks="
+ valuesForNewTasks
+ '}')
}
override fun describeContents() = 0
override fun areItemsTheSame(other: FilterListItem): Boolean {
return other is Filter && originalSqlQuery == other.originalSqlQuery
return other is Filter && id == other.id && originalSqlQuery == other.originalSqlQuery
}
override fun areContentsTheSame(other: FilterListItem): Boolean {
return super.areContentsTheSame(other) && originalSqlQuery == (other as Filter).originalSqlQuery
return this == other
}
override fun toString(): String {
return "Filter(valuesForNewTasks=$valuesForNewTasks, originalSqlQuery=$originalSqlQuery, filterOverride=$filterOverride, id=$id, icon=$icon, listingTitle=$listingTitle, tint=$tint, count=$count, order=$order)"
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as Filter
if (valuesForNewTasks != other.valuesForNewTasks) return false
if (originalSqlQuery != other.originalSqlQuery) return false
if (filterOverride != other.filterOverride) return false
if (id != other.id) return false
if (icon != other.icon) return false
if (listingTitle != other.listingTitle) return false
if (tint != other.tint) return false
if (count != other.count) return false
if (order != other.order) return false
return isReadOnly == other.isReadOnly
}
override fun hashCode(): Int {
var result = valuesForNewTasks.hashCode()
result = 31 * result + (originalSqlQuery?.hashCode() ?: 0)
result = 31 * result + (filterOverride?.hashCode() ?: 0)
result = 31 * result + id.hashCode()
result = 31 * result + icon
result = 31 * result + (listingTitle?.hashCode() ?: 0)
result = 31 * result + tint
result = 31 * result + count
result = 31 * result + order
result = 31 * result + isReadOnly.hashCode()
return result
}
companion object {
const val NO_ORDER = -1
@JvmField
val CREATOR: Parcelable.Creator<Filter> = object : Parcelable.Creator<Filter> {
/** {@inheritDoc} */

@ -1,110 +0,0 @@
/*
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.api;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import org.tasks.R;
import java.util.Objects;
/**
* Represents an item displayed by Astrid's FilterListActivity
*
* @author Tim Su <tim@todoroo.com>
*/
public abstract class FilterListItem implements Parcelable {
public static final int NO_ORDER = -1;
/** Title of this item displayed on the Filters page */
public String listingTitle = null;
public long id = 0;
public int icon = -1;
public int tint = 0;
public int count = -1;
public int principals = 0;
public int order = NO_ORDER;
public abstract Type getItemType();
@Override
public int describeContents() {
return 0;
}
/** {@inheritDoc} */
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(listingTitle);
dest.writeInt(icon);
dest.writeInt(tint);
dest.writeInt(count);
dest.writeInt(order);
dest.writeLong(id);
}
// --- parcelable helpers
/** Utility method to read FilterListItem properties from a parcel. */
protected void readFromParcel(Parcel source) {
listingTitle = source.readString();
icon = source.readInt();
tint = source.readInt();
count = source.readInt();
order = source.readInt();
id = source.readLong();
}
public long getId() {
return id;
}
public boolean areItemsTheSame(@NonNull FilterListItem other) {
return getClass().equals(other.getClass()) && id == other.id;
}
public boolean areContentsTheSame(@NonNull FilterListItem other) {
return Objects.equals(listingTitle, other.listingTitle)
&& icon == other.icon
&& tint == other.tint
&& count == other.count
&& order == other.order
&& principals == other.principals;
}
@Override
public String toString() {
return "FilterListItem{" +
"listingTitle='" + listingTitle + '\'' +
", id=" + id +
", icon=" + icon +
", tint=" + tint +
", count=" + count +
", principals=" + principals +
", order=" + order +
'}';
}
public enum Type {
ITEM(R.layout.filter_adapter_row),
ACTION(R.layout.filter_adapter_action),
SUBHEADER(R.layout.filter_adapter_subheader),
SEPARATOR(R.layout.filter_adapter_separator);
public final int layout;
Type(@LayoutRes int layout) {
this.layout = layout;
}
}
}

@ -0,0 +1,19 @@
package com.todoroo.astrid.api
import android.os.Parcelable
import androidx.annotation.LayoutRes
import org.tasks.R
interface FilterListItem : Parcelable {
val itemType: Type
fun areItemsTheSame(other: FilterListItem): Boolean
fun areContentsTheSame(other: FilterListItem): Boolean
enum class Type(@param:LayoutRes val layout: Int) {
ITEM(R.layout.filter_adapter_row),
ACTION(R.layout.filter_adapter_action),
SUBHEADER(R.layout.filter_adapter_subheader),
SEPARATOR(R.layout.filter_adapter_separator)
}
}

@ -43,9 +43,11 @@ class TaskDeleter @Inject constructor(
}
suspend fun clearCompleted(filter: Filter): Int {
val deleteFilter = Filter(null, null)
deleteFilter.setFilterQueryOverride(
QueryUtils.removeOrder(QueryUtils.showHiddenAndCompleted(filter.originalSqlQuery!!)))
val deleteFilter = Filter(
null,
QueryUtils.removeOrder(QueryUtils.showHiddenAndCompleted(filter.originalSqlQuery!!)),
emptyMap()
)
val completed = taskDao.fetchTasks(preferences, deleteFilter)
.filter(TaskContainer::isCompleted)
.filterNot(TaskContainer::isReadOnly)

@ -48,7 +48,7 @@ class SubtasksFilterUpdater @Inject constructor(
query = query.replace("ORDER BY .*".toRegex(), "")
query += "ORDER BY $orderString"
query = showHiddenAndCompleted(query)
filter.setFilterQueryOverride(query)
filter.filterOverride = query
}
fun getIndentForTask(targetTaskId: String?): Int {

@ -18,7 +18,6 @@ import org.tasks.data.TaskListMetadataDao
import org.tasks.db.QueryUtils.showHiddenAndCompleted
import org.tasks.preferences.QueryPreferences
import timber.log.Timber
import java.util.*
import javax.inject.Inject
class SubtasksHelper @Inject constructor(
@ -33,7 +32,7 @@ class SubtasksHelper @Inject constructor(
): String {
var query = originalQuery
if (filter.supportsAstridSorting() && preferences.isAstridSort) {
val tagData = tagDataDao.getTagByName(filter.listingTitle)
val tagData = tagDataDao.getTagByName(filter.listingTitle!!)
val tlm = when {
tagData != null ->
taskListMetadataDao.fetchByTagOrFilter(tagData.remoteId!!)
@ -47,7 +46,7 @@ class SubtasksHelper @Inject constructor(
query = query.replace("ORDER BY .*".toRegex(), "")
query += " ORDER BY ${getOrderString(tagData, tlm)}"
query = showHiddenAndCompleted(query)
filter.setFilterQueryOverride(query)
filter.filterOverride = query
}
}
return query

@ -9,20 +9,32 @@ import android.view.MenuItem
import androidx.appcompat.widget.Toolbar
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.ItemTouchHelper.*
import androidx.recyclerview.widget.ItemTouchHelper.ACTION_STATE_DRAG
import androidx.recyclerview.widget.ItemTouchHelper.Callback
import androidx.recyclerview.widget.ItemTouchHelper.Callback.makeMovementFlags
import androidx.recyclerview.widget.ItemTouchHelper.DOWN
import androidx.recyclerview.widget.ItemTouchHelper.UP
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.todoroo.astrid.adapter.FilterViewHolder
import com.todoroo.astrid.adapter.NavigationDrawerAdapter
import com.todoroo.astrid.api.*
import com.todoroo.astrid.api.CaldavFilter
import com.todoroo.astrid.api.CustomFilter
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.FilterListItem
import com.todoroo.astrid.api.FilterListItem.Type.ITEM
import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.api.TagFilter
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import org.tasks.LocalBroadcastManager
import org.tasks.R
import org.tasks.caldav.BaseCaldavCalendarSettingsActivity
import org.tasks.data.*
import org.tasks.data.CaldavDao
import org.tasks.data.FilterDao
import org.tasks.data.GoogleTaskListDao
import org.tasks.data.LocationDao
import org.tasks.data.TagDataDao
import org.tasks.databinding.ActivityTagOrganizerBinding
import org.tasks.filters.FilterProvider
import org.tasks.filters.PlaceFilter
@ -88,7 +100,11 @@ class NavigationDrawerCustomization : ThemedInjectingAppCompatActivity(), Toolba
private fun updateFilters() = lifecycleScope.launch {
filterProvider
.drawerCustomizationItems()
.onEach { f -> f.count = 0 }
.onEach { f ->
if (f is Filter) {
f.count = 0
}
}
.let { adapter.submitList(it) }
}
@ -203,8 +219,10 @@ class NavigationDrawerCustomization : ThemedInjectingAppCompatActivity(), Toolba
}
.filter(getPredicate(viewHolder.filter))
.forEachIndexed { order, filter ->
filter.order = order
setOrder(order, filter)
if (filter is Filter) {
filter.order = order
setOrder(order, filter)
}
}
updateFilters()
}
@ -223,7 +241,7 @@ class NavigationDrawerCustomization : ThemedInjectingAppCompatActivity(), Toolba
}
}
private suspend fun setOrder(order: Int, filter: FilterListItem) {
private suspend fun setOrder(order: Int, filter: Filter) {
when (filter) {
is GtasksFilter -> caldavDao.setOrder(filter.list.id, order)
is CaldavFilter -> caldavDao.setOrder(filter.calendar.id, order)

@ -18,6 +18,7 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.todoroo.astrid.api.CaldavFilter
import com.todoroo.astrid.api.Filter
import org.tasks.R
import org.tasks.compose.collectAsStateLifecycleAware
@ -40,7 +41,7 @@ fun FilterPicker(
when (filter) {
is NavigationDrawerSubheader -> {
CollapsibleRow(
text = filter.listingTitle,
text = filter.listingTitle!!,
collapsed = filter.isCollapsed,
onClick = { viewModel.onClick(filter) },
)
@ -54,13 +55,13 @@ fun FilterPicker(
) {
Row(verticalAlignment = CenterVertically) {
Text(
text = filter.listingTitle,
text = filter.listingTitle!!,
style = MaterialTheme.typography.body2.copy(
fontWeight = FontWeight.Medium
),
modifier = Modifier.weight(1f),
)
if (filter.principals > 0) {
if (filter is CaldavFilter && filter.principals > 0) {
Icon(
painter = painterResource(
id = when (filter.principals) {

@ -5,7 +5,7 @@ import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.todoroo.andlib.data.Table
import com.todoroo.astrid.api.FilterListItem.NO_ORDER
import com.todoroo.astrid.api.Filter.Companion.NO_ORDER
import com.todoroo.astrid.data.Task
import kotlinx.parcelize.Parcelize
import org.tasks.themes.CustomIcons.LIST

@ -2,9 +2,14 @@ package org.tasks.data
import android.content.Context
import androidx.lifecycle.LiveData
import androidx.room.*
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Transaction
import androidx.room.Update
import com.todoroo.andlib.utility.DateUtilities.now
import com.todoroo.astrid.api.FilterListItem.NO_ORDER
import com.todoroo.astrid.api.Filter.Companion.NO_ORDER
import com.todoroo.astrid.core.SortHelper.APPLE_EPOCH
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.helper.UUIDHelper

@ -4,7 +4,7 @@ import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.todoroo.andlib.utility.AndroidUtilities
import com.todoroo.astrid.api.FilterListItem.NO_ORDER
import com.todoroo.astrid.api.Filter.Companion.NO_ORDER
import org.tasks.Strings
import org.tasks.themes.CustomIcons.FILTER

@ -1,7 +1,11 @@
package org.tasks.data
import androidx.room.*
import com.todoroo.astrid.api.FilterListItem.NO_ORDER
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import com.todoroo.astrid.api.Filter.Companion.NO_ORDER
@Dao
interface FilterDao {

@ -1,6 +1,6 @@
package org.tasks.data
import com.todoroo.astrid.api.FilterListItem.NO_ORDER
import com.todoroo.astrid.api.Filter.Companion.NO_ORDER
@Deprecated("Only used for backup migration")
data class GoogleTaskList(

@ -8,7 +8,7 @@ import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import com.todoroo.andlib.utility.DateUtilities.now
import com.todoroo.astrid.api.FilterListItem.NO_ORDER
import com.todoroo.astrid.api.Filter.Companion.NO_ORDER
import com.todoroo.astrid.data.Task
import org.tasks.data.Alarm.Companion.TYPE_SNOOZE
import org.tasks.filters.LocationFilters

@ -9,7 +9,7 @@ import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
import com.todoroo.andlib.data.Table
import com.todoroo.astrid.api.FilterListItem.NO_ORDER
import com.todoroo.astrid.api.Filter.Companion.NO_ORDER
import com.todoroo.astrid.helper.UUIDHelper
import kotlinx.parcelize.Parcelize
import org.tasks.Strings

@ -7,7 +7,7 @@ import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
import com.todoroo.astrid.api.FilterListItem.NO_ORDER
import com.todoroo.astrid.api.Filter.Companion.NO_ORDER
import com.todoroo.astrid.data.Task
import org.tasks.themes.CustomIcons.LABEL

@ -8,7 +8,7 @@ import androidx.room.Insert
import androidx.room.Query
import androidx.room.Transaction
import androidx.room.Update
import com.todoroo.astrid.api.FilterListItem.NO_ORDER
import com.todoroo.astrid.api.Filter.Companion.NO_ORDER
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.helper.UUIDHelper
import org.tasks.db.DbUtils

@ -7,7 +7,7 @@ import androidx.room.DeleteColumn
import androidx.room.migration.AutoMigrationSpec
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.todoroo.astrid.api.FilterListItem.NO_ORDER
import com.todoroo.astrid.api.Filter.Companion.NO_ORDER
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.data.Task.Companion.NOTIFY_AFTER_DEADLINE
import com.todoroo.astrid.data.Task.Companion.NOTIFY_AT_DEADLINE

@ -73,6 +73,8 @@ class FilterPickerViewModel @Inject constructor(
NavigationDrawerSubheader.SubheaderType.TASKS,
NavigationDrawerSubheader.SubheaderType.ETESYNC ->
caldavDao.setCollapsed(subheader.id, collapsed)
else -> throw IllegalStateException()
}
localBroadcastManager.broadcastRefreshList()
}

@ -1,44 +0,0 @@
package org.tasks.filters;
import androidx.room.Embedded;
import com.todoroo.astrid.api.CaldavFilter;
import org.tasks.data.CaldavCalendar;
import java.util.Objects;
public class CaldavFilters {
@Embedded public CaldavCalendar caldavCalendar;
public int count;
public int principals;
CaldavFilter toCaldavFilter() {
CaldavFilter filter = new CaldavFilter(caldavCalendar);
filter.count = count;
filter.principals = principals;
return filter;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof CaldavFilters)) {
return false;
}
CaldavFilters that = (CaldavFilters) o;
return count == that.count && Objects.equals(caldavCalendar, that.caldavCalendar);
}
@Override
public int hashCode() {
return Objects.hash(caldavCalendar, count);
}
@Override
public String toString() {
return "CaldavFilters{" + "caldavCalendar=" + caldavCalendar + ", count=" + count + '}';
}
}

@ -0,0 +1,20 @@
package org.tasks.filters
import androidx.room.Embedded
import com.todoroo.astrid.api.CaldavFilter
import org.tasks.data.CaldavCalendar
data class CaldavFilters(
@JvmField @Embedded val caldavCalendar: CaldavCalendar,
@JvmField val count: Int,
@JvmField val principals: Int,
) {
fun toCaldavFilter(): CaldavFilter {
val filter = CaldavFilter(
calendar = caldavCalendar,
principals = principals,
)
filter.count = count
return filter
}
}

@ -4,21 +4,27 @@ import android.content.Context
import android.content.Intent
import com.todoroo.astrid.api.CustomFilter
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.Filter.Companion.NO_ORDER
import com.todoroo.astrid.api.FilterListItem
import com.todoroo.astrid.api.FilterListItem.NO_ORDER
import com.todoroo.astrid.core.BuiltInFilterExposer
import dagger.hilt.android.qualifiers.ApplicationContext
import org.tasks.BuildConfig
import org.tasks.R
import org.tasks.Tasks.Companion.IS_GENERIC
import org.tasks.activities.GoogleTaskListSettingsActivity
import org.tasks.activities.NavigationDrawerCustomization
import org.tasks.activities.TagSettingsActivity
import org.tasks.billing.Inventory
import org.tasks.caldav.BaseCaldavCalendarSettingsActivity
import org.tasks.data.*
import org.tasks.data.CaldavAccount
import org.tasks.data.CaldavAccount.Companion.TYPE_ETESYNC
import org.tasks.data.CaldavAccount.Companion.TYPE_LOCAL
import org.tasks.data.CaldavAccount.Companion.TYPE_OPENTASKS
import org.tasks.data.CaldavDao
import org.tasks.data.FilterDao
import org.tasks.data.GoogleTaskListDao
import org.tasks.data.LocationDao
import org.tasks.data.TagDataDao
import org.tasks.filters.NavigationDrawerSubheader.SubheaderType
import org.tasks.location.LocationPickerActivity
import org.tasks.preferences.HelpAndFeedback
@ -172,7 +178,7 @@ class FilterProvider @Inject constructor(
private val navDrawerFooter: List<FilterListItem>
get() = listOf(NavigationDrawerSeparator())
.plusIf(BuildConfig.FLAVOR == "generic" && !inventory.hasTasksAccount) {
.plusIf(IS_GENERIC && !inventory.hasTasksAccount) {
NavigationDrawerAction(
context.getString(R.string.TLA_menu_donate),
R.drawable.ic_outline_attach_money_24px,
@ -184,21 +190,30 @@ class FilterProvider @Inject constructor(
R.drawable.ic_outline_attach_money_24px,
NavigationDrawerFragment.REQUEST_PURCHASE)
}
.plus(NavigationDrawerAction(
.plus(
NavigationDrawerAction(
context.getString(R.string.manage_drawer),
R.drawable.ic_outline_edit_24px,
Intent(context, NavigationDrawerCustomization::class.java),
0))
.plus(NavigationDrawerAction(
0,
Intent(context, NavigationDrawerCustomization::class.java)
)
)
.plus(
NavigationDrawerAction(
context.getString(R.string.TLA_menu_settings),
R.drawable.ic_outline_settings_24px,
Intent(context, MainPreferences::class.java),
NavigationDrawerFragment.REQUEST_SETTINGS))
.plus(NavigationDrawerAction(
NavigationDrawerFragment.REQUEST_SETTINGS,
Intent(context, MainPreferences::class.java)
)
)
.plus(
NavigationDrawerAction(
context.getString(R.string.help_and_feedback),
R.drawable.ic_outline_help_outline_24px,
Intent(context, HelpAndFeedback::class.java),
0))
0,
Intent(context, HelpAndFeedback::class.java)
)
)
private suspend fun googleTaskFilter(account: CaldavAccount, showCreate: Boolean): List<FilterListItem> =
listOf(

@ -1,42 +0,0 @@
package org.tasks.filters;
import androidx.room.Embedded;
import com.todoroo.astrid.api.GtasksFilter;
import org.tasks.data.CaldavCalendar;
import java.util.Objects;
public class GoogleTaskFilters {
@Embedded public CaldavCalendar googleTaskList;
public int count;
GtasksFilter toGtasksFilter() {
GtasksFilter filter = new GtasksFilter(googleTaskList);
filter.count = count;
return filter;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof GoogleTaskFilters)) {
return false;
}
GoogleTaskFilters that = (GoogleTaskFilters) o;
return count == that.count && Objects.equals(googleTaskList, that.googleTaskList);
}
@Override
public int hashCode() {
return Objects.hash(googleTaskList, count);
}
@Override
public String toString() {
return "GoogleTaskFilters{" + "googleTaskList=" + googleTaskList + ", count=" + count + '}';
}
}

@ -0,0 +1,16 @@
package org.tasks.filters
import androidx.room.Embedded
import com.todoroo.astrid.api.GtasksFilter
import org.tasks.data.CaldavCalendar
data class GoogleTaskFilters(
@JvmField @Embedded val googleTaskList: CaldavCalendar,
@JvmField val count: Int,
) {
fun toGtasksFilter(): GtasksFilter {
val filter = GtasksFilter(googleTaskList)
filter.count = count
return filter
}
}

@ -1,38 +0,0 @@
package org.tasks.filters;
import androidx.room.Embedded;
import java.util.Objects;
import org.tasks.data.Place;
public class LocationFilters {
@Embedded public Place place;
public int count;
PlaceFilter toLocationFilter() {
PlaceFilter filter = new PlaceFilter(place);
filter.count = count;
return filter;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof LocationFilters)) {
return false;
}
LocationFilters that = (LocationFilters) o;
return count == that.count && Objects.equals(place, that.place);
}
@Override
public int hashCode() {
return Objects.hash(place, count);
}
@Override
public String toString() {
return "LocationFilters{" + "place=" + place + ", count=" + count + '}';
}
}

@ -0,0 +1,15 @@
package org.tasks.filters
import androidx.room.Embedded
import org.tasks.data.Place
data class LocationFilters(
@JvmField @Embedded var place: Place,
@JvmField var count: Int
) {
fun toLocationFilter(): PlaceFilter {
val filter = PlaceFilter(place)
filter.count = count
return filter
}
}

@ -1,71 +0,0 @@
package org.tasks.filters;
import android.content.Intent;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import com.todoroo.astrid.api.FilterListItem;
public class NavigationDrawerAction extends FilterListItem {
/** Parcelable Creator Object */
public static final Parcelable.Creator<NavigationDrawerAction> CREATOR =
new Parcelable.Creator<>() {
/** {@inheritDoc} */
@Override
public NavigationDrawerAction createFromParcel(Parcel source) {
NavigationDrawerAction item = new NavigationDrawerAction();
item.readFromParcel(source);
return item;
}
/** {@inheritDoc} */
@Override
public NavigationDrawerAction[] newArray(int size) {
return new NavigationDrawerAction[size];
}
};
public Intent intent;
public int requestCode;
private NavigationDrawerAction() {}
public NavigationDrawerAction(String listingTitle, int icon, int requestCode) {
this(listingTitle, icon, null, requestCode);
}
public NavigationDrawerAction(String listingTitle, int icon, Intent intent, int requestCode) {
this.listingTitle = listingTitle;
this.icon = icon;
this.intent = intent;
this.requestCode = requestCode;
}
@Override
public Type getItemType() {
return Type.ACTION;
}
/** {@inheritDoc} */
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeParcelable(intent, 0);
dest.writeInt(requestCode);
}
@Override
protected void readFromParcel(Parcel source) {
super.readFromParcel(source);
intent = source.readParcelable(Intent.class.getClassLoader());
requestCode = source.readInt();
}
@Override
public boolean areItemsTheSame(@NonNull FilterListItem other) {
return other instanceof NavigationDrawerAction
&& requestCode == ((NavigationDrawerAction) other).requestCode;
}
}

@ -0,0 +1,21 @@
package org.tasks.filters
import android.content.Intent
import com.todoroo.astrid.api.FilterListItem
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
@Parcelize
data class NavigationDrawerAction(
val listingTitle: String,
val icon: Int,
val requestCode: Int,
val intent: Intent? = null,
) : FilterListItem {
@IgnoredOnParcel
override val itemType = FilterListItem.Type.ACTION
override fun areItemsTheSame(other: FilterListItem) = this == other
override fun areContentsTheSame(other: FilterListItem) = true
}

@ -1,42 +0,0 @@
package org.tasks.filters;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import com.todoroo.astrid.api.FilterListItem;
public class NavigationDrawerSeparator extends FilterListItem {
public static final Parcelable.Creator<NavigationDrawerSeparator> CREATOR =
new Parcelable.Creator<>() {
/** {@inheritDoc} */
@Override
public NavigationDrawerSeparator createFromParcel(Parcel source) {
NavigationDrawerSeparator navigationDrawerSeparator = new NavigationDrawerSeparator();
navigationDrawerSeparator.readFromParcel(source);
return navigationDrawerSeparator;
}
/** {@inheritDoc} */
@Override
public NavigationDrawerSeparator[] newArray(int size) {
return new NavigationDrawerSeparator[size];
}
};
@Override
public Type getItemType() {
return Type.SEPARATOR;
}
@Override
public boolean areItemsTheSame(@NonNull FilterListItem other) {
return other instanceof NavigationDrawerSeparator;
}
@Override
public boolean areContentsTheSame(@NonNull FilterListItem other) {
return true;
}
}

@ -0,0 +1,19 @@
package org.tasks.filters
import com.todoroo.astrid.api.FilterListItem
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
@Parcelize
class NavigationDrawerSeparator : FilterListItem {
@IgnoredOnParcel
override val itemType = FilterListItem.Type.SEPARATOR
override fun areItemsTheSame(other: FilterListItem): Boolean {
return other is NavigationDrawerSeparator
}
override fun areContentsTheSame(other: FilterListItem): Boolean {
return true
}
}

@ -1,157 +0,0 @@
package org.tasks.filters;
import android.content.Intent;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.os.ParcelCompat;
import com.todoroo.astrid.api.FilterListItem;
public class NavigationDrawerSubheader extends FilterListItem {
public static final Parcelable.Creator<NavigationDrawerSubheader> CREATOR =
new Parcelable.Creator<>() {
/** {@inheritDoc} */
@Override
public NavigationDrawerSubheader createFromParcel(Parcel source) {
NavigationDrawerSubheader navigationDrawerSubheader = new NavigationDrawerSubheader();
navigationDrawerSubheader.readFromParcel(source);
return navigationDrawerSubheader;
}
/** {@inheritDoc} */
@Override
public NavigationDrawerSubheader[] newArray(int size) {
return new NavigationDrawerSubheader[size];
}
};
public boolean error;
private boolean collapsed;
private SubheaderType subheaderType;
private long id;
@Nullable
private Intent addIntent;
private int addIntentRc;
private NavigationDrawerSubheader() {}
public NavigationDrawerSubheader(
String listingTitle,
boolean error,
boolean collapsed,
SubheaderType subheaderType,
long id,
int addIntentRc,
@Nullable Intent addIntent
) {
this.error = error;
this.collapsed = collapsed;
this.subheaderType = subheaderType;
this.id = id;
this.addIntent = addIntent;
this.addIntentRc = addIntentRc;
this.listingTitle = listingTitle;
}
public long getId() {
return id;
}
public boolean isCollapsed() {
return collapsed;
}
@Nullable
public Intent getAddIntent() {
return addIntent;
}
public int getAddIntentRc() {
return addIntentRc;
}
public SubheaderType getSubheaderType() {
return subheaderType;
}
@Override
protected void readFromParcel(Parcel source) {
super.readFromParcel(source);
error = ParcelCompat.readBoolean(source);
collapsed = ParcelCompat.readBoolean(source);
subheaderType = (SubheaderType) source.readSerializable();
id = source.readLong();
addIntent = source.readParcelable(getClass().getClassLoader());
addIntentRc = source.readInt();
}
@Override
public boolean areItemsTheSame(@NonNull FilterListItem other) {
return other instanceof NavigationDrawerSubheader
&& subheaderType == ((NavigationDrawerSubheader) other).getSubheaderType()
&& id == other.getId();
}
@Override
public boolean areContentsTheSame(@NonNull FilterListItem other) {
return this.equals(other);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof NavigationDrawerSubheader)) {
return false;
}
NavigationDrawerSubheader that = (NavigationDrawerSubheader) o;
if (error != that.error) {
return false;
}
if (collapsed != that.collapsed) {
return false;
}
if (id != that.id) {
return false;
}
return subheaderType == that.subheaderType;
}
@Override
public int hashCode() {
int result = (error ? 1 : 0);
result = 31 * result + (collapsed ? 1 : 0);
result = 31 * result + (subheaderType != null ? subheaderType.hashCode() : 0);
result = 31 * result + (int) (id ^ (id >>> 32));
return result;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
ParcelCompat.writeBoolean(dest, error);
ParcelCompat.writeBoolean(dest, collapsed);
dest.writeSerializable(subheaderType);
dest.writeLong(id);
dest.writeParcelable(addIntent, 0);
dest.writeInt(addIntentRc);
}
@Override
public Type getItemType() {
return Type.SUBHEADER;
}
public enum SubheaderType {
PREFERENCE,
GOOGLE_TASKS,
CALDAV,
TASKS,
@Deprecated ETESYNC
}
}

@ -0,0 +1,37 @@
package org.tasks.filters
import android.content.Intent
import com.todoroo.astrid.api.FilterListItem
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
@Parcelize
data class NavigationDrawerSubheader(
val listingTitle: String?,
val error: Boolean,
val isCollapsed: Boolean,
val subheaderType: SubheaderType,
val id: Long,
val addIntentRc: Int,
val addIntent: Intent?,
) : FilterListItem {
override fun areItemsTheSame(other: FilterListItem): Boolean {
return other is NavigationDrawerSubheader && subheaderType == other.subheaderType && id == other.id
}
override fun areContentsTheSame(other: FilterListItem): Boolean {
return this == other
}
@IgnoredOnParcel
override val itemType = FilterListItem.Type.SUBHEADER
enum class SubheaderType {
PREFERENCE,
GOOGLE_TASKS,
CALDAV,
TASKS,
@Deprecated("")
ETESYNC
}
}

@ -1,39 +0,0 @@
package org.tasks.filters;
import androidx.room.Embedded;
import com.todoroo.astrid.api.TagFilter;
import java.util.Objects;
import org.tasks.data.TagData;
public class TagFilters {
@Embedded public TagData tagData;
public int count;
TagFilter toTagFilter() {
TagFilter filter = new TagFilter(tagData);
filter.count = count;
return filter;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof TagFilters)) {
return false;
}
TagFilters that = (TagFilters) o;
return count == that.count && Objects.equals(tagData, that.tagData);
}
@Override
public int hashCode() {
return Objects.hash(tagData, count);
}
@Override
public String toString() {
return "TagFilters{" + "tagData=" + tagData + ", count=" + count + '}';
}
}

@ -0,0 +1,16 @@
package org.tasks.filters
import androidx.room.Embedded
import com.todoroo.astrid.api.TagFilter
import org.tasks.data.TagData
data class TagFilters(
@JvmField @Embedded var tagData: TagData,
@JvmField var count: Int,
) {
fun toTagFilter(): TagFilter {
val filter = TagFilter(tagData)
filter.count = count
return filter
}
}

@ -94,7 +94,9 @@ class NavigationDrawerFragment : BottomSheetDialogFragment() {
REQUEST_PURCHASE ->
startActivity(Intent(context, PurchaseActivity::class.java))
REQUEST_DONATE -> context?.openUri(R.string.url_donate)
else -> activity?.startActivityForResult(item.intent, item.requestCode)
else -> item.intent?.let {
activity?.startActivityForResult(it, item.requestCode)
}
}
}
dismiss()

Loading…
Cancel
Save