Add string resources

All views now use resources
This commit is contained in:
Geoffroy Bonneville
2025-10-29 22:37:14 -04:00
parent 60cd307a87
commit f297427d13
10 changed files with 121 additions and 42 deletions

View File

@@ -1,9 +1,11 @@
package com.wismna.geoffroy.donext.domain.model package com.wismna.geoffroy.donext.domain.model
enum class Priority(val value: Int, val label: String) { import com.wismna.geoffroy.donext.R
LOW(0, "Low"),
NORMAL(1, "Normal"), enum class Priority(val value: Int, val label: Int) {
HIGH(2, "High"); LOW(0, R.string.task_priority_low),
NORMAL(1, R.string.task_priority_normal),
HIGH(2, R.string.task_priority_high);
companion object { companion object {
fun fromValue(value: Int): Priority = fun fromValue(value: Int): Priority =

View File

@@ -15,8 +15,10 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import com.wismna.geoffroy.donext.R
import com.wismna.geoffroy.donext.presentation.viewmodel.DueTodayViewModel import com.wismna.geoffroy.donext.presentation.viewmodel.DueTodayViewModel
@Composable @Composable
@@ -38,7 +40,7 @@ fun DueTodayTasksScreen(
contentDescription = "Due today background icon", contentDescription = "Due today background icon",
modifier = Modifier.size(60.dp), modifier = Modifier.size(60.dp),
tint = MaterialTheme.colorScheme.secondary) tint = MaterialTheme.colorScheme.secondary)
Text("Nothing due today !", color = MaterialTheme.colorScheme.secondary) Text(stringResource(R.string.today_no_tasks), color = MaterialTheme.colorScheme.secondary)
} }
} }
} else { } else {

View File

@@ -57,6 +57,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.Dialog
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
@@ -67,6 +68,7 @@ import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument import androidx.navigation.navArgument
import com.wismna.geoffroy.donext.R
import com.wismna.geoffroy.donext.domain.model.AppDestination import com.wismna.geoffroy.donext.domain.model.AppDestination
import com.wismna.geoffroy.donext.presentation.ui.events.UiEvent import com.wismna.geoffroy.donext.presentation.ui.events.UiEvent
import com.wismna.geoffroy.donext.presentation.viewmodel.MainViewModel import com.wismna.geoffroy.donext.presentation.viewmodel.MainViewModel
@@ -197,6 +199,7 @@ fun AppContent(
) { ) {
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() } val snackbarHostState = remember { SnackbarHostState() }
val snackbarActionLabel = stringResource(R.string.snackbar_action)
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
viewModel.uiEventBus.events.collectLatest { event -> viewModel.uiEventBus.events.collectLatest { event ->
@@ -209,7 +212,7 @@ fun AppContent(
is UiEvent.ShowUndoSnackbar -> { is UiEvent.ShowUndoSnackbar -> {
val result = snackbarHostState.showSnackbar( val result = snackbarHostState.showSnackbar(
message = event.message, message = event.message,
actionLabel = "Undo", actionLabel = snackbarActionLabel,
duration = SnackbarDuration.Short duration = SnackbarDuration.Short
) )
if (result == SnackbarResult.ActionPerformed) { if (result == SnackbarResult.ActionPerformed) {
@@ -283,7 +286,7 @@ fun AppContent(
ExtendedFloatingActionButton( ExtendedFloatingActionButton(
onClick = { viewModel.onNewTaskButtonClicked(dest.taskListId) }, onClick = { viewModel.onNewTaskButtonClicked(dest.taskListId) },
icon = { Icon(Icons.Filled.Add, "Create a task.") }, icon = { Icon(Icons.Filled.Add, "Create a task.") },
text = { Text("Create a task") }, text = { Text(stringResource(R.string.action_create_list)) },
) )
} }
else -> null else -> null

View File

@@ -45,12 +45,14 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.CustomAccessibilityAction import androidx.compose.ui.semantics.CustomAccessibilityAction
import androidx.compose.ui.semantics.clearAndSetSemantics import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.customActions import androidx.compose.ui.semantics.customActions
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import com.wismna.geoffroy.donext.R
import com.wismna.geoffroy.donext.presentation.viewmodel.ManageListsViewModel import com.wismna.geoffroy.donext.presentation.viewmodel.ManageListsViewModel
import sh.calvin.reorderable.ReorderableItem import sh.calvin.reorderable.ReorderableItem
import sh.calvin.reorderable.rememberReorderableLazyListState import sh.calvin.reorderable.rememberReorderableLazyListState
@@ -69,7 +71,7 @@ fun ManageListsScreen(
modifier = modifier.fillMaxSize(), modifier = modifier.fillMaxSize(),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
Text("Tap + to create a new task list.") Text(stringResource(R.string.tasklist_no_tasks))
} }
return return
} }
@@ -231,7 +233,7 @@ fun AddListScreen(
//var description by remember { mutableStateOf("") } //var description by remember { mutableStateOf("") }
Column(modifier = Modifier.padding(16.dp)) { Column(modifier = Modifier.padding(16.dp)) {
Text("New List", style = MaterialTheme.typography.titleMedium) Text(stringResource(R.string.tasklist_new_title), style = MaterialTheme.typography.titleMedium)
Spacer(Modifier.height(8.dp)) Spacer(Modifier.height(8.dp))
/*TextField( /*TextField(
@@ -244,7 +246,7 @@ fun AddListScreen(
value = name, value = name,
singleLine = true, singleLine = true,
onValueChange = { name = it }, onValueChange = { name = it },
label = { Text("Title") }, label = { Text(stringResource(R.string.tasklist_new_name)) },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.focusRequester(titleFocusRequester) .focusRequester(titleFocusRequester)
@@ -272,7 +274,7 @@ fun AddListScreen(
}, },
enabled = name.isNotBlank() enabled = name.isNotBlank()
) { ) {
Text("Create") Text(stringResource(R.string.tasklist_new_create))
} }
} }
} }

View File

@@ -21,9 +21,11 @@ import androidx.compose.material3.NavigationDrawerItemDefaults
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import com.wismna.geoffroy.donext.R
import com.wismna.geoffroy.donext.domain.model.AppDestination import com.wismna.geoffroy.donext.domain.model.AppDestination
import com.wismna.geoffroy.donext.presentation.viewmodel.MenuViewModel import com.wismna.geoffroy.donext.presentation.viewmodel.MenuViewModel
@@ -46,18 +48,18 @@ fun MenuScreen(
) { ) {
Column { Column {
Text( Text(
text = "DoNext v2", text = stringResource(R.string.navigation_title),
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
modifier = Modifier.padding(16.dp) modifier = Modifier.padding(16.dp)
) )
NavigationDrawerItem( NavigationDrawerItem(
label = { label = {
Row (modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { Row (modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
Text("Due Today") Text(stringResource(R.string.navigation_due_today))
Text(viewModel.dueTodayTasksCount.toString()) Text(viewModel.dueTodayTasksCount.toString())
} }
}, },
icon = { Icon(Icons.Default.Today, contentDescription = "Due Today") }, icon = { Icon(Icons.Default.Today, contentDescription = stringResource(R.string.navigation_due_today)) },
selected = currentDestination is AppDestination.DueTodayList, selected = currentDestination is AppDestination.DueTodayList,
onClick = { viewModel.navigateTo(AppDestination.DueTodayList.route, currentDestination.route) }, onClick = { viewModel.navigateTo(AppDestination.DueTodayList.route, currentDestination.route) },
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding) modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
@@ -89,15 +91,15 @@ fun MenuScreen(
Column { Column {
HorizontalDivider() HorizontalDivider()
NavigationDrawerItem( NavigationDrawerItem(
label = { Text("Recycle Bin") }, label = { Text(stringResource(R.string.navigation_recycle_bin)) },
icon = { Icon(Icons.Default.Delete, contentDescription = "Recycle Bin") }, icon = { Icon(Icons.Default.Delete, contentDescription = stringResource(R.string.navigation_recycle_bin)) },
selected = currentDestination is AppDestination.RecycleBin, selected = currentDestination is AppDestination.RecycleBin,
onClick = { viewModel.navigateTo(AppDestination.RecycleBin.route, currentDestination.route) }, onClick = { viewModel.navigateTo(AppDestination.RecycleBin.route, currentDestination.route) },
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding) modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
) )
NavigationDrawerItem( NavigationDrawerItem(
label = { Text("Edit Lists") }, label = { Text(stringResource(R.string.navigation_edit_lists)) },
icon = { Icon(Icons.Default.EditNote, contentDescription = "Edit Lists") }, icon = { Icon(Icons.Default.EditNote, contentDescription = stringResource(R.string.navigation_edit_lists)) },
selected = currentDestination is AppDestination.ManageLists, selected = currentDestination is AppDestination.ManageLists,
onClick = { viewModel.navigateTo(AppDestination.ManageLists.route, currentDestination.route) }, onClick = { viewModel.navigateTo(AppDestination.ManageLists.route, currentDestination.route) },
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding) modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)

View File

@@ -26,10 +26,12 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.alpha
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.wismna.geoffroy.donext.R
import com.wismna.geoffroy.donext.presentation.viewmodel.RecycleBinViewModel import com.wismna.geoffroy.donext.presentation.viewmodel.RecycleBinViewModel
@Composable @Composable
@@ -53,7 +55,7 @@ fun RecycleBinScreen(
modifier = Modifier.size(60.dp), modifier = Modifier.size(60.dp),
tint = MaterialTheme.colorScheme.secondary tint = MaterialTheme.colorScheme.secondary
) )
Text("Recycle Bin is empty", color = MaterialTheme.colorScheme.secondary) Text(stringResource(R.string.recycle_bin_no_tasks), color = MaterialTheme.colorScheme.secondary)
} }
} }
return return
@@ -65,9 +67,9 @@ fun RecycleBinScreen(
if (taskToDelete != null) { if (taskToDelete != null) {
AlertDialog( AlertDialog(
onDismissRequest = { viewModel.onCancelDelete() }, onDismissRequest = { viewModel.onCancelDelete() },
title = { Text("Delete task") }, title = { Text(stringResource(R.string.dialog_delete_task_title)) },
text = { text = {
Text("Are you sure you want to permanently delete this task? This cannot be undone.") Text(stringResource(R.string.dialog_delete_task_description))
}, },
confirmButton = { confirmButton = {
TextButton( TextButton(
@@ -79,12 +81,12 @@ fun RecycleBinScreen(
contentColor = MaterialTheme.colorScheme.error contentColor = MaterialTheme.colorScheme.error
) )
) { ) {
Text("Delete") Text(stringResource(R.string.dialog_delete_task_delete))
} }
}, },
dismissButton = { dismissButton = {
TextButton(onClick = { viewModel.onCancelDelete() }) { TextButton(onClick = { viewModel.onCancelDelete() }) {
Text("Cancel") Text(stringResource(R.string.dialog_delete_task_cancel))
} }
} }
) )
@@ -132,7 +134,7 @@ fun EmptyRecycleBinAction(viewModel: RecycleBinViewModel = hiltViewModel()) {
Icon( Icon(
Icons.Default.DeleteSweep, Icons.Default.DeleteSweep,
modifier = Modifier.alpha(if (isEmpty) 0.5f else 1.0f), modifier = Modifier.alpha(if (isEmpty) 0.5f else 1.0f),
contentDescription = "Empty Recycle Bin", contentDescription = stringResource(R.string.dialog_empty_task_title),
tint = MaterialTheme.colorScheme.onPrimaryContainer tint = MaterialTheme.colorScheme.onPrimaryContainer
) )
} }
@@ -140,9 +142,9 @@ fun EmptyRecycleBinAction(viewModel: RecycleBinViewModel = hiltViewModel()) {
if (emptyRecycleBin) { if (emptyRecycleBin) {
AlertDialog( AlertDialog(
onDismissRequest = { viewModel.onCancelEmptyRecycleBinRequest() }, onDismissRequest = { viewModel.onCancelEmptyRecycleBinRequest() },
title = { Text("Empty Recycle Bin") }, title = { Text(stringResource(R.string.dialog_empty_task_title)) },
text = { text = {
Text("Are you sure you want to permanently delete all tasks in the recycle bin? This cannot be undone.") Text(stringResource(R.string.dialog_empty_task_description))
}, },
confirmButton = { confirmButton = {
TextButton( TextButton(
@@ -153,12 +155,12 @@ fun EmptyRecycleBinAction(viewModel: RecycleBinViewModel = hiltViewModel()) {
contentColor = MaterialTheme.colorScheme.error contentColor = MaterialTheme.colorScheme.error
) )
) { ) {
Text("Delete") Text(stringResource(R.string.dialog_empty_task_delete))
} }
}, },
dismissButton = { dismissButton = {
TextButton(onClick = { viewModel.onCancelEmptyRecycleBinRequest() }) { TextButton(onClick = { viewModel.onCancelEmptyRecycleBinRequest() }) {
Text("Cancel") Text(stringResource(R.string.dialog_empty_task_cancel))
} }
} }
) )

View File

@@ -32,11 +32,13 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.wismna.geoffroy.donext.R
import com.wismna.geoffroy.donext.domain.model.Priority import com.wismna.geoffroy.donext.domain.model.Priority
import com.wismna.geoffroy.donext.domain.model.Task import com.wismna.geoffroy.donext.domain.model.Task
import com.wismna.geoffroy.donext.presentation.viewmodel.TaskItemViewModel import com.wismna.geoffroy.donext.presentation.viewmodel.TaskItemViewModel
@@ -57,7 +59,6 @@ fun TaskItemScreen(
else if (it == SwipeToDismissBoxValue.EndToStart) onSwipeLeft() else if (it == SwipeToDismissBoxValue.EndToStart) onSwipeLeft()
return@rememberSwipeToDismissBoxState false return@rememberSwipeToDismissBoxState false
}, },
// positional threshold of 25%
positionalThreshold = { it * .25f } positionalThreshold = { it * .25f }
) )
@@ -184,12 +185,12 @@ fun DismissBackground(dismissState: SwipeToDismissBoxState, isDone: Boolean, isD
Icon( Icon(
if (isDeleted) Icons.Default.DeleteForever else Icons.Default.DeleteOutline, if (isDeleted) Icons.Default.DeleteForever else Icons.Default.DeleteOutline,
tint = Color.LightGray, tint = Color.LightGray,
contentDescription = "Delete" contentDescription = stringResource(R.string.task_action_delete)
) )
Text( Text(
color = MaterialTheme.colorScheme.onPrimary, color = MaterialTheme.colorScheme.onPrimary,
fontSize = 10.sp, fontSize = 10.sp,
text = if (isDeleted) "Delete" else "Recycle" text = if (isDeleted) stringResource(R.string.task_action_delete) else stringResource(R.string.task_action_recycle)
) )
} }
Spacer(modifier = Modifier) Spacer(modifier = Modifier)
@@ -198,12 +199,16 @@ fun DismissBackground(dismissState: SwipeToDismissBoxState, isDone: Boolean, isD
if (isDeleted) Icons.Default.RestoreFromTrash else if (isDeleted) Icons.Default.RestoreFromTrash else
if (isDone) Icons.Outlined.Unpublished else Icons.Outlined.CheckCircle, if (isDone) Icons.Outlined.Unpublished else Icons.Outlined.CheckCircle,
tint = Color.LightGray, tint = Color.LightGray,
contentDescription = "Archive" contentDescription = stringResource(R.string.task_action_done)
) )
Text( Text(
color = MaterialTheme.colorScheme.onPrimary, color = MaterialTheme.colorScheme.onPrimary,
fontSize = 10.sp, fontSize = 10.sp,
text = if (isDeleted) "Restore" else if (isDone) "Undone" else "Done" text = stringResource(
if (isDeleted) R.string.task_action_restore
else
if (isDone) R.string.task_action_undone
else R.string.task_action_done)
) )
} }
} }

View File

@@ -14,8 +14,10 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import com.wismna.geoffroy.donext.R
import com.wismna.geoffroy.donext.presentation.viewmodel.TaskListViewModel import com.wismna.geoffroy.donext.presentation.viewmodel.TaskListViewModel
@Composable @Composable
@@ -31,7 +33,7 @@ fun TaskListScreen(
modifier = modifier.fillMaxSize(), modifier = modifier.fillMaxSize(),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
Text("Tap + to create a new task.") Text(stringResource(R.string.tasklist_no_tasks))
} }
return return
} }

View File

@@ -36,8 +36,10 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import com.wismna.geoffroy.donext.R
import com.wismna.geoffroy.donext.domain.extension.toLocalDate import com.wismna.geoffroy.donext.domain.extension.toLocalDate
import com.wismna.geoffroy.donext.domain.model.Priority import com.wismna.geoffroy.donext.domain.model.Priority
import com.wismna.geoffroy.donext.presentation.viewmodel.TaskViewModel import com.wismna.geoffroy.donext.presentation.viewmodel.TaskViewModel
@@ -72,7 +74,7 @@ fun TaskScreen(
singleLine = true, singleLine = true,
readOnly = viewModel.isDeleted, readOnly = viewModel.isDeleted,
onValueChange = { viewModel.onTitleChanged(it) }, onValueChange = { viewModel.onTitleChanged(it) },
label = { Text("Title") }, label = { Text(stringResource(R.string.task_name)) },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.focusRequester(titleFocusRequester) .focusRequester(titleFocusRequester)
@@ -84,7 +86,7 @@ fun TaskScreen(
value = viewModel.description, value = viewModel.description,
readOnly = viewModel.isDeleted, readOnly = viewModel.isDeleted,
onValueChange = { viewModel.onDescriptionChanged(it) }, onValueChange = { viewModel.onDescriptionChanged(it) },
label = { Text("Description") }, label = { Text(stringResource(R.string.task_description)) },
maxLines = 3, maxLines = 3,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) )
@@ -96,7 +98,7 @@ fun TaskScreen(
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Text("Priority", style = MaterialTheme.typography.labelLarge) Text(stringResource(R.string.task_priority), style = MaterialTheme.typography.labelLarge)
SingleChoiceSegmentedButton( SingleChoiceSegmentedButton(
value = viewModel.priority, value = viewModel.priority,
isEnabled = !viewModel.isDeleted, isEnabled = !viewModel.isDeleted,
@@ -116,7 +118,7 @@ fun TaskScreen(
value = formattedDate, value = formattedDate,
onValueChange = {}, onValueChange = {},
readOnly = true, readOnly = true,
label = { Text("Due Date") }, label = { Text(stringResource(R.string.task_due_date)) },
trailingIcon = { trailingIcon = {
Row { Row {
if (viewModel.dueDate != null) { if (viewModel.dueDate != null) {
@@ -159,10 +161,10 @@ fun TaskScreen(
onClick = { onClick = {
datePickerState.selectedDateMillis?.let { viewModel.onDueDateChanged(it) } datePickerState.selectedDateMillis?.let { viewModel.onDueDateChanged(it) }
showDatePicker = false showDatePicker = false
}) { Text("OK") } }) { Text(stringResource(R.string.dialog_due_date_ok)) }
}, },
dismissButton = { dismissButton = {
TextButton(onClick = { showDatePicker = false }) { Text("Cancel") } TextButton(onClick = { showDatePicker = false }) { Text(stringResource(R.string.dialog_due_date_cancel)) }
} }
) { ) {
DatePicker(state = datePickerState) DatePicker(state = datePickerState)
@@ -191,7 +193,7 @@ fun TaskScreen(
}, },
enabled = viewModel.title.isNotBlank() && !viewModel.isDeleted, enabled = viewModel.title.isNotBlank() && !viewModel.isDeleted,
) { ) {
Text(if (viewModel.isEditing()) "Save" else "Create") Text(stringResource(if (viewModel.isEditing()) R.string.task_save_edit else R.string.task_save_new))
} }
} }
} }
@@ -215,7 +217,7 @@ fun SingleChoiceSegmentedButton(
enabled = isEnabled, enabled = isEnabled,
onClick = { onValueChange(Priority.fromValue(index)) }, onClick = { onValueChange(Priority.fromValue(index)) },
selected = index == value.value, selected = index == value.value,
label = { Text(label) } label = { Text(stringResource(label)) }
) )
} }
} }

View File

@@ -1,4 +1,61 @@
<resources> <resources>
<string name="app_name">DoNext</string> <string name="app_name">DoNext</string>
<string name="title_activity_main">MainActivity</string> <string name="title_activity_main">MainActivity</string>
<string name="navigation_title">DoNext v2</string>
<string name="navigation_edit_lists">Edit lists</string>
<string name="navigation_recycle_bin">Recycle Bin</string>
<string name="navigation_due_today">Due Today</string>
<string name="action_create_list">Create a task</string>
<string name="tasklist_no_tasks">Tap + to create a new task.</string>
<string name="recycle_bin_no_tasks">Recycle Bin is empty</string>
<string name="today_no_tasks">Nothing due today!</string>
<string name="task_title_new">New Task</string>
<string name="task_title_edit">Edit Task</string>
<string name="task_name">Title</string>
<string name="task_description">Description</string>
<string name="task_priority">Priority</string>
<string name="task_priority_low">Low</string>
<string name="task_priority_normal">Normal</string>
<string name="task_priority_high">High</string>
<string name="task_due_date">Due Date</string>
<string name="task_save_new">Create</string>
<string name="task_save_edit">Save</string>
<string name="task_cancel">Cancel</string>
<string name="due_date_yesterday">Yesterday</string>
<string name="due_date_today">Today</string>
<string name="due_date_tomorrow">Tomorrow</string>
<string name="task_action_recycle">Recycle</string>
<string name="task_action_delete">Delete</string>
<string name="task_action_restore">Restore</string>
<string name="task_action_done">Done</string>
<string name="task_action_undone">Undone</string>
<string name="dialog_due_date_ok">OK</string>
<string name="dialog_due_date_cancel">Cancel</string>
<string name="dialog_delete_task_title">Delete task</string>
<string name="dialog_delete_task_description">Are you sure you want to permanently delete this task? This cannot be undone.</string>
<string name="dialog_delete_task_cancel">Cancel</string>
<string name="dialog_delete_task_delete">Delete</string>
<string name="dialog_empty_task_title">Empty Recycle Bin</string>
<string name="dialog_empty_task_description">Are you sure you want to permanently delete all tasks in the recycle bin? This cannot be undone.</string>
<string name="dialog_empty_task_cancel">Cancel</string>
<string name="dialog_empty_task_delete">Empty</string>
<string name="tasklist_new_title">New list</string>
<string name="tasklist_new_name">Title</string>
<string name="tasklist_new_create">Create</string>
<string name="snackbar_message_done">Task done</string>
<string name="snackbar_message_undone">Task undone</string>
<string name="snackbar_message_recycle">Task moved to recycle bin</string>
<string name="snackbar_message_restore">Task restored</string>
<string name="snackbar_action">Undo</string>
</resources> </resources>