diff --git a/app/src/main/java/co/adityarajput/fileflow/data/models/Action.kt b/app/src/main/java/co/adityarajput/fileflow/data/models/Action.kt
index d0786d2..bf0d9be 100644
--- a/app/src/main/java/co/adityarajput/fileflow/data/models/Action.kt
+++ b/app/src/main/java/co/adityarajput/fileflow/data/models/Action.kt
@@ -8,10 +8,13 @@ import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.withStyle
import co.adityarajput.fileflow.R
import co.adityarajput.fileflow.data.Verb
+import co.adityarajput.fileflow.utils.File
import co.adityarajput.fileflow.utils.FileSuperlative
import co.adityarajput.fileflow.utils.getGetDirectoryFromUri
import co.adityarajput.fileflow.utils.toShortHumanReadableTime
import kotlinx.serialization.Serializable
+import kotlin.uuid.ExperimentalUuidApi
+import kotlin.uuid.Uuid
@Suppress("ClassName")
@Serializable
@@ -65,6 +68,19 @@ sealed class Action {
withStyle(dullStyle) { append("\nas ") }
append(destFileNameTemplate)
}
+
+ @OptIn(ExperimentalUuidApi::class)
+ fun getDestFileName(srcFile: File) =
+ srcFile.name!!.replace(
+ Regex(srcFileNamePattern),
+ destFileNameTemplate.replace(
+ $$"${uuid}",
+ Uuid.random().toString(),
+ ).replace(
+ $$"${folder}",
+ srcFile.parent?.name ?: "",
+ ),
+ )
}
@Serializable
diff --git a/app/src/main/java/co/adityarajput/fileflow/services/FlowExecutor.kt b/app/src/main/java/co/adityarajput/fileflow/services/FlowExecutor.kt
index 4b388a8..2f26669 100644
--- a/app/src/main/java/co/adityarajput/fileflow/services/FlowExecutor.kt
+++ b/app/src/main/java/co/adityarajput/fileflow/services/FlowExecutor.kt
@@ -52,13 +52,7 @@ class FlowExecutor(private val context: Context) {
continue
}
- val destFileName = srcFile.name!!.replace(
- regex,
- rule.action.destFileNameTemplate.replace(
- $$"${folder}",
- srcFile.parent?.name ?: "",
- ),
- )
+ val destFileName = rule.action.getDestFileName(srcFile)
var destFile = destSubDir.listChildren(false)
.firstOrNull { it.isFile && it.name == destFileName }
diff --git a/app/src/main/java/co/adityarajput/fileflow/viewmodels/UpsertRuleViewModel.kt b/app/src/main/java/co/adityarajput/fileflow/viewmodels/UpsertRuleViewModel.kt
index 5cce07f..2e232df 100644
--- a/app/src/main/java/co/adityarajput/fileflow/viewmodels/UpsertRuleViewModel.kt
+++ b/app/src/main/java/co/adityarajput/fileflow/viewmodels/UpsertRuleViewModel.kt
@@ -107,15 +107,9 @@ class UpsertRuleViewModel(
?.also { if (it.isEmpty()) warning = FormWarning.NO_MATCHES_IN_SRC }
if (matchingSrcFiles != null && values.destFileNameTemplate.isNotBlank()) {
- predictedDestFileNames = matchingSrcFiles.map {
- it.name!!.replace(
- regex,
- values.destFileNameTemplate.replace(
- $$"${folder}",
- it.parent?.name ?: "",
- ),
- )
- }.distinct()
+ predictedDestFileNames = matchingSrcFiles
+ .map { (values.toRule().action as Action.MOVE).getDestFileName(it) }
+ .distinct()
}
} catch (_: Exception) {
}
diff --git a/app/src/main/java/co/adityarajput/fileflow/views/screens/OnboardingScreen.kt b/app/src/main/java/co/adityarajput/fileflow/views/screens/OnboardingScreen.kt
index 5c2da60..73ce1fb 100644
--- a/app/src/main/java/co/adityarajput/fileflow/views/screens/OnboardingScreen.kt
+++ b/app/src/main/java/co/adityarajput/fileflow/views/screens/OnboardingScreen.kt
@@ -1,6 +1,5 @@
package co.adityarajput.fileflow.views.screens
-import android.annotation.SuppressLint
import android.os.Handler
import android.os.Looper
import androidx.compose.foundation.layout.*
@@ -22,7 +21,6 @@ private val permissions = listOf(
Permission.MANAGE_EXTERNAL_STORAGE,
)
-@SuppressLint("BatteryLife")
@Composable
fun OnboardingScreen(goToRulesScreen: () -> Unit = {}) {
val context = LocalContext.current
diff --git a/app/src/main/java/co/adityarajput/fileflow/views/screens/UpsertRuleScreen.kt b/app/src/main/java/co/adityarajput/fileflow/views/screens/UpsertRuleScreen.kt
index 676cb78..e58fd03 100644
--- a/app/src/main/java/co/adityarajput/fileflow/views/screens/UpsertRuleScreen.kt
+++ b/app/src/main/java/co/adityarajput/fileflow/views/screens/UpsertRuleScreen.kt
@@ -324,7 +324,31 @@ private fun ColumnScope.ActionPage(viewModel: UpsertRuleViewModel) {
label = { Text(stringResource(R.string.file_name_template)) },
placeholder = { Text(stringResource(R.string.template_placeholder)) },
supportingText = {
- if (viewModel.state.values.predictedDestFileNames?.isNotEmpty() ?: false)
+ if (viewModel.state.values.predictedDestFileNames.isNullOrEmpty()) {
+ Text(
+ buildAnnotatedString {
+ append(stringResource(R.string.blank_template_supporting))
+ if (viewModel.state.values.destFileNameTemplate != "$0") {
+ withLink(
+ LinkAnnotation.Clickable(
+ "keep_name",
+ TextLinkStyles(
+ SpanStyle(
+ MaterialTheme.colorScheme.primary,
+ textDecoration = TextDecoration.Underline,
+ ),
+ ),
+ ) {
+ viewModel.updateForm(
+ context,
+ viewModel.state.values.copy(destFileNameTemplate = "$0"),
+ )
+ },
+ ) { append(stringResource(R.string.keep_name)) }
+ }
+ },
+ )
+ } else {
Text(
stringResource(
R.string.template_will_yield,
@@ -332,6 +356,7 @@ private fun ColumnScope.ActionPage(viewModel: UpsertRuleViewModel) {
.joinToString(stringResource(R.string.or), limit = 3),
),
)
+ }
},
colors = OutlinedTextFieldDefaults.colors(
focusedContainerColor = MaterialTheme.colorScheme.secondaryContainer,
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5944dfe..6fc05f8 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -109,6 +109,8 @@
Recreate source folder-structure in destination
File name template
Enter a regex template
+ "Template will be used to name the file in the destination. "
+ Keep original name?
Template will yield %1$s
Overwrite existing files in the destination, in case of conflict
Mark stale if unmodified for