From 8a3e43d4aa0823b72dbc21954a2b4cb794e0689b Mon Sep 17 00:00:00 2001 From: flaviuvsp Date: Wed, 10 Apr 2024 11:27:04 +0300 Subject: [PATCH 1/6] Add Sequence screen --- .../ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt diff --git a/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt b/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt new file mode 100644 index 00000000..7b6fc543 --- /dev/null +++ b/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt @@ -0,0 +1,4 @@ +package org.permanent.permanent.ui.bulkEditMetadata.compose + +class SequenceFileNamesScreen { +} \ No newline at end of file From 84b5faa640d2412c3184d2740302d9bfa60230d5 Mon Sep 17 00:00:00 2001 From: flaviuvsp Date: Thu, 11 Apr 2024 11:34:16 +0300 Subject: [PATCH 2/6] Add Sequence implementation --- .../compose/EditFileNamesScreen.kt | 14 +- .../compose/SequenceFileNamesScreen.kt | 379 +++++++++++++++++- app/src/main/res/values/strings.xml | 9 +- 3 files changed, 390 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/EditFileNamesScreen.kt b/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/EditFileNamesScreen.kt index 2160f74a..e81bce9e 100644 --- a/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/EditFileNamesScreen.kt +++ b/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/EditFileNamesScreen.kt @@ -144,7 +144,11 @@ fun EditFileNamesScreen( applyChanges = viewModel::applyChanges, cancel = cancel ) - EditFilesOptions.SEQUENCE -> PrependContent() + EditFilesOptions.SEQUENCE -> SequenceFileNamesScreen(uiState = uiState, + append = viewModel::append, + applyChanges = viewModel::applyChanges, + cancel = cancel + ) } } } @@ -176,10 +180,4 @@ private enum class EditFilesOptions(val titleID: Int, val resource: Int) { SEQUENCE(R.string.sequence, R.drawable.sequence); fun getLabel(context: Context) = context.getString(titleID) -} - -@Composable -fun AppendContent() { /* ... */ } - -@Composable -fun PrependContent() { /* ... */ } \ No newline at end of file +} \ No newline at end of file diff --git a/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt b/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt index 7b6fc543..bf1ac209 100644 --- a/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt +++ b/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt @@ -1,4 +1,379 @@ package org.permanent.permanent.ui.bulkEditMetadata.compose -class SequenceFileNamesScreen { -} \ No newline at end of file +import CustomDialog +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.unit.toSize +import androidx.core.content.ContextCompat +import org.permanent.permanent.R +import org.permanent.permanent.viewmodels.EditFileNamesUIState + +@Composable +fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, + append: (String, Boolean) -> Unit, + applyChanges: (String, Boolean) -> Unit, + cancel: () -> Unit) { + + val semiBoldFont = FontFamily(Font(R.font.open_sans_semibold_ttf)) + val regularFont = FontFamily(Font(R.font.open_sans_regular_ttf)) + var text by remember { mutableStateOf("") } + val context = LocalContext.current + val middleGrey = Color(ContextCompat.getColor(context, R.color.middleGrey)) + val superLightBlue = Color(ContextCompat.getColor(context, R.color.superLightBlue)) + val blue900 = Color(ContextCompat.getColor(context, R.color.blue900)) + val openAlertDialog = remember { mutableStateOf(false) } + + var expanded by remember { mutableStateOf(false) } + var whereDropdownSize by remember { mutableStateOf(Size.Zero) } + var formatDropdownSize by remember { mutableStateOf(Size.Zero) } + var dateDropdownSize by remember { mutableStateOf(Size.Zero) } + + val formatOptions = listOf( + SequenceFormatOptions.DATETIME, + SequenceFormatOptions.COUNT, + ) + var selectedFormatOption by remember { mutableStateOf(SequenceFormatOptions.DATETIME) } + + val whereOptions = listOf( + SequenceWhereOptions.BEFORE, + SequenceWhereOptions.AFTER, + ) + var selectedWhereOption by remember { mutableStateOf(SequenceWhereOptions.BEFORE) } + + val dateOptions = listOf( + SequenceDateOptions.CREATED, + SequenceDateOptions.LAST_MODIFIED, + SequenceDateOptions.UPLOADED, + ) + var selectedDateOption by remember { mutableStateOf(SequenceDateOptions.CREATED) } + + Column(modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.spacedBy(22.dp) + ) { + Column( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text(text = stringResource(id = R.string.text).uppercase(), + style = TextStyle( + fontSize = 10.sp, + fontFamily = semiBoldFont, + color = middleGrey) + ) + Box( + modifier = Modifier + .border( + width = 1.dp, + color = superLightBlue, + shape = RoundedCornerShape(size = 2.dp) + ) + .height(48.dp) + .background( + color = superLightBlue.copy(0.5f), + shape = RoundedCornerShape(size = 2.dp) + ), + contentAlignment = Alignment.CenterStart, + ) { + BasicTextField( + value = text, + onValueChange = { + text = it + }, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + textStyle = TextStyle( + fontFamily = regularFont, + fontSize = 13.sp, + color = blue900, + lineHeight = 16.sp + ), + singleLine = true + ) + } + } + Row() { + Column( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + text = stringResource(id = R.string.where).uppercase(), + style = TextStyle( + fontSize = 10.sp, + fontFamily = semiBoldFont, + color = middleGrey + ) + ) + Box( + modifier = Modifier + .border( + width = 1.dp, + color = superLightBlue, + shape = RoundedCornerShape(size = 2.dp) + ) + .onGloballyPositioned { coordinates -> + //This value is used to assign to the DropDown the same width + formatDropdownSize = coordinates.size.toSize() + } + .height(48.dp) + .background( + color = superLightBlue.copy(0.5f), + shape = RoundedCornerShape(size = 2.dp) + ) + .clickable { + expanded = !expanded + }, + contentAlignment = Alignment.CenterStart, + ) { + BasicTextField( + value = stringResource(id = selectedFormatOption.titleID), + onValueChange = {}, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + textStyle = TextStyle( + fontFamily = regularFont, + fontSize = 13.sp, + color = blue900, + lineHeight = 16.sp + ), + singleLine = true, + enabled = false + ) + DropdownMenu( + modifier = Modifier + .background(Color.White) + .width(with(LocalDensity.current) { formatDropdownSize.width.toDp() }), + expanded = expanded, + onDismissRequest = { expanded = false } + ) { + formatOptions.forEach { + DropdownMenuItem( + modifier = Modifier + .background(Color.White), + text = { Text(stringResource(id = it.titleID)) }, + onClick = { + expanded = false + selectedFormatOption = it +// append(text, selectedOption.appendBefore()) + }) + } + } + } + } + + Column( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + text = stringResource(id = R.string.where).uppercase(), + style = TextStyle( + fontSize = 10.sp, + fontFamily = semiBoldFont, + color = middleGrey + ) + ) + Box( + modifier = Modifier + .border( + width = 1.dp, + color = superLightBlue, + shape = RoundedCornerShape(size = 2.dp) + ) + .onGloballyPositioned { coordinates -> + //This value is used to assign to the DropDown the same width + whereDropdownSize = coordinates.size.toSize() + } + .height(48.dp) + .background( + color = superLightBlue.copy(0.5f), + shape = RoundedCornerShape(size = 2.dp) + ) + .clickable { + expanded = !expanded + }, + contentAlignment = Alignment.CenterStart, + ) { + BasicTextField( + value = stringResource(id = selectedWhereOption.titleID), + onValueChange = {}, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + textStyle = TextStyle( + fontFamily = regularFont, + fontSize = 13.sp, + color = blue900, + lineHeight = 16.sp + ), + singleLine = true, + enabled = false + ) + DropdownMenu( + modifier = Modifier + .background(Color.White) + .width(with(LocalDensity.current) { whereDropdownSize.width.toDp() }), + expanded = expanded, + onDismissRequest = { expanded = false } + ) { + whereOptions.forEach { + DropdownMenuItem( + modifier = Modifier + .background(Color.White), + text = { Text(stringResource(id = it.titleID)) }, + onClick = { + expanded = false + selectedWhereOption = it +// append(text, selectedOption.appendBefore()) + }) + } + } + } + } + } + Column( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + text = stringResource(id = R.string.where).uppercase(), + style = TextStyle( + fontSize = 10.sp, + fontFamily = semiBoldFont, + color = middleGrey + ) + ) + Box( + modifier = Modifier + .border( + width = 1.dp, + color = superLightBlue, + shape = RoundedCornerShape(size = 2.dp) + ) + .fillMaxWidth() + .onGloballyPositioned { coordinates -> + //This value is used to assign to the DropDown the same width + dateDropdownSize = coordinates.size.toSize() + } + .height(48.dp) + .background( + color = superLightBlue.copy(0.5f), + shape = RoundedCornerShape(size = 2.dp) + ) + .clickable { + expanded = !expanded + }, + contentAlignment = Alignment.CenterStart, + ) { + BasicTextField( + value = stringResource(id = selectedDateOption.titleID), + onValueChange = {}, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + textStyle = TextStyle( + fontFamily = regularFont, + fontSize = 13.sp, + color = blue900, + lineHeight = 16.sp + ), + singleLine = true, + enabled = false + ) + DropdownMenu( + modifier = Modifier + .background(Color.White) + .width(with(LocalDensity.current) { dateDropdownSize.width.toDp() }), + expanded = expanded, + onDismissRequest = { expanded = false } + ) { + dateOptions.forEach { + DropdownMenuItem( + modifier = Modifier + .background(Color.White), + text = { Text(stringResource(id = it.titleID)) }, + onClick = { + expanded = false + selectedDateOption = it +// append(text, selectedOption.appendBefore()) + }) + } + } + } + } + Spacer(modifier = Modifier.weight(1.0f)) + EditFileNamesFooter(uiState, + cancel = { + cancel() + }, apply = { + openAlertDialog.value = true + }) + when { + openAlertDialog.value -> { + CustomDialog( + title = stringResource(id = R.string.modify_file_names), + subtitle = stringResource(id = R.string.replace_confirmation_substring, uiState.recordsNumber), + okButtonText = stringResource(id = R.string.modify), + cancelButtonText = stringResource(id = R.string.button_cancel), + onConfirm = { + openAlertDialog.value = false +// applyChanges(text, selectedOption.appendBefore()) + }) { + openAlertDialog.value = false + } + } + } + } +} + +private enum class SequenceFormatOptions(val titleID: Int) { + DATETIME(R.string.date_time), + COUNT(R.string.count); +} + +private enum class SequenceWhereOptions(val titleID: Int) { + BEFORE(R.string.before_name), + AFTER(R.string.after_name); + + fun appendBefore(): Boolean { + return this == BEFORE + } +} + +private enum class SequenceDateOptions(val titleID: Int) { + CREATED(R.string.created), + LAST_MODIFIED(R.string.last_modified), + UPLOADED(R.string.uploaded); +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0e91e83b..539825ef 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -678,8 +678,13 @@ Find Text Where - Before Name - After Name + Before name + After name + Date & Time + Count + Created + Last modified + Uploaded From 6cbed10c4c892ce127d33c7defc7199373019d8a Mon Sep 17 00:00:00 2001 From: flaviuvsp Date: Fri, 19 Apr 2024 16:23:21 +0300 Subject: [PATCH 3/6] Add server call --- .../compose/EditFileNamesScreen.kt | 6 +- .../compose/SequenceFileNamesScreen.kt | 224 ++++++++++++------ .../viewmodels/EditFileNamesViewModel.kt | 55 +++++ app/src/main/res/values/strings.xml | 4 + 4 files changed, 209 insertions(+), 80 deletions(-) diff --git a/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/EditFileNamesScreen.kt b/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/EditFileNamesScreen.kt index e81bce9e..3d0cde7b 100644 --- a/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/EditFileNamesScreen.kt +++ b/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/EditFileNamesScreen.kt @@ -145,8 +145,10 @@ fun EditFileNamesScreen( cancel = cancel ) EditFilesOptions.SEQUENCE -> SequenceFileNamesScreen(uiState = uiState, - append = viewModel::append, - applyChanges = viewModel::applyChanges, + formatDate = viewModel::formatDate, + formatCount = viewModel::formatCount, + applyDateChanges = viewModel::applyChanges, + applyCountChanges = viewModel::applyChanges, cancel = cancel ) } diff --git a/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt b/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt index bf1ac209..577b5da6 100644 --- a/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt +++ b/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt @@ -16,6 +16,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.Text @@ -35,6 +36,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.toSize @@ -44,20 +46,23 @@ import org.permanent.permanent.viewmodels.EditFileNamesUIState @Composable fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, - append: (String, Boolean) -> Unit, - applyChanges: (String, Boolean) -> Unit, + formatDate: (String, Boolean, SequenceDateOptions) -> Unit, + formatCount:(String, Boolean, String) -> Unit, + applyDateChanges: (String, Boolean, SequenceDateOptions) -> Unit, + applyCountChanges: (String, Boolean, String) -> Unit, cancel: () -> Unit) { val semiBoldFont = FontFamily(Font(R.font.open_sans_semibold_ttf)) val regularFont = FontFamily(Font(R.font.open_sans_regular_ttf)) var text by remember { mutableStateOf("") } + var count by remember { mutableStateOf("") } val context = LocalContext.current val middleGrey = Color(ContextCompat.getColor(context, R.color.middleGrey)) val superLightBlue = Color(ContextCompat.getColor(context, R.color.superLightBlue)) val blue900 = Color(ContextCompat.getColor(context, R.color.blue900)) val openAlertDialog = remember { mutableStateOf(false) } - var expanded by remember { mutableStateOf(false) } + var expandedField by remember { mutableStateOf(-1) } var whereDropdownSize by remember { mutableStateOf(Size.Zero) } var formatDropdownSize by remember { mutableStateOf(Size.Zero) } var dateDropdownSize by remember { mutableStateOf(Size.Zero) } @@ -81,13 +86,25 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, ) var selectedDateOption by remember { mutableStateOf(SequenceDateOptions.CREATED) } + fun updateFormat() { + if (selectedFormatOption == SequenceFormatOptions.DATETIME) { + formatDate( + text, + selectedWhereOption.appendBefore(), + selectedDateOption + ) + } else { + formatCount(text, selectedWhereOption.appendBefore(), count) + } + } + Column(modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.spacedBy(22.dp) ) { Column( verticalArrangement = Arrangement.spacedBy(8.dp) ) { - Text(text = stringResource(id = R.string.text).uppercase(), + Text(text = stringResource(id = R.string.base).uppercase(), style = TextStyle( fontSize = 10.sp, fontFamily = semiBoldFont, @@ -111,6 +128,7 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, value = text, onValueChange = { text = it + updateFormat() }, modifier = Modifier .fillMaxWidth() @@ -125,12 +143,16 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, ) } } - Row() { + Row( + horizontalArrangement = Arrangement.spacedBy(24.dp), + modifier = Modifier.fillMaxWidth() + ) { Column( - verticalArrangement = Arrangement.spacedBy(8.dp) + verticalArrangement = Arrangement.spacedBy(8.dp), + modifier = Modifier.weight(1.0f) ) { Text( - text = stringResource(id = R.string.where).uppercase(), + text = stringResource(id = R.string.format).uppercase(), style = TextStyle( fontSize = 10.sp, fontFamily = semiBoldFont, @@ -154,7 +176,7 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, shape = RoundedCornerShape(size = 2.dp) ) .clickable { - expanded = !expanded + expandedField = 0 }, contentAlignment = Alignment.CenterStart, ) { @@ -177,8 +199,8 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, modifier = Modifier .background(Color.White) .width(with(LocalDensity.current) { formatDropdownSize.width.toDp() }), - expanded = expanded, - onDismissRequest = { expanded = false } + expanded = expandedField == 0, + onDismissRequest = { expandedField = -1 } ) { formatOptions.forEach { DropdownMenuItem( @@ -186,9 +208,9 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, .background(Color.White), text = { Text(stringResource(id = it.titleID)) }, onClick = { - expanded = false + expandedField = -1 selectedFormatOption = it -// append(text, selectedOption.appendBefore()) + updateFormat() }) } } @@ -196,7 +218,8 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, } Column( - verticalArrangement = Arrangement.spacedBy(8.dp) + verticalArrangement = Arrangement.spacedBy(8.dp), + modifier = Modifier.weight(1.0f) ) { Text( text = stringResource(id = R.string.where).uppercase(), @@ -223,7 +246,7 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, shape = RoundedCornerShape(size = 2.dp) ) .clickable { - expanded = !expanded + expandedField = 1 }, contentAlignment = Alignment.CenterStart, ) { @@ -246,8 +269,8 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, modifier = Modifier .background(Color.White) .width(with(LocalDensity.current) { whereDropdownSize.width.toDp() }), - expanded = expanded, - onDismissRequest = { expanded = false } + expanded = expandedField == 1, + onDismissRequest = { expandedField = -1 } ) { whereOptions.forEach { DropdownMenuItem( @@ -255,9 +278,9 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, .background(Color.White), text = { Text(stringResource(id = it.titleID)) }, onClick = { - expanded = false + expandedField = -1 selectedWhereOption = it -// append(text, selectedOption.appendBefore()) + updateFormat() }) } } @@ -267,69 +290,111 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, Column( verticalArrangement = Arrangement.spacedBy(8.dp) ) { - Text( - text = stringResource(id = R.string.where).uppercase(), - style = TextStyle( - fontSize = 10.sp, - fontFamily = semiBoldFont, - color = middleGrey - ) - ) - Box( - modifier = Modifier - .border( - width = 1.dp, - color = superLightBlue, - shape = RoundedCornerShape(size = 2.dp) - ) - .fillMaxWidth() - .onGloballyPositioned { coordinates -> - //This value is used to assign to the DropDown the same width - dateDropdownSize = coordinates.size.toSize() - } - .height(48.dp) - .background( - color = superLightBlue.copy(0.5f), - shape = RoundedCornerShape(size = 2.dp) + if (selectedFormatOption == SequenceFormatOptions.DATETIME) { + Text( + text = stringResource(id = R.string.date_value).uppercase(), + style = TextStyle( + fontSize = 10.sp, + fontFamily = semiBoldFont, + color = middleGrey ) - .clickable { - expanded = !expanded - }, - contentAlignment = Alignment.CenterStart, - ) { - BasicTextField( - value = stringResource(id = selectedDateOption.titleID), - onValueChange = {}, + ) + Box( modifier = Modifier + .border( + width = 1.dp, + color = superLightBlue, + shape = RoundedCornerShape(size = 2.dp) + ) .fillMaxWidth() - .padding(horizontal = 16.dp), - textStyle = TextStyle( - fontFamily = regularFont, - fontSize = 13.sp, - color = blue900, - lineHeight = 16.sp - ), - singleLine = true, - enabled = false + .onGloballyPositioned { coordinates -> + //This value is used to assign to the DropDown the same width + dateDropdownSize = coordinates.size.toSize() + } + .height(48.dp) + .background( + color = superLightBlue.copy(0.5f), + shape = RoundedCornerShape(size = 2.dp) + ) + .clickable { + expandedField = 2 + }, + contentAlignment = Alignment.CenterStart, + ) { + BasicTextField( + value = stringResource(id = selectedDateOption.titleID), + onValueChange = {}, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + textStyle = TextStyle( + fontFamily = regularFont, + fontSize = 13.sp, + color = blue900, + lineHeight = 16.sp + ), + singleLine = true, + enabled = false + ) + DropdownMenu( + modifier = Modifier + .background(Color.White) + .width(with(LocalDensity.current) { dateDropdownSize.width.toDp() }), + expanded = expandedField == 2, + onDismissRequest = { expandedField = -1 } + ) { + dateOptions.forEach { + DropdownMenuItem( + modifier = Modifier + .background(Color.White), + text = { Text(stringResource(id = it.titleID)) }, + onClick = { + expandedField = -1 + selectedDateOption = it + updateFormat() + }) + } + } + } + } else { + Text(text = stringResource(id = R.string.count).uppercase(), + style = TextStyle( + fontSize = 10.sp, + fontFamily = semiBoldFont, + color = middleGrey) ) - DropdownMenu( + Box( modifier = Modifier - .background(Color.White) - .width(with(LocalDensity.current) { dateDropdownSize.width.toDp() }), - expanded = expanded, - onDismissRequest = { expanded = false } + .border( + width = 1.dp, + color = superLightBlue, + shape = RoundedCornerShape(size = 2.dp) + ) + .height(48.dp) + .background( + color = superLightBlue.copy(0.5f), + shape = RoundedCornerShape(size = 2.dp) + ), + contentAlignment = Alignment.CenterStart, ) { - dateOptions.forEach { - DropdownMenuItem( - modifier = Modifier - .background(Color.White), - text = { Text(stringResource(id = it.titleID)) }, - onClick = { - expanded = false - selectedDateOption = it -// append(text, selectedOption.appendBefore()) - }) - } + BasicTextField( + value = count, + onValueChange = { + count = it + updateFormat() + }, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + textStyle = TextStyle( + fontFamily = regularFont, + fontSize = 13.sp, + color = blue900, + lineHeight = 16.sp + ), + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), + singleLine = true + ) } } } @@ -349,7 +414,11 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, cancelButtonText = stringResource(id = R.string.button_cancel), onConfirm = { openAlertDialog.value = false -// applyChanges(text, selectedOption.appendBefore()) + if (selectedFormatOption == SequenceFormatOptions.DATETIME) { + applyDateChanges(text, selectedWhereOption.appendBefore(), selectedDateOption) + } else { + applyCountChanges(text, selectedWhereOption.appendBefore(), count) + } }) { openAlertDialog.value = false } @@ -371,8 +440,7 @@ private enum class SequenceWhereOptions(val titleID: Int) { return this == BEFORE } } - -private enum class SequenceDateOptions(val titleID: Int) { +enum class SequenceDateOptions(val titleID: Int) { CREATED(R.string.created), LAST_MODIFIED(R.string.last_modified), UPLOADED(R.string.uploaded); diff --git a/app/src/main/java/org/permanent/permanent/viewmodels/EditFileNamesViewModel.kt b/app/src/main/java/org/permanent/permanent/viewmodels/EditFileNamesViewModel.kt index ae82f46a..1ddce680 100644 --- a/app/src/main/java/org/permanent/permanent/viewmodels/EditFileNamesViewModel.kt +++ b/app/src/main/java/org/permanent/permanent/viewmodels/EditFileNamesViewModel.kt @@ -6,6 +6,7 @@ import org.permanent.permanent.models.Record import org.permanent.permanent.network.IResponseListener import org.permanent.permanent.repositories.FileRepositoryImpl import org.permanent.permanent.repositories.IFileRepository +import org.permanent.permanent.ui.bulkEditMetadata.compose.SequenceDateOptions import org.permanent.permanent.ui.bytesToHumanReadableString class EditFileNamesViewModel(application: Application) : ObservableAndroidViewModel(application) { @@ -75,6 +76,28 @@ class EditFileNamesViewModel(application: Application) : ObservableAndroidViewMo } } + fun formatDate(text: String, before: Boolean, dateOption: SequenceDateOptions) { + var record = records.firstOrNull() + var date = when(dateOption) { + SequenceDateOptions.CREATED -> record?.fileData?.displayDate + SequenceDateOptions.UPLOADED -> record?.fileData?.createdDate + SequenceDateOptions.LAST_MODIFIED -> record?.fileData?.updatedDate + } + if(before) { + uiState.value = uiState.value.copy(fileName = date + text) + } else { + uiState.value = uiState.value.copy(fileName = text + date) + } + } + + fun formatCount(text: String, before: Boolean, count: String) { + if(before) { + uiState.value = uiState.value.copy(fileName = count + text) + } else { + uiState.value = uiState.value.copy(fileName = text + count) + } + } + fun applyChanges(findText: String, replaceText: String) { for(record in records) { val newName = record.displayName?.replace(findText, replaceText) @@ -96,6 +119,38 @@ class EditFileNamesViewModel(application: Application) : ObservableAndroidViewMo applyChanges() } + fun applyChanges(text: String, before: Boolean, dateOption: SequenceDateOptions) { + for (record in records) { + var date = when(dateOption) { + SequenceDateOptions.CREATED -> record.fileData?.displayDate + SequenceDateOptions.UPLOADED -> record.fileData?.createdDate + SequenceDateOptions.LAST_MODIFIED -> record.fileData?.updatedDate + } + + var newName = if(before) { + date + text + } else { + text + date + } + record.displayName = newName + } + + applyChanges() + } + + fun applyChanges(text: String, before: Boolean, count: String) { + var countInt = count.toInt() + for (record in records) { + record.displayName = if(before) { + countInt.toString() + text + } else { + text + countInt.toString() + } + countInt++ + } + applyChanges() + } + fun toggleLoading() { val currentState = uiState.value uiState.value = currentState.toggleIsBusy() diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 539825ef..3d4d0d04 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -685,6 +685,10 @@ Created Last modified Uploaded + Base + Format + Date Value + Start With From bb98b6ecba50d20665c1c9ed402c7bda6357c168 Mon Sep 17 00:00:00 2001 From: flaviuvsp Date: Mon, 22 Apr 2024 15:26:35 +0300 Subject: [PATCH 4/6] Add error handling --- .../compose/SequenceFileNamesScreen.kt | 6 ++++-- .../viewmodels/EditFileNamesViewModel.kt | 20 +++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt b/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt index 577b5da6..7a9f92cc 100644 --- a/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt +++ b/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt @@ -380,8 +380,10 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, BasicTextField( value = count, onValueChange = { - count = it - updateFormat() + if(it.toIntOrNull() != null || it.isEmpty()) { + count = it + updateFormat() + } }, modifier = Modifier .fillMaxWidth() diff --git a/app/src/main/java/org/permanent/permanent/viewmodels/EditFileNamesViewModel.kt b/app/src/main/java/org/permanent/permanent/viewmodels/EditFileNamesViewModel.kt index eb3ca079..fc3350e4 100644 --- a/app/src/main/java/org/permanent/permanent/viewmodels/EditFileNamesViewModel.kt +++ b/app/src/main/java/org/permanent/permanent/viewmodels/EditFileNamesViewModel.kt @@ -147,16 +147,20 @@ class EditFileNamesViewModel(application: Application) : ObservableAndroidViewMo } fun applyChanges(text: String, before: Boolean, count: String) { - var countInt = count.toInt() - for (record in records) { - record.displayName = if(before) { - countInt.toString() + text - } else { - text + countInt.toString() + var countInt = count.toIntOrNull() + if (countInt != null) { + for (record in records) { + record.displayName = if (before) { + countInt.toString() + text + } else { + text + countInt.toString() + } + countInt++ } - countInt++ + applyChanges() + } else { + updateError("Count value needs to be a number.") } - applyChanges() } fun toggleLoading() { From 2f25afa9a8af055d24c5d3b11207c93de99e884a Mon Sep 17 00:00:00 2001 From: flaviuvsp Date: Mon, 22 Apr 2024 15:35:22 +0300 Subject: [PATCH 5/6] Include changelog into the release --- fastlane/Fastfile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index a46cb014..9e7618c5 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -45,12 +45,18 @@ platform :android do "android.injected.signing.key.alias" => ENV['KEYSTORE_ALIAS'], "android.injected.signing.key.password" => ENV['KEYSTORE_PASSWORD'], }) + + changelog = changelog_from_git_commits( + between: "HEAD", + commits_count: 10 + ) firebase_app_distribution( app: ENV['APP_ID'], android_artifact_type: "APK", firebase_cli_token: ENV['FIREBASEAPPDISTRO_CLI_TOKEN'], - groups: "Android" + groups: "Android", + release_notes: "## Changelog\n" + changelog ) end From e7b52d89bccc02808a12d9172f00c9b56d8ae8cb Mon Sep 17 00:00:00 2001 From: flaviuvsp Date: Tue, 23 Apr 2024 14:49:45 +0300 Subject: [PATCH 6/6] Add enum to hold the field that is expanded --- .../compose/SequenceFileNamesScreen.kt | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt b/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt index 7a9f92cc..1046abd4 100644 --- a/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt +++ b/app/src/main/java/org/permanent/permanent/ui/bulkEditMetadata/compose/SequenceFileNamesScreen.kt @@ -62,11 +62,17 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, val blue900 = Color(ContextCompat.getColor(context, R.color.blue900)) val openAlertDialog = remember { mutableStateOf(false) } - var expandedField by remember { mutableStateOf(-1) } + var expandedField: SequenceDropdownOptions? by remember { mutableStateOf(null) } var whereDropdownSize by remember { mutableStateOf(Size.Zero) } var formatDropdownSize by remember { mutableStateOf(Size.Zero) } var dateDropdownSize by remember { mutableStateOf(Size.Zero) } + var dropdownOptions = listOf( + SequenceDropdownOptions.FORMAT, + SequenceDropdownOptions.WHERE, + SequenceDropdownOptions.DATE, + ) + val formatOptions = listOf( SequenceFormatOptions.DATETIME, SequenceFormatOptions.COUNT, @@ -176,7 +182,7 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, shape = RoundedCornerShape(size = 2.dp) ) .clickable { - expandedField = 0 + expandedField = SequenceDropdownOptions.FORMAT }, contentAlignment = Alignment.CenterStart, ) { @@ -199,8 +205,8 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, modifier = Modifier .background(Color.White) .width(with(LocalDensity.current) { formatDropdownSize.width.toDp() }), - expanded = expandedField == 0, - onDismissRequest = { expandedField = -1 } + expanded = expandedField == SequenceDropdownOptions.FORMAT, + onDismissRequest = { expandedField = null } ) { formatOptions.forEach { DropdownMenuItem( @@ -208,7 +214,7 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, .background(Color.White), text = { Text(stringResource(id = it.titleID)) }, onClick = { - expandedField = -1 + expandedField = null selectedFormatOption = it updateFormat() }) @@ -246,7 +252,7 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, shape = RoundedCornerShape(size = 2.dp) ) .clickable { - expandedField = 1 + expandedField = SequenceDropdownOptions.WHERE }, contentAlignment = Alignment.CenterStart, ) { @@ -269,8 +275,8 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, modifier = Modifier .background(Color.White) .width(with(LocalDensity.current) { whereDropdownSize.width.toDp() }), - expanded = expandedField == 1, - onDismissRequest = { expandedField = -1 } + expanded = expandedField == SequenceDropdownOptions.WHERE, + onDismissRequest = { expandedField = null } ) { whereOptions.forEach { DropdownMenuItem( @@ -278,7 +284,7 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, .background(Color.White), text = { Text(stringResource(id = it.titleID)) }, onClick = { - expandedField = -1 + expandedField = null selectedWhereOption = it updateFormat() }) @@ -317,7 +323,7 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, shape = RoundedCornerShape(size = 2.dp) ) .clickable { - expandedField = 2 + expandedField = SequenceDropdownOptions.DATE }, contentAlignment = Alignment.CenterStart, ) { @@ -340,8 +346,8 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, modifier = Modifier .background(Color.White) .width(with(LocalDensity.current) { dateDropdownSize.width.toDp() }), - expanded = expandedField == 2, - onDismissRequest = { expandedField = -1 } + expanded = expandedField == SequenceDropdownOptions.DATE, + onDismissRequest = { expandedField = null } ) { dateOptions.forEach { DropdownMenuItem( @@ -349,7 +355,7 @@ fun SequenceFileNamesScreen(uiState: EditFileNamesUIState, .background(Color.White), text = { Text(stringResource(id = it.titleID)) }, onClick = { - expandedField = -1 + expandedField = null selectedDateOption = it updateFormat() }) @@ -447,3 +453,9 @@ enum class SequenceDateOptions(val titleID: Int) { LAST_MODIFIED(R.string.last_modified), UPLOADED(R.string.uploaded); } + +private enum class SequenceDropdownOptions() { + FORMAT, + WHERE, + DATE +}