609 lines
25 KiB
Python
609 lines
25 KiB
Python
import sys
|
||
|
||
with open('c:/dev/git/Android/ShaarIt/app/src/main/java/com/shaarit/presentation/todo/TodoScreen.kt', 'r', encoding='utf-8') as f:
|
||
lines = f.readlines()
|
||
|
||
replacement = \"\"\"// ====== Edit / Create Todo Screen ======
|
||
|
||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
|
||
@Composable
|
||
private fun EditTodoDialog(
|
||
state: EditTodoDialogUiState,
|
||
groupNames: List<String>,
|
||
timezoneId: String = java.util.TimeZone.getDefault().id,
|
||
onDismiss: () -> Unit,
|
||
onContentChanged: (String) -> Unit,
|
||
onDueDateChanged: (Long?) -> Unit,
|
||
onGroupChanged: (String) -> Unit,
|
||
onNewSubtaskTextChanged: (String) -> Unit,
|
||
onAddSubtask: () -> Unit,
|
||
onRemoveSubtask: (Int) -> Unit,
|
||
onToggleSubtask: (Int) -> Unit,
|
||
onUpdateSubtaskContent: (Int, String) -> Unit,
|
||
onNewTagTextChanged: (String) -> Unit,
|
||
onAddTag: () -> Unit,
|
||
onRemoveTag: (String) -> Unit,
|
||
onSave: () -> Unit
|
||
) {
|
||
var showDatePicker by remember { mutableStateOf(false) }
|
||
|
||
androidx.compose.ui.window.Dialog(
|
||
onDismissRequest = onDismiss,
|
||
properties = androidx.compose.ui.window.DialogProperties(
|
||
usePlatformDefaultWidth = false,
|
||
decorFitsSystemWindows = true
|
||
)
|
||
) {
|
||
Scaffold(
|
||
topBar = {
|
||
TopAppBar(
|
||
title = { },
|
||
navigationIcon = {
|
||
IconButton(onClick = onSave, enabled = !state.isSaving && state.content.isNotBlank()) {
|
||
if (state.isSaving) {
|
||
CircularProgressIndicator(modifier = Modifier.size(24.dp))
|
||
} else {
|
||
Icon(Icons.Default.Check, contentDescription = "Enregistrer")
|
||
}
|
||
}
|
||
},
|
||
actions = {
|
||
IconButton(onClick = onDismiss) {
|
||
Icon(Icons.Default.Close, contentDescription = "Fermer")
|
||
}
|
||
},
|
||
colors = TopAppBarDefaults.topAppBarColors(
|
||
containerColor = MaterialTheme.colorScheme.surface
|
||
)
|
||
)
|
||
},
|
||
containerColor = MaterialTheme.colorScheme.surface
|
||
) { paddingValues ->
|
||
Column(
|
||
modifier = Modifier
|
||
.fillMaxSize()
|
||
.padding(paddingValues)
|
||
.verticalScroll(rememberScrollState())
|
||
) {
|
||
// Task Title
|
||
Row(
|
||
verticalAlignment = Alignment.Top,
|
||
modifier = Modifier.padding(16.dp).fillMaxWidth()
|
||
) {
|
||
Icon(
|
||
androidx.compose.material.icons.outlined.CheckBoxOutlineBlank,
|
||
contentDescription = null,
|
||
tint = MaterialTheme.colorScheme.primary,
|
||
modifier = Modifier.padding(top = 4.dp)
|
||
)
|
||
Spacer(Modifier.width(16.dp))
|
||
androidx.compose.foundation.text.BasicTextField(
|
||
value = state.content,
|
||
onValueChange = onContentChanged,
|
||
textStyle = MaterialTheme.typography.titleLarge.copy(color = MaterialTheme.colorScheme.onSurface),
|
||
modifier = Modifier.fillMaxWidth(),
|
||
keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Sentences),
|
||
decorationBox = { innerTextField ->
|
||
if (state.content.isEmpty()) {
|
||
Text("Nom de la t<>che", color = MaterialTheme.colorScheme.onSurfaceVariant, style = MaterialTheme.typography.titleLarge)
|
||
}
|
||
innerTextField()
|
||
}
|
||
)
|
||
}
|
||
|
||
androidx.compose.material3.HorizontalDivider(color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f))
|
||
|
||
// Due Date
|
||
val dateText = state.dueDate?.let { formatDateTime(it, timezoneId) } ?: "Aucune date d'<EFBFBD>ch<EFBFBD>ance"
|
||
TaskActionRow(
|
||
icon = Icons.Default.Schedule,
|
||
text = dateText,
|
||
onClick = { showDatePicker = true },
|
||
isSet = state.dueDate != null
|
||
)
|
||
|
||
androidx.compose.material3.HorizontalDivider(color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f))
|
||
|
||
// Group (Famille)
|
||
TaskGroupRow(
|
||
groupName = state.groupName,
|
||
groupNames = groupNames,
|
||
onGroupChanged = onGroupChanged
|
||
)
|
||
|
||
androidx.compose.material3.HorizontalDivider(color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f))
|
||
|
||
// Tags
|
||
TaskTagsRow(
|
||
tags = state.tags,
|
||
newTagText = state.newTagText,
|
||
onNewTagTextChanged = onNewTagTextChanged,
|
||
onAddTag = onAddTag,
|
||
onRemoveTag = onRemoveTag
|
||
)
|
||
|
||
androidx.compose.material3.HorizontalDivider(color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f))
|
||
|
||
// Subtasks
|
||
TaskSubtasksSection(
|
||
subtasks = state.subtasks,
|
||
newSubtaskText = state.newSubtaskText,
|
||
onNewSubtaskTextChanged = onNewSubtaskTextChanged,
|
||
onAddSubtask = onAddSubtask,
|
||
onRemoveSubtask = onRemoveSubtask,
|
||
onToggleSubtask = onToggleSubtask,
|
||
onUpdateSubtaskContent = onUpdateSubtaskContent
|
||
)
|
||
|
||
Spacer(modifier = Modifier.height(32.dp))
|
||
}
|
||
}
|
||
|
||
if (showDatePicker) {
|
||
DateTimePickerBottomSheet(
|
||
initialDate = state.dueDate,
|
||
timezoneId = timezoneId,
|
||
onDismiss = { showDatePicker = false },
|
||
onDateSelected = onDueDateChanged
|
||
)
|
||
}
|
||
}
|
||
}
|
||
|
||
@Composable
|
||
private fun TaskActionRow(
|
||
icon: androidx.compose.ui.graphics.vector.ImageVector,
|
||
text: String,
|
||
onClick: () -> Unit = {},
|
||
isSet: Boolean = false
|
||
) {
|
||
Row(
|
||
modifier = Modifier
|
||
.fillMaxWidth()
|
||
.clickable(onClick = onClick)
|
||
.padding(horizontal = 16.dp, vertical = 16.dp),
|
||
verticalAlignment = Alignment.CenterVertically
|
||
) {
|
||
Icon(
|
||
icon,
|
||
contentDescription = null,
|
||
tint = if (isSet) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant
|
||
)
|
||
Spacer(modifier = Modifier.width(16.dp))
|
||
Text(
|
||
text,
|
||
color = if (isSet) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant,
|
||
style = MaterialTheme.typography.bodyLarge
|
||
)
|
||
}
|
||
}
|
||
|
||
@Composable
|
||
private fun TaskGroupRow(
|
||
groupName: String,
|
||
groupNames: List<String>,
|
||
onGroupChanged: (String) -> Unit
|
||
) {
|
||
var expanded by remember { mutableStateOf(false) }
|
||
var isEditing by remember { mutableStateOf(false) }
|
||
var customGroup by remember { mutableStateOf("") }
|
||
|
||
Row(
|
||
modifier = Modifier
|
||
.fillMaxWidth()
|
||
.clickable { expanded = true }
|
||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||
verticalAlignment = Alignment.CenterVertically
|
||
) {
|
||
Icon(Icons.Default.List, contentDescription = null, tint = MaterialTheme.colorScheme.onSurfaceVariant)
|
||
Spacer(modifier = Modifier.width(16.dp))
|
||
|
||
if (groupName.isNotBlank()) {
|
||
Surface(
|
||
color = MaterialTheme.colorScheme.surfaceVariant,
|
||
shape = MaterialTheme.shapes.small,
|
||
onClick = { expanded = true }
|
||
) {
|
||
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp)) {
|
||
Icon(Icons.Default.List, contentDescription = null, modifier = Modifier.size(16.dp))
|
||
Spacer(Modifier.width(6.dp))
|
||
Text(groupName.uppercase(), style = MaterialTheme.typography.labelMedium)
|
||
}
|
||
}
|
||
} else {
|
||
Text("Aucune liste", color = MaterialTheme.colorScheme.onSurfaceVariant, style = MaterialTheme.typography.bodyLarge)
|
||
}
|
||
|
||
androidx.compose.material3.DropdownMenu(
|
||
expanded = expanded,
|
||
onDismissRequest = { expanded = false }
|
||
) {
|
||
androidx.compose.material3.DropdownMenuItem(
|
||
text = { Text("Aucune liste") },
|
||
onClick = { onGroupChanged(""); expanded = false }
|
||
)
|
||
groupNames.forEach { group ->
|
||
androidx.compose.material3.DropdownMenuItem(
|
||
text = { Text(group) },
|
||
onClick = { onGroupChanged(group); expanded = false }
|
||
)
|
||
}
|
||
androidx.compose.material3.HorizontalDivider()
|
||
androidx.compose.material3.DropdownMenuItem(
|
||
text = { Text("Nouvelle liste...") },
|
||
onClick = { isEditing = true; expanded = false }
|
||
)
|
||
}
|
||
}
|
||
|
||
if (isEditing) {
|
||
AlertDialog(
|
||
onDismissRequest = { isEditing = false },
|
||
title = { Text("Nouvelle liste") },
|
||
text = {
|
||
OutlinedTextField(
|
||
value = customGroup,
|
||
onValueChange = { customGroup = it },
|
||
singleLine = true,
|
||
placeholder = { Text("Nom de la liste") }
|
||
)
|
||
},
|
||
confirmButton = {
|
||
TextButton(onClick = {
|
||
if (customGroup.isNotBlank()) {
|
||
onGroupChanged(customGroup)
|
||
}
|
||
isEditing = false
|
||
}) { Text("Ajouter") }
|
||
},
|
||
dismissButton = {
|
||
TextButton(onClick = { isEditing = false }) { Text("Annuler") }
|
||
}
|
||
)
|
||
}
|
||
}
|
||
|
||
@OptIn(ExperimentalLayoutApi::class)
|
||
@Composable
|
||
private fun TaskTagsRow(
|
||
tags: List<String>,
|
||
newTagText: String,
|
||
onNewTagTextChanged: (String) -> Unit,
|
||
onAddTag: () -> Unit,
|
||
onRemoveTag: (String) -> Unit
|
||
) {
|
||
var isEditing by remember { mutableStateOf(false) }
|
||
|
||
Column(
|
||
modifier = Modifier
|
||
.fillMaxWidth()
|
||
.clickable { isEditing = true }
|
||
.padding(horizontal = 16.dp, vertical = 12.dp)
|
||
) {
|
||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||
Icon(Icons.Default.Folder, contentDescription = null, tint = MaterialTheme.colorScheme.onSurfaceVariant)
|
||
Spacer(modifier = Modifier.width(16.dp))
|
||
|
||
if (tags.isEmpty() && !isEditing) {
|
||
Text("Ajouter des <20>tiquettes", color = MaterialTheme.colorScheme.onSurfaceVariant, style = MaterialTheme.typography.bodyLarge)
|
||
} else {
|
||
FlowRow(
|
||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||
) {
|
||
tags.forEach { tag ->
|
||
Surface(
|
||
color = MaterialTheme.colorScheme.secondaryContainer,
|
||
shape = MaterialTheme.shapes.small,
|
||
onClick = { onRemoveTag(tag) }
|
||
) {
|
||
Row(
|
||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
|
||
verticalAlignment = Alignment.CenterVertically
|
||
) {
|
||
Text("#\", style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onSecondaryContainer)
|
||
Spacer(modifier = Modifier.width(4.dp))
|
||
Icon(Icons.Default.Close, contentDescription = null, modifier = Modifier.size(12.dp), tint = MaterialTheme.colorScheme.onSecondaryContainer)
|
||
}
|
||
}
|
||
}
|
||
|
||
if (isEditing) {
|
||
androidx.compose.foundation.text.BasicTextField(
|
||
value = newTagText,
|
||
onValueChange = onNewTagTextChanged,
|
||
textStyle = MaterialTheme.typography.bodyMedium.copy(color = MaterialTheme.colorScheme.onSurface),
|
||
modifier = Modifier.width(100.dp).align(Alignment.CenterVertically),
|
||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
||
keyboardActions = KeyboardActions(onDone = { onAddTag(); isEditing = false }),
|
||
decorationBox = { inner ->
|
||
if (newTagText.isEmpty()) Text("Nouveau tag...", color = MaterialTheme.colorScheme.onSurfaceVariant)
|
||
inner()
|
||
}
|
||
)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
@Composable
|
||
private fun TaskSubtasksSection(
|
||
subtasks: List<SubTask>,
|
||
newSubtaskText: String,
|
||
onNewSubtaskTextChanged: (String) -> Unit,
|
||
onAddSubtask: () -> Unit,
|
||
onRemoveSubtask: (Int) -> Unit,
|
||
onToggleSubtask: (Int) -> Unit,
|
||
onUpdateSubtaskContent: (Int, String) -> Unit
|
||
) {
|
||
Column(modifier = Modifier.fillMaxWidth()) {
|
||
Row(
|
||
modifier = Modifier
|
||
.fillMaxWidth()
|
||
.padding(horizontal = 16.dp, vertical = 16.dp),
|
||
verticalAlignment = Alignment.CenterVertically
|
||
) {
|
||
Icon(Icons.Default.Add, contentDescription = null, tint = MaterialTheme.colorScheme.onSurfaceVariant)
|
||
Spacer(modifier = Modifier.width(16.dp))
|
||
Text("Ajouter une sous-t<>che", color = MaterialTheme.colorScheme.onSurfaceVariant, style = MaterialTheme.typography.bodyLarge)
|
||
}
|
||
|
||
subtasks.forEachIndexed { index, sub ->
|
||
Row(
|
||
modifier = Modifier.fillMaxWidth().padding(start = 48.dp, end = 16.dp, top = 4.dp, bottom = 4.dp),
|
||
verticalAlignment = Alignment.CenterVertically
|
||
) {
|
||
Checkbox(
|
||
checked = sub.isDone,
|
||
onCheckedChange = { onToggleSubtask(index) },
|
||
modifier = Modifier.size(32.dp)
|
||
)
|
||
androidx.compose.foundation.text.BasicTextField(
|
||
value = sub.content,
|
||
onValueChange = { onUpdateSubtaskContent(index, it) },
|
||
modifier = Modifier.weight(1f).padding(horizontal = 8.dp),
|
||
textStyle = MaterialTheme.typography.bodyMedium.copy(
|
||
color = MaterialTheme.colorScheme.onSurface,
|
||
textDecoration = if (sub.isDone) TextDecoration.LineThrough else TextDecoration.None
|
||
)
|
||
)
|
||
IconButton(onClick = { onRemoveSubtask(index) }, modifier = Modifier.size(32.dp)) {
|
||
Icon(Icons.Default.Close, contentDescription = "Supprimer", modifier = Modifier.size(16.dp), tint = MaterialTheme.colorScheme.onSurfaceVariant)
|
||
}
|
||
}
|
||
}
|
||
|
||
Row(
|
||
modifier = Modifier.fillMaxWidth().padding(start = 48.dp, end = 16.dp, top = 4.dp, bottom = 12.dp),
|
||
verticalAlignment = Alignment.CenterVertically
|
||
) {
|
||
Icon(Icons.Default.Add, contentDescription = null, modifier = Modifier.size(24.dp).padding(4.dp), tint = MaterialTheme.colorScheme.onSurfaceVariant)
|
||
androidx.compose.foundation.text.BasicTextField(
|
||
value = newSubtaskText,
|
||
onValueChange = onNewSubtaskTextChanged,
|
||
modifier = Modifier.weight(1f).padding(horizontal = 8.dp),
|
||
textStyle = MaterialTheme.typography.bodyMedium.copy(color = MaterialTheme.colorScheme.onSurface),
|
||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
||
keyboardActions = KeyboardActions(onDone = onAddSubtask),
|
||
decorationBox = { inner ->
|
||
if (newSubtaskText.isEmpty()) Text("Nouvelle sous-t<>che...", color = MaterialTheme.colorScheme.onSurfaceVariant)
|
||
inner()
|
||
}
|
||
)
|
||
}
|
||
}
|
||
}
|
||
|
||
@OptIn(ExperimentalMaterial3Api::class)
|
||
@Composable
|
||
private fun DateTimePickerBottomSheet(
|
||
initialDate: Long?,
|
||
timezoneId: String,
|
||
onDismiss: () -> Unit,
|
||
onDateSelected: (Long?) -> Unit
|
||
) {
|
||
val sheetState = androidx.compose.material3.rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||
var showTimePicker by remember { mutableStateOf(false) }
|
||
|
||
val tz = TimeZone.getTimeZone(timezoneId)
|
||
val calendar = remember {
|
||
Calendar.getInstance(tz).apply {
|
||
if (initialDate != null) timeInMillis = initialDate
|
||
}
|
||
}
|
||
|
||
var selectedDateMillis by remember { mutableStateOf(initialDate) }
|
||
val datePickerState = androidx.compose.material3.rememberDatePickerState(
|
||
initialSelectedDateMillis = initialDate
|
||
)
|
||
|
||
LaunchedEffect(datePickerState.selectedDateMillis) {
|
||
if (datePickerState.selectedDateMillis != null) {
|
||
val newDateCal = Calendar.getInstance(tz).apply {
|
||
timeInMillis = datePickerState.selectedDateMillis!!
|
||
}
|
||
calendar.set(Calendar.YEAR, newDateCal.get(Calendar.YEAR))
|
||
calendar.set(Calendar.MONTH, newDateCal.get(Calendar.MONTH))
|
||
calendar.set(Calendar.DAY_OF_MONTH, newDateCal.get(Calendar.DAY_OF_MONTH))
|
||
selectedDateMillis = calendar.timeInMillis
|
||
}
|
||
}
|
||
|
||
if (showTimePicker) {
|
||
CustomTimePickerDialog(
|
||
initialHour = calendar.get(Calendar.HOUR_OF_DAY),
|
||
initialMinute = calendar.get(Calendar.MINUTE),
|
||
onDismiss = { showTimePicker = false },
|
||
onTimeSelected = { hour, minute ->
|
||
calendar.set(Calendar.HOUR_OF_DAY, hour)
|
||
calendar.set(Calendar.MINUTE, minute)
|
||
selectedDateMillis = calendar.timeInMillis
|
||
showTimePicker = false
|
||
}
|
||
)
|
||
}
|
||
|
||
androidx.compose.material3.ModalBottomSheet(
|
||
onDismissRequest = onDismiss,
|
||
sheetState = sheetState,
|
||
dragHandle = { androidx.compose.material3.BottomSheetDefaults.DragHandle() },
|
||
containerColor = MaterialTheme.colorScheme.surface
|
||
) {
|
||
Column(modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)) {
|
||
Row(modifier = Modifier.fillMaxWidth()) {
|
||
Column(modifier = Modifier.weight(1f)) {
|
||
ActionItem(Icons.Default.Event, "Date d'<EFBFBD>ch<EFBFBD>ance") { }
|
||
ActionItem(Icons.Default.Schedule, "Heure d'<EFBFBD>ch<EFBFBD>ance") { showTimePicker = true }
|
||
ActionItem(Icons.Default.Close, "Aucune date", tint = MaterialTheme.colorScheme.primary) {
|
||
onDateSelected(null)
|
||
onDismiss()
|
||
}
|
||
}
|
||
Column(modifier = Modifier.weight(1f)) {
|
||
ActionItem(androidx.compose.material.icons.outlined.Coffee, "9 h 00 a.m.") {
|
||
calendar.set(Calendar.HOUR_OF_DAY, 9)
|
||
calendar.set(Calendar.MINUTE, 0)
|
||
selectedDateMillis = calendar.timeInMillis
|
||
}
|
||
ActionItem(androidx.compose.material.icons.outlined.WbSunny, "1 h 00 p.m.") {
|
||
calendar.set(Calendar.HOUR_OF_DAY, 13)
|
||
calendar.set(Calendar.MINUTE, 0)
|
||
selectedDateMillis = calendar.timeInMillis
|
||
}
|
||
ActionItem(androidx.compose.material.icons.outlined.WbTwilight, "5 h 00 p.m.") {
|
||
calendar.set(Calendar.HOUR_OF_DAY, 17)
|
||
calendar.set(Calendar.MINUTE, 0)
|
||
selectedDateMillis = calendar.timeInMillis
|
||
}
|
||
ActionItem(androidx.compose.material.icons.outlined.NightsStay, "8 h 00 p.m.") {
|
||
calendar.set(Calendar.HOUR_OF_DAY, 20)
|
||
calendar.set(Calendar.MINUTE, 0)
|
||
selectedDateMillis = calendar.timeInMillis
|
||
}
|
||
ActionItem(Icons.Default.Schedule, "Choisir l'heure") {
|
||
showTimePicker = true
|
||
}
|
||
ActionItem(Icons.Default.Close, "Aucune heure", tint = MaterialTheme.colorScheme.primary) {
|
||
calendar.set(Calendar.HOUR_OF_DAY, 0)
|
||
calendar.set(Calendar.MINUTE, 0)
|
||
selectedDateMillis = calendar.timeInMillis
|
||
}
|
||
}
|
||
}
|
||
|
||
Spacer(modifier = Modifier.height(16.dp))
|
||
|
||
androidx.compose.material3.DatePicker(
|
||
state = datePickerState,
|
||
showModeToggle = false,
|
||
title = null,
|
||
headline = null,
|
||
modifier = Modifier.fillMaxWidth()
|
||
)
|
||
|
||
Row(
|
||
modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp, top = 8.dp),
|
||
horizontalArrangement = Arrangement.End
|
||
) {
|
||
TextButton(onClick = onDismiss) { Text("Annuler") }
|
||
Spacer(modifier = Modifier.width(8.dp))
|
||
TextButton(onClick = {
|
||
onDateSelected(selectedDateMillis)
|
||
onDismiss()
|
||
}) { Text("Valider") }
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
@Composable
|
||
private fun ActionItem(
|
||
icon: androidx.compose.ui.graphics.vector.ImageVector,
|
||
text: String,
|
||
tint: androidx.compose.ui.graphics.Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||
onClick: () -> Unit
|
||
) {
|
||
Row(
|
||
modifier = Modifier
|
||
.fillMaxWidth()
|
||
.clickable(onClick = onClick)
|
||
.padding(vertical = 12.dp, horizontal = 4.dp),
|
||
verticalAlignment = Alignment.CenterVertically
|
||
) {
|
||
Icon(icon, contentDescription = null, modifier = Modifier.size(20.dp), tint = tint)
|
||
Spacer(modifier = Modifier.width(12.dp))
|
||
Text(text, style = MaterialTheme.typography.bodyMedium, color = tint)
|
||
}
|
||
}
|
||
|
||
@OptIn(ExperimentalMaterial3Api::class)
|
||
@Composable
|
||
private fun CustomTimePickerDialog(
|
||
initialHour: Int,
|
||
initialMinute: Int,
|
||
onDismiss: () -> Unit,
|
||
onTimeSelected: (Int, Int) -> Unit
|
||
) {
|
||
val context = androidx.compose.ui.platform.LocalContext.current
|
||
val prefs = context.getSharedPreferences("time_picker_prefs", android.content.Context.MODE_PRIVATE)
|
||
var isDialMode by remember { mutableStateOf(prefs.getBoolean("is_dial_mode", true)) }
|
||
|
||
val timePickerState = androidx.compose.material3.rememberTimePickerState(
|
||
initialHour = initialHour,
|
||
initialMinute = initialMinute,
|
||
is24Hour = false
|
||
)
|
||
|
||
androidx.compose.ui.window.Dialog(onDismissRequest = onDismiss) {
|
||
Surface(
|
||
shape = MaterialTheme.shapes.extraLarge,
|
||
color = MaterialTheme.colorScheme.surface,
|
||
modifier = Modifier.wrapContentSize()
|
||
) {
|
||
Column(
|
||
modifier = Modifier.padding(24.dp),
|
||
horizontalAlignment = Alignment.CenterHorizontally
|
||
) {
|
||
if (isDialMode) {
|
||
androidx.compose.material3.TimePicker(state = timePickerState)
|
||
} else {
|
||
androidx.compose.material3.TimeInput(state = timePickerState)
|
||
}
|
||
Spacer(modifier = Modifier.height(24.dp))
|
||
Row(
|
||
modifier = Modifier.fillMaxWidth(),
|
||
horizontalArrangement = Arrangement.SpaceBetween,
|
||
verticalAlignment = Alignment.CenterVertically
|
||
) {
|
||
IconButton(onClick = {
|
||
isDialMode = !isDialMode
|
||
prefs.edit().putBoolean("is_dial_mode", isDialMode).apply()
|
||
}) {
|
||
Icon(
|
||
if (isDialMode) androidx.compose.material.icons.outlined.Keyboard else Icons.Default.Schedule,
|
||
contentDescription = "Changer de mode"
|
||
)
|
||
}
|
||
Row {
|
||
TextButton(onClick = onDismiss) { Text("Annuler") }
|
||
Spacer(modifier = Modifier.width(8.dp))
|
||
TextButton(onClick = {
|
||
onTimeSelected(timePickerState.hour, timePickerState.minute)
|
||
}) { Text("Valider") }
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
\"\"\"
|
||
new_lines = lines[:640] + [replacement + \"\\n\"] + lines[918:]
|
||
|
||
with open('c:/dev/git/Android/ShaarIt/app/src/main/java/com/shaarit/presentation/todo/TodoScreen.kt', 'w', encoding='utf-8') as f:
|
||
f.writelines(new_lines)
|
||
|
||
print('Success')
|