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,17 +161,16 @@ 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 } else if (abs(verticalOffset) < appBarLayout.totalScrollRange) {
} else if (abs(verticalOffset) < appBarLayout.totalScrollRange) { title.visibility = View.INVISIBLE
title.visibility = View.INVISIBLE 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, val isNew = task.isNew
location: Location?,
tags: List<TagData>, var creationDate: Long = task.creationDate
alarms: List<Alarm>, var modificationDate: Long = task.modificationDate
) { var completionDate: Long = task.completionDate
this.task = task var title: String? = task.title
dueDate.value = task.dueDate var completed: Boolean = task.isCompleted
startDate.value = task.hideUntil var priority = MutableStateFlow(task.priority)
isNew = task.isNew var description: String? = task.notes.stripCarriageReturns()
originalList = list val recurrence = MutableStateFlow(task.recurrence)
selectedList.value = list val repeatAfterCompletion = MutableStateFlow(task.repeatAfterCompletion())
originalLocation = location var eventUri = MutableStateFlow(task.calendarURI)
originalTags = tags.toList() val timerStarted = MutableStateFlow(task.timerStart)
selectedTags.value = ArrayList(tags) val estimatedSeconds = MutableStateFlow(task.estimatedSeconds)
originalAlarms = val elapsedSeconds = MutableStateFlow(task.elapsedSeconds)
if (isNew) { var newSubtasks = MutableStateFlow(emptyList<Task>())
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
get() = field ?: task.completionDate
var title: String? = null
get() = field ?: task.title
var completed: Boolean? = null
get() = field ?: task.isCompleted
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 var selectedCalendar = MutableStateFlow(originalCalendar)
selectedCalendar.value = value
}
var selectedCalendar = MutableStateFlow<String?>(null)
var eventUri = MutableStateFlow<String?>(null)
var isNew: Boolean = false
private set
val timerStarted = MutableStateFlow(0L) private val originalList: Filter = savedStateHandle[TaskEditFragment.EXTRA_LIST]!!
val estimatedSeconds = MutableStateFlow(0) var selectedList = MutableStateFlow(originalList)
val elapsedSeconds = MutableStateFlow(0)
private lateinit var originalList: Filter private var originalLocation: Location? = savedStateHandle[TaskEditFragment.EXTRA_LOCATION]
var selectedLocation = MutableStateFlow(originalLocation)
var selectedList = MutableStateFlow(null as Filter?) private val originalTags: List<TagData> =
savedStateHandle.get<ArrayList<TagData>>(TaskEditFragment.EXTRA_TAGS) ?: emptyList()
val selectedTags = MutableStateFlow(ArrayList(originalTags))
var originalLocation: Location? = null private val originalAlarms: List<Alarm> = if (isNew) {
private set(value) { ArrayList<Alarm>().apply {
field = value if (task.isNotifyAtStart) {
selectedLocation.value = value add(Alarm.whenStarted(0))
}
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)
@ -444,4 +383,4 @@ class TaskEditViewModel @Inject constructor(
companion object { companion object {
fun String?.stripCarriageReturns(): String? = this?.replace("\\r\\n?".toRegex(), "\n") fun String?.stripCarriageReturns(): String? = this?.replace("\\r\\n?".toRegex(), "\n")
} }
} }

Loading…
Cancel
Save