Load initial data in task edit view model

pull/2803/head
Alex Baker 2 months ago
parent 3448808c94
commit b2efb42d55

@ -52,10 +52,6 @@ open class BaseTaskEditViewModelTest : InjectingTestCase() {
context, context,
SavedStateHandle().apply { SavedStateHandle().apply {
set(TaskEditFragment.EXTRA_TASK, task) set(TaskEditFragment.EXTRA_TASK, task)
set(TaskEditFragment.EXTRA_LIST, defaultFilterProvider.getList(task))
set(TaskEditFragment.EXTRA_LOCATION, locationDao.getLocation(task, preferences))
set(TaskEditFragment.EXTRA_TAGS, tagDataDao.getTags(task))
set(TaskEditFragment.EXTRA_ALARMS, alarmDao.getAlarms(task))
}, },
taskDao, taskDao,
taskDeleter, taskDeleter,
@ -78,6 +74,7 @@ open class BaseTaskEditViewModelTest : InjectingTestCase() {
userActivityDao = userActivityDao, userActivityDao = userActivityDao,
taskAttachmentDao = db.taskAttachmentDao, taskAttachmentDao = db.taskAttachmentDao,
alarmDao = db.alarmDao, alarmDao = db.alarmDao,
defaultFilterProvider = defaultFilterProvider,
) )
} }

@ -28,7 +28,6 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
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.astrid.activity.TaskEditFragment.Companion.newTaskEditFragment
import com.todoroo.astrid.adapter.SubheaderClickHandler import com.todoroo.astrid.adapter.SubheaderClickHandler
import com.todoroo.astrid.api.Filter import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
@ -36,14 +35,11 @@ import com.todoroo.astrid.data.Task
import com.todoroo.astrid.service.TaskCreator import com.todoroo.astrid.service.TaskCreator
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.tasks.BuildConfig import org.tasks.BuildConfig
import org.tasks.R import org.tasks.R
import org.tasks.Tasks.Companion.IS_GENERIC import org.tasks.Tasks.Companion.IS_GENERIC
@ -426,25 +422,10 @@ class MainActivity : AppCompatActivity() {
} }
} }
private suspend fun newTaskEditFragment(task: Task): TaskEditFragment { private fun newTaskEditFragment(task: Task): TaskEditFragment {
AndroidUtilities.assertMainThread() AndroidUtilities.assertMainThread()
clearUi() clearUi()
return coroutineScope { return TaskEditFragment.newTaskEditFragment(task)
withContext(Dispatchers.Default) {
val freshTask = async { if (task.isNew) task else taskDao.fetch(task.id) ?: task }
val list = async { defaultFilterProvider.getList(task) }
val location = async { locationDao.getLocation(task, preferences) }
val tags = async { tagDataDao.getTags(task) }
val alarms = async { alarmDao.getAlarms(task) }
newTaskEditFragment(
freshTask.await(),
list.await(),
location.await(),
tags.await(),
alarms.await(),
)
}
}
} }
private val isSinglePaneLayout: Boolean private val isSinglePaneLayout: Boolean

@ -44,7 +44,6 @@ 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.composethemeadapter.MdcTheme import com.google.android.material.composethemeadapter.MdcTheme
import com.todoroo.andlib.utility.DateUtilities import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task import com.todoroo.astrid.data.Task
import com.todoroo.astrid.files.FilesControlSet import com.todoroo.astrid.files.FilesControlSet
@ -70,9 +69,6 @@ import org.tasks.compose.edit.DueDateRow
import org.tasks.compose.edit.InfoRow import org.tasks.compose.edit.InfoRow
import org.tasks.compose.edit.ListRow import org.tasks.compose.edit.ListRow
import org.tasks.compose.edit.PriorityRow import org.tasks.compose.edit.PriorityRow
import org.tasks.data.Alarm
import org.tasks.data.Location
import org.tasks.data.TagData
import org.tasks.data.UserActivityDao import org.tasks.data.UserActivityDao
import org.tasks.databinding.FragmentTaskEditBinding import org.tasks.databinding.FragmentTaskEditBinding
import org.tasks.databinding.TaskEditCalendarBinding import org.tasks.databinding.TaskEditCalendarBinding
@ -519,10 +515,6 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {
companion object { companion object {
const val EXTRA_TASK = "extra_task" 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"
private const val FRAG_TAG_GOOGLE_TASK_LIST_SELECTION = private const val FRAG_TAG_GOOGLE_TASK_LIST_SELECTION =
"frag_tag_google_task_list_selection" "frag_tag_google_task_list_selection"
@ -540,18 +532,10 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {
fun newTaskEditFragment( fun newTaskEditFragment(
task: Task, task: Task,
list: Filter,
location: Location?,
tags: ArrayList<TagData>,
alarms: ArrayList<Alarm>,
): TaskEditFragment { ): TaskEditFragment {
val taskEditFragment = TaskEditFragment() val taskEditFragment = TaskEditFragment()
val arguments = Bundle() val arguments = Bundle()
arguments.putParcelable(EXTRA_TASK, task) arguments.putParcelable(EXTRA_TASK, task)
arguments.putParcelable(EXTRA_LIST, list)
arguments.putParcelable(EXTRA_LOCATION, location)
arguments.putParcelableArrayList(EXTRA_TAGS, tags)
arguments.putParcelableArrayList(EXTRA_ALARMS, alarms)
taskEditFragment.arguments = arguments taskEditFragment.arguments = arguments
return taskEditFragment return taskEditFragment
} }

@ -2,13 +2,15 @@ package org.tasks.compose.edit
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
@ -23,10 +25,15 @@ import com.google.accompanist.permissions.PermissionStatus
import com.google.android.material.composethemeadapter.MdcTheme import com.google.android.material.composethemeadapter.MdcTheme
import com.todoroo.astrid.ui.ReminderControlSetViewModel import com.todoroo.astrid.ui.ReminderControlSetViewModel
import org.tasks.R import org.tasks.R
import org.tasks.compose.* import org.tasks.compose.AddAlarmDialog
import org.tasks.compose.AddReminderDialog
import org.tasks.compose.ClearButton
import org.tasks.compose.DisabledText
import org.tasks.compose.TaskEditRow
import org.tasks.compose.collectAsStateLifecycleAware
import org.tasks.data.Alarm import org.tasks.data.Alarm
import org.tasks.reminders.AlarmToString import org.tasks.reminders.AlarmToString
import java.util.* import java.util.Locale
@OptIn(ExperimentalPermissionsApi::class, ExperimentalComposeUiApi::class) @OptIn(ExperimentalPermissionsApi::class, ExperimentalComposeUiApi::class)
@Composable @Composable
@ -144,11 +151,7 @@ fun Alarms(
text = stringResource(id = R.string.add_reminder), text = stringResource(id = R.string.add_reminder),
modifier = Modifier modifier = Modifier
.padding(vertical = 12.dp) .padding(vertical = 12.dp)
.clickable( .clickable(onClick = addAlarm)
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(bounded = false),
onClick = addAlarm,
)
) )
Spacer(modifier = Modifier.weight(1f)) Spacer(modifier = Modifier.weight(1f))
if (alarms.isNotEmpty()) { if (alarms.isNotEmpty()) {
@ -165,11 +168,7 @@ fun Alarms(
), ),
modifier = Modifier modifier = Modifier
.padding(vertical = 12.dp, horizontal = 16.dp) .padding(vertical = 12.dp, horizontal = 16.dp)
.clickable( .clickable(onClick = openRingType)
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(bounded = false),
onClick = openRingType
)
) )
} }
} }

@ -58,6 +58,7 @@ import org.tasks.data.UserActivityDao
import org.tasks.date.DateTimeUtils.toDateTime import org.tasks.date.DateTimeUtils.toDateTime
import org.tasks.files.FileHelper import org.tasks.files.FileHelper
import org.tasks.location.GeofenceApi import org.tasks.location.GeofenceApi
import org.tasks.preferences.DefaultFilterProvider
import org.tasks.preferences.PermissionChecker import org.tasks.preferences.PermissionChecker
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import org.tasks.time.DateTimeUtils.currentTimeMillis import org.tasks.time.DateTimeUtils.currentTimeMillis
@ -67,32 +68,33 @@ import javax.inject.Inject
@HiltViewModel @HiltViewModel
class TaskEditViewModel @Inject constructor( class TaskEditViewModel @Inject constructor(
@ApplicationContext private val context: Context, @ApplicationContext private val applicationContext: Context,
savedStateHandle: SavedStateHandle, 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,
private val permissionChecker: PermissionChecker, private val permissionChecker: PermissionChecker,
private val calendarEventProvider: CalendarEventProvider, private val calendarEventProvider: CalendarEventProvider,
private val gCalHelper: GCalHelper, private val gCalHelper: GCalHelper,
private val taskMover: TaskMover, private val taskMover: TaskMover,
private val locationDao: LocationDao, private val locationDao: LocationDao,
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, private val 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,
private val alarmService: AlarmService, private val alarmService: AlarmService,
private val taskListEvents: TaskListEventBus, private val taskListEvents: TaskListEventBus,
private val mainActivityEvents: MainActivityEventBus, private val mainActivityEvents: MainActivityEventBus,
private val firebase: Firebase? = null, private val firebase: Firebase? = null,
private val userActivityDao: UserActivityDao, private val userActivityDao: UserActivityDao,
private val alarmDao: AlarmDao, private val alarmDao: AlarmDao,
private val taskAttachmentDao: TaskAttachmentDao, private val taskAttachmentDao: TaskAttachmentDao,
private val defaultFilterProvider: DefaultFilterProvider,
) : ViewModel() { ) : ViewModel() {
private val resources = context.resources private val resources = applicationContext.resources
private var cleared = false private var cleared = false
val task: Task = savedStateHandle[TaskEditFragment.EXTRA_TASK]!! val task: Task = savedStateHandle[TaskEditFragment.EXTRA_TASK]!!
@ -144,18 +146,19 @@ class TaskEditViewModel @Inject constructor(
} }
var selectedCalendar = MutableStateFlow(originalCalendar) var selectedCalendar = MutableStateFlow(originalCalendar)
val originalList: Filter = savedStateHandle[TaskEditFragment.EXTRA_LIST]!! val originalList: Filter = runBlocking { defaultFilterProvider.getList(task) }
var selectedList = MutableStateFlow(originalList) var selectedList = MutableStateFlow(originalList)
private var originalLocation: Location? = savedStateHandle[TaskEditFragment.EXTRA_LOCATION] private val originalLocation: Location? =
runBlocking { locationDao.getLocation(task, preferences) }
var selectedLocation = MutableStateFlow(originalLocation) var selectedLocation = MutableStateFlow(originalLocation)
private val originalTags: List<TagData> = private val originalTags: List<TagData> = runBlocking { tagDataDao.getTags(task) }
savedStateHandle.get<ArrayList<TagData>>(TaskEditFragment.EXTRA_TAGS) ?: emptyList()
val selectedTags = MutableStateFlow(ArrayList(originalTags)) val selectedTags = MutableStateFlow(ArrayList(originalTags))
private lateinit var originalAttachments: List<TaskAttachment> private val originalAttachments: List<TaskAttachment> =
val selectedAttachments = MutableStateFlow(emptyList<TaskAttachment>()) runBlocking { taskAttachmentDao.getAttachments(task.id) }
val selectedAttachments = MutableStateFlow(originalAttachments)
private val originalAlarms: List<Alarm> = if (isNew) { private val originalAlarms: List<Alarm> = if (isNew) {
ArrayList<Alarm>().apply { ArrayList<Alarm>().apply {
@ -173,9 +176,8 @@ class TaskEditViewModel @Inject constructor(
} }
} }
} else { } else {
savedStateHandle[TaskEditFragment.EXTRA_ALARMS]!! runBlocking { alarmDao.getAlarms(task) }
} }
var selectedAlarms = MutableStateFlow(originalAlarms) var selectedAlarms = MutableStateFlow(originalAlarms)
var ringNonstop: Boolean = task.isNotifyModeNonstop var ringNonstop: Boolean = task.isNotifyModeNonstop
@ -226,8 +228,7 @@ class TaskEditViewModel @Inject constructor(
originalList != selectedList.value || originalList != selectedList.value ||
originalLocation != selectedLocation.value || originalLocation != selectedLocation.value ||
originalTags.toHashSet() != selectedTags.value.toHashSet() || originalTags.toHashSet() != selectedTags.value.toHashSet() ||
(::originalAttachments.isInitialized && originalAttachments.toHashSet() != selectedAttachments.value.toHashSet() ||
originalAttachments.toHashSet() != selectedAttachments.value.toHashSet()) ||
newSubtasks.value.isNotEmpty() || newSubtasks.value.isNotEmpty() ||
getRingFlags() != when { getRingFlags() != when {
task.isNotifyModeFive -> NOTIFY_MODE_FIVE task.isNotifyModeFive -> NOTIFY_MODE_FIVE
@ -362,10 +363,7 @@ class TaskEditViewModel @Inject constructor(
task.modificationDate = now() task.modificationDate = now()
} }
if ( if (selectedAttachments.value.toHashSet() != originalAttachments.toHashSet()) {
this@TaskEditViewModel::originalAttachments.isInitialized &&
selectedAttachments.value.toHashSet() != originalAttachments.toHashSet()
) {
originalAttachments originalAttachments
.minus(selectedAttachments.value.toSet()) .minus(selectedAttachments.value.toSet())
.map { it.remoteId } .map { it.remoteId }
@ -430,7 +428,7 @@ class TaskEditViewModel @Inject constructor(
if (isNew) { if (isNew) {
timerPlugin.stopTimer(task) timerPlugin.stopTimer(task)
originalAttachments.plus(selectedAttachments.value).toSet().takeIf { it.isNotEmpty() } originalAttachments.plus(selectedAttachments.value).toSet().takeIf { it.isNotEmpty() }
?.onEach { FileHelper.delete(context, it.uri.toUri()) } ?.onEach { FileHelper.delete(applicationContext, it.uri.toUri()) }
?.let { taskAttachmentDao.delete(it.toList()) } ?.let { taskAttachmentDao.delete(it.toList()) }
} }
clear(remove) clear(remove)
@ -470,7 +468,7 @@ class TaskEditViewModel @Inject constructor(
fun addComment(message: String?, picture: Uri?) { fun addComment(message: String?, picture: Uri?) {
val userActivity = UserActivity() val userActivity = UserActivity()
if (picture != null) { if (picture != null) {
val output = FileHelper.copyToUri(context, preferences.attachmentsDirectory!!, picture) val output = FileHelper.copyToUri(applicationContext, preferences.attachmentsDirectory!!, picture)
userActivity.setPicture(output) userActivity.setPicture(output)
} }
userActivity.message = message userActivity.message = message
@ -483,15 +481,6 @@ class TaskEditViewModel @Inject constructor(
} }
} }
init {
viewModelScope.launch {
taskAttachmentDao.getAttachments(task.id).let { attachments ->
selectedAttachments.update { attachments }
originalAttachments = attachments
}
}
}
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