Create edit fragments off main thread

pull/1051/head
Alex Baker 6 years ago
parent 275369c807
commit 0226440833

@ -4,6 +4,7 @@ import android.content.Context
import com.todoroo.astrid.alarms.AlarmService import com.todoroo.astrid.alarms.AlarmService
import com.todoroo.astrid.dao.Database import com.todoroo.astrid.dao.Database
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.gcal.GCalHelper import com.todoroo.astrid.gcal.GCalHelper
import com.todoroo.astrid.service.TaskCompleter import com.todoroo.astrid.service.TaskCompleter
import com.todoroo.astrid.service.TaskDeleter import com.todoroo.astrid.service.TaskDeleter
@ -14,6 +15,9 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Before import org.junit.Before
import org.tasks.calendars.CalendarEventProvider import org.tasks.calendars.CalendarEventProvider
import org.tasks.data.AlarmDao
import org.tasks.data.LocationDao
import org.tasks.data.TagDataDao
import org.tasks.injection.InjectingTestCase import org.tasks.injection.InjectingTestCase
import org.tasks.location.GeofenceApi import org.tasks.location.GeofenceApi
import org.tasks.preferences.DefaultFilterProvider import org.tasks.preferences.DefaultFilterProvider
@ -33,9 +37,12 @@ open class BaseTaskEditViewModelTest : InjectingTestCase() {
@Inject lateinit var taskMover: TaskMover @Inject lateinit var taskMover: TaskMover
@Inject lateinit var geofenceApi: GeofenceApi @Inject lateinit var geofenceApi: GeofenceApi
@Inject lateinit var preferences: Preferences @Inject lateinit var preferences: Preferences
@Inject lateinit var defaultFilterProvider: DefaultFilterProvider
@Inject lateinit var taskCompleter: TaskCompleter @Inject lateinit var taskCompleter: TaskCompleter
@Inject lateinit var alarmService: AlarmService @Inject lateinit var alarmService: AlarmService
@Inject lateinit var defaultFilterProvider: DefaultFilterProvider
@Inject lateinit var locationDao: LocationDao
@Inject lateinit var tagDataDao: TagDataDao
@Inject lateinit var alarmDao: AlarmDao
protected lateinit var viewModel: TaskEditViewModel protected lateinit var viewModel: TaskEditViewModel
@ -56,14 +63,22 @@ open class BaseTaskEditViewModelTest : InjectingTestCase() {
db.tagDao, db.tagDao,
db.tagDataDao, db.tagDataDao,
preferences, preferences,
defaultFilterProvider,
db.googleTaskDao, db.googleTaskDao,
db.caldavDao, db.caldavDao,
taskCompleter, taskCompleter,
db.alarmDao,
alarmService) alarmService)
} }
protected fun setup(task: Task) = runBlocking {
viewModel.setup(
task,
defaultFilterProvider.getList(task),
locationDao.getLocation(task, preferences),
tagDataDao.getTags(task),
alarmDao.getAlarms(task).map { it.time }.toLongArray()
)
}
protected fun save(): Boolean = runBlocking(Dispatchers.Main) { protected fun save(): Boolean = runBlocking(Dispatchers.Main) {
viewModel.save() viewModel.save()
} }

@ -14,7 +14,7 @@ import org.tasks.makers.TaskMaker
class PriorityTests : BaseTaskEditViewModelTest() { class PriorityTests : BaseTaskEditViewModelTest() {
@Test @Test
fun changePriorityCausesChange() { fun changePriorityCausesChange() {
viewModel.setup(TaskMaker.newTask(MakeItEasy.with(TaskMaker.PRIORITY, Task.Priority.HIGH))) setup(TaskMaker.newTask(MakeItEasy.with(TaskMaker.PRIORITY, Task.Priority.HIGH)))
viewModel.priority = Task.Priority.MEDIUM viewModel.priority = Task.Priority.MEDIUM
@ -24,7 +24,7 @@ class PriorityTests : BaseTaskEditViewModelTest() {
@Test @Test
fun applyPriorityChange() { fun applyPriorityChange() {
val task = TaskMaker.newTask(MakeItEasy.with(TaskMaker.PRIORITY, Task.Priority.HIGH)) val task = TaskMaker.newTask(MakeItEasy.with(TaskMaker.PRIORITY, Task.Priority.HIGH))
viewModel.setup(task) setup(task)
viewModel.priority = Task.Priority.MEDIUM viewModel.priority = Task.Priority.MEDIUM
save() save()
@ -34,7 +34,7 @@ class PriorityTests : BaseTaskEditViewModelTest() {
@Test @Test
fun noChangeWhenRevertingPriority() { fun noChangeWhenRevertingPriority() {
viewModel.setup(TaskMaker.newTask(MakeItEasy.with(TaskMaker.PRIORITY, Task.Priority.HIGH))) setup(TaskMaker.newTask(MakeItEasy.with(TaskMaker.PRIORITY, Task.Priority.HIGH)))
viewModel.priority = Task.Priority.MEDIUM viewModel.priority = Task.Priority.MEDIUM
viewModel.priority = Task.Priority.HIGH viewModel.priority = Task.Priority.HIGH

@ -15,7 +15,7 @@ class ReminderTests : BaseTaskEditViewModelTest() {
@Test @Test
fun whenDueReminder() = runBlocking { fun whenDueReminder() = runBlocking {
val task = newTask() val task = newTask()
viewModel.setup(task) setup(task)
viewModel.whenDue = true viewModel.whenDue = true
@ -27,7 +27,7 @@ class ReminderTests : BaseTaskEditViewModelTest() {
@Test @Test
fun whenOverDueReminder() = runBlocking { fun whenOverDueReminder() = runBlocking {
val task = newTask() val task = newTask()
viewModel.setup(task) setup(task)
viewModel.whenOverdue = true viewModel.whenOverdue = true
@ -39,7 +39,7 @@ class ReminderTests : BaseTaskEditViewModelTest() {
@Test @Test
fun ringFiveTimes() = runBlocking { fun ringFiveTimes() = runBlocking {
val task = newTask() val task = newTask()
viewModel.setup(task) setup(task)
viewModel.ringFiveTimes = true viewModel.ringFiveTimes = true
@ -51,7 +51,7 @@ class ReminderTests : BaseTaskEditViewModelTest() {
@Test @Test
fun ringNonstop() = runBlocking { fun ringNonstop() = runBlocking {
val task = newTask() val task = newTask()
viewModel.setup(task) setup(task)
viewModel.ringNonstop = true viewModel.ringNonstop = true
@ -63,7 +63,7 @@ class ReminderTests : BaseTaskEditViewModelTest() {
@Test @Test
fun ringFiveTimesCantRingNonstop() = runBlocking { fun ringFiveTimesCantRingNonstop() = runBlocking {
val task = newTask() val task = newTask()
viewModel.setup(task) setup(task)
viewModel.ringNonstop = true viewModel.ringNonstop = true
viewModel.ringFiveTimes = true viewModel.ringFiveTimes = true
@ -77,7 +77,7 @@ class ReminderTests : BaseTaskEditViewModelTest() {
@Test @Test
fun ringNonStopCantRingFiveTimes() = runBlocking { fun ringNonStopCantRingFiveTimes() = runBlocking {
val task = newTask() val task = newTask()
viewModel.setup(task) setup(task)
viewModel.ringFiveTimes = true viewModel.ringFiveTimes = true
viewModel.ringNonstop = true viewModel.ringNonstop = true

@ -17,7 +17,7 @@ class RepeatTests : BaseTaskEditViewModelTest() {
@Test @Test
fun changeRepeatAfterCompletion() = runBlocking { fun changeRepeatAfterCompletion() = runBlocking {
val task = newTask(with(TaskMaker.RRULE, RRule("RRULE:FREQ=DAILY;INTERVAL=1"))) val task = newTask(with(TaskMaker.RRULE, RRule("RRULE:FREQ=DAILY;INTERVAL=1")))
viewModel.setup(task) setup(task)
viewModel.repeatAfterCompletion = true viewModel.repeatAfterCompletion = true
@ -32,7 +32,7 @@ class RepeatTests : BaseTaskEditViewModelTest() {
fun removeRepeatAfterCompletion() = runBlocking { fun removeRepeatAfterCompletion() = runBlocking {
val task = newTask() val task = newTask()
task.recurrence = "RRULE:FREQ=DAILY;INTERVAL=1;FROM=COMPLETION" task.recurrence = "RRULE:FREQ=DAILY;INTERVAL=1;FROM=COMPLETION"
viewModel.setup(task) setup(task)
viewModel.repeatAfterCompletion = false viewModel.repeatAfterCompletion = false

@ -15,14 +15,14 @@ import org.tasks.makers.TaskMaker.newTask
class TaskEditViewModelTest : BaseTaskEditViewModelTest() { class TaskEditViewModelTest : BaseTaskEditViewModelTest() {
@Test @Test
fun noChangesForNewTask() { fun noChangesForNewTask() {
viewModel.setup(newTask()) setup(newTask())
assertFalse(viewModel.hasChanges()) assertFalse(viewModel.hasChanges())
} }
@Test @Test
fun dontSaveTaskWithoutChanges() = runBlocking { fun dontSaveTaskWithoutChanges() = runBlocking {
viewModel.setup(newTask()) setup(newTask())
assertFalse(save()) assertFalse(save())
@ -31,7 +31,7 @@ class TaskEditViewModelTest : BaseTaskEditViewModelTest() {
@Test @Test
fun dontSaveTaskTwice() = runBlocking { fun dontSaveTaskTwice() = runBlocking {
viewModel.setup(newTask()) setup(newTask())
viewModel.priority = Task.Priority.HIGH viewModel.priority = Task.Priority.HIGH

@ -17,7 +17,7 @@ import org.tasks.makers.TaskMaker.newTask
class TitleTests : BaseTaskEditViewModelTest() { class TitleTests : BaseTaskEditViewModelTest() {
@Test @Test
fun changeTitleCausesChange() { fun changeTitleCausesChange() {
viewModel.setup(newTask()) setup(newTask())
viewModel.title = "Test" viewModel.title = "Test"
@ -27,7 +27,7 @@ class TitleTests : BaseTaskEditViewModelTest() {
@Test @Test
fun saveWithEmptyTitle() = runBlocking { fun saveWithEmptyTitle() = runBlocking {
val task = newTask() val task = newTask()
viewModel.setup(task) setup(task)
viewModel.priority = HIGH viewModel.priority = HIGH
@ -38,7 +38,7 @@ class TitleTests : BaseTaskEditViewModelTest() {
@Test @Test
fun newTaskPrepopulatedWithTitleHasChanges() { fun newTaskPrepopulatedWithTitleHasChanges() {
viewModel.setup(newTask(with(TaskMaker.TITLE, "some title"))) setup(newTask(with(TaskMaker.TITLE, "some title")))
assertTrue(viewModel.hasChanges()) assertTrue(viewModel.hasChanges())
} }

@ -34,6 +34,7 @@ import org.tasks.LocalBroadcastManager
import org.tasks.R import org.tasks.R
import org.tasks.activities.TagSettingsActivity import org.tasks.activities.TagSettingsActivity
import org.tasks.billing.Inventory import org.tasks.billing.Inventory
import org.tasks.data.AlarmDao
import org.tasks.data.LocationDao import org.tasks.data.LocationDao
import org.tasks.data.Place import org.tasks.data.Place
import org.tasks.data.TagDataDao import org.tasks.data.TagDataDao
@ -73,6 +74,7 @@ class MainActivity : InjectingAppCompatActivity(), TaskListFragmentCallbackHandl
@Inject lateinit var colorProvider: ColorProvider @Inject lateinit var colorProvider: ColorProvider
@Inject lateinit var locationDao: LocationDao @Inject lateinit var locationDao: LocationDao
@Inject lateinit var tagDataDao: TagDataDao @Inject lateinit var tagDataDao: TagDataDao
@Inject lateinit var alarmDao: AlarmDao
private lateinit var navigationDrawer: NavigationDrawerFragment private lateinit var navigationDrawer: NavigationDrawerFragment
private var currentNightMode = 0 private var currentNightMode = 0
@ -315,7 +317,13 @@ class MainActivity : InjectingAppCompatActivity(), TaskListFragmentCallbackHandl
} }
} }
clearUi() clearUi()
val fragment = newTaskEditFragment(task, filterColor) val fragment = newTaskEditFragment(
task,
defaultFilterProvider.getList(task),
locationDao.getLocation(task, preferences),
tagDataDao.getTags(task),
alarmDao.getAlarms(task),
filterColor)
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
.replace(R.id.detail, fragment, TaskEditFragment.TAG_TASKEDIT_FRAGMENT) .replace(R.id.detail, fragment, TaskEditFragment.TAG_TASKEDIT_FRAGMENT)
.addToBackStack(TaskEditFragment.TAG_TASKEDIT_FRAGMENT) .addToBackStack(TaskEditFragment.TAG_TASKEDIT_FRAGMENT)

@ -44,8 +44,7 @@ import org.tasks.Event
import org.tasks.R import org.tasks.R
import org.tasks.Strings.isNullOrEmpty import org.tasks.Strings.isNullOrEmpty
import org.tasks.analytics.Firebase import org.tasks.analytics.Firebase
import org.tasks.data.UserActivity import org.tasks.data.*
import org.tasks.data.UserActivityDao
import org.tasks.databinding.FragmentTaskEditBinding import org.tasks.databinding.FragmentTaskEditBinding
import org.tasks.date.DateTimeUtils.newDateTime import org.tasks.date.DateTimeUtils.newDateTime
import org.tasks.dialogs.DialogBuilder import org.tasks.dialogs.DialogBuilder
@ -82,7 +81,13 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
editViewModel.setup(requireArguments().getParcelable(EXTRA_TASK)!!) val args = requireArguments()
editViewModel.setup(
args.getParcelable(EXTRA_TASK)!!,
args.getParcelable(EXTRA_LIST)!!,
args.getParcelable(EXTRA_LOCATION),
args.getParcelableArrayList(EXTRA_TAGS)!!,
args.getLongArray(EXTRA_ALARMS)!!)
val activity = requireActivity() as MainActivity val activity = requireActivity() as MainActivity
editViewModel.cleared.observe(activity, Observer<Event<Boolean>> { editViewModel.cleared.observe(activity, Observer<Event<Boolean>> {
activity.removeTaskEditFragment() activity.removeTaskEditFragment()
@ -339,12 +344,26 @@ 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 EXTRA_TASK = "extra_task" 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"
private const val EXTRA_THEME = "extra_theme" private const val EXTRA_THEME = "extra_theme"
fun newTaskEditFragment(task: Task, themeColor: ThemeColor?): TaskEditFragment { fun newTaskEditFragment(
task: Task,
list: Filter,
location: Location?,
tags: ArrayList<TagData>,
alarms: ArrayList<Alarm>,
themeColor: ThemeColor?): 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.putLongArray(EXTRA_ALARMS, alarms.map { it.time }.toLongArray())
arguments.putParcelable(EXTRA_THEME, themeColor) arguments.putParcelable(EXTRA_THEME, themeColor)
taskEditFragment.arguments = arguments taskEditFragment.arguments = arguments
return taskEditFragment return taskEditFragment

@ -29,14 +29,13 @@ import kotlinx.collections.immutable.ImmutableSet
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toImmutableSet import kotlinx.collections.immutable.toImmutableSet
import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking
import org.tasks.Event import org.tasks.Event
import org.tasks.R import org.tasks.R
import org.tasks.Strings import org.tasks.Strings
import org.tasks.calendars.CalendarEventProvider import org.tasks.calendars.CalendarEventProvider
import org.tasks.data.* import org.tasks.data.*
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.DateTime import org.tasks.time.DateTime
@ -58,32 +57,25 @@ class TaskEditViewModel @ViewModelInject constructor(
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 defaultFilterProvider: DefaultFilterProvider,
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 alarmDao: AlarmDao,
private val alarmService: AlarmService) : ViewModel() { private val alarmService: AlarmService) : ViewModel() {
val cleared = MutableLiveData<Event<Boolean>>() val cleared = MutableLiveData<Event<Boolean>>()
fun setup(task: Task) { fun setup(
task: Task, list: Filter, location: Location?, tags: List<TagData>, alarms: LongArray) {
this.task = task this.task = task
isNew = task.isNew isNew = task.isNew
runBlocking { originalList = list
val list = async { defaultFilterProvider.getList(task) } originalLocation = location
val location = async { locationDao.getLocation(task, preferences) } originalTags = tags.toImmutableList()
val tags = async { tagDataDao.getTags(task) } originalAlarms = alarms.toList().toImmutableSet()
val alarms = async { alarmDao.getAlarms(task) }
originalList = list.await()
originalLocation = location.await()
originalTags = tags.await().toImmutableList()
originalAlarms = alarms.await().map { it.time }.toImmutableSet()
if (isNew && permissionChecker.canAccessCalendars()) { if (isNew && permissionChecker.canAccessCalendars()) {
originalCalendar = preferences.defaultCalendar originalCalendar = preferences.defaultCalendar
} }
} }
}
var task: Task? = null var task: Task? = null
private set private set

Loading…
Cancel
Save