Skip to content

Commit

Permalink
Use lifecycle-runtime-compose
Browse files Browse the repository at this point in the history
  • Loading branch information
abaker committed Jun 18, 2024
1 parent 12c7170 commit 01a788b
Show file tree
Hide file tree
Showing 25 changed files with 135 additions and 100 deletions.
3 changes: 2 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ dependencies {

implementation(libs.androidx.fragment.ktx)
implementation(libs.androidx.lifecycle.runtime)
implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.androidx.lifecycle.viewmodel)
implementation(libs.androidx.room)
implementation(libs.androidx.sqlite)
Expand All @@ -201,7 +202,7 @@ dependencies {
debugImplementation(libs.kotlin.reflect)

implementation(libs.kotlin.jdk8)
implementation(libs.kotlin.immutable)
implementation(libs.kotlinx.immutable)
implementation(libs.kotlinx.serialization)
implementation(libs.okhttp)
implementation(libs.persistent.cookiejar)
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/todoroo/astrid/activity/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode
import androidx.core.content.IntentCompat.getParcelableExtra
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
Expand All @@ -38,7 +39,6 @@ import org.tasks.activities.TagSettingsActivity
import org.tasks.analytics.Firebase
import org.tasks.billing.Inventory
import org.tasks.caldav.BaseCaldavCalendarSettingsActivity
import org.tasks.compose.collectAsStateLifecycleAware
import org.tasks.compose.drawer.TasksMenu
import org.tasks.data.dao.AlarmDao
import org.tasks.data.dao.CaldavDao
Expand Down Expand Up @@ -105,7 +105,7 @@ class MainActivity : AppCompatActivity() {
handleIntent()

binding.composeView.setContent {
val state = viewModel.state.collectAsStateLifecycleAware().value
val state = viewModel.state.collectAsStateWithLifecycle().value
if (state.drawerOpen) {
TasksTheme {
TasksMenu(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import androidx.core.os.BundleCompat
import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.appbar.AppBarLayout.Behavior.DragCallback
Expand All @@ -63,7 +64,6 @@ import org.tasks.calendars.CalendarPicker
import org.tasks.compose.BeastModeBanner
import org.tasks.compose.FilterSelectionActivity.Companion.launch
import org.tasks.compose.FilterSelectionActivity.Companion.registerForListPickerResult
import org.tasks.compose.collectAsStateLifecycleAware
import org.tasks.compose.edit.CommentsRow
import org.tasks.compose.edit.DescriptionRow
import org.tasks.compose.edit.DueDateRow
Expand Down Expand Up @@ -435,7 +435,7 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {

@Composable
private fun DueDateRow() {
val dueDate = editViewModel.dueDate.collectAsStateLifecycleAware().value
val dueDate = editViewModel.dueDate.collectAsStateWithLifecycle().value
DueDateRow(
dueDate = if (dueDate == 0L) {
null
Expand Down Expand Up @@ -470,7 +470,7 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {
@Composable
private fun PriorityRow() {
PriorityRow(
priority = editViewModel.priority.collectAsStateLifecycleAware().value,
priority = editViewModel.priority.collectAsStateWithLifecycle().value,
onChangePriority = { editViewModel.priority.value = it },
desaturate = preferences.desaturateDarkMode,
)
Expand All @@ -488,7 +488,7 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {

@Composable
private fun ListRow() {
val list = editViewModel.selectedList.collectAsStateLifecycleAware().value
val list = editViewModel.selectedList.collectAsStateWithLifecycle().value
ListRow(
list = list,
colorProvider = { chipProvider.getColor(it) },
Expand Down Expand Up @@ -517,7 +517,7 @@ class TaskEditFragment : Fragment(), Toolbar.OnMenuItemClickListener {
CommentsRow(
comments = userActivityDao
.watchComments(editViewModel.task.uuid)
.collectAsStateLifecycleAware(emptyList())
.collectAsStateWithLifecycle(emptyList())
.value,
deleteComment = {
lifecycleScope.launch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.DefaultItemAnimator
Expand All @@ -61,8 +62,6 @@ import com.todoroo.astrid.adapter.TaskAdapterProvider
import com.todoroo.astrid.api.AstridApiConstants.EXTRAS_OLD_DUE_DATE
import com.todoroo.astrid.api.AstridApiConstants.EXTRAS_TASK_ID
import com.todoroo.astrid.api.CustomFilter
import org.tasks.filters.GtasksFilter
import org.tasks.filters.TagFilter
import com.todoroo.astrid.core.BuiltInFilterExposer
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.repeats.RepeatTaskHelper
Expand Down Expand Up @@ -94,7 +93,6 @@ import org.tasks.compose.FilterSelectionActivity.Companion.launch
import org.tasks.compose.FilterSelectionActivity.Companion.registerForListPickerResult
import org.tasks.compose.NotificationsDisabledBanner
import org.tasks.compose.SubscriptionNagBanner
import org.tasks.compose.collectAsStateLifecycleAware
import org.tasks.compose.rememberReminderPermissionState
import org.tasks.data.TaskContainer
import org.tasks.data.dao.CaldavDao
Expand Down Expand Up @@ -124,7 +122,9 @@ import org.tasks.filters.AstridOrderingFilter
import org.tasks.filters.CaldavFilter
import org.tasks.filters.Filter
import org.tasks.filters.FilterImpl
import org.tasks.filters.GtasksFilter
import org.tasks.filters.PlaceFilter
import org.tasks.filters.TagFilter
import org.tasks.markdown.MarkdownProvider
import org.tasks.preferences.Device
import org.tasks.preferences.Preferences
Expand Down Expand Up @@ -357,7 +357,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
setupMenu(toolbar)
binding.banner.setContent {
val context = LocalContext.current
val state = listViewModel.state.collectAsStateLifecycleAware().value
val state = listViewModel.state.collectAsStateWithLifecycle().value
TasksTheme {
val hasRemindersPermission by rememberReminderPermissionState()
val notificationPermissions = if (AndroidUtilities.atLeastTiramisu()) {
Expand Down
6 changes: 3 additions & 3 deletions app/src/main/java/com/todoroo/astrid/files/FilesControlSet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import androidx.compose.ui.platform.ComposeView
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.tasks.R
import org.tasks.Strings
import org.tasks.compose.collectAsStateLifecycleAware
import org.tasks.compose.edit.AttachmentRow
import org.tasks.data.entity.TaskAttachment
import org.tasks.data.dao.TaskAttachmentDao
import org.tasks.data.entity.TaskAttachment
import org.tasks.dialogs.AddAttachmentDialog
import org.tasks.files.FileHelper
import org.tasks.preferences.Preferences
Expand Down Expand Up @@ -50,7 +50,7 @@ class FilesControlSet : TaskEditControlFragment() {
setContent {
TasksTheme {
AttachmentRow(
attachments = viewModel.selectedAttachments.collectAsStateLifecycleAware().value,
attachments = viewModel.selectedAttachments.collectAsStateWithLifecycle().value,
openAttachment = {
FileHelper.startActionView(
requireActivity(),
Expand Down
12 changes: 6 additions & 6 deletions app/src/main/java/com/todoroo/astrid/repeats/RepeatControlSet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@ import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import androidx.compose.ui.platform.ComposeView
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import org.tasks.filters.CaldavFilter
import org.tasks.filters.GtasksFilter
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import net.fortuna.ical4j.model.Recur
import net.fortuna.ical4j.model.WeekDay
import org.tasks.R
import org.tasks.compose.collectAsStateLifecycleAware
import org.tasks.compose.edit.RepeatRow
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.dao.CaldavDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.filters.CaldavFilter
import org.tasks.filters.GtasksFilter
import org.tasks.repeats.BasicRecurrenceDialog
import org.tasks.repeats.RecurrenceUtils.newRecur
import org.tasks.repeats.RepeatRuleToString
Expand Down Expand Up @@ -87,10 +87,10 @@ class RepeatControlSet : TaskEditControlFragment() {
setContent {
TasksTheme {
RepeatRow(
recurrence = viewModel.recurrence.collectAsStateLifecycleAware().value?.let {
recurrence = viewModel.recurrence.collectAsStateWithLifecycle().value?.let {
repeatRuleToString.toString(it)
},
repeatAfterCompletion = viewModel.repeatAfterCompletion.collectAsStateLifecycleAware().value,
repeatAfterCompletion = viewModel.repeatAfterCompletion.collectAsStateWithLifecycle().value,
onClick = {
lifecycleScope.launch {
val accountType = viewModel.selectedList.value
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/todoroo/astrid/tags/TagsControlSet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import android.content.Intent
import android.view.View
import android.view.ViewGroup
import androidx.compose.ui.platform.ComposeView
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.update
import org.tasks.R
import org.tasks.compose.collectAsStateLifecycleAware
import org.tasks.compose.edit.TagsRow
import org.tasks.tags.TagPickerActivity
import org.tasks.themes.TasksTheme
Expand All @@ -31,7 +31,7 @@ class TagsControlSet : TaskEditControlFragment() {
setContent {
TasksTheme {
TagsRow(
tags = viewModel.selectedTags.collectAsStateLifecycleAware().value,
tags = viewModel.selectedTags.collectAsStateWithLifecycle().value,
colorProvider = { chipProvider.getColor(it) },
onClick = this@TagsControlSet::onRowClick,
onClear = { tag ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.compose.ui.platform.ComposeView
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.ui.TimeDurationControlSet
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import org.tasks.R
import org.tasks.compose.collectAsStateLifecycleAware
import org.tasks.compose.edit.TimerRow
import org.tasks.data.entity.Task
import org.tasks.date.DateTimeUtils
Expand Down Expand Up @@ -91,9 +91,9 @@ class TimerControlSet : TaskEditControlFragment() {
setContent {
TasksTheme {
TimerRow(
started = viewModel.timerStarted.collectAsStateLifecycleAware().value,
estimated = viewModel.estimatedSeconds.collectAsStateLifecycleAware().value,
elapsed = viewModel.elapsedSeconds.collectAsStateLifecycleAware().value,
started = viewModel.timerStarted.collectAsStateWithLifecycle().value,
estimated = viewModel.estimatedSeconds.collectAsStateWithLifecycle().value,
elapsed = viewModel.elapsedSeconds.collectAsStateWithLifecycle().value,
timerClicked = this@TimerControlSet::timerClicked,
onClick = this@TimerControlSet::onRowClick,
)
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/todoroo/astrid/ui/ReminderControlSet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.ComposeView
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.PermissionStatus
import com.google.accompanist.permissions.rememberPermissionState
import com.todoroo.andlib.utility.AndroidUtilities
import dagger.hilt.android.AndroidEntryPoint
import org.tasks.R
import org.tasks.activities.DateAndTimePickerActivity
import org.tasks.compose.collectAsStateLifecycleAware
import org.tasks.compose.edit.AlarmRow
import org.tasks.compose.rememberReminderPermissionState
import org.tasks.data.entity.Alarm
Expand Down Expand Up @@ -105,7 +105,7 @@ class ReminderControlSet : TaskEditControlFragment() {
}
AlarmRow(
locale = locale,
alarms = viewModel.selectedAlarms.collectAsStateLifecycleAware().value,
alarms = viewModel.selectedAlarms.collectAsStateWithLifecycle().value,
hasNotificationPermissions = hasReminderPermissions &&
(notificationPermissions == null || notificationPermissions.status == PermissionStatus.Granted),
fixNotificationPermissions = {
Expand Down
10 changes: 5 additions & 5 deletions app/src/main/java/com/todoroo/astrid/ui/StartDateControlSet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import android.os.Bundle
import android.view.ViewGroup
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.viewModels
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.andlib.utility.DateUtilities.getTimeString
import dagger.hilt.android.AndroidEntryPoint
import org.tasks.R
import org.tasks.compose.collectAsStateLifecycleAware
import org.tasks.compose.edit.StartDateRow
import org.tasks.date.DateTimeUtils.newDateTime
import org.tasks.dialogs.StartDatePicker
Expand Down Expand Up @@ -49,13 +49,13 @@ class StartDateControlSet : TaskEditControlFragment() {
(parent as ComposeView).apply {
setContent {
TasksTheme {
val selectedDay = vm.selectedDay.collectAsStateLifecycleAware().value
val selectedTime = vm.selectedTime.collectAsStateLifecycleAware().value
val selectedDay = vm.selectedDay.collectAsStateWithLifecycle().value
val selectedTime = vm.selectedTime.collectAsStateWithLifecycle().value
StartDateRow(
startDate = viewModel.startDate.collectAsStateLifecycleAware().value,
startDate = viewModel.startDate.collectAsStateWithLifecycle().value,
selectedDay = selectedDay,
selectedTime = selectedTime,
hasDueDate = viewModel.dueDate.collectAsStateLifecycleAware().value > 0,
hasDueDate = viewModel.dueDate.collectAsStateWithLifecycle().value > 0,
printDate = {
DateUtilities.getRelativeDateTime(
context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.res.painterResource
import androidx.core.view.isVisible
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import org.tasks.R
import org.tasks.compose.ListSettingsComposables.PrincipalList
import org.tasks.compose.ShareInvite.ShareInviteDialog
import org.tasks.compose.collectAsStateLifecycleAware
import org.tasks.data.PrincipalWithAccess
import org.tasks.data.dao.PrincipalDao
import org.tasks.data.entity.CaldavAccount
Expand Down Expand Up @@ -54,7 +54,7 @@ class CaldavCalendarSettingsActivity : BaseCaldavCalendarSettingsActivity() {
caldavCalendar?.takeIf { it.id > 0 }?.let {
findViewById<ComposeView>(R.id.people).setContent {
TasksTheme {
val principals = principalDao.getPrincipals(it.id).collectAsStateLifecycleAware(initial = emptyList()).value
val principals = principalDao.getPrincipals(it.id).collectAsStateWithLifecycle(initialValue = emptyList()).value
PrincipalList(
principals = principals,
onRemove = if (canRemovePrincipals) { { onRemove(it) } } else null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.unit.dp
import androidx.core.content.IntentCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import dagger.hilt.android.AndroidEntryPoint
import org.tasks.LocalBroadcastManager
Expand Down Expand Up @@ -54,7 +55,7 @@ class FilterSelectionActivity : AppCompatActivity() {
colorScheme = if (isSystemInDarkTheme()) darkColorScheme() else lightColorScheme()
) {
val viewModel: FilterPickerViewModel = viewModel()
val state = viewModel.viewState.collectAsStateLifecycleAware().value
val state = viewModel.viewState.collectAsStateWithLifecycle().value
BasicAlertDialog(
onDismissRequest = { finish() },
modifier = Modifier.padding(vertical = 32.dp)
Expand Down
36 changes: 0 additions & 36 deletions app/src/main/java/org/tasks/compose/FlowHelpers.kt
Original file line number Diff line number Diff line change
@@ -1,49 +1,13 @@
package org.tasks.compose

import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.flowWithLifecycle
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.flow
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext

fun <T> Flow<T>.throttleLatest(period: Long) = flow {
conflate().collect {
emit(it)
delay(period)
}
}

// https://proandroiddev.com/how-to-collect-flows-lifecycle-aware-in-jetpack-compose-babd53582d0b

@Composable
fun <T> rememberFlow(
flow: Flow<T>,
lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current
): Flow<T> {
return remember(key1 = flow, key2 = lifecycleOwner) { flow.flowWithLifecycle(lifecycleOwner.lifecycle, Lifecycle.State.STARTED) }
}

@Composable
fun <T : R, R> Flow<T>.collectAsStateLifecycleAware(
initial: R,
context: CoroutineContext = EmptyCoroutineContext
): State<R> {
val lifecycleAwareFlow = rememberFlow(flow = this)
return lifecycleAwareFlow.collectAsState(initial = initial, context = context)
}

@Suppress("StateFlowValueCalledInComposition")
@Composable
fun <T> StateFlow<T>.collectAsStateLifecycleAware(
context: CoroutineContext = EmptyCoroutineContext
): State<T> = collectAsStateLifecycleAware(value, context)
Loading

0 comments on commit 01a788b

Please sign in to comment.