Error indicators for relative alarms

Use error colors if a relative start or end alarm is set without a start
or end date
pull/3486/head
Alex Baker 8 months ago
parent 5692f48e75
commit 03cfe259f0

@ -7,7 +7,6 @@ import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.fragment.app.Fragment
@ -68,7 +67,6 @@ class TaskEditFragment : Fragment() {
}
val context = LocalContext.current
val keyboard = LocalSoftwareKeyboardController.current
val scope = rememberCoroutineScope()
TaskEditScreen(
editViewModel = editViewModel,

@ -80,6 +80,8 @@ class ReminderControlSet : TaskEditControlFragment() {
viewModel.addAlarm(Alarm(time = timestamp, type = TYPE_DATE_TIME))
}
val viewState = viewModel.viewState.collectAsStateWithLifecycle().value
val startDate = viewModel.startDate.collectAsStateWithLifecycle().value
val dueDate = viewModel.dueDate.collectAsStateWithLifecycle().value
val context = LocalContext.current
AlarmRow(
alarms = viewState.alarms,
@ -94,6 +96,8 @@ class ReminderControlSet : TaskEditControlFragment() {
},
ringMode = ringMode,
addAlarm = viewModel::addAlarm,
hasStartDate = startDate > 0,
hasDueDate = dueDate > 0,
openRingType = {
val modes = resources.getStringArray(R.array.reminder_ring_modes)
val selectedIndex = when {

@ -5,12 +5,14 @@ import android.content.Context
import android.content.Intent
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.fragment.app.viewModels
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.runBlocking
import org.tasks.R
import org.tasks.compose.edit.StartDateRow
import org.tasks.data.entity.Alarm
import org.tasks.dialogs.StartDatePicker
import org.tasks.dialogs.StartDatePicker.Companion.EXTRA_DAY
import org.tasks.dialogs.StartDatePicker.Companion.EXTRA_TIME
@ -44,10 +46,14 @@ class StartDateControlSet : TaskEditControlFragment() {
val dueDate = viewModel.dueDate.collectAsStateWithLifecycle().value
val selectedDay = vm.selectedDay.collectAsStateWithLifecycle().value
val selectedTime = vm.selectedTime.collectAsStateWithLifecycle().value
val viewState = viewModel.viewState.collectAsStateWithLifecycle().value
StartDateRow(
startDate = viewModel.startDate.collectAsStateWithLifecycle().value,
selectedDay = selectedDay,
selectedTime = selectedTime,
hasStartAlarm = remember (viewState.alarms) {
viewState.alarms.any { it.type == Alarm.TYPE_REL_START }
},
hasDueDate = dueDate > 0,
printDate = {
runBlocking {

@ -12,8 +12,8 @@ import androidx.compose.ui.unit.dp
@Composable
fun DisabledText(
modifier: Modifier = Modifier,
text: String,
modifier: Modifier = Modifier
) {
Text(
text = text,

@ -13,8 +13,8 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.tooling.preview.Preview
@ -42,6 +42,8 @@ fun AlarmRow(
fixNotificationPermissions: () -> Unit,
alarms: ImmutableSet<Alarm>,
ringMode: Int,
hasStartDate: Boolean,
hasDueDate: Boolean,
addAlarm: (Alarm) -> Unit,
deleteAlarm: (Alarm) -> Unit,
openRingType: () -> Unit,
@ -55,6 +57,8 @@ fun AlarmRow(
Alarms(
alarms = alarms,
ringMode = ringMode,
hasStartDate = hasStartDate,
hasDueDate = hasDueDate,
replaceAlarm = {
vm.setReplace(it)
vm.showAddAlarm(visible = true)
@ -74,12 +78,12 @@ fun AlarmRow(
Spacer(modifier = Modifier.height(20.dp))
Text(
text = stringResource(id = R.string.enable_reminders),
color = colorResource(id = org.tasks.kmp.R.color.red_500),
color = MaterialTheme.colorScheme.error,
)
Text(
text = stringResource(id = R.string.enable_reminders_description),
style = MaterialTheme.typography.bodySmall,
color = colorResource(id = org.tasks.kmp.R.color.red_500),
color = MaterialTheme.colorScheme.error,
)
Spacer(modifier = Modifier.height(20.dp))
}
@ -123,6 +127,8 @@ fun AlarmRow(
fun Alarms(
alarms: ImmutableSet<Alarm>,
ringMode: Int,
hasStartDate: Boolean,
hasDueDate: Boolean,
replaceAlarm: (Alarm) -> Unit,
addAlarm: () -> Unit,
deleteAlarm: (Alarm) -> Unit,
@ -133,6 +139,19 @@ fun Alarms(
alarms.forEach { alarm ->
AlarmRow(
text = AlarmToString(LocalContext.current).toString(alarm),
color = when (alarm.type) {
Alarm.TYPE_REL_START -> if (hasStartDate) {
MaterialTheme.colorScheme.onSurface
} else {
MaterialTheme.colorScheme.error
}
Alarm.TYPE_REL_END -> if (hasDueDate) {
MaterialTheme.colorScheme.onSurface
} else {
MaterialTheme.colorScheme.error
}
else -> MaterialTheme.colorScheme.onSurface
},
onClick = { replaceAlarm(alarm) },
remove = { deleteAlarm(alarm) }
)
@ -171,6 +190,7 @@ fun Alarms(
@Composable
private fun AlarmRow(
text: String,
color: Color,
onClick: () -> Unit,
remove: () -> Unit,
) {
@ -184,7 +204,7 @@ private fun AlarmRow(
modifier = Modifier
.padding(vertical = 12.dp)
.weight(weight = 1f),
color = MaterialTheme.colorScheme.onSurface,
color = color,
)
ClearButton(onClick = remove)
}
@ -198,6 +218,8 @@ fun NoAlarms() {
AlarmRow(
alarms = persistentSetOf(),
ringMode = 0,
hasStartDate = true,
hasDueDate = true,
addAlarm = {},
deleteAlarm = {},
openRingType = {},
@ -216,6 +238,8 @@ fun PermissionDenied() {
AlarmRow(
alarms = persistentSetOf(),
ringMode = 0,
hasStartDate = true,
hasDueDate = true,
addAlarm = {},
deleteAlarm = {},
openRingType = {},

@ -2,18 +2,19 @@ package org.tasks.compose.edit
import android.content.res.Configuration
import androidx.compose.foundation.layout.padding
import androidx.compose.material.ContentAlpha
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.runBlocking
import org.tasks.R
import org.tasks.compose.DisabledText
import org.tasks.compose.TaskEditRow
import org.tasks.data.entity.Task
import org.tasks.date.DateTimeUtils.newDateTime
@ -24,13 +25,21 @@ import org.tasks.themes.TasksTheme
@Composable
fun DueDateRow(
dueDate: Long,
hasDueDateAlarm: Boolean,
is24HourFormat: Boolean,
alwaysDisplayFullDate: Boolean,
onClick: () -> Unit,
) {
val overdue = remember (dueDate) {
when {
Task.hasDueTime(dueDate) -> newDateTime(dueDate).isBeforeNow
dueDate > 0 -> newDateTime(dueDate).endOfDay().isBeforeNow
else -> false
}
}
DueDateRow(
dueDate = if (dueDate == 0L) {
null
stringResource(id = R.string.no_due_date)
} else {
runBlocking {
getRelativeDateTime(
@ -41,10 +50,11 @@ fun DueDateRow(
)
}
},
overdue = if (Task.hasDueTime(dueDate)) {
newDateTime(dueDate).isBeforeNow
} else {
newDateTime(dueDate).endOfDay().isBeforeNow
color = when {
overdue -> MaterialTheme.colorScheme.error
dueDate == 0L && hasDueDateAlarm -> MaterialTheme.colorScheme.error
dueDate == 0L -> MaterialTheme.colorScheme.onSurface.copy(alpha = ContentAlpha.disabled)
else -> MaterialTheme.colorScheme.onSurface
},
onClick = { onClick() },
)
@ -52,8 +62,8 @@ fun DueDateRow(
@Composable
private fun DueDateRow(
dueDate: String?,
overdue: Boolean,
dueDate: String,
color: Color,
onClick: () -> Unit,
) {
TaskEditRow(
@ -61,7 +71,7 @@ private fun DueDateRow(
content = {
DueDate(
dueDate = dueDate,
overdue = overdue,
color = color,
)
},
onClick = onClick,
@ -69,23 +79,15 @@ private fun DueDateRow(
}
@Composable
fun DueDate(dueDate: String?, overdue: Boolean) {
if (dueDate.isNullOrBlank()) {
DisabledText(
text = stringResource(id = R.string.no_due_date),
modifier = Modifier.padding(top = 20.dp, bottom = 20.dp, end = 16.dp)
)
} else {
Text(
text = dueDate,
color = if (overdue) {
colorResource(id = R.color.overdue)
} else {
MaterialTheme.colorScheme.onSurface
},
modifier = Modifier.padding(top = 20.dp, bottom = 20.dp, end = 16.dp)
)
}
fun DueDate(
dueDate: String,
color: Color,
) {
Text(
text = dueDate,
color = color,
modifier = Modifier.padding(top = 20.dp, bottom = 20.dp, end = 16.dp)
)
}
@ExperimentalComposeUiApi
@ -96,7 +98,7 @@ fun DueDatePreview() {
TasksTheme {
DueDateRow(
dueDate = "Today",
overdue = false,
color = MaterialTheme.colorScheme.onSurface,
) {}
}
}
@ -108,8 +110,8 @@ fun DueDatePreview() {
fun NoDueDatePreview() {
TasksTheme {
DueDateRow(
dueDate = null,
overdue = false,
dueDate = stringResource(R.string.no_due_date),
color = MaterialTheme.colorScheme.onSurface.copy(alpha = ContentAlpha.disabled),
) {}
}
}

@ -9,7 +9,6 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@ -26,6 +25,7 @@ fun StartDateRow(
selectedDay: Long,
selectedTime: Int,
currentTime: Long = currentTimeMillis(),
hasStartAlarm: Boolean,
hasDueDate: Boolean,
printDate: () -> String,
onClick: () -> Unit,
@ -38,6 +38,7 @@ fun StartDateRow(
selectedDay = selectedDay,
selectedTime = selectedTime,
currentTime = currentTime,
hasStartAlarm = hasStartAlarm,
hasDueDate = hasDueDate,
printDate = printDate,
)
@ -52,6 +53,7 @@ fun StartDate(
selectedDay: Long,
selectedTime: Int,
currentTime: Long,
hasStartAlarm: Boolean,
hasDueDate: Boolean,
printDate: () -> String,
) {
@ -66,9 +68,10 @@ fun StartDate(
else -> stringResource(id = R.string.no_start_date)
},
color = when {
selectedDay < 0 && !hasDueDate -> colorResource(id = R.color.overdue)
selectedDay < 0 && !hasDueDate -> MaterialTheme.colorScheme.error
startDate == 0L && hasStartAlarm -> MaterialTheme.colorScheme.error
startDate == 0L -> MaterialTheme.colorScheme.onSurface.copy(alpha = ContentAlpha.disabled)
startDate < currentTime -> colorResource(id = R.color.overdue)
startDate < currentTime -> MaterialTheme.colorScheme.error
else -> MaterialTheme.colorScheme.onSurface
},
modifier = Modifier
@ -87,6 +90,7 @@ fun NoStartDate() {
selectedDay = StartDatePicker.NO_DAY,
selectedTime = StartDatePicker.NO_TIME,
currentTime = 1657080392000L,
hasStartAlarm = true,
hasDueDate = false,
printDate = { "" },
onClick = {},
@ -104,6 +108,7 @@ fun FutureStartDate() {
selectedDay = StartDatePicker.DUE_DATE,
selectedTime = StartDatePicker.NO_TIME,
currentTime = 1657080392000L,
hasStartAlarm = true,
hasDueDate = false,
printDate = { "" },
onClick = {},
@ -121,6 +126,7 @@ fun PastStartDate() {
selectedDay = StartDatePicker.DUE_TIME,
selectedTime = StartDatePicker.NO_TIME,
currentTime = 1657080392001L,
hasStartAlarm = true,
hasDueDate = false,
printDate = { "" },
onClick = {},

@ -29,6 +29,7 @@ import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
@ -51,6 +52,7 @@ import org.tasks.R
import org.tasks.compose.BeastModeBanner
import org.tasks.compose.FilterSelectionActivity.Companion.EXTRA_FILTER
import org.tasks.compose.FilterSelectionActivity.Companion.launch
import org.tasks.data.entity.Alarm
import org.tasks.data.entity.UserActivity
import org.tasks.dialogs.Linkify
import org.tasks.extensions.Context.findActivity
@ -217,6 +219,9 @@ fun TaskEditScreen(
TAG_DUE_DATE -> DueDateRow(
dueDate = editViewModel.dueDate.collectAsStateWithLifecycle().value,
hasDueDateAlarm = remember (viewState.alarms) {
viewState.alarms.any { it.type == Alarm.TYPE_REL_END }
},
is24HourFormat = context.is24HourFormat,
alwaysDisplayFullDate = viewState.alwaysDisplayFullDate,
onClick = onClickDueDate,

Loading…
Cancel
Save