From 114ec3f03b3e61caca04507540c1b17369cbec55 Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Thu, 20 Apr 2023 15:10:08 -0500 Subject: [PATCH] Convert Task to data class --- .../main/java/com/todoroo/astrid/data/Task.kt | 269 +++--------------- .../java/org/tasks/ui/SubtaskControlSet.kt | 7 +- 2 files changed, 47 insertions(+), 229 deletions(-) diff --git a/app/src/main/java/com/todoroo/astrid/data/Task.kt b/app/src/main/java/com/todoroo/astrid/data/Task.kt index 2b19ede65..c8962e4ef 100644 --- a/app/src/main/java/com/todoroo/astrid/data/Task.kt +++ b/app/src/main/java/com/todoroo/astrid/data/Task.kt @@ -1,15 +1,14 @@ package com.todoroo.astrid.data -import android.content.ContentValues -import android.os.Parcel import android.os.Parcelable import androidx.annotation.IntDef -import androidx.core.os.ParcelCompat import androidx.room.* import com.google.gson.annotations.SerializedName import com.todoroo.andlib.data.Table import com.todoroo.andlib.sql.Field import com.todoroo.andlib.utility.DateUtilities +import kotlinx.parcelize.Parcelize +import kotlinx.parcelize.RawValue import net.fortuna.ical4j.model.Recur import org.tasks.Strings import org.tasks.data.Tag @@ -18,130 +17,67 @@ import org.tasks.date.DateTimeUtils.toDateTime import org.tasks.time.DateTimeUtils.startOfDay import timber.log.Timber +@Parcelize @Entity( tableName = Task.TABLE_NAME, indices = [ Index(name = "t_rid", value = ["remoteId"], unique = true), Index(name = "active_and_visible", value = ["completed", "deleted", "hideUntil"])]) -class Task : Parcelable { - /** ID */ +data class Task( @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "_id") @Transient - var id = NO_ID - - /** Name of Task */ + var id: Long = NO_ID, @ColumnInfo(name = "title") - var title: String? = null - + var title: String? = null, @ColumnInfo(name = "importance") - var priority = Priority.NONE - - /** Unixtime Task is due, 0 if not set */ + var priority: Int = Priority.NONE, @ColumnInfo(name = "dueDate") - var dueDate = 0L - - /** Unixtime Task should be hidden until, 0 if not set */ + var dueDate: Long = 0L, @ColumnInfo(name = "hideUntil") - var hideUntil = 0L - - /** Unixtime Task was created */ + var hideUntil: Long = 0L, @ColumnInfo(name = "created") - var creationDate = 0L - - /** Unixtime Task was last touched */ + var creationDate: Long = 0L, @ColumnInfo(name = "modified") - var modificationDate = 0L - - /** Unixtime Task was completed. 0 means active */ + var modificationDate: Long = 0L, @ColumnInfo(name = "completed") - var completionDate = 0L - - /** Unixtime Task was deleted. 0 means not deleted */ + var completionDate: Long = 0L, @ColumnInfo(name = "deleted") - var deletionDate = 0L - - // --- data access boilerplate + var deletionDate: Long = 0L, @ColumnInfo(name = "notes") - var notes: String? = null - + var notes: String? = null, @ColumnInfo(name = "estimatedSeconds") - var estimatedSeconds = 0 - + var estimatedSeconds: Int = 0, @ColumnInfo(name = "elapsedSeconds") - var elapsedSeconds = 0 - + var elapsedSeconds: Int = 0, @ColumnInfo(name = "timerStart") - var timerStart = 0L - - /** Flags for when to send reminders */ + var timerStart: Long = 0L, @ColumnInfo(name = "notificationFlags") @SerializedName("ringFlags", alternate = ["reminderFlags"]) - var ringFlags = 0 - - /** Unixtime the last reminder was triggered */ + var ringFlags: Int = 0, @ColumnInfo(name = "lastNotified") - var reminderLast = 0L - + var reminderLast: Long = 0L, @ColumnInfo(name = "recurrence") - var recurrence: String? = null - + var recurrence: String? = null, @ColumnInfo(name = "repeat_from", defaultValue = RepeatFrom.DUE_DATE.toString()) - var repeatFrom: Int = RepeatFrom.DUE_DATE - + var repeatFrom: Int = RepeatFrom.DUE_DATE, @ColumnInfo(name = "calendarUri") - var calendarURI: String? = null - - /** Remote id */ + var calendarURI: String? = null, @ColumnInfo(name = "remoteId") - var remoteId: String? = NO_UUID - + var remoteId: String? = NO_UUID, @ColumnInfo(name = "collapsed") - var isCollapsed = false - + var isCollapsed: Boolean = false, @ColumnInfo(name = "parent") @Transient - var parent = 0L - + var parent: Long = 0L, @ColumnInfo(name = "order") - var order: Long? = null - + var order: Long? = null, @ColumnInfo(name = "read_only", defaultValue = "0") - var readOnly: Boolean = false - + var readOnly: Boolean = false, @Ignore @Transient - private var transitoryData: HashMap? = null - - constructor() - - @Ignore - constructor(parcel: Parcel) { - calendarURI = parcel.readString() - completionDate = parcel.readLong() - creationDate = parcel.readLong() - deletionDate = parcel.readLong() - dueDate = parcel.readLong() - elapsedSeconds = parcel.readInt() - estimatedSeconds = parcel.readInt() - hideUntil = parcel.readLong() - id = parcel.readLong() - priority = parcel.readInt() - modificationDate = parcel.readLong() - notes = parcel.readString() - recurrence = parcel.readString() - ringFlags = parcel.readInt() - reminderLast = parcel.readLong() - timerStart = parcel.readLong() - title = parcel.readString() - remoteId = parcel.readString() ?: NO_UUID - transitoryData = parcel.readHashMap(ContentValues::class.java.classLoader) as HashMap? - isCollapsed = ParcelCompat.readBoolean(parcel) - parent = parcel.readLong() - readOnly = ParcelCompat.readBoolean(parcel) - order = parcel.readLong() - } - + private var transitoryData: @RawValue HashMap? = null, +) : Parcelable { var uuid: String get() = if (Strings.isNullOrEmpty(remoteId)) NO_UUID else remoteId!! set(uuid) { @@ -247,36 +183,6 @@ class Task : Parcelable { val isNew: Boolean get() = id == NO_ID - /** {@inheritDoc} */ - override fun describeContents() = 0 - - /** {@inheritDoc} */ - override fun writeToParcel(dest: Parcel, flags: Int) { - dest.writeString(calendarURI) - dest.writeLong(completionDate) - dest.writeLong(creationDate) - dest.writeLong(deletionDate) - dest.writeLong(dueDate) - dest.writeInt(elapsedSeconds) - dest.writeInt(estimatedSeconds) - dest.writeLong(hideUntil) - dest.writeLong(id) - dest.writeInt(priority) - dest.writeLong(modificationDate) - dest.writeString(notes) - dest.writeString(recurrence) - dest.writeInt(ringFlags) - dest.writeLong(reminderLast) - dest.writeLong(timerStart) - dest.writeString(title) - dest.writeString(remoteId) - dest.writeMap(transitoryData as Map<*, *>?) - ParcelCompat.writeBoolean(dest, isCollapsed) - dest.writeLong(parent) - ParcelCompat.writeBoolean(dest, readOnly) - dest.writeLong(order ?: 0) - } - fun insignificantChange(task: Task?): Boolean { if (this === task) { return true @@ -384,11 +290,7 @@ class Task : Parcelable { return transitoryData != null && transitoryData!!.containsKey(key) } - fun getTransitory(key: String?): T? { - return if (transitoryData == null) { - null - } else transitoryData!![key] as T? - } + fun getTransitory(key: String?): T? = transitoryData?.get(key) as T? // --- Convenience wrappers for using transitories as flags fun checkTransitory(flag: String?): Boolean { @@ -396,68 +298,6 @@ class Task : Parcelable { return trans != null } - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is Task) return false - - if (id != other.id) return false - if (title != other.title) return false - if (priority != other.priority) return false - if (dueDate != other.dueDate) return false - if (hideUntil != other.hideUntil) return false - if (creationDate != other.creationDate) return false - if (modificationDate != other.modificationDate) return false - if (completionDate != other.completionDate) return false - if (deletionDate != other.deletionDate) return false - if (notes != other.notes) return false - if (estimatedSeconds != other.estimatedSeconds) return false - if (elapsedSeconds != other.elapsedSeconds) return false - if (timerStart != other.timerStart) return false - if (ringFlags != other.ringFlags) return false - if (reminderLast != other.reminderLast) return false - if (recurrence != other.recurrence) return false - if (calendarURI != other.calendarURI) return false - if (remoteId != other.remoteId) return false - if (isCollapsed != other.isCollapsed) return false - if (parent != other.parent) return false - if (transitoryData != other.transitoryData) return false - if (readOnly != other.readOnly) return false - if (order != other.order) return false - - return true - } - - override fun hashCode(): Int { - var result = id.hashCode() - result = 31 * result + (title?.hashCode() ?: 0) - result = 31 * result + priority - result = 31 * result + dueDate.hashCode() - result = 31 * result + hideUntil.hashCode() - result = 31 * result + creationDate.hashCode() - result = 31 * result + modificationDate.hashCode() - result = 31 * result + completionDate.hashCode() - result = 31 * result + deletionDate.hashCode() - result = 31 * result + (notes?.hashCode() ?: 0) - result = 31 * result + estimatedSeconds - result = 31 * result + elapsedSeconds - result = 31 * result + timerStart.hashCode() - result = 31 * result + ringFlags - result = 31 * result + reminderLast.hashCode() - result = 31 * result + (recurrence?.hashCode() ?: 0) - result = 31 * result + (calendarURI?.hashCode() ?: 0) - result = 31 * result + remoteId.hashCode() - result = 31 * result + isCollapsed.hashCode() - result = 31 * result + parent.hashCode() - result = 31 * result + (transitoryData?.hashCode() ?: 0) - result = 31 * result + readOnly.hashCode() - result = 31 * result + order.hashCode() - return result - } - - override fun toString(): String { - return "Task(id=$id, title=$title, priority=$priority, dueDate=$dueDate, hideUntil=$hideUntil, creationDate=$creationDate, modificationDate=$modificationDate, completionDate=$completionDate, deletionDate=$deletionDate, notes=$notes, estimatedSeconds=$estimatedSeconds, elapsedSeconds=$elapsedSeconds, timerStart=$timerStart, ringFlags=$ringFlags, reminderLast=$reminderLast, recurrence=$recurrence, calendarURI=$calendarURI, remoteId='$remoteId', isCollapsed=$isCollapsed, parent=$parent, transitoryData=$transitoryData, readOnly=$readOnly, order=$order)" - } - @Retention(AnnotationRetention.SOURCE) @IntDef(Priority.HIGH, Priority.MEDIUM, Priority.LOW, Priority.NONE) annotation class Priority { @@ -478,41 +318,32 @@ class Task : Parcelable { } } - fun clone(): Task { - val parcel = Parcel.obtain() - writeToParcel(parcel, 0) - parcel.setDataPosition(0) - val task = Task(parcel) - parcel.recycle() - return task - } - companion object { const val TABLE_NAME = "tasks" // --- table and uri /** table for this model */ - @JvmField val TABLE = Table(TABLE_NAME) - @JvmField val FIELDS = Field.field("$TABLE_NAME.*") + val TABLE = Table(TABLE_NAME) + val FIELDS = Field.field("$TABLE_NAME.*") const val NO_ID: Long = 0 // --- properties @JvmField val ID = TABLE.column("_id") @JvmField val TITLE = TABLE.column("title") - @JvmField val IMPORTANCE = TABLE.column("importance") - @JvmField val DUE_DATE = TABLE.column("dueDate") - @JvmField val HIDE_UNTIL = TABLE.column("hideUntil") + val IMPORTANCE = TABLE.column("importance") + val DUE_DATE = TABLE.column("dueDate") + val HIDE_UNTIL = TABLE.column("hideUntil") @JvmField val MODIFICATION_DATE = TABLE.column("modified") @JvmField val CREATION_DATE = TABLE.column("created") - @JvmField val COMPLETION_DATE = TABLE.column("completed") + val COMPLETION_DATE = TABLE.column("completed") @JvmField val DELETION_DATE = TABLE.column("deleted") - @JvmField val NOTES = TABLE.column("notes") - @JvmField val TIMER_START = TABLE.column("timerStart") - @JvmField val PARENT = TABLE.column("parent") - @JvmField val RECURRENCE = TABLE.column("recurrence") + val NOTES = TABLE.column("notes") + val TIMER_START = TABLE.column("timerStart") + val PARENT = TABLE.column("parent") + val RECURRENCE = TABLE.column("recurrence") /** constant value for no uuid */ const val NO_UUID = "0" // $NON-NLS-1$ - @JvmField val UUID = TABLE.column("remoteId") + val UUID = TABLE.column("remoteId") /** whether to send a reminder at deadline */ const val NOTIFY_AT_DEADLINE = 1 shl 1 @@ -528,16 +359,6 @@ class Task : Parcelable { const val NOTIFY_AT_START = 1 shl 5 - @JvmField val CREATOR: Parcelable.Creator = object : Parcelable.Creator { - override fun createFromParcel(source: Parcel): Task? { - return Task(source) - } - - override fun newArray(size: Int): Array { - return arrayOfNulls(size) - } - } - /** urgency array index -> significance */ const val URGENCY_NONE = 0 const val URGENCY_SPECIFIC_DAY = 7 @@ -574,7 +395,7 @@ class Task : Parcelable { * @param setting one of the URGENCY_* constants * @param customDate if specific day or day & time is set, this value */ - @JvmStatic fun createDueDate(setting: Int, customDate: Long): Long { + fun createDueDate(setting: Int, customDate: Long): Long { val date: Long = when (setting) { URGENCY_NONE -> 0 URGENCY_TODAY -> DateUtilities.now() @@ -605,7 +426,7 @@ class Task : Parcelable { return dueDate > 0 && dueDate % 60000 > 0 } - @JvmStatic fun isValidUuid(uuid: String): Boolean { + fun isValidUuid(uuid: String): Boolean { return try { val value = uuid.toLong() value > 0 @@ -615,14 +436,12 @@ class Task : Parcelable { } } - @JvmStatic fun String?.sanitizeRecur(): String? = this ?.replace("BYDAY=;", "") ?.replace(INVALID_COUNT, "") // ical4j adds COUNT=-1 if there is an UNTIL value - @JvmStatic fun isUuidEmpty(uuid: String?): Boolean { + fun isUuidEmpty(uuid: String?): Boolean { return NO_UUID == uuid || Strings.isNullOrEmpty(uuid) } - } } diff --git a/app/src/main/java/org/tasks/ui/SubtaskControlSet.kt b/app/src/main/java/org/tasks/ui/SubtaskControlSet.kt index 4311f5680..141dfe825 100644 --- a/app/src/main/java/org/tasks/ui/SubtaskControlSet.kt +++ b/app/src/main/java/org/tasks/ui/SubtaskControlSet.kt @@ -68,10 +68,9 @@ class SubtaskControlSet : TaskEditControlFragment() { completeNewSubtask = { viewModel.newSubtasks.value = ArrayList(viewModel.newSubtasks.value).apply { - val modified = it.clone().apply { - completionDate = - if (isCompleted) 0 else now() - } + val modified = it.copy( + completionDate = if (it.isCompleted) 0 else now() + ) set(indexOf(it), modified) } },