Simplify task edit view model

pull/1952/head
Alex Baker 3 years ago
parent 9c8e897f3a
commit c532abc87f

@ -32,7 +32,6 @@ import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.appbar.AppBarLayout.Behavior.DragCallback import com.google.android.material.appbar.AppBarLayout.Behavior.DragCallback
import com.google.android.material.appbar.AppBarLayout.OnOffsetChangedListener
import com.google.android.material.composethemeadapter.MdcTheme import com.google.android.material.composethemeadapter.MdcTheme
import com.todoroo.andlib.utility.AndroidUtilities import com.todoroo.andlib.utility.AndroidUtilities
import com.todoroo.andlib.utility.DateUtilities import com.todoroo.andlib.utility.DateUtilities
@ -91,26 +90,11 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {
lateinit var binding: FragmentTaskEditBinding lateinit var binding: FragmentTaskEditBinding
private var showKeyboard = false private var showKeyboard = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
val args = requireArguments()
editViewModel.setup(
args.getParcelable(EXTRA_TASK)!!,
args.getParcelable(EXTRA_LIST)!!,
args.getParcelable(EXTRA_LOCATION),
args.getParcelableArrayList(EXTRA_TAGS)!!,
args.getParcelableArrayList(EXTRA_ALARMS)!!
)
}
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = FragmentTaskEditBinding.inflate(inflater) binding = FragmentTaskEditBinding.inflate(inflater)
val view: View = binding.root val view: View = binding.root
val model = editViewModel.task!! val model = editViewModel.task
val toolbar = binding.toolbar val toolbar = binding.toolbar
toolbar.navigationIcon = context.getDrawable(R.drawable.ic_outline_save_24px) toolbar.navigationIcon = context.getDrawable(R.drawable.ic_outline_save_24px)
toolbar.setNavigationOnClickListener { toolbar.setNavigationOnClickListener {
@ -161,12 +145,12 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {
title.maxLines = 5 title.maxLines = 5
if (model.isNew || preferences.getBoolean(R.string.p_hide_check_button, false)) { if (model.isNew || preferences.getBoolean(R.string.p_hide_check_button, false)) {
binding.fab.visibility = View.INVISIBLE binding.fab.visibility = View.INVISIBLE
} else if (editViewModel.completed!!) { } else if (editViewModel.completed) {
title.paintFlags = title.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG title.paintFlags = title.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
binding.fab.setImageResource(R.drawable.ic_outline_check_box_outline_blank_24px) binding.fab.setImageResource(R.drawable.ic_outline_check_box_outline_blank_24px)
} }
binding.fab.setOnClickListener { binding.fab.setOnClickListener {
if (editViewModel.completed!!) { if (editViewModel.completed) {
editViewModel.completed = false editViewModel.completed = false
title.paintFlags = title.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv() title.paintFlags = title.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
binding.fab.setImageResource(R.drawable.ic_outline_check_box_24px) binding.fab.setImageResource(R.drawable.ic_outline_check_box_24px)
@ -177,8 +161,7 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {
} }
} }
} }
binding.appbarlayout.addOnOffsetChangedListener( binding.appbarlayout.addOnOffsetChangedListener { appBarLayout, verticalOffset ->
OnOffsetChangedListener { appBarLayout: AppBarLayout, verticalOffset: Int ->
if (verticalOffset == 0) { if (verticalOffset == 0) {
title.visibility = View.VISIBLE title.visibility = View.VISIBLE
binding.collapsingtoolbarlayout.isTitleEnabled = false binding.collapsingtoolbarlayout.isTitleEnabled = false
@ -187,7 +170,7 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {
binding.collapsingtoolbarlayout.title = title.text binding.collapsingtoolbarlayout.title = title.text
binding.collapsingtoolbarlayout.isTitleEnabled = true binding.collapsingtoolbarlayout.isTitleEnabled = true
} }
}) }
if (!model.isNew) { if (!model.isNew) {
lifecycleScope.launch { lifecycleScope.launch {
notificationManager.cancel(model.id) notificationManager.cancel(model.id)
@ -233,7 +216,6 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {
.launchIn(viewLifecycleOwner.lifecycleScope) .launchIn(viewLifecycleOwner.lifecycleScope)
} }
@OptIn(ExperimentalAnimationApi::class)
private suspend fun process(event: TaskEditEvent) { private suspend fun process(event: TaskEditEvent) {
when (event) { when (event) {
is TaskEditEvent.Discard -> is TaskEditEvent.Discard ->
@ -302,7 +284,7 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {
} }
suspend fun stopTimer(): Task { suspend fun stopTimer(): Task {
val model = editViewModel.task!! val model = editViewModel.task
timerPlugin.stopTimer(model) timerPlugin.stopTimer(model)
val elapsedTime = DateUtils.formatElapsedTime(model.elapsedSeconds.toLong()) val elapsedTime = DateUtils.formatElapsedTime(model.elapsedSeconds.toLong())
addComment(String.format( addComment(String.format(
@ -316,7 +298,7 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {
} }
suspend fun startTimer(): Task { suspend fun startTimer(): Task {
val model = editViewModel.task!! val model = editViewModel.task
timerPlugin.startTimer(model) timerPlugin.startTimer(model)
addComment(String.format( addComment(String.format(
"%s %s", "%s %s",
@ -368,7 +350,7 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {
*/ */
fun addComment(message: String?, picture: Uri?) { fun addComment(message: String?, picture: Uri?) {
val model = editViewModel.task!! val model = editViewModel.task
val userActivity = UserActivity() val userActivity = UserActivity()
if (picture != null) { if (picture != null) {
val output = FileHelper.copyToUri(context, preferences.attachmentsDirectory!!, picture) val output = FileHelper.copyToUri(context, preferences.attachmentsDirectory!!, picture)
@ -388,11 +370,11 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {
companion object { companion object {
const val TAG_TASKEDIT_FRAGMENT = "taskedit_fragment" const val TAG_TASKEDIT_FRAGMENT = "taskedit_fragment"
private const val FRAG_TAG_COMMENT_BAR = "comment_bar" private const val FRAG_TAG_COMMENT_BAR = "comment_bar"
private const val EXTRA_TASK = "extra_task" const val EXTRA_TASK = "extra_task"
private const val EXTRA_LIST = "extra_list" const val EXTRA_LIST = "extra_list"
private const val EXTRA_LOCATION = "extra_location" const val EXTRA_LOCATION = "extra_location"
private const val EXTRA_TAGS = "extra_tags" const val EXTRA_TAGS = "extra_tags"
private const val EXTRA_ALARMS = "extra_alarms" const val EXTRA_ALARMS = "extra_alarms"
fun newTaskEditFragment( fun newTaskEditFragment(
task: Task, task: Task,

@ -2,8 +2,10 @@ package org.tasks.ui
import android.content.Context import android.content.Context
import androidx.annotation.MainThread import androidx.annotation.MainThread
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import com.todoroo.andlib.utility.DateUtilities.now import com.todoroo.andlib.utility.DateUtilities.now
import com.todoroo.astrid.activity.TaskEditFragment
import com.todoroo.astrid.alarms.AlarmService import com.todoroo.astrid.alarms.AlarmService
import com.todoroo.astrid.api.CaldavFilter import com.todoroo.astrid.api.CaldavFilter
import com.todoroo.astrid.api.Filter import com.todoroo.astrid.api.Filter
@ -31,12 +33,8 @@ import org.tasks.Strings
import org.tasks.analytics.Firebase import org.tasks.analytics.Firebase
import org.tasks.calendars.CalendarEventProvider import org.tasks.calendars.CalendarEventProvider
import org.tasks.data.* import org.tasks.data.*
import org.tasks.data.Alarm.Companion.TYPE_RANDOM
import org.tasks.data.Alarm.Companion.TYPE_REL_END import org.tasks.data.Alarm.Companion.TYPE_REL_END
import org.tasks.data.Alarm.Companion.TYPE_REL_START import org.tasks.data.Alarm.Companion.TYPE_REL_START
import org.tasks.data.Alarm.Companion.whenDue
import org.tasks.data.Alarm.Companion.whenOverdue
import org.tasks.data.Alarm.Companion.whenStarted
import org.tasks.date.DateTimeUtils.toDateTime import org.tasks.date.DateTimeUtils.toDateTime
import org.tasks.location.GeofenceApi import org.tasks.location.GeofenceApi
import org.tasks.preferences.PermissionChecker import org.tasks.preferences.PermissionChecker
@ -48,7 +46,8 @@ import javax.inject.Inject
@HiltViewModel @HiltViewModel
class TaskEditViewModel @Inject constructor( class TaskEditViewModel @Inject constructor(
@ApplicationContext private val context: Context, @ApplicationContext context: Context,
savedStateHandle: SavedStateHandle,
private val taskDao: TaskDao, private val taskDao: TaskDao,
private val taskDeleter: TaskDeleter, private val taskDeleter: TaskDeleter,
private val timerPlugin: TimerPlugin, private val timerPlugin: TimerPlugin,
@ -60,7 +59,7 @@ class TaskEditViewModel @Inject constructor(
private val geofenceApi: GeofenceApi, private val geofenceApi: GeofenceApi,
private val tagDao: TagDao, private val tagDao: TagDao,
private val tagDataDao: TagDataDao, private val tagDataDao: TagDataDao,
private val preferences: Preferences, preferences: Preferences,
private val googleTaskDao: GoogleTaskDao, private val googleTaskDao: GoogleTaskDao,
private val caldavDao: CaldavDao, private val caldavDao: CaldavDao,
private val taskCompleter: TaskCompleter, private val taskCompleter: TaskCompleter,
@ -69,76 +68,29 @@ class TaskEditViewModel @Inject constructor(
private val mainActivityEvents: MainActivityEventBus, private val mainActivityEvents: MainActivityEventBus,
private val firebase: Firebase? = null, private val firebase: Firebase? = null,
) : ViewModel() { ) : ViewModel() {
private val resources = context.resources
private var cleared = false private var cleared = false
fun setup( val task: Task = savedStateHandle[TaskEditFragment.EXTRA_TASK]!!
task: Task,
list: Filter,
location: Location?,
tags: List<TagData>,
alarms: List<Alarm>,
) {
this.task = task
dueDate.value = task.dueDate
startDate.value = task.hideUntil
isNew = task.isNew
originalList = list
selectedList.value = list
originalLocation = location
originalTags = tags.toList()
selectedTags.value = ArrayList(tags)
originalAlarms =
if (isNew) {
ArrayList<Alarm>().apply {
if (task.isNotifyAtStart) {
add(whenStarted(0))
}
if (task.isNotifyAtDeadline) {
add(whenDue(0))
}
if (task.isNotifyAfterDeadline) {
add(whenOverdue(0))
}
if (task.randomReminder > 0) {
add(Alarm(0, task.randomReminder, TYPE_RANDOM))
}
}
} else {
alarms
}
selectedAlarms.value = originalAlarms
if (isNew && permissionChecker.canAccessCalendars()) {
originalCalendar = preferences.defaultCalendar
}
eventUri.value = task.calendarURI
priority.value = task.priority
elapsedSeconds.value = task.elapsedSeconds
estimatedSeconds.value = task.estimatedSeconds
timerStarted.value = task.timerStart
recurrence.value = task.recurrence
repeatAfterCompletion.value = task.repeatAfterCompletion()
}
lateinit var task: Task
private set
var creationDate: Long? = null
get() = field ?: task.creationDate
var modificationDate: Long? = null
get() = field ?: task.modificationDate
var completionDate: Long? = null val isNew = task.isNew
get() = field ?: task.completionDate
var title: String? = null
get() = field ?: task.title
var completed: Boolean? = null var creationDate: Long = task.creationDate
get() = field ?: task.isCompleted var modificationDate: Long = task.modificationDate
var completionDate: Long = task.completionDate
var title: String? = task.title
var completed: Boolean = task.isCompleted
var priority = MutableStateFlow(task.priority)
var description: String? = task.notes.stripCarriageReturns()
val recurrence = MutableStateFlow(task.recurrence)
val repeatAfterCompletion = MutableStateFlow(task.repeatAfterCompletion())
var eventUri = MutableStateFlow(task.calendarURI)
val timerStarted = MutableStateFlow(task.timerStart)
val estimatedSeconds = MutableStateFlow(task.estimatedSeconds)
val elapsedSeconds = MutableStateFlow(task.elapsedSeconds)
var newSubtasks = MutableStateFlow(emptyList<Task>())
val dueDate = MutableStateFlow(0L) val dueDate = MutableStateFlow(task.dueDate)
fun setDueDate(value: Long) { fun setDueDate(value: Long) {
dueDate.value = when { dueDate.value = when {
@ -148,12 +100,7 @@ class TaskEditViewModel @Inject constructor(
} }
} }
var priority = MutableStateFlow(Task.Priority.NONE) val startDate = MutableStateFlow(task.hideUntil)
var description: String? = null
get() = field ?: task.notes.stripCarriageReturns()
val startDate = MutableStateFlow(0L)
fun setStartDate(value: Long) { fun setStartDate(value: Long) {
startDate.value = when { startDate.value = when {
@ -164,62 +111,56 @@ class TaskEditViewModel @Inject constructor(
} }
} }
val recurrence = MutableStateFlow<String?>(null) private var originalCalendar: String? = if (isNew && permissionChecker.canAccessCalendars()) {
val repeatAfterCompletion = MutableStateFlow(false) preferences.defaultCalendar
} else {
private var originalCalendar: String? = null null
private set(value) {
field = value
selectedCalendar.value = value
} }
var selectedCalendar = MutableStateFlow(originalCalendar)
var selectedCalendar = MutableStateFlow<String?>(null) private val originalList: Filter = savedStateHandle[TaskEditFragment.EXTRA_LIST]!!
var selectedList = MutableStateFlow(originalList)
var eventUri = MutableStateFlow<String?>(null)
var isNew: Boolean = false
private set
val timerStarted = MutableStateFlow(0L) private var originalLocation: Location? = savedStateHandle[TaskEditFragment.EXTRA_LOCATION]
val estimatedSeconds = MutableStateFlow(0) var selectedLocation = MutableStateFlow(originalLocation)
val elapsedSeconds = MutableStateFlow(0)
private lateinit var originalList: Filter private val originalTags: List<TagData> =
savedStateHandle.get<ArrayList<TagData>>(TaskEditFragment.EXTRA_TAGS) ?: emptyList()
val selectedTags = MutableStateFlow(ArrayList(originalTags))
var selectedList = MutableStateFlow(null as Filter?) private val originalAlarms: List<Alarm> = if (isNew) {
ArrayList<Alarm>().apply {
var originalLocation: Location? = null if (task.isNotifyAtStart) {
private set(value) { add(Alarm.whenStarted(0))
field = value }
selectedLocation.value = value if (task.isNotifyAtDeadline) {
add(Alarm.whenDue(0))
}
if (task.isNotifyAfterDeadline) {
add(Alarm.whenOverdue(0))
}
if (task.randomReminder > 0) {
add(Alarm(0, task.randomReminder, Alarm.TYPE_RANDOM))
}
}
} else {
savedStateHandle[TaskEditFragment.EXTRA_ALARMS]!!
} }
var selectedLocation = MutableStateFlow<Location?>(null) var selectedAlarms = MutableStateFlow(originalAlarms)
private lateinit var originalTags: List<TagData>
val selectedTags = MutableStateFlow(ArrayList<TagData>())
var newSubtasks = MutableStateFlow(emptyList<Task>())
private lateinit var originalAlarms: List<Alarm>
var selectedAlarms = MutableStateFlow(emptyList<Alarm>())
var ringNonstop: Boolean? = null var ringNonstop: Boolean = task.isNotifyModeNonstop
get() = field ?: task.isNotifyModeNonstop
set(value) { set(value) {
field = value field = value
if (value == true) { if (value) {
ringFiveTimes = false ringFiveTimes = false
} }
} }
var ringFiveTimes:Boolean? = null var ringFiveTimes:Boolean = task.isNotifyModeFive
get() = field ?: task.isNotifyModeFive
set(value) { set(value) {
field = value field = value
if (value == true) { if (value) {
ringNonstop = false ringNonstop = false
} }
} }
@ -270,7 +211,7 @@ class TaskEditViewModel @Inject constructor(
return@withContext false return@withContext false
} }
clear(remove) clear(remove)
task.title = if (title.isNullOrBlank()) context.getString(R.string.no_title) else title task.title = if (title.isNullOrBlank()) resources.getString(R.string.no_title) else title
task.dueDate = dueDate.value task.dueDate = dueDate.value
task.priority = priority.value task.priority = priority.value
task.notes = description task.notes = description
@ -287,15 +228,13 @@ class TaskEditViewModel @Inject constructor(
applyCalendarChanges() applyCalendarChanges()
val isNew = task.isNew
if (isNew) { if (isNew) {
taskDao.createNew(task) taskDao.createNew(task)
} }
if (isNew || originalList != selectedList.value) { if (isNew || originalList != selectedList.value) {
task.parent = 0 task.parent = 0
taskMover.move(listOf(task.id), selectedList.value!!) taskMover.move(listOf(task.id), selectedList.value)
} }
if ((isNew && selectedLocation.value != null) || originalLocation != selectedLocation.value) { if ((isNew && selectedLocation.value != null) || originalLocation != selectedLocation.value) {
@ -370,8 +309,8 @@ class TaskEditViewModel @Inject constructor(
task.modificationDate = now() task.modificationDate = now()
} }
if (task.isCompleted != completed!!) { if (task.isCompleted != completed) {
taskCompleter.setComplete(task, completed!!) taskCompleter.setComplete(task, completed)
} }
if (isNew) { if (isNew) {
@ -405,8 +344,8 @@ class TaskEditViewModel @Inject constructor(
} }
private fun getRingFlags() = when { private fun getRingFlags() = when {
ringNonstop == true -> NOTIFY_MODE_NONSTOP ringNonstop -> NOTIFY_MODE_NONSTOP
ringFiveTimes == true -> NOTIFY_MODE_FIVE ringFiveTimes -> NOTIFY_MODE_FIVE
else -> 0 else -> 0
} }
@ -416,7 +355,7 @@ class TaskEditViewModel @Inject constructor(
} }
suspend fun discard(remove: Boolean = true) { suspend fun discard(remove: Boolean = true) {
if (task.isNew) { if (isNew) {
timerPlugin.stopTimer(task) timerPlugin.stopTimer(task)
} }
clear(remove) clear(remove)

Loading…
Cancel
Save