From d00d700a4be8c85c74437ceaba014cee018659aa Mon Sep 17 00:00:00 2001 From: FooIbar <118464521+FooIbar@users.noreply.github.com> Date: Tue, 9 Jul 2024 21:43:27 +0800 Subject: [PATCH] Improve Path/Uri conversion --- .../com/hippo/ehviewer/cronet/CronetKt.kt | 6 ++--- .../ehviewer/ui/settings/DownloadScreen.kt | 4 +++- .../kotlin/com/hippo/ehviewer/util/Crash.kt | 2 +- .../com/hippo/ehviewer/util/PathUtils.kt | 15 +++++++++--- .../com/hippo/files/AndroidFileSystem.kt | 2 +- app/src/main/kotlin/com/hippo/files/Paths.kt | 23 ++++++++++++++----- 6 files changed, 37 insertions(+), 15 deletions(-) diff --git a/app/src/main/kotlin/com/hippo/ehviewer/cronet/CronetKt.kt b/app/src/main/kotlin/com/hippo/ehviewer/cronet/CronetKt.kt index cc45103c1..7952919db 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/cronet/CronetKt.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/cronet/CronetKt.kt @@ -1,7 +1,7 @@ package com.hippo.ehviewer.cronet import com.hippo.ehviewer.Settings -import okio.Path.Companion.toOkioPath +import java.io.File import org.chromium.net.CronetEngine import splitties.init.appCtx @@ -10,8 +10,8 @@ val cronetHttpClient: CronetEngine = CronetEngine.Builder(appCtx).apply { setUserAgent(Settings.userAgent) // Cache Quic hint only since the real cache mechanism should on Ktor layer - val cache = (appCtx.cacheDir.toOkioPath() / "http_cache").toFile().apply { mkdirs() } - setStoragePath(cache.absolutePath) + val cache = File(appCtx.cacheDir, "http_cache").apply { mkdirs() } + setStoragePath(cache.path) enableHttpCache(CronetEngine.Builder.HTTP_CACHE_DISK_NO_HTTP, 4096) addQuicHint("e-hentai.org", 443, 443) diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/DownloadScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/DownloadScreen.kt index a279a06bc..693854f17 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/DownloadScreen.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/DownloadScreen.kt @@ -96,7 +96,9 @@ fun DownloadScreen(navigator: DestinationsNavigator) = composing(navigator) { launchIO { runCatching { contentResolver.takePersistableUriPermission(treeUri, FLAG_GRANT_READ_URI_PERMISSION or FLAG_GRANT_WRITE_URI_PERMISSION) - downloadLocationState = DocumentsContract.buildDocumentUriUsingTree(treeUri, DocumentsContract.getTreeDocumentId(treeUri)).toOkioPath() + val path = DocumentsContract.buildDocumentUriUsingTree(treeUri, DocumentsContract.getTreeDocumentId(treeUri)).toOkioPath() + check(path.isDirectory) { "$path is not a directory" } + downloadLocationState = path launchNonCancellable { keepNoMediaFileStatus(downloadLocationState) } diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/Crash.kt b/app/src/main/kotlin/com/hippo/ehviewer/util/Crash.kt index 56f63403e..e9888515d 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/util/Crash.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/util/Crash.kt @@ -74,7 +74,7 @@ object Crash { } if (t is OutOfMemoryError) { val dumpFile = File(dir, "hprof-$nowString.hprof") - Debug.dumpHprofData(dumpFile.absolutePath) + Debug.dumpHprofData(dumpFile.path) } } } diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/PathUtils.kt b/app/src/main/kotlin/com/hippo/ehviewer/util/PathUtils.kt index 7777e7dbd..370a86e73 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/util/PathUtils.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/util/PathUtils.kt @@ -14,11 +14,20 @@ val Uri.displayPath: String? return path } - if (DocumentsContract.isDocumentUri(appCtx, this)) { + val context = appCtx + if (DocumentsContract.isDocumentUri(context, this)) { + val (type, path) = DocumentsContract.getDocumentId(this).split(":", limit = 2) if (authority == "com.android.externalstorage.documents") { - val (type, id) = DocumentsContract.getDocumentId(this).split(":", limit = 2) if (type == "primary") { - return Environment.getExternalStorageDirectory().absolutePath + "/" + id + return Environment.getExternalStorageDirectory().path + "/" + path + } + } + + context.externalCacheDirs.forEach { + val cachePath = it.path + val index = cachePath.indexOf(type) + if (index != -1) { + return cachePath.substring(0, index + type.length) + "/" + path } } } diff --git a/app/src/main/kotlin/com/hippo/files/AndroidFileSystem.kt b/app/src/main/kotlin/com/hippo/files/AndroidFileSystem.kt index 4c447bf18..2c61516ab 100644 --- a/app/src/main/kotlin/com/hippo/files/AndroidFileSystem.kt +++ b/app/src/main/kotlin/com/hippo/files/AndroidFileSystem.kt @@ -190,7 +190,7 @@ class AndroidFileSystem(context: Context) : FileSystem() { } } -private fun Path.isPhysicalFile() = toString().first() == '/' +private fun Path.isPhysicalFile() = toString().startsWith('/') private fun Uri.isCifsDocument() = authority == "com.wa2c.android.cifsdocumentsprovider.documents" diff --git a/app/src/main/kotlin/com/hippo/files/Paths.kt b/app/src/main/kotlin/com/hippo/files/Paths.kt index dd8349ba0..20e88b3ab 100644 --- a/app/src/main/kotlin/com/hippo/files/Paths.kt +++ b/app/src/main/kotlin/com/hippo/files/Paths.kt @@ -1,5 +1,6 @@ package com.hippo.files +import android.content.ContentResolver import android.net.Uri import android.os.ParcelFileDescriptor import androidx.core.net.toUri @@ -30,10 +31,16 @@ fun Path.openInputStream(): FileInputStream = fun Path.openOutputStream(): FileOutputStream = ParcelFileDescriptor.AutoCloseOutputStream(SystemFileSystem.openFileDescriptor(this, "wt")) -fun Path.toUri(): Uri = toString().replaceFirst("content:/", "content://").toUri().let { - val paths = it.pathSegments - if (paths.size > 3 && paths[0] == "tree") { - it.buildUpon().apply { +fun Path.toUri(): Uri { + val str = toString() + if (str.startsWith('/')) { + return toFile().toUri() + } + + val uri = str.replaceFirst("content:/", "content://").toUri() + val paths = uri.pathSegments + return if (paths.size > 3 && paths[0] == "tree") { + uri.buildUpon().apply { path(null) repeat(3) { i -> appendPath(paths[i]) @@ -41,8 +48,12 @@ fun Path.toUri(): Uri = toString().replaceFirst("content:/", "content://").toUri appendPath(paths.subList(3, paths.size).joinToString("/").replaceFirst(":/", ":")) }.build() } else { - it + uri } } -fun Uri.toOkioPath() = toString().toPath() +fun Uri.toOkioPath() = if (scheme == ContentResolver.SCHEME_FILE) { + path!! +} else { + toString() +}.toPath()