Add navigation drawer view model

pull/1964/head
Alex Baker 2 years ago
parent c2e87a86fa
commit 9a33f54202

@ -140,7 +140,7 @@ class MainActivity : InjectingAppCompatActivity(), TaskListFragmentCallbackHandl
private fun clearUi() {
finishActionMode()
navigationDrawer?.closeDrawer()
navigationDrawer?.dismiss()
}
private suspend fun getTaskToLoad(filter: Filter?): Task? {

@ -6,7 +6,6 @@
package com.todoroo.astrid.adapter
import android.app.Activity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
@ -48,14 +47,6 @@ class NavigationDrawerAdapter @Inject constructor(
this.onClick = onClick
}
fun save(outState: Bundle) {
outState.putParcelable(TOKEN_SELECTED, selected)
}
fun restore(savedInstanceState: Bundle) {
selected = savedInstanceState.getParcelable(TOKEN_SELECTED)
}
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
super.dispose()
}
@ -117,10 +108,6 @@ class NavigationDrawerAdapter @Inject constructor(
old[oldPosition].areContentsTheSame(new[newPosition])
}
companion object {
private const val TOKEN_SELECTED = "token_selected"
}
override fun onChanged(position: Int, count: Int, payload: Any?) =
notifyItemRangeChanged(position, count, payload)

@ -16,7 +16,7 @@ import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.PermaSql
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.timers.TimerPlugin
import dagger.hilt.android.qualifiers.ActivityContext
import dagger.hilt.android.qualifiers.ApplicationContext
import org.tasks.R
import org.tasks.data.*
import org.tasks.data.TaskDao.TaskCriteria.activeAndVisible
@ -34,7 +34,7 @@ import javax.inject.Inject
* @author Tim Su <tim></tim>@todoroo.com>
*/
class BuiltInFilterExposer @Inject constructor(
@param:ActivityContext private val context: Context,
@param:ApplicationContext private val context: Context,
private val preferences: Preferences,
private val taskDao: TaskDao) {

@ -7,7 +7,7 @@ import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.FilterListItem
import com.todoroo.astrid.api.FilterListItem.NO_ORDER
import com.todoroo.astrid.core.BuiltInFilterExposer
import dagger.hilt.android.qualifiers.ActivityContext
import dagger.hilt.android.qualifiers.ApplicationContext
import org.tasks.BuildConfig
import org.tasks.R
import org.tasks.activities.GoogleTaskListSettingsActivity
@ -28,7 +28,7 @@ import org.tasks.ui.NavigationDrawerFragment
import javax.inject.Inject
class FilterProvider @Inject constructor(
@param:ActivityContext private val context: Context,
@param:ApplicationContext private val context: Context,
private val inventory: Inventory,
private val builtInFilterExposer: BuiltInFilterExposer,
private val filterDao: FilterDao,

@ -1,9 +1,6 @@
package org.tasks.ui
import android.app.Activity
import android.app.Dialog
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.os.Bundle
@ -11,6 +8,9 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
@ -22,13 +22,11 @@ import com.todoroo.astrid.adapter.NavigationDrawerAdapter
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.FilterListItem
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import org.tasks.LocalBroadcastManager
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.tasks.R
import org.tasks.billing.PurchaseActivity
import org.tasks.data.TaskDao
import org.tasks.extensions.Context.openUri
import org.tasks.filters.FilterProvider
import org.tasks.filters.NavigationDrawerAction
import org.tasks.intents.TaskIntents
import org.tasks.preferences.Preferences
@ -36,32 +34,26 @@ import javax.inject.Inject
@AndroidEntryPoint
class NavigationDrawerFragment : BottomSheetDialogFragment() {
private val refreshReceiver = RefreshReceiver()
@Inject lateinit var localBroadcastManager: LocalBroadcastManager
@Inject lateinit var adapter: NavigationDrawerAdapter
@Inject lateinit var filterProvider: FilterProvider
@Inject lateinit var taskDao: TaskDao
@Inject lateinit var preferences: Preferences
override fun getTheme() = R.style.CustomBottomSheetDialog
private lateinit var recyclerView: RecyclerView
private val viewModel: NavigationDrawerViewModel by activityViewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState != null) {
adapter.restore(savedInstanceState)
}
arguments?.getParcelable<Filter>(EXTRA_SELECTED)?.let {
adapter.setSelected(it)
viewModel.setSelected(it)
}
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
dialog.setOnShowListener {
val bottomSheet = dialog.findViewById<FrameLayout>(com.google.android.material.R.id.design_bottom_sheet)
val bottomSheet =
dialog.findViewById<FrameLayout>(com.google.android.material.R.id.design_bottom_sheet)
val behavior = BottomSheetBehavior.from(bottomSheet!!)
behavior.skipCollapsed = true
if (preferences.isTopAppBar) {
@ -73,28 +65,29 @@ class NavigationDrawerFragment : BottomSheetDialogFragment() {
return dialog
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
requireActivity().setDefaultKeyMode(Activity.DEFAULT_KEYS_SEARCH_LOCAL)
setUpList()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
val layout = inflater.inflate(R.layout.fragment_navigation_drawer, container, false)
recyclerView = layout.findViewById(R.id.recycler_view)
(recyclerView.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
return layout
}
private fun setUpList() {
adapter.setOnClick { item: FilterListItem? -> onFilterItemSelected(item) }
adapter.setOnClick(this::onFilterItemSelected)
recyclerView.layoutManager = LinearLayoutManager(context)
recyclerView.adapter = adapter
viewModel
.viewState
.flowWithLifecycle(lifecycle, Lifecycle.State.RESUMED)
.onEach {
adapter.setSelected(it.selected)
adapter.submitList(it.filters)
}
.launchIn(lifecycleScope)
return layout
}
private fun onFilterItemSelected(item: FilterListItem?) {
if (item is Filter) {
viewModel.setSelected(item)
activity?.startActivity(TaskIntents.getTaskListIntent(activity, item))
} else if (item is NavigationDrawerAction) {
when (item.requestCode) {
@ -104,52 +97,9 @@ class NavigationDrawerFragment : BottomSheetDialogFragment() {
else -> activity?.startActivityForResult(item.intent, item.requestCode)
}
}
closeDrawer()
}
override fun onPause() {
super.onPause()
localBroadcastManager.unregisterReceiver(refreshReceiver)
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
adapter.save(outState)
}
fun closeDrawer() {
dismiss()
}
override fun onResume() {
super.onResume()
localBroadcastManager.registerRefreshListReceiver(refreshReceiver)
updateFilters()
}
private fun updateFilters() = lifecycleScope.launch {
filterProvider
.navDrawerItems()
.onEach {
if (it is Filter && it.count == -1) {
it.count = taskDao.count(it)
}
}
.let { adapter.submitList(it) }
}
private inner class RefreshReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) {
if (intent == null) {
return
}
val action = intent.action
if (LocalBroadcastManager.REFRESH == action || LocalBroadcastManager.REFRESH_LIST == action) {
updateFilters()
}
}
}
companion object {
const val REQUEST_NEW_LIST = 10100
const val REQUEST_SETTINGS = 10101

@ -0,0 +1,68 @@
package org.tasks.ui
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.FilterListItem
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.tasks.LocalBroadcastManager
import org.tasks.data.TaskDao
import org.tasks.filters.FilterProvider
import javax.inject.Inject
@HiltViewModel
class NavigationDrawerViewModel @Inject constructor(
private val filterProvider: FilterProvider,
private val taskDao: TaskDao,
private val localBroadcastManager: LocalBroadcastManager,
) : ViewModel() {
data class ViewState(
val selected: Filter? = null,
val filters: List<FilterListItem> = emptyList(),
)
private val _viewState = MutableStateFlow(ViewState())
private val refreshReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
when (intent?.action) {
LocalBroadcastManager.REFRESH,
LocalBroadcastManager.REFRESH_LIST -> updateFilters()
}
}
}
val viewState: StateFlow<ViewState>
get() = _viewState.asStateFlow()
fun setSelected(filter: Filter?) {
_viewState.update { it.copy(selected = filter) }
}
fun updateFilters() = viewModelScope.launch {
filterProvider
.navDrawerItems()
.onEach {
if (it is Filter && it.count == -1) {
it.count = taskDao.count(it)
}
}
.let { filters -> _viewState.update { it.copy(filters = filters) } }
}
override fun onCleared() {
localBroadcastManager.unregisterReceiver(refreshReceiver)
}
init {
localBroadcastManager.registerRefreshListReceiver(refreshReceiver)
updateFilters()
}
}
Loading…
Cancel
Save