Support closing Okio FileSystem

master
Koitharu 1 year ago
parent 6360731f34
commit 169539f42f
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -55,15 +55,16 @@ class LocalMangaParser(private val uri: Uri) {
private val rootFile: File = File(uri.schemeSpecificPart) private val rootFile: File = File(uri.schemeSpecificPart)
suspend fun getManga(withDetails: Boolean): LocalManga = runInterruptible(Dispatchers.IO) { suspend fun getManga(withDetails: Boolean): LocalManga = runInterruptible(Dispatchers.IO) {
val (fileSystem, rootPath) = uri.resolveFsAndPath() (uri.resolveFsAndPath()).use { (fileSystem, rootPath) ->
val index = MangaIndex.read(fileSystem, rootPath / ENTRY_NAME_INDEX) val index = MangaIndex.read(fileSystem, rootPath / ENTRY_NAME_INDEX)
val mangaInfo = index?.getMangaInfo() val mangaInfo = index?.getMangaInfo()
if (mangaInfo != null) { if (mangaInfo != null) {
val coverEntry: Path? = index.getCoverEntry()?.let { rootPath / it } ?: fileSystem.findFirstImage(rootPath) val coverEntry: Path? =
index.getCoverEntry()?.let { rootPath / it } ?: fileSystem.findFirstImage(rootPath)
mangaInfo.copy( mangaInfo.copy(
source = LocalMangaSource, source = LocalMangaSource,
url = rootFile.toUri().toString(), url = rootFile.toUri().toString(),
coverUrl = coverEntry?.let { uri.child(it, resolve = true).toString() }.orEmpty(), coverUrl = coverEntry?.let { uri.child(it, resolve = true).toString() },
largeCoverUrl = null, largeCoverUrl = null,
chapters = if (withDetails) { chapters = if (withDetails) {
mangaInfo.chapters?.mapNotNull { c -> mangaInfo.chapters?.mapNotNull { c ->
@ -92,9 +93,7 @@ class LocalMangaParser(private val uri: Uri) {
url = rootFile.toUri().toString(), url = rootFile.toUri().toString(),
publicUrl = rootFile.toUri().toString(), publicUrl = rootFile.toUri().toString(),
source = LocalMangaSource, source = LocalMangaSource,
coverUrl = coverEntry?.let { coverUrl = coverEntry?.let { uri.child(it, resolve = true).toString() },
uri.child(it, resolve = true).toString()
}.orEmpty(),
chapters = if (withDetails) { chapters = if (withDetails) {
val chapters = fileSystem.listRecursively(rootPath) val chapters = fileSystem.listRecursively(rootPath)
.mapNotNullTo(HashSet()) { path -> .mapNotNullTo(HashSet()) { path ->
@ -138,16 +137,18 @@ class LocalMangaParser(private val uri: Uri) {
) )
}.let { LocalManga(it, rootFile) } }.let { LocalManga(it, rootFile) }
} }
}
suspend fun getMangaInfo(): Manga? = runInterruptible(Dispatchers.IO) { suspend fun getMangaInfo(): Manga? = runInterruptible(Dispatchers.IO) {
val (fileSystem, rootPath) = uri.resolveFsAndPath() uri.resolveFsAndPath().use { (fileSystem, rootPath) ->
val index = MangaIndex.read(fileSystem, rootPath / ENTRY_NAME_INDEX) val index = MangaIndex.read(fileSystem, rootPath / ENTRY_NAME_INDEX)
index?.getMangaInfo() index?.getMangaInfo()
} }
}
suspend fun getPages(chapter: MangaChapter): List<MangaPage> = runInterruptible(Dispatchers.IO) { suspend fun getPages(chapter: MangaChapter): List<MangaPage> = runInterruptible(Dispatchers.IO) {
val chapterUri = chapter.url.toUri().resolve() val chapterUri = chapter.url.toUri().resolve()
val (fileSystem, rootPath) = chapterUri.resolveFsAndPath() chapterUri.resolveFsAndPath().use { (fileSystem, rootPath) ->
val index = MangaIndex.read(fileSystem, rootPath / ENTRY_NAME_INDEX) val index = MangaIndex.read(fileSystem, rootPath / ENTRY_NAME_INDEX)
val entries = fileSystem.listRecursively(rootPath) val entries = fileSystem.listRecursively(rootPath)
.filter { fileSystem.isRegularFile(it) } .filter { fileSystem.isRegularFile(it) }
@ -167,6 +168,7 @@ class LocalMangaParser(private val uri: Uri) {
) )
} }
} }
}
private fun Uri.child(path: Path, resolve: Boolean): Uri { private fun Uri.child(path: Path, resolve: Boolean): Uri {
val builder = buildUpon() val builder = buildUpon()
@ -184,6 +186,23 @@ class LocalMangaParser(private val uri: Uri) {
return builder.build() return builder.build()
} }
private class FsAndPath(
val fileSystem: FileSystem,
val path: Path,
private val isCloseable: Boolean,
) : AutoCloseable {
override fun close() {
if (isCloseable) {
fileSystem.close()
}
}
operator fun component1() = fileSystem
operator fun component2() = path
}
companion object { companion object {
@Blocking @Blocking
@ -240,20 +259,25 @@ class LocalMangaParser(private val uri: Uri) {
} }
@Blocking @Blocking
private fun Uri.resolveFsAndPath(): Pair<FileSystem, Path> { private fun Uri.resolveFsAndPath(): FsAndPath {
val resolved = resolve() val resolved = resolve()
return when { return when {
resolved.isZipUri() -> { resolved.isZipUri() -> FsAndPath(
FileSystem.SYSTEM.openZip(resolved.schemeSpecificPart.toPath()) to resolved.fragment.orEmpty() FileSystem.SYSTEM.openZip(resolved.schemeSpecificPart.toPath()),
.toRootedPath() resolved.fragment.orEmpty().toRootedPath(),
} isCloseable = true,
)
isFileUri() -> { isFileUri() -> {
val file = toFile() val file = toFile()
if (file.isZipArchive) { if (file.isZipArchive) {
FileSystem.SYSTEM.openZip(schemeSpecificPart.toPath()) to fragment.orEmpty().toRootedPath() FsAndPath(
FileSystem.SYSTEM.openZip(schemeSpecificPart.toPath()),
fragment.orEmpty().toRootedPath(),
isCloseable = true,
)
} else { } else {
FileSystem.SYSTEM to file.toOkioPath() FsAndPath(FileSystem.SYSTEM, file.toOkioPath(), isCloseable = false)
} }
} }

Loading…
Cancel
Save