feat: allow editing synced lists, not just device-only ones
The edit pencil was gated to local lists even though rename/delete already worked end to end for synced collections. Read-only shares keep the icon but show it disabled, with a hint on tap explaining why. Refs #29
This commit is contained in:
@@ -52,6 +52,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.MediumTopAppBar
|
||||
import androidx.compose.material3.Scaffold
|
||||
@@ -139,9 +140,12 @@ fun TaskListScreen(
|
||||
val list = content?.list
|
||||
val listName = list?.name
|
||||
val listId = (filter as? TaskFilter.OfList)?.listId
|
||||
// Editing is offered for a device-only list. A collection that belongs to an
|
||||
// account is the server's to rename or remove, not ours.
|
||||
// Editing is offered for any writable list, device or synced — renaming and
|
||||
// recolouring a synced collection is a server write the same sheet already
|
||||
// handles. A read-only share keeps the icon but disables it: tapping it
|
||||
// explains why rather than the button silently not being there.
|
||||
var editingList by rememberSaveable { mutableStateOf(false) }
|
||||
var readOnlyHint by rememberSaveable { mutableStateOf(false) }
|
||||
val listWriteFailure by viewModel.listWriteFailure.collectAsStateWithLifecycle()
|
||||
val listDeleted by viewModel.listDeleted.collectAsStateWithLifecycle()
|
||||
// The list this screen is about is gone; there is nothing left to show.
|
||||
@@ -152,6 +156,12 @@ fun TaskListScreen(
|
||||
viewModel.clearListWriteFailure()
|
||||
}
|
||||
}
|
||||
LaunchedEffect(readOnlyHint) {
|
||||
if (readOnlyHint) {
|
||||
delay(4_000)
|
||||
readOnlyHint = false
|
||||
}
|
||||
}
|
||||
// One add affordance, never two: a real list with the setting on gets a pinned
|
||||
// bottom quick-add bar; everything else (incl. smart lists, which have no single
|
||||
// target list) gets the floating "New task" button.
|
||||
@@ -181,11 +191,20 @@ fun TaskListScreen(
|
||||
IconButton(onClick = { showSort = true }, enabled = content != null) {
|
||||
Icon(Icons.AutoMirrored.Rounded.Sort, contentDescription = stringResource(R.string.sort_title))
|
||||
}
|
||||
if (list != null && list.isLocal) {
|
||||
IconButton(onClick = { editingList = true }) {
|
||||
if (list != null) {
|
||||
IconButton(
|
||||
onClick = {
|
||||
if (list.isReadOnly) readOnlyHint = true else editingList = true
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
Icons.Rounded.Edit,
|
||||
contentDescription = stringResource(R.string.list_edit_title),
|
||||
tint = if (list.isReadOnly) {
|
||||
LocalContentColor.current.copy(alpha = 0.38f)
|
||||
} else {
|
||||
LocalContentColor.current
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -230,23 +249,28 @@ fun TaskListScreen(
|
||||
.height(SnackChipHeight),
|
||||
contentAlignment = Alignment.CenterStart,
|
||||
) {
|
||||
// One chip, one anchor: the undo receipt takes precedence, and a
|
||||
// refused list write reports itself once the undo window is clear.
|
||||
// One chip, one anchor, in priority order: the undo receipt first,
|
||||
// then a refused list write once the undo window is clear, then the
|
||||
// read-only edit hint — the quietest of the three, so it never
|
||||
// outranks something the other two are actually reporting.
|
||||
val failure = listWriteFailure
|
||||
if (undo != null || failure == null) {
|
||||
SnackChip(
|
||||
visible = undo != null,
|
||||
when {
|
||||
undo != null -> SnackChip(
|
||||
visible = true,
|
||||
message = stringResource(
|
||||
if (undo is UndoReceipt.Completed) R.string.task_completed else R.string.task_deleted,
|
||||
),
|
||||
actionLabel = stringResource(R.string.undo),
|
||||
onAction = viewModel::undo,
|
||||
)
|
||||
} else {
|
||||
SnackChip(
|
||||
failure != null -> SnackChip(
|
||||
visible = true,
|
||||
message = stringResource(listWriteFailureMessage(failure)),
|
||||
)
|
||||
else -> SnackChip(
|
||||
visible = readOnlyHint,
|
||||
message = stringResource(R.string.list_read_only),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user