Fix UniFile.fromUri for children of tree uri

This commit is contained in:
FooIbar committed 2024-04-15 23:50:54 +08:00
1 parent 65613f07ba
commit b39e24467c
6 files changed
+13 -44

No files matched your search

@@ -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()
}
@@ -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
@@ -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 {
@@ -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
@@ -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
@@ -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))