diff --git a/app/src/main/java/com/todoroo/astrid/activity/TaskEditFragment.kt b/app/src/main/java/com/todoroo/astrid/activity/TaskEditFragment.kt index 42a4622ac..983103d48 100755 --- a/app/src/main/java/com/todoroo/astrid/activity/TaskEditFragment.kt +++ b/app/src/main/java/com/todoroo/astrid/activity/TaskEditFragment.kt @@ -32,7 +32,6 @@ import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope import com.google.android.material.appbar.AppBarLayout 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.todoroo.andlib.utility.AndroidUtilities import com.todoroo.andlib.utility.DateUtilities @@ -91,26 +90,11 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener { lateinit var binding: FragmentTaskEditBinding 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( - inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { binding = FragmentTaskEditBinding.inflate(inflater) val view: View = binding.root - val model = editViewModel.task!! + val model = editViewModel.task val toolbar = binding.toolbar toolbar.navigationIcon = context.getDrawable(R.drawable.ic_outline_save_24px) toolbar.setNavigationOnClickListener { @@ -161,12 +145,12 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener { title.maxLines = 5 if (model.isNew || preferences.getBoolean(R.string.p_hide_check_button, false)) { binding.fab.visibility = View.INVISIBLE - } else if (editViewModel.completed!!) { + } else if (editViewModel.completed) { title.paintFlags = title.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG binding.fab.setImageResource(R.drawable.ic_outline_check_box_outline_blank_24px) } binding.fab.setOnClickListener { - if (editViewModel.completed!!) { + if (editViewModel.completed) { editViewModel.completed = false title.paintFlags = title.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv() binding.fab.setImageResource(R.drawable.ic_outline_check_box_24px) @@ -177,17 +161,16 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener { } } } - binding.appbarlayout.addOnOffsetChangedListener( - OnOffsetChangedListener { appBarLayout: AppBarLayout, verticalOffset: Int -> - if (verticalOffset == 0) { - title.visibility = View.VISIBLE - binding.collapsingtoolbarlayout.isTitleEnabled = false - } else if (abs(verticalOffset) < appBarLayout.totalScrollRange) { - title.visibility = View.INVISIBLE - binding.collapsingtoolbarlayout.title = title.text - binding.collapsingtoolbarlayout.isTitleEnabled = true - } - }) + binding.appbarlayout.addOnOffsetChangedListener { appBarLayout, verticalOffset -> + if (verticalOffset == 0) { + title.visibility = View.VISIBLE + binding.collapsingtoolbarlayout.isTitleEnabled = false + } else if (abs(verticalOffset) < appBarLayout.totalScrollRange) { + title.visibility = View.INVISIBLE + binding.collapsingtoolbarlayout.title = title.text + binding.collapsingtoolbarlayout.isTitleEnabled = true + } + } if (!model.isNew) { lifecycleScope.launch { notificationManager.cancel(model.id) @@ -233,7 +216,6 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener { .launchIn(viewLifecycleOwner.lifecycleScope) } - @OptIn(ExperimentalAnimationApi::class) private suspend fun process(event: TaskEditEvent) { when (event) { is TaskEditEvent.Discard -> @@ -302,7 +284,7 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener { } suspend fun stopTimer(): Task { - val model = editViewModel.task!! + val model = editViewModel.task timerPlugin.stopTimer(model) val elapsedTime = DateUtils.formatElapsedTime(model.elapsedSeconds.toLong()) addComment(String.format( @@ -316,7 +298,7 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener { } suspend fun startTimer(): Task { - val model = editViewModel.task!! + val model = editViewModel.task timerPlugin.startTimer(model) addComment(String.format( "%s %s", @@ -368,7 +350,7 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener { */ fun addComment(message: String?, picture: Uri?) { - val model = editViewModel.task!! + val model = editViewModel.task val userActivity = UserActivity() if (picture != null) { val output = FileHelper.copyToUri(context, preferences.attachmentsDirectory!!, picture) @@ -388,11 +370,11 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener { companion object { const val TAG_TASKEDIT_FRAGMENT = "taskedit_fragment" private const val FRAG_TAG_COMMENT_BAR = "comment_bar" - private const val EXTRA_TASK = "extra_task" - private const val EXTRA_LIST = "extra_list" - private const val EXTRA_LOCATION = "extra_location" - private const val EXTRA_TAGS = "extra_tags" - private const val EXTRA_ALARMS = "extra_alarms" + const val EXTRA_TASK = "extra_task" + const val EXTRA_LIST = "extra_list" + const val EXTRA_LOCATION = "extra_location" + const val EXTRA_TAGS = "extra_tags" + const val EXTRA_ALARMS = "extra_alarms" fun newTaskEditFragment( task: Task, diff --git a/app/src/main/java/org/tasks/ui/TaskEditViewModel.kt b/app/src/main/java/org/tasks/ui/TaskEditViewModel.kt index 158e707cf..0549b958d 100644 --- a/app/src/main/java/org/tasks/ui/TaskEditViewModel.kt +++ b/app/src/main/java/org/tasks/ui/TaskEditViewModel.kt @@ -2,8 +2,10 @@ package org.tasks.ui import android.content.Context import androidx.annotation.MainThread +import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import com.todoroo.andlib.utility.DateUtilities.now +import com.todoroo.astrid.activity.TaskEditFragment import com.todoroo.astrid.alarms.AlarmService import com.todoroo.astrid.api.CaldavFilter import com.todoroo.astrid.api.Filter @@ -31,12 +33,8 @@ import org.tasks.Strings import org.tasks.analytics.Firebase import org.tasks.calendars.CalendarEventProvider 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_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.location.GeofenceApi import org.tasks.preferences.PermissionChecker @@ -48,7 +46,8 @@ import javax.inject.Inject @HiltViewModel class TaskEditViewModel @Inject constructor( - @ApplicationContext private val context: Context, + @ApplicationContext context: Context, + savedStateHandle: SavedStateHandle, private val taskDao: TaskDao, private val taskDeleter: TaskDeleter, private val timerPlugin: TimerPlugin, @@ -60,7 +59,7 @@ class TaskEditViewModel @Inject constructor( private val geofenceApi: GeofenceApi, private val tagDao: TagDao, private val tagDataDao: TagDataDao, - private val preferences: Preferences, + preferences: Preferences, private val googleTaskDao: GoogleTaskDao, private val caldavDao: CaldavDao, private val taskCompleter: TaskCompleter, @@ -69,76 +68,29 @@ class TaskEditViewModel @Inject constructor( private val mainActivityEvents: MainActivityEventBus, private val firebase: Firebase? = null, ) : ViewModel() { - + private val resources = context.resources private var cleared = false - fun setup( - task: Task, - list: Filter, - location: Location?, - tags: List, - alarms: List, - ) { - 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().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 task: Task = savedStateHandle[TaskEditFragment.EXTRA_TASK]!! + + val isNew = task.isNew + + var creationDate: Long = task.creationDate + 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()) - val dueDate = MutableStateFlow(0L) + val dueDate = MutableStateFlow(task.dueDate) fun setDueDate(value: Long) { dueDate.value = when { @@ -148,12 +100,7 @@ class TaskEditViewModel @Inject constructor( } } - var priority = MutableStateFlow(Task.Priority.NONE) - - var description: String? = null - get() = field ?: task.notes.stripCarriageReturns() - - val startDate = MutableStateFlow(0L) + val startDate = MutableStateFlow(task.hideUntil) fun setStartDate(value: Long) { startDate.value = when { @@ -164,62 +111,56 @@ class TaskEditViewModel @Inject constructor( } } - val recurrence = MutableStateFlow(null) - val repeatAfterCompletion = MutableStateFlow(false) - - private var originalCalendar: String? = null - private set(value) { - field = value - selectedCalendar.value = value - } - - var selectedCalendar = MutableStateFlow(null) - - var eventUri = MutableStateFlow(null) - - var isNew: Boolean = false - private set + private var originalCalendar: String? = if (isNew && permissionChecker.canAccessCalendars()) { + preferences.defaultCalendar + } else { + null + } + var selectedCalendar = MutableStateFlow(originalCalendar) - val timerStarted = MutableStateFlow(0L) - val estimatedSeconds = MutableStateFlow(0) - val elapsedSeconds = MutableStateFlow(0) + private val originalList: Filter = savedStateHandle[TaskEditFragment.EXTRA_LIST]!! + var selectedList = MutableStateFlow(originalList) - 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 = + savedStateHandle.get>(TaskEditFragment.EXTRA_TAGS) ?: emptyList() + val selectedTags = MutableStateFlow(ArrayList(originalTags)) - var originalLocation: Location? = null - private set(value) { - field = value - selectedLocation.value = value + private val originalAlarms: List = if (isNew) { + ArrayList().apply { + if (task.isNotifyAtStart) { + 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(null) - - private lateinit var originalTags: List - - val selectedTags = MutableStateFlow(ArrayList()) - - var newSubtasks = MutableStateFlow(emptyList()) - - private lateinit var originalAlarms: List - - var selectedAlarms = MutableStateFlow(emptyList()) + var selectedAlarms = MutableStateFlow(originalAlarms) - var ringNonstop: Boolean? = null - get() = field ?: task.isNotifyModeNonstop + var ringNonstop: Boolean = task.isNotifyModeNonstop set(value) { field = value - if (value == true) { + if (value) { ringFiveTimes = false } } - var ringFiveTimes:Boolean? = null - get() = field ?: task.isNotifyModeFive + var ringFiveTimes:Boolean = task.isNotifyModeFive set(value) { field = value - if (value == true) { + if (value) { ringNonstop = false } } @@ -270,7 +211,7 @@ class TaskEditViewModel @Inject constructor( return@withContext false } 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.priority = priority.value task.notes = description @@ -287,15 +228,13 @@ class TaskEditViewModel @Inject constructor( applyCalendarChanges() - val isNew = task.isNew - if (isNew) { taskDao.createNew(task) } if (isNew || originalList != selectedList.value) { 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) { @@ -370,8 +309,8 @@ class TaskEditViewModel @Inject constructor( task.modificationDate = now() } - if (task.isCompleted != completed!!) { - taskCompleter.setComplete(task, completed!!) + if (task.isCompleted != completed) { + taskCompleter.setComplete(task, completed) } if (isNew) { @@ -405,8 +344,8 @@ class TaskEditViewModel @Inject constructor( } private fun getRingFlags() = when { - ringNonstop == true -> NOTIFY_MODE_NONSTOP - ringFiveTimes == true -> NOTIFY_MODE_FIVE + ringNonstop -> NOTIFY_MODE_NONSTOP + ringFiveTimes -> NOTIFY_MODE_FIVE else -> 0 } @@ -416,7 +355,7 @@ class TaskEditViewModel @Inject constructor( } suspend fun discard(remove: Boolean = true) { - if (task.isNew) { + if (isNew) { timerPlugin.stopTimer(task) } clear(remove) @@ -444,4 +383,4 @@ class TaskEditViewModel @Inject constructor( companion object { fun String?.stripCarriageReturns(): String? = this?.replace("\\r\\n?".toRegex(), "\n") } -} \ No newline at end of file +}