diff --git a/donextv2/src/main/java/com/wismna/geoffroy/donext/domain/model/Priority.kt b/donextv2/src/main/java/com/wismna/geoffroy/donext/domain/model/Priority.kt index 249a536..a7dc1ee 100644 --- a/donextv2/src/main/java/com/wismna/geoffroy/donext/domain/model/Priority.kt +++ b/donextv2/src/main/java/com/wismna/geoffroy/donext/domain/model/Priority.kt @@ -1,9 +1,11 @@ package com.wismna.geoffroy.donext.domain.model -enum class Priority(val value: Int, val label: String) { - LOW(0, "Low"), - NORMAL(1, "Normal"), - HIGH(2, "High"); +import com.wismna.geoffroy.donext.R + +enum class Priority(val value: Int, val label: Int) { + LOW(0, R.string.task_priority_low), + NORMAL(1, R.string.task_priority_normal), + HIGH(2, R.string.task_priority_high); companion object { fun fromValue(value: Int): Priority = diff --git a/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/DueTodayTasksScreen.kt b/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/DueTodayTasksScreen.kt index 7de745f..3499b0b 100644 --- a/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/DueTodayTasksScreen.kt +++ b/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/DueTodayTasksScreen.kt @@ -15,8 +15,10 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import com.wismna.geoffroy.donext.R import com.wismna.geoffroy.donext.presentation.viewmodel.DueTodayViewModel @Composable @@ -38,7 +40,7 @@ fun DueTodayTasksScreen( contentDescription = "Due today background icon", modifier = Modifier.size(60.dp), tint = MaterialTheme.colorScheme.secondary) - Text("Nothing due today !", color = MaterialTheme.colorScheme.secondary) + Text(stringResource(R.string.today_no_tasks), color = MaterialTheme.colorScheme.secondary) } } } else { diff --git a/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/MainScreen.kt b/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/MainScreen.kt index a9160a6..b0e539f 100644 --- a/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/MainScreen.kt +++ b/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/MainScreen.kt @@ -57,6 +57,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog 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.rememberNavController import androidx.navigation.navArgument +import com.wismna.geoffroy.donext.R import com.wismna.geoffroy.donext.domain.model.AppDestination import com.wismna.geoffroy.donext.presentation.ui.events.UiEvent import com.wismna.geoffroy.donext.presentation.viewmodel.MainViewModel @@ -197,6 +199,7 @@ fun AppContent( ) { val scope = rememberCoroutineScope() val snackbarHostState = remember { SnackbarHostState() } + val snackbarActionLabel = stringResource(R.string.snackbar_action) LaunchedEffect(Unit) { viewModel.uiEventBus.events.collectLatest { event -> @@ -209,7 +212,7 @@ fun AppContent( is UiEvent.ShowUndoSnackbar -> { val result = snackbarHostState.showSnackbar( message = event.message, - actionLabel = "Undo", + actionLabel = snackbarActionLabel, duration = SnackbarDuration.Short ) if (result == SnackbarResult.ActionPerformed) { @@ -283,7 +286,7 @@ fun AppContent( ExtendedFloatingActionButton( onClick = { viewModel.onNewTaskButtonClicked(dest.taskListId) }, icon = { Icon(Icons.Filled.Add, "Create a task.") }, - text = { Text("Create a task") }, + text = { Text(stringResource(R.string.action_create_list)) }, ) } else -> null diff --git a/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/ManageListsScreen.kt b/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/ManageListsScreen.kt index d6ed644..d169395 100644 --- a/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/ManageListsScreen.kt +++ b/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/ManageListsScreen.kt @@ -45,12 +45,14 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier 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.clearAndSetSemantics import androidx.compose.ui.semantics.customActions import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import com.wismna.geoffroy.donext.R import com.wismna.geoffroy.donext.presentation.viewmodel.ManageListsViewModel import sh.calvin.reorderable.ReorderableItem import sh.calvin.reorderable.rememberReorderableLazyListState @@ -69,7 +71,7 @@ fun ManageListsScreen( modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { - Text("Tap + to create a new task list.") + Text(stringResource(R.string.tasklist_no_tasks)) } return } @@ -231,7 +233,7 @@ fun AddListScreen( //var description by remember { mutableStateOf("") } 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)) /*TextField( @@ -244,7 +246,7 @@ fun AddListScreen( value = name, singleLine = true, onValueChange = { name = it }, - label = { Text("Title") }, + label = { Text(stringResource(R.string.tasklist_new_name)) }, modifier = Modifier .fillMaxWidth() .focusRequester(titleFocusRequester) @@ -272,7 +274,7 @@ fun AddListScreen( }, enabled = name.isNotBlank() ) { - Text("Create") + Text(stringResource(R.string.tasklist_new_create)) } } } diff --git a/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/MenuScreen.kt b/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/MenuScreen.kt index ce81c44..50cca34 100644 --- a/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/MenuScreen.kt +++ b/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/MenuScreen.kt @@ -21,9 +21,11 @@ import androidx.compose.material3.NavigationDrawerItemDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp 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.presentation.viewmodel.MenuViewModel @@ -46,18 +48,18 @@ fun MenuScreen( ) { Column { Text( - text = "DoNext v2", + text = stringResource(R.string.navigation_title), style = MaterialTheme.typography.titleMedium, modifier = Modifier.padding(16.dp) ) NavigationDrawerItem( label = { Row (modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { - Text("Due Today") + Text(stringResource(R.string.navigation_due_today)) 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, onClick = { viewModel.navigateTo(AppDestination.DueTodayList.route, currentDestination.route) }, modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding) @@ -89,15 +91,15 @@ fun MenuScreen( Column { HorizontalDivider() NavigationDrawerItem( - label = { Text("Recycle Bin") }, - icon = { Icon(Icons.Default.Delete, contentDescription = "Recycle Bin") }, + label = { Text(stringResource(R.string.navigation_recycle_bin)) }, + icon = { Icon(Icons.Default.Delete, contentDescription = stringResource(R.string.navigation_recycle_bin)) }, selected = currentDestination is AppDestination.RecycleBin, onClick = { viewModel.navigateTo(AppDestination.RecycleBin.route, currentDestination.route) }, modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding) ) NavigationDrawerItem( - label = { Text("Edit Lists") }, - icon = { Icon(Icons.Default.EditNote, contentDescription = "Edit Lists") }, + label = { Text(stringResource(R.string.navigation_edit_lists)) }, + icon = { Icon(Icons.Default.EditNote, contentDescription = stringResource(R.string.navigation_edit_lists)) }, selected = currentDestination is AppDestination.ManageLists, onClick = { viewModel.navigateTo(AppDestination.ManageLists.route, currentDestination.route) }, modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding) diff --git a/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/RecycleBinScreen.kt b/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/RecycleBinScreen.kt index a4cdd98..59a499c 100644 --- a/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/RecycleBinScreen.kt +++ b/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/RecycleBinScreen.kt @@ -26,10 +26,12 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.wismna.geoffroy.donext.R import com.wismna.geoffroy.donext.presentation.viewmodel.RecycleBinViewModel @Composable @@ -53,7 +55,7 @@ fun RecycleBinScreen( modifier = Modifier.size(60.dp), 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 @@ -65,9 +67,9 @@ fun RecycleBinScreen( if (taskToDelete != null) { AlertDialog( onDismissRequest = { viewModel.onCancelDelete() }, - title = { Text("Delete task") }, + title = { Text(stringResource(R.string.dialog_delete_task_title)) }, 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 = { TextButton( @@ -79,12 +81,12 @@ fun RecycleBinScreen( contentColor = MaterialTheme.colorScheme.error ) ) { - Text("Delete") + Text(stringResource(R.string.dialog_delete_task_delete)) } }, dismissButton = { TextButton(onClick = { viewModel.onCancelDelete() }) { - Text("Cancel") + Text(stringResource(R.string.dialog_delete_task_cancel)) } } ) @@ -132,7 +134,7 @@ fun EmptyRecycleBinAction(viewModel: RecycleBinViewModel = hiltViewModel()) { Icon( Icons.Default.DeleteSweep, 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 ) } @@ -140,9 +142,9 @@ fun EmptyRecycleBinAction(viewModel: RecycleBinViewModel = hiltViewModel()) { if (emptyRecycleBin) { AlertDialog( onDismissRequest = { viewModel.onCancelEmptyRecycleBinRequest() }, - title = { Text("Empty Recycle Bin") }, + title = { Text(stringResource(R.string.dialog_empty_task_title)) }, 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 = { TextButton( @@ -153,12 +155,12 @@ fun EmptyRecycleBinAction(viewModel: RecycleBinViewModel = hiltViewModel()) { contentColor = MaterialTheme.colorScheme.error ) ) { - Text("Delete") + Text(stringResource(R.string.dialog_empty_task_delete)) } }, dismissButton = { TextButton(onClick = { viewModel.onCancelEmptyRecycleBinRequest() }) { - Text("Cancel") + Text(stringResource(R.string.dialog_empty_task_cancel)) } } ) diff --git a/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/TaskItemScreen.kt b/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/TaskItemScreen.kt index 6598e97..74ffbc5 100644 --- a/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/TaskItemScreen.kt +++ b/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/TaskItemScreen.kt @@ -32,11 +32,13 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp 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.Task import com.wismna.geoffroy.donext.presentation.viewmodel.TaskItemViewModel @@ -57,7 +59,6 @@ fun TaskItemScreen( else if (it == SwipeToDismissBoxValue.EndToStart) onSwipeLeft() return@rememberSwipeToDismissBoxState false }, - // positional threshold of 25% positionalThreshold = { it * .25f } ) @@ -184,12 +185,12 @@ fun DismissBackground(dismissState: SwipeToDismissBoxState, isDone: Boolean, isD Icon( if (isDeleted) Icons.Default.DeleteForever else Icons.Default.DeleteOutline, tint = Color.LightGray, - contentDescription = "Delete" + contentDescription = stringResource(R.string.task_action_delete) ) Text( color = MaterialTheme.colorScheme.onPrimary, 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) @@ -198,12 +199,16 @@ fun DismissBackground(dismissState: SwipeToDismissBoxState, isDone: Boolean, isD if (isDeleted) Icons.Default.RestoreFromTrash else if (isDone) Icons.Outlined.Unpublished else Icons.Outlined.CheckCircle, tint = Color.LightGray, - contentDescription = "Archive" + contentDescription = stringResource(R.string.task_action_done) ) Text( color = MaterialTheme.colorScheme.onPrimary, 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) ) } } diff --git a/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/TaskListScreen.kt b/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/TaskListScreen.kt index 029ad27..a7a3b16 100644 --- a/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/TaskListScreen.kt +++ b/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/TaskListScreen.kt @@ -14,8 +14,10 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import com.wismna.geoffroy.donext.R import com.wismna.geoffroy.donext.presentation.viewmodel.TaskListViewModel @Composable @@ -31,7 +33,7 @@ fun TaskListScreen( modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { - Text("Tap + to create a new task.") + Text(stringResource(R.string.tasklist_no_tasks)) } return } diff --git a/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/TaskScreen.kt b/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/TaskScreen.kt index b791f02..2231801 100644 --- a/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/TaskScreen.kt +++ b/donextv2/src/main/java/com/wismna/geoffroy/donext/presentation/screen/TaskScreen.kt @@ -36,8 +36,10 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier 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.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.model.Priority import com.wismna.geoffroy.donext.presentation.viewmodel.TaskViewModel @@ -72,7 +74,7 @@ fun TaskScreen( singleLine = true, readOnly = viewModel.isDeleted, onValueChange = { viewModel.onTitleChanged(it) }, - label = { Text("Title") }, + label = { Text(stringResource(R.string.task_name)) }, modifier = Modifier .fillMaxWidth() .focusRequester(titleFocusRequester) @@ -84,7 +86,7 @@ fun TaskScreen( value = viewModel.description, readOnly = viewModel.isDeleted, onValueChange = { viewModel.onDescriptionChanged(it) }, - label = { Text("Description") }, + label = { Text(stringResource(R.string.task_description)) }, maxLines = 3, modifier = Modifier.fillMaxWidth() ) @@ -96,7 +98,7 @@ fun TaskScreen( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - Text("Priority", style = MaterialTheme.typography.labelLarge) + Text(stringResource(R.string.task_priority), style = MaterialTheme.typography.labelLarge) SingleChoiceSegmentedButton( value = viewModel.priority, isEnabled = !viewModel.isDeleted, @@ -116,7 +118,7 @@ fun TaskScreen( value = formattedDate, onValueChange = {}, readOnly = true, - label = { Text("Due Date") }, + label = { Text(stringResource(R.string.task_due_date)) }, trailingIcon = { Row { if (viewModel.dueDate != null) { @@ -159,10 +161,10 @@ fun TaskScreen( onClick = { datePickerState.selectedDateMillis?.let { viewModel.onDueDateChanged(it) } showDatePicker = false - }) { Text("OK") } + }) { Text(stringResource(R.string.dialog_due_date_ok)) } }, dismissButton = { - TextButton(onClick = { showDatePicker = false }) { Text("Cancel") } + TextButton(onClick = { showDatePicker = false }) { Text(stringResource(R.string.dialog_due_date_cancel)) } } ) { DatePicker(state = datePickerState) @@ -191,7 +193,7 @@ fun TaskScreen( }, 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, onClick = { onValueChange(Priority.fromValue(index)) }, selected = index == value.value, - label = { Text(label) } + label = { Text(stringResource(label)) } ) } } diff --git a/donextv2/src/main/res/values/strings.xml b/donextv2/src/main/res/values/strings.xml index a751aca..adc49a6 100644 --- a/donextv2/src/main/res/values/strings.xml +++ b/donextv2/src/main/res/values/strings.xml @@ -1,4 +1,61 @@ DoNext MainActivity + + DoNext v2 + Edit lists + Recycle Bin + Due Today + + Create a task + + Tap + to create a new task. + Recycle Bin is empty + Nothing due today! + + New Task + Edit Task + Title + Description + Priority + Low + Normal + High + Due Date + Create + Save + Cancel + + Yesterday + Today + Tomorrow + + Recycle + Delete + Restore + Done + Undone + + OK + Cancel + + Delete task + Are you sure you want to permanently delete this task? This cannot be undone. + Cancel + Delete + + Empty Recycle Bin + Are you sure you want to permanently delete all tasks in the recycle bin? This cannot be undone. + Cancel + Empty + + New list + Title + Create + + Task done + Task undone + Task moved to recycle bin + Task restored + Undo \ No newline at end of file