Replace java.io.File in ExportCSVTask with UserFile abstraction

This commit is contained in:
Alinson S. Xavier 2026-04-07 04:12:22 -05:00
parent d467dd643c
commit 22d289d6cb
8 changed files with 28 additions and 14 deletions

View File

@ -19,6 +19,8 @@
package org.isoron.uhabits.activities
import me.tatarka.inject.annotations.Inject
import org.isoron.platform.io.JavaUserFile
import org.isoron.platform.io.UserFile
import org.isoron.uhabits.AndroidDirFinder
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitMenuPresenter
@ -28,7 +30,7 @@ class HabitsDirFinder(
private val androidDirFinder: AndroidDirFinder
) : ShowHabitMenuPresenter.System, ListHabitsBehavior.DirFinder {
override fun getCSVOutputDir(): String {
return androidDirFinder.getFilesDir("CSV")!!.absolutePath
override fun getCSVOutputDir(): UserFile {
return JavaUserFile(androidDirFinder.getFilesDir("CSV")!!.toPath())
}
}

View File

@ -87,6 +87,12 @@ interface UserFile {
* Reads the first [limit] bytes from the file.
*/
suspend fun readBytes(limit: Int): ByteArray
/**
* Returns a [UserFile] whose path is [child] resolved against this file's
* parent directory (or this file itself, if it represents a directory).
*/
fun resolve(child: String): UserFile
}
/**

View File

@ -19,16 +19,16 @@
package org.isoron.uhabits.core.tasks
import kotlinx.coroutines.runBlocking
import org.isoron.platform.io.UserFile
import org.isoron.platform.time.getToday
import org.isoron.uhabits.core.io.HabitsCSVExporter
import org.isoron.uhabits.core.models.Habit
import org.isoron.uhabits.core.models.HabitList
import java.io.File
class ExportCSVTask(
private val habitList: HabitList,
private val selectedHabits: List<Habit>,
private val outputDir: String,
private val outputDir: UserFile,
private val listener: ExportCSVListener
) : Task {
private var archiveFilename: String? = null
@ -37,11 +37,9 @@ class ExportCSVTask(
val exporter = HabitsCSVExporter(habitList, selectedHabits)
val bytes = runBlocking { exporter.writeArchive() }
val date = getToday().toCSVString()
val dir = File(outputDir)
dir.mkdirs()
val zipFile = File(dir, "Loop Habits CSV $date.zip")
zipFile.writeBytes(bytes)
archiveFilename = zipFile.absolutePath
val zipFile = outputDir.resolve("Loop Habits CSV $date.zip")
runBlocking { zipFile.writeBytes(bytes) }
archiveFilename = zipFile.pathString
} catch (e: Exception) {
e.printStackTrace()
}

View File

@ -19,6 +19,7 @@
package org.isoron.uhabits.core.ui.screens.habits.list
import me.tatarka.inject.annotations.Inject
import org.isoron.platform.io.UserFile
import org.isoron.platform.time.LocalDate
import org.isoron.platform.time.getToday
import org.isoron.uhabits.core.commands.CommandRunner
@ -151,7 +152,7 @@ open class ListHabitsBehavior(
}
interface DirFinder {
fun getCSVOutputDir(): String
fun getCSVOutputDir(): UserFile
}
interface Screen {

View File

@ -18,6 +18,7 @@
*/
package org.isoron.uhabits.core.ui.screens.habits.show
import org.isoron.platform.io.UserFile
import org.isoron.platform.time.getToday
import org.isoron.uhabits.core.commands.ArchiveHabitsCommand
import org.isoron.uhabits.core.commands.CommandRunner
@ -126,6 +127,6 @@ class ShowHabitMenuPresenter(
}
interface System {
fun getCSVOutputDir(): String
fun getCSVOutputDir(): UserFile
}
}

View File

@ -99,6 +99,10 @@ class JavaUserFile(val path: Path) : UserFile {
return if (n <= 0) ByteArray(0) else buf.copyOf(n)
}
}
override fun resolve(child: String): UserFile {
return JavaUserFile(path.resolve(child))
}
}
@Suppress("NewApi")

View File

@ -21,6 +21,7 @@ package org.isoron.uhabits.core.ui.screens.habits.list
import org.apache.commons.io.FileUtils
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.core.IsEqual.equalTo
import org.isoron.platform.io.JavaUserFile
import org.isoron.platform.time.getToday
import org.isoron.uhabits.core.BaseUnitTest
import org.isoron.uhabits.core.models.Entry
@ -92,7 +93,7 @@ class ListHabitsBehaviorTest : BaseUnitTest() {
@Throws(Exception::class)
fun testOnExportCSV() {
val outputDir = Files.createTempDirectory("CSV").toFile()
whenever(dirFinder.getCSVOutputDir()).thenReturn(outputDir.absolutePath)
whenever(dirFinder.getCSVOutputDir()).thenReturn(JavaUserFile(outputDir.toPath()))
behavior.onExportCSV()
verify(screen).showSendFileScreen(any())
assertThat(FileUtils.listFiles(outputDir, null, false).size, equalTo(1))
@ -104,7 +105,7 @@ class ListHabitsBehaviorTest : BaseUnitTest() {
fun testOnExportCSV_fail() {
val outputDir = Files.createTempDirectory("CSV").toFile()
outputDir.setWritable(false)
whenever(dirFinder.getCSVOutputDir()).thenReturn(outputDir.absolutePath)
whenever(dirFinder.getCSVOutputDir()).thenReturn(JavaUserFile(outputDir.toPath()))
behavior.onExportCSV()
verify(screen).showMessage(ListHabitsBehavior.Message.COULD_NOT_EXPORT)
assertTrue(outputDir.delete())

View File

@ -21,6 +21,7 @@ package org.isoron.uhabits.core.ui.screens.habits.show
import org.apache.commons.io.FileUtils
import org.hamcrest.CoreMatchers.equalTo
import org.hamcrest.MatcherAssert.assertThat
import org.isoron.platform.io.JavaUserFile
import org.isoron.uhabits.core.BaseUnitTest
import org.isoron.uhabits.core.models.Habit
import org.junit.Test
@ -61,7 +62,7 @@ class ShowHabitMenuPresenterTest : BaseUnitTest() {
@Throws(Exception::class)
fun testOnExport() {
val outputDir = Files.createTempDirectory("CSV").toFile()
whenever(system.getCSVOutputDir()).thenReturn(outputDir.absolutePath)
whenever(system.getCSVOutputDir()).thenReturn(JavaUserFile(outputDir.toPath()))
menu.onExportCSV()
assertThat(FileUtils.listFiles(outputDir, null, false).size, equalTo(1))
FileUtils.deleteDirectory(outputDir)