From 5c3af50c9d3f3686e585b62a3c7f1b50ae64494a Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Thu, 21 Jul 2022 00:38:55 -0500 Subject: [PATCH] Move more Start and due date logic into composables --- .../todoroo/astrid/ui/StartDateControlSet.kt | 112 ++++++++++----- .../java/org/tasks/compose/TaskEditIcon.kt | 2 +- .../java/org/tasks/ui/DeadlineControlSet.kt | 130 ++++++++++++------ .../ui/TaskEditControlComposeFragment.kt | 2 +- .../org/tasks/ui/TaskEditControlFragment.kt | 2 +- 5 files changed, 170 insertions(+), 78 deletions(-) diff --git a/app/src/main/java/com/todoroo/astrid/ui/StartDateControlSet.kt b/app/src/main/java/com/todoroo/astrid/ui/StartDateControlSet.kt index 3d8ca6462..d454d8512 100644 --- a/app/src/main/java/com/todoroo/astrid/ui/StartDateControlSet.kt +++ b/app/src/main/java/com/todoroo/astrid/ui/StartDateControlSet.kt @@ -5,6 +5,7 @@ import android.content.Context import android.content.Intent import android.content.res.Configuration import android.os.Bundle +import android.view.ViewGroup import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material.ContentAlpha @@ -12,6 +13,7 @@ import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource @@ -26,6 +28,8 @@ import com.todoroo.andlib.utility.DateUtilities.now import com.todoroo.astrid.ui.StartDateControlSet.Companion.getRelativeDateString import dagger.hilt.android.AndroidEntryPoint import org.tasks.R +import org.tasks.compose.TaskEditIcon +import org.tasks.compose.TaskEditRow import org.tasks.compose.collectAsStateLifecycleAware import org.tasks.date.DateTimeUtils.newDateTime import org.tasks.dialogs.StartDatePicker @@ -39,6 +43,7 @@ import org.tasks.dialogs.StartDatePicker.Companion.NO_TIME import org.tasks.dialogs.StartDatePicker.Companion.WEEK_BEFORE_DUE import org.tasks.preferences.Preferences import org.tasks.ui.TaskEditControlComposeFragment +import org.tasks.ui.TaskEditViewModel import java.time.format.FormatStyle import java.util.* import javax.inject.Inject @@ -50,19 +55,6 @@ class StartDateControlSet : TaskEditControlComposeFragment() { private val vm: StartDateViewModel by viewModels() - override fun onRowClick() { - val fragmentManager = parentFragmentManager - if (fragmentManager.findFragmentByTag(FRAG_TAG_DATE_PICKER) == null) { - StartDatePicker.newDateTimePicker( - this, - REQUEST_START_DATE, - vm.selectedDay.value, - vm.selectedTime.value, - preferences.getBoolean(R.string.p_auto_dismiss_datetime_edit_screen, false)) - .show(fragmentManager, FRAG_TAG_DATE_PICKER) - } - } - override fun createView(savedInstanceState: Bundle?) { if (savedInstanceState == null) { vm.init(viewModel.dueDate.value, viewModel.startDate.value, viewModel.isNew) @@ -74,23 +66,39 @@ class StartDateControlSet : TaskEditControlComposeFragment() { } } - @Composable - override fun Body() { - StartDate( - startDate = viewModel.startDate.collectAsStateLifecycleAware().value, - selectedDay = vm.selectedDay.collectAsStateLifecycleAware().value, - selectedTime = vm.selectedTime.collectAsStateLifecycleAware().value, - displayFullDate = preferences.alwaysDisplayFullDate, - locale = locale, - ) - } - - override val icon = R.drawable.ic_pending_actions_24px + override fun bind(parent: ViewGroup?) = + (parent as ComposeView).apply { + setContent { + MdcTheme { + StartDateRow( + viewModel = viewModel, + vm = vm, + preferences = preferences, + locale = locale, + onClick = { + val fragmentManager = parentFragmentManager + if (fragmentManager.findFragmentByTag(FRAG_TAG_DATE_PICKER) == null) { + StartDatePicker.newDateTimePicker( + this@StartDateControlSet, + REQUEST_START_DATE, + vm.selectedDay.value, + vm.selectedTime.value, + preferences.getBoolean( + R.string.p_auto_dismiss_datetime_edit_screen, + false + ) + ) + .show(fragmentManager, FRAG_TAG_DATE_PICKER) + } + } + ) + } + } + } override fun controlId() = TAG - override val isClickable = true - + @Deprecated("Deprecated in Java") override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if (requestCode == REQUEST_START_DATE) { if (resultCode == Activity.RESULT_OK) { @@ -123,6 +131,41 @@ class StartDateControlSet : TaskEditControlComposeFragment() { } } +@Composable +fun StartDateRow( + viewModel: TaskEditViewModel, + vm: StartDateViewModel, + preferences: Preferences, + locale: Locale, + onClick: () -> Unit, +) { + TaskEditRow( + icon = { + TaskEditIcon( + id = R.drawable.ic_pending_actions_24px, + modifier = Modifier + .padding( + start = 16.dp, + top = 20.dp, + end = 32.dp, + bottom = 20.dp + ) + ) + }, + content = { + StartDate( + startDate = viewModel.startDate.collectAsStateLifecycleAware().value, + selectedDay = vm.selectedDay.collectAsStateLifecycleAware().value, + selectedTime = vm.selectedTime.collectAsStateLifecycleAware().value, + displayFullDate = preferences.alwaysDisplayFullDate, + locale = locale, + hasDueDate = viewModel.dueDate.collectAsStateLifecycleAware().value > 0 + ) + }, + onClick = onClick + ) +} + @Composable fun StartDate( startDate: Long, @@ -131,6 +174,7 @@ fun StartDate( displayFullDate: Boolean, locale: Locale = Locale.getDefault(), currentTime: Long = now(), + hasDueDate: Boolean, ) { val context = LocalContext.current Text( @@ -150,11 +194,14 @@ fun StartDate( else -> stringResource(id = R.string.no_start_date) }, color = when { + selectedDay < 0 && !hasDueDate -> colorResource(id = R.color.overdue) startDate == 0L -> MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled) startDate < currentTime -> colorResource(id = R.color.overdue) else -> MaterialTheme.colors.onSurface }, - modifier = Modifier.padding(vertical = 20.dp).height(24.dp), + modifier = Modifier + .padding(vertical = 20.dp) + .height(24.dp), ) } @@ -168,7 +215,8 @@ fun NoStartDate() { selectedDay = NO_DAY, selectedTime = NO_TIME, displayFullDate = false, - currentTime = 1657080392000L + currentTime = 1657080392000L, + hasDueDate = false, ) } } @@ -183,7 +231,8 @@ fun FutureStartDate() { selectedDay = DUE_DATE, selectedTime = NO_TIME, displayFullDate = false, - currentTime = 1657080392000L + currentTime = 1657080392000L, + hasDueDate = false, ) } } @@ -198,7 +247,8 @@ fun PastStartDate() { selectedDay = DUE_TIME, selectedTime = NO_TIME, displayFullDate = false, - currentTime = 1657080392001L + currentTime = 1657080392001L, + hasDueDate = false, ) } } diff --git a/app/src/main/java/org/tasks/compose/TaskEditIcon.kt b/app/src/main/java/org/tasks/compose/TaskEditIcon.kt index cf929c73c..6555d7437 100644 --- a/app/src/main/java/org/tasks/compose/TaskEditIcon.kt +++ b/app/src/main/java/org/tasks/compose/TaskEditIcon.kt @@ -13,6 +13,6 @@ fun TaskEditIcon(@DrawableRes id: Int, modifier: Modifier = Modifier) { Icon( painter = painterResource(id = id), contentDescription = null, - modifier = modifier.alpha(ContentAlpha.high), + modifier = modifier.alpha(ContentAlpha.medium), ) } \ No newline at end of file diff --git a/app/src/main/java/org/tasks/ui/DeadlineControlSet.kt b/app/src/main/java/org/tasks/ui/DeadlineControlSet.kt index c575212a2..038cc7d4a 100644 --- a/app/src/main/java/org/tasks/ui/DeadlineControlSet.kt +++ b/app/src/main/java/org/tasks/ui/DeadlineControlSet.kt @@ -2,25 +2,30 @@ package org.tasks.ui import android.app.Activity import android.content.Intent +import android.view.ViewGroup import androidx.compose.foundation.layout.padding import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import com.google.android.material.composethemeadapter.MdcTheme import com.todoroo.andlib.utility.DateUtilities import com.todoroo.astrid.data.Task.Companion.hasDueTime import dagger.hilt.android.AndroidEntryPoint import org.tasks.R import org.tasks.compose.DisabledText +import org.tasks.compose.TaskEditIcon +import org.tasks.compose.TaskEditRow import org.tasks.compose.collectAsStateLifecycleAware import org.tasks.date.DateTimeUtils import org.tasks.dialogs.DateTimePicker -import org.tasks.dialogs.DateTimePicker.Companion.newDateTimePicker import org.tasks.preferences.Preferences +import org.tasks.ui.DeadlineControlSet.Companion.isOverdue import java.time.format.FormatStyle import java.util.* import javax.inject.Inject @@ -30,49 +35,29 @@ class DeadlineControlSet : TaskEditControlComposeFragment() { @Inject lateinit var locale: Locale @Inject lateinit var preferences: Preferences - override fun onRowClick() { - val fragmentManager = parentFragmentManager - if (fragmentManager.findFragmentByTag(FRAG_TAG_DATE_PICKER) == null) { - newDateTimePicker( - this, - REQUEST_DATE, - viewModel.dueDate.value, - preferences.getBoolean(R.string.p_auto_dismiss_datetime_edit_screen, false)) - .show(fragmentManager, FRAG_TAG_DATE_PICKER) - } - } - - override val isClickable = true - - @Composable - override fun Body() { - val dueDate = viewModel.dueDate.collectAsStateLifecycleAware().value - if (dueDate == 0L) { - DisabledText( - text = stringResource(id = R.string.no_due_date), - modifier = Modifier.padding(vertical = 20.dp) - ) - } else { - Text( - text = DateUtilities.getRelativeDateTime( - LocalContext.current, - dueDate, - locale, - FormatStyle.FULL, - preferences.alwaysDisplayFullDate, - false - ), - color = if (dueDate.isOverdue) { - colorResource(id = R.color.overdue) - } else { - MaterialTheme.colors.onSurface - }, - modifier = Modifier.padding(vertical = 20.dp) - ) + override fun bind(parent: ViewGroup?) = + (parent as ComposeView).apply { + setContent { + MdcTheme { + DueDateRow( + viewModel = viewModel, + locale = locale, + displayFullDate = preferences.alwaysDisplayFullDate, + onClick = { + val fragmentManager = parentFragmentManager + if (fragmentManager.findFragmentByTag(FRAG_TAG_DATE_PICKER) == null) { + DateTimePicker.newDateTimePicker( + this@DeadlineControlSet, + REQUEST_DATE, + viewModel.dueDate.value, + preferences.getBoolean(R.string.p_auto_dismiss_datetime_edit_screen, false)) + .show(fragmentManager, FRAG_TAG_DATE_PICKER) + } + } + ) + } + } } - } - - override val icon = R.drawable.ic_outline_schedule_24px override fun controlId() = TAG @@ -91,11 +76,68 @@ class DeadlineControlSet : TaskEditControlComposeFragment() { private const val REQUEST_DATE = 504 private const val FRAG_TAG_DATE_PICKER = "frag_tag_date_picker" - private val Long.isOverdue: Boolean + val Long.isOverdue: Boolean get() = if (hasDueTime(this)) { DateTimeUtils.newDateTime(this).isBeforeNow } else { DateTimeUtils.newDateTime(this).endOfDay().isBeforeNow } } +} + +@Composable +fun DueDateRow( + viewModel: TaskEditViewModel, + locale: Locale, + displayFullDate: Boolean, + onClick: () -> Unit, +) { + TaskEditRow( + icon = { + TaskEditIcon( + id = R.drawable.ic_outline_schedule_24px, + modifier = Modifier.padding( + start = 16.dp, + top = 20.dp, + end = 32.dp, + bottom = 20.dp + ) + ) + }, + content = { + DueDate( + dueDate = viewModel.dueDate.collectAsStateLifecycleAware().value, + locale = locale, + displayFullDate = displayFullDate, + ) + }, + onClick = onClick, + ) +} + +@Composable +fun DueDate(dueDate: Long, locale: Locale, displayFullDate: Boolean) { + if (dueDate == 0L) { + DisabledText( + text = stringResource(id = R.string.no_due_date), + modifier = Modifier.padding(vertical = 20.dp) + ) + } else { + Text( + text = DateUtilities.getRelativeDateTime( + LocalContext.current, + dueDate, + locale, + FormatStyle.FULL, + displayFullDate, + false + ), + color = if (dueDate.isOverdue) { + colorResource(id = R.color.overdue) + } else { + MaterialTheme.colors.onSurface + }, + modifier = Modifier.padding(vertical = 20.dp) + ) + } } \ No newline at end of file diff --git a/app/src/main/java/org/tasks/ui/TaskEditControlComposeFragment.kt b/app/src/main/java/org/tasks/ui/TaskEditControlComposeFragment.kt index 0f7caba38..ba14b303c 100644 --- a/app/src/main/java/org/tasks/ui/TaskEditControlComposeFragment.kt +++ b/app/src/main/java/org/tasks/ui/TaskEditControlComposeFragment.kt @@ -57,5 +57,5 @@ abstract class TaskEditControlComposeFragment : TaskEditControlFragment() { } @Composable - protected abstract fun Body() + protected open fun Body() {} } \ No newline at end of file diff --git a/app/src/main/java/org/tasks/ui/TaskEditControlFragment.kt b/app/src/main/java/org/tasks/ui/TaskEditControlFragment.kt index c4216a8da..5b8f6cd77 100644 --- a/app/src/main/java/org/tasks/ui/TaskEditControlFragment.kt +++ b/app/src/main/java/org/tasks/ui/TaskEditControlFragment.kt @@ -15,7 +15,7 @@ abstract class TaskEditControlFragment : Fragment() { protected open val isClickable: Boolean get() = false - protected abstract val icon: Int + protected open val icon = 0 abstract fun controlId(): Int protected abstract fun bind(parent: ViewGroup?): View } \ No newline at end of file