Add MainActivity and TaskList event buses

pull/1817/head
Alex Baker 2 years ago
parent 51609e54a9
commit ce191d3325

@ -13,7 +13,9 @@ import android.os.Bundle
import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.appcompat.view.ActionMode
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.todoroo.andlib.utility.AndroidUtilities
import com.todoroo.astrid.activity.TaskEditFragment.Companion.newTaskEditFragment
import com.todoroo.astrid.activity.TaskListFragment.TaskListFragmentCallbackHandler
@ -23,7 +25,12 @@ import com.todoroo.astrid.data.Task
import com.todoroo.astrid.service.TaskCreator
import com.todoroo.astrid.timers.TimerControlSet.TimerControlSetCallback
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.tasks.BuildConfig
import org.tasks.LocalBroadcastManager
import org.tasks.R
@ -49,6 +56,8 @@ import org.tasks.themes.ThemeColor
import org.tasks.ui.DeadlineControlSet.DueDateChangeListener
import org.tasks.ui.EmptyTaskEditFragment.Companion.newEmptyTaskEditFragment
import org.tasks.ui.ListFragment.OnListChanged
import org.tasks.ui.MainActivityEventBus
import org.tasks.ui.MainActivityEvent
import org.tasks.ui.NavigationDrawerFragment
import org.tasks.ui.NavigationDrawerFragment.Companion.newNavigationDrawer
import timber.log.Timber
@ -67,6 +76,7 @@ class MainActivity : InjectingAppCompatActivity(), TaskListFragmentCallbackHandl
@Inject lateinit var locationDao: LocationDao
@Inject lateinit var tagDataDao: TagDataDao
@Inject lateinit var alarmDao: AlarmDao
@Inject lateinit var eventBus: MainActivityEventBus
private var currentNightMode = 0
private var currentPro = false
@ -88,6 +98,17 @@ class MainActivity : InjectingAppCompatActivity(), TaskListFragmentCallbackHandl
applyTheme()
}
handleIntent()
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
eventBus.collect(this@MainActivity::process)
}
}
}
private suspend fun process(event: MainActivityEvent) = when (event) {
is MainActivityEvent.OpenTask ->
onTaskListItemClicked(event.task)
}
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
@ -377,7 +398,7 @@ class MainActivity : InjectingAppCompatActivity(), TaskListFragmentCallbackHandl
finish()
}
val taskListFragment: TaskListFragment?
private val taskListFragment: TaskListFragment?
get() = supportFragmentManager.findFragmentByTag(FRAG_TAG_TASK_LIST) as TaskListFragment?
val taskEditFragment: TaskEditFragment?

@ -50,7 +50,6 @@ import org.tasks.databinding.FragmentTaskEditBinding
import org.tasks.date.DateTimeUtils.newDateTime
import org.tasks.dialogs.DialogBuilder
import org.tasks.dialogs.Linkify
import org.tasks.extensions.Context.openUri
import org.tasks.files.FileHelper
import org.tasks.fragments.TaskEditControlSetFragmentManager
import org.tasks.markdown.MarkdownProvider
@ -265,22 +264,7 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {
return model
}
/** Save task model from values in UI components */
suspend fun save() = withContext(NonCancellable) {
val tlf = (activity as MainActivity?)?.taskListFragment
val saved = editViewModel.save()
if (saved && editViewModel.isNew) {
tlf?.let { taskListFragment ->
val model = editViewModel.task!!
taskListFragment.onTaskCreated(model.uuid)
if (!isNullOrEmpty(model.calendarURI)) {
taskListFragment.makeSnackbar(R.string.calendar_event_created, model.title)
?.setAction(R.string.action_open) { context.openUri(model.calendarURI) }
?.show()
}
}
}
}
suspend fun save() = editViewModel.save()
/*
* ======================================================================

@ -30,7 +30,9 @@ import androidx.core.view.isVisible
import androidx.core.view.setMargins
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.paging.PagedList
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
@ -67,6 +69,7 @@ import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Job
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.tasks.LocalBroadcastManager
@ -88,6 +91,7 @@ import org.tasks.db.SuspendDbUtils.chunkedMap
import org.tasks.dialogs.DateTimePicker.Companion.newDateTimePicker
import org.tasks.dialogs.DialogBuilder
import org.tasks.dialogs.SortDialog
import org.tasks.extensions.Context.openUri
import org.tasks.extensions.Context.toast
import org.tasks.extensions.Fragment.safeStartActivityForResult
import org.tasks.extensions.setOnQueryTextListener
@ -106,6 +110,8 @@ import org.tasks.tasklist.TaskViewHolder
import org.tasks.tasklist.ViewHolderFactory
import org.tasks.themes.ColorProvider
import org.tasks.themes.ThemeColor
import org.tasks.ui.TaskListEventBus
import org.tasks.ui.TaskListEvent
import org.tasks.ui.TaskListViewModel
import java.time.format.FormatStyle
import javax.inject.Inject
@ -141,6 +147,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
@Inject lateinit var locale: Locale
@Inject lateinit var firebase: Firebase
@Inject lateinit var repeatTaskHelper: RepeatTaskHelper
@Inject lateinit var eventBus: TaskListEventBus
private lateinit var swipeRefreshLayout: SwipeRefreshLayout
private lateinit var emptyRefreshLayout: SwipeRefreshLayout
@ -159,6 +166,15 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
private lateinit var callbacks: TaskListFragmentCallbackHandler
private lateinit var binding: FragmentTaskListBinding
private fun process(event: TaskListEvent) = when (event) {
is TaskListEvent.TaskCreated ->
onTaskCreated(event.uuid)
is TaskListEvent.CalendarEventCreated ->
makeSnackbar(R.string.calendar_event_created, event.title)
?.setAction(R.string.action_open) { context?.openUri(event.uri) }
?.show()
}
override fun onRefresh() {
syncAdapters.sync(true)
lifecycleScope.launch {
@ -263,6 +279,13 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
toolbar.setOnMenuItemClickListener(this)
toolbar.setNavigationOnClickListener { callbacks.onNavigationIconClicked() }
setupMenu(toolbar)
lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
eventBus.collect(this@TaskListFragment::process)
}
}
return binding.root
}
@ -500,7 +523,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
refresh()
}
fun makeSnackbar(@StringRes res: Int, vararg args: Any?): Snackbar? {
private fun makeSnackbar(@StringRes res: Int, vararg args: Any?): Snackbar? {
return makeSnackbar(getString(res, *args))
}

@ -0,0 +1,28 @@
package org.tasks.injection
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityRetainedComponent
import dagger.hilt.android.scopes.ActivityRetainedScoped
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.MutableSharedFlow
import org.tasks.ui.MainActivityEventBus
import org.tasks.ui.TaskListEventBus
@Module
@InstallIn(ActivityRetainedComponent::class)
class ActivityRetainedModule {
@Provides
@ActivityRetainedScoped
fun getTaskListBus(): TaskListEventBus = makeFlow()
@Provides
@ActivityRetainedScoped
fun getMainActivityBus(): MainActivityEventBus = makeFlow()
private fun <T> makeFlow() = MutableSharedFlow<T>(
extraBufferCapacity = 1,
onBufferOverflow = BufferOverflow.DROP_OLDEST
)
}

@ -0,0 +1,11 @@
package org.tasks.ui
import com.todoroo.astrid.data.Task
import kotlinx.coroutines.flow.MutableSharedFlow
typealias MainActivityEventBus = MutableSharedFlow<MainActivityEvent>
sealed interface MainActivityEvent {
data class OpenTask(val task: Task) : MainActivityEvent
}

@ -24,7 +24,6 @@ import com.todoroo.andlib.sql.Criterion
import com.todoroo.andlib.sql.Join
import com.todoroo.andlib.sql.QueryTemplate
import com.todoroo.andlib.utility.DateUtilities.now
import com.todoroo.astrid.activity.MainActivity
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.dao.TaskDao
@ -60,6 +59,7 @@ class SubtaskControlSet : TaskEditControlFragment(), SubtaskViewHolder.Callbacks
@Inject lateinit var locale: Locale
@Inject lateinit var checkBoxProvider: CheckBoxProvider
@Inject lateinit var chipProvider: ChipProvider
@Inject lateinit var eventBus: MainActivityEventBus
private val listViewModel: TaskListViewModel by viewModels()
private val refreshReceiver = RefreshReceiver()
@ -197,7 +197,9 @@ class SubtaskControlSet : TaskEditControlFragment(), SubtaskViewHolder.Callbacks
}
override fun openSubtask(task: Task) {
(activity as MainActivity).taskListFragment?.onTaskListItemClicked(task)
lifecycleScope.launch {
eventBus.emit(MainActivityEvent.OpenTask(task))
}
}
override fun toggleSubtask(taskId: Long, collapsed: Boolean) {

@ -28,6 +28,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import net.fortuna.ical4j.model.Recur
import org.tasks.Event
import org.tasks.R
@ -79,7 +80,8 @@ class TaskEditViewModel @Inject constructor(
private val googleTaskDao: GoogleTaskDao,
private val caldavDao: CaldavDao,
private val taskCompleter: TaskCompleter,
private val alarmService: AlarmService
private val alarmService: AlarmService,
private val taskListEvents: TaskListEventBus,
) : ViewModel() {
val cleared = MutableLiveData<Event<Boolean>>()
@ -320,13 +322,13 @@ class TaskEditViewModel @Inject constructor(
fun cleared() = cleared.value?.value == true
@MainThread
suspend fun save(): Boolean {
suspend fun save() = withContext(NonCancellable) {
if (cleared()) {
return false
return@withContext
}
if (!hasChanges()) {
discard()
return false
return@withContext
}
clear()
task.title = if (title.isNullOrBlank()) context.getString(R.string.no_title) else title
@ -428,7 +430,13 @@ class TaskEditViewModel @Inject constructor(
taskCompleter.setComplete(task, completed!!)
}
return true
if (isNew) {
val model = task
taskListEvents.emit(TaskListEvent.TaskCreated(model.uuid))
model.calendarURI?.takeIf { it.isNotBlank() }?.let {
taskListEvents.emit(TaskListEvent.CalendarEventCreated(model.title, it))
}
}
}
private suspend fun applyCalendarChanges() {
@ -478,7 +486,7 @@ class TaskEditViewModel @Inject constructor(
override fun onCleared() {
cleared.value.let {
if (it == null || !it.value) {
runBlocking(NonCancellable) {
runBlocking {
save()
}
}

@ -0,0 +1,10 @@
package org.tasks.ui
import kotlinx.coroutines.flow.MutableSharedFlow
typealias TaskListEventBus = MutableSharedFlow<TaskListEvent>
sealed interface TaskListEvent {
data class TaskCreated(val uuid: String) : TaskListEvent
data class CalendarEventCreated(val title: String?, val uri: String) : TaskListEvent
}
Loading…
Cancel
Save