Show task timestamp on WearOS

pull/2983/head
Alex Baker 1 year ago
parent d4aeb34b87
commit 675b43ff95

@ -1,5 +1,6 @@
package org.tasks.wear
import android.text.format.DateFormat
import androidx.datastore.core.DataStore
import androidx.lifecycle.lifecycleScope
import com.google.android.horologist.annotations.ExperimentalHorologistApi
@ -58,6 +59,7 @@ class WearDataService : BaseGrpcDataService<WearServiceGrpcKt.WearServiceCorouti
colorProvider = colorProvider,
defaultFilterProvider = defaultFilterProvider,
taskCreator = taskCreator,
is24HourTime = DateFormat.is24HourFormat(applicationContext),
)
}
}

@ -1,6 +1,7 @@
package org.tasks.wear
import androidx.datastore.core.DataStore
import com.todoroo.astrid.core.SortHelper.SORT_DUE
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.service.TaskCompleter
import com.todoroo.astrid.service.TaskCreator
@ -30,12 +31,16 @@ import org.tasks.filters.MyTasksFilter
import org.tasks.filters.NavigationDrawerSubheader
import org.tasks.filters.getIcon
import org.tasks.kmp.org.tasks.time.DateStyle
import org.tasks.kmp.org.tasks.time.getRelativeDateTime
import org.tasks.kmp.org.tasks.time.getTimeString
import org.tasks.preferences.DefaultFilterProvider
import org.tasks.preferences.Preferences
import org.tasks.tasklist.HeaderFormatter
import org.tasks.tasklist.SectionedDataSource
import org.tasks.tasklist.UiItem
import org.tasks.themes.ColorProvider
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import org.tasks.time.startOfDay
import timber.log.Timber
class WearService(
@ -50,6 +55,7 @@ class WearService(
private val colorProvider: ColorProvider,
private val defaultFilterProvider: DefaultFilterProvider,
private val taskCreator: TaskCreator,
private val is24HourTime: Boolean,
) : WearServiceGrpcKt.WearServiceCoroutineImplBase() {
override suspend fun getTasks(request: GetTasksRequest): Tasks {
val position = request.position
@ -84,7 +90,23 @@ class WearService(
.setCollapsed(collapsed.contains(item.value))
.build()
is UiItem.Task ->
is UiItem.Task -> {
val timestamp = if (preferences.groupMode == SORT_DUE &&
(item.task.sortGroup
?: 0) >= currentTimeMillis().startOfDay()
) {
item.task.takeIf { it.hasDueTime() }?.let {
getTimeString(item.task.dueDate, is24HourTime)
}
} else if (item.task.hasDueDate()) {
getRelativeDateTime(
item.task.dueDate,
is24HourTime,
)
} else {
null
}
GrpcProto.UiItem.newBuilder()
.setType(ListItemType.Item)
.setId(item.task.id)
@ -98,9 +120,13 @@ class WearService(
if (item.task.title != null) {
setTitle(item.task.title)
}
if (timestamp != null) {
setTimestamp(timestamp)
}
}
.setRepeating(item.task.task.isRecurring)
.build()
}
}
}
)

@ -21,6 +21,7 @@ message UiItem {
bool hidden = 8;
uint32 indent = 9;
uint32 numSubtasks = 10;
optional string timestamp = 11;
}
message Tasks {

@ -1,9 +1,14 @@
package org.tasks.presentation.components
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -21,6 +26,7 @@ import androidx.wear.compose.material.Text
@Composable
fun TaskCard(
text: String,
timestamp: String?,
hidden: Boolean = false,
numSubtasks: Int = 0,
subtasksCollapsed: Boolean = false,
@ -44,26 +50,56 @@ fun TaskCard(
maxLines = 2,
overflow = TextOverflow.Ellipsis,
color = contentColor,
modifier = Modifier.alpha(if (hidden) .6f else 1f).weight(1f),
modifier = Modifier
.alpha(if (hidden) .6f else 1f)
.weight(1f),
)
if (numSubtasks > 0) {
Button(
onClick = toggleSubtasks,
colors = ButtonDefaults.outlinedButtonColors()
colors = ButtonDefaults.outlinedButtonColors(),
shape = if (timestamp.isNullOrBlank()) CircleShape else RoundedCornerShape(16.dp),
modifier = Modifier.wrapContentWidth(),
) {
Row(
verticalAlignment = Alignment.CenterVertically
Column(
horizontalAlignment = Alignment.End,
) {
Text(
text = numSubtasks.toString(), // TODO: use number formatter
color = contentColor,
)
Chevron(subtasksCollapsed)
Timestamp(timestamp, contentColor)
Row(
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = numSubtasks.toString(), // TODO: use number formatter
color = contentColor,
)
Chevron(subtasksCollapsed)
}
}
}
} else {
Timestamp(timestamp, contentColor)
Spacer(modifier = Modifier.width(12.dp))
}
}
}
}
@Composable
private fun Timestamp(
timestamp: String?,
color: Color,
) {
if (timestamp.isNullOrBlank()) {
return
}
Text(
text = timestamp,
color = color,
style = MaterialTheme.typography.caption2,
modifier = Modifier
.alpha(.6f)
.padding(start = 4.dp),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}

@ -58,7 +58,7 @@ fun TaskEditScreen(
keyboardInputRequest.openKeyboard()
}
}
if (uiState.taskId == 0L) {
if (!uiState.loaded) {
Box(
modifier = Modifier.fillMaxRectangle(),
contentAlignment = Alignment.Center,

@ -17,6 +17,7 @@ import org.tasks.extensions.wearDataLayerRegistry
import timber.log.Timber
data class UiState(
val loaded: Boolean = false,
val taskId: Long = 0,
val completed: Boolean = false,
val repeating: Boolean = false,
@ -27,9 +28,9 @@ data class UiState(
@OptIn(ExperimentalHorologistApi::class)
class TaskEditViewModel(
applicationContext: Context,
private val taskId: Long,
taskId: Long,
) : ViewModel() {
private val _uiState = MutableStateFlow(UiState())
private val _uiState = MutableStateFlow(UiState(taskId = taskId))
val uiState = _uiState.asStateFlow()
private val registry = applicationContext.wearDataLayerRegistry(viewModelScope)
@ -54,6 +55,7 @@ class TaskEditViewModel(
Timber.d("Received $task")
_uiState.update {
it.copy(
loaded = true,
taskId = taskId,
completed = task.completed,
title = task.title,
@ -77,7 +79,7 @@ class TaskEditViewModel(
wearService.saveTask(
GrpcProto.SaveTaskRequest.newBuilder()
.setTitle(state.title)
.setTaskId(taskId)
.setTaskId(state.taskId)
.setCompleted(state.completed)
.build()
)

@ -112,6 +112,7 @@ fun TaskListScreen(
}
TaskCard(
text = item.title,
timestamp = item.timestamp,
hidden = item.hidden,
subtasksCollapsed = item.collapsed,
numSubtasks = item.numSubtasks,

Loading…
Cancel
Save