Avoid failing when the user chooses a filename that already exists in Downloads

This commit is contained in:
Pierre-Yves Nicolas
2025-07-05 22:14:22 +02:00
parent c535ce4262
commit d5864a3f03
3 changed files with 76 additions and 2 deletions

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2025 Pierre-Yves Nicolas
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option)
* any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.mydomain.myscan
import java.io.File
fun getAvailableFilename(desiredFile: File): File {
var file = desiredFile
val dir = desiredFile.parentFile
val desiredName = desiredFile.name
val nameWithoutExtension = desiredName.removeSuffix(".pdf")
var counter = 1
while (file.exists()) {
file = File(dir, "${nameWithoutExtension}_$counter.pdf")
counter++
}
return file
}

View File

@@ -126,8 +126,8 @@ class MainActivity : ComponentActivity() {
downloadsDir.mkdirs()
}
val generatedFile = generatedPdf.uri.toFile()
val targetFile = File(downloadsDir, generatedFile.name)
// TODO Handle case where the target file already exists (choose a unique name)
val desiredFile = File(downloadsDir, generatedFile.name)
val targetFile = getAvailableFilename(desiredFile)
generatedFile.copyTo(targetFile)
viewModel.markFileSaved(targetFile.toUri())

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2025 Pierre-Yves Nicolas
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option)
* any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.mydomain.myscan
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
import java.io.File
import kotlin.io.path.createTempDirectory
class FileUtilsTest {
@Test
fun getAvailableName() {
val dir = createTempDirectory().toFile()
val f = File(dir, "f.pdf")
val f1 = File(dir, "f_1.pdf")
val f2 = File(dir, "f_2.pdf")
assertThat(f.exists()).isFalse
assertThat(f1.exists()).isFalse
assertThat(getAvailableFilename(f)).isEqualTo(f)
f.apply { writeText("dummy") }
assertThat(f.exists()).isTrue
assertThat(getAvailableFilename(f)).isEqualTo(f1)
f1.apply { writeText("dummy") }
assertThat(f1.exists()).isTrue
assertThat(getAvailableFilename(f)).isEqualTo(f2)
}
}