From b39e24467c2b25760e36656084991d2b7e1d8354 Mon Sep 17 00:00:00 2001 From: FooIbar <118464521+FooIbar@users.noreply.github.com> Date: Mon, 15 Apr 2024 23:39:40 +0800 Subject: [PATCH] Fix `UniFile.fromUri` for children of tree uri --- .../hippo/unifile/DocumentsContractApi21.kt | 20 +++++-------------- .../kotlin/com/hippo/unifile/MediaFile.kt | 2 +- .../main/kotlin/com/hippo/unifile/RawFile.kt | 3 +-- .../com/hippo/unifile/SingleDocumentFile.kt | 2 +- .../com/hippo/unifile/TreeDocumentFile.kt | 11 +++------- .../main/kotlin/com/hippo/unifile/UniFile.kt | 19 ++---------------- 6 files changed, 13 insertions(+), 44 deletions(-) diff --git a/app/src/main/kotlin/com/hippo/unifile/DocumentsContractApi21.kt b/app/src/main/kotlin/com/hippo/unifile/DocumentsContractApi21.kt index 282e0cc0a..245d8c38b 100644 --- a/app/src/main/kotlin/com/hippo/unifile/DocumentsContractApi21.kt +++ b/app/src/main/kotlin/com/hippo/unifile/DocumentsContractApi21.kt @@ -15,20 +15,18 @@ */ package com.hippo.unifile -import android.content.Context import android.net.Uri import android.provider.DocumentsContract import splitties.init.appCtx object DocumentsContractApi21 { - private const val PATH_DOCUMENT = "document" - private const val PATH_TREE = "tree" private val resolver = appCtx.contentResolver private val projection = arrayOf( DocumentsContract.Document.COLUMN_DOCUMENT_ID, DocumentsContract.Document.COLUMN_DISPLAY_NAME, DocumentsContract.Document.COLUMN_MIME_TYPE, ) + fun createFile(self: Uri, mimeType: String, displayName: String) = runCatching { DocumentsContract.createDocument(resolver, self, mimeType, displayName) }.getOrNull() @@ -38,22 +36,14 @@ object DocumentsContractApi21 { fun prepareTreeUri(treeUri: Uri?): Uri { return DocumentsContract.buildDocumentUriUsingTree( treeUri, - DocumentsContract.getTreeDocumentId(treeUri), + DocumentsContract.getDocumentId(treeUri), ) } - fun getTreeDocumentPath(documentUri: Uri): String { - val paths = documentUri.pathSegments - if (paths.size >= 4 && PATH_TREE == paths[0] && PATH_DOCUMENT == paths[2]) { - return paths[3] - } - error("Invalid URI: $documentUri") - } - fun buildChildUri(uri: Uri, displayName: String): Uri { return DocumentsContract.buildDocumentUriUsingTree( uri, - getTreeDocumentPath(uri) + "/" + displayName, + DocumentsContract.getDocumentId(uri) + "/" + displayName, ) } @@ -70,7 +60,7 @@ object DocumentsContractApi21 { } } - fun renameTo(context: Context, self: Uri, displayName: String) = runCatching { - DocumentsContract.renameDocument(context.contentResolver, self, displayName) + fun renameTo(self: Uri, displayName: String) = runCatching { + DocumentsContract.renameDocument(resolver, self, displayName) }.getOrNull() } diff --git a/app/src/main/kotlin/com/hippo/unifile/MediaFile.kt b/app/src/main/kotlin/com/hippo/unifile/MediaFile.kt index 5d8bb742f..c06ec3df3 100644 --- a/app/src/main/kotlin/com/hippo/unifile/MediaFile.kt +++ b/app/src/main/kotlin/com/hippo/unifile/MediaFile.kt @@ -18,7 +18,7 @@ package com.hippo.unifile import android.net.Uri import java.io.IOException -class MediaFile(override val uri: Uri) : UniFile(null) { +class MediaFile(override val uri: Uri) : UniFile() { override fun createFile(displayName: String) = null override fun createDirectory(displayName: String) = null diff --git a/app/src/main/kotlin/com/hippo/unifile/RawFile.kt b/app/src/main/kotlin/com/hippo/unifile/RawFile.kt index fe3308da4..c1cfa95b1 100644 --- a/app/src/main/kotlin/com/hippo/unifile/RawFile.kt +++ b/app/src/main/kotlin/com/hippo/unifile/RawFile.kt @@ -24,8 +24,7 @@ import eu.kanade.tachiyomi.util.system.logcat import java.io.File import java.util.Locale -class RawFile(parent: UniFile?, private var file: File) : UniFile(parent) { - private val parent = parent as? RawFile +class RawFile(private val parent: RawFile?, private var file: File) : UniFile() { private var cachePresent = false private val allChildren by lazy { diff --git a/app/src/main/kotlin/com/hippo/unifile/SingleDocumentFile.kt b/app/src/main/kotlin/com/hippo/unifile/SingleDocumentFile.kt index e00ad133d..2b0e4d2b1 100644 --- a/app/src/main/kotlin/com/hippo/unifile/SingleDocumentFile.kt +++ b/app/src/main/kotlin/com/hippo/unifile/SingleDocumentFile.kt @@ -17,7 +17,7 @@ package com.hippo.unifile import android.net.Uri -class SingleDocumentFile(parent: UniFile?, override val uri: Uri) : UniFile(parent) { +class SingleDocumentFile(override val uri: Uri) : UniFile() { override fun createFile(displayName: String) = null diff --git a/app/src/main/kotlin/com/hippo/unifile/TreeDocumentFile.kt b/app/src/main/kotlin/com/hippo/unifile/TreeDocumentFile.kt index a4bb8eb6b..fc9ea4411 100644 --- a/app/src/main/kotlin/com/hippo/unifile/TreeDocumentFile.kt +++ b/app/src/main/kotlin/com/hippo/unifile/TreeDocumentFile.kt @@ -18,19 +18,16 @@ package com.hippo.unifile import android.net.Uri import android.provider.DocumentsContract.Document.MIME_TYPE_DIR import android.webkit.MimeTypeMap -import eu.kanade.tachiyomi.util.system.logcat -import splitties.init.appCtx class TreeDocumentFile( - parent: UniFile?, + private val parent: UniFile?, override var uri: Uri, override var name: String = getFilenameForUri(uri), mimeType: String? = null, -) : UniFile(parent) { +) : UniFile() { private var cachePresent = false private val allChildren by lazy { cachePresent = true - logcat { "Directory lookup cache created for $name" } DocumentsContractApi21.listFiles(uri).mapTo(mutableListOf()) { (uri, name, mimeType) -> TreeDocumentFile(this, uri, name, mimeType) } @@ -98,7 +95,6 @@ class TreeDocumentFile( override fun ensureDir(): Boolean { if (isDirectory) return true if (isFile) return false - val parent = parentFile return if (parent != null && parent.ensureDir()) { parent.createDirectory(name) != null } else { @@ -109,7 +105,6 @@ class TreeDocumentFile( override fun ensureFile(): Boolean { if (isFile) return true if (isDirectory) return false - val parent = parentFile return if (parent != null && parent.ensureDir()) { parent.createFile(name) != null } else { @@ -135,7 +130,7 @@ class TreeDocumentFile( } override fun renameTo(displayName: String): Boolean { - val result = DocumentsContractApi21.renameTo(appCtx, uri, displayName) + val result = DocumentsContractApi21.renameTo(uri, displayName) if (result != null) { uri = result name = displayName diff --git a/app/src/main/kotlin/com/hippo/unifile/UniFile.kt b/app/src/main/kotlin/com/hippo/unifile/UniFile.kt index 26d9ea276..b8731d677 100644 --- a/app/src/main/kotlin/com/hippo/unifile/UniFile.kt +++ b/app/src/main/kotlin/com/hippo/unifile/UniFile.kt @@ -28,7 +28,7 @@ import splitties.init.appCtx * In Android files can be accessed via [java.io.File] and [android.net.Uri]. * The UniFile is designed to emulate File interface for both File and Uri. */ -abstract class UniFile internal constructor(private val parent: UniFile?) { +sealed class UniFile { /** * Create a new file as a direct child of this directory. * @@ -79,21 +79,6 @@ abstract class UniFile internal constructor(private val parent: UniFile?) { */ abstract val type: String? - /** - * Return the parent file of this file. Only defined inside of the - * user-selected tree; you can never escape above the top of the tree. - * - * - * The underlying [android.provider.DocumentsProvider] only defines a - * forward mapping from parent to child, so the reverse mapping of child to - * parent offered here is purely a convenience method, and it may be - * incorrect if the underlying tree structure changes. - * - * @return parent of the file, or null if it is the top of the file tree - */ - val parentFile: UniFile? - get() = parent - /** * Indicates if this file represents a *directory*. * @@ -235,7 +220,7 @@ abstract class UniFile internal constructor(private val parent: UniFile?) { companion object { fun fromFile(file: File) = RawFile(null, file) - private fun fromSingleUri(singleUri: Uri) = SingleDocumentFile(null, singleUri) + private fun fromSingleUri(singleUri: Uri) = SingleDocumentFile(singleUri) private fun fromTreeUri(treeUri: Uri) = TreeDocumentFile(null, DocumentsContractApi21.prepareTreeUri(treeUri))