From 5634e94f3eaf9719a4e452b38102e47e8aa836f7 Mon Sep 17 00:00:00 2001 From: Pupil Date: Mon, 10 Feb 2020 16:28:13 +0900 Subject: [PATCH] DocumentFileX --- app/build.gradle | 7 +- .../quaver/pupil/util/saf/DocumentFileX.kt | 52 ++++++++ .../quaver/pupil/util/saf/RawDocumentFileX.kt | 84 +++++++++++++ .../pupil/util/saf/TreeDocumentFileX.kt | 118 ++++++++++++++++++ 4 files changed, 256 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/xyz/quaver/pupil/util/saf/DocumentFileX.kt create mode 100644 app/src/main/java/xyz/quaver/pupil/util/saf/RawDocumentFileX.kt create mode 100644 app/src/main/java/xyz/quaver/pupil/util/saf/TreeDocumentFileX.kt diff --git a/app/build.gradle b/app/build.gradle index 5df53c31..be2fd917 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -60,9 +60,6 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.preference:preference:1.1.0' implementation 'androidx.gridlayout:gridlayout:1.0.0' - implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' - implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' - implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation "androidx.biometric:biometric:1.0.1" implementation 'com.android.support:multidex:1.0.3' implementation "com.daimajia.swipelayout:library:1.2.0@aar" @@ -72,7 +69,7 @@ dependencies { implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1' implementation 'com.github.arimorty:floatingsearchview:2.1.1' implementation 'com.github.clans:fab:1.6.4' - implementation 'com.github.bumptech.glide:glide:4.10.0' + implementation 'com.github.bumptech.glide:glide:4.11.0' implementation('com.github.bumptech.glide:recyclerview-integration:4.11.0') { transitive = false } @@ -81,7 +78,7 @@ dependencies { implementation 'com.github.chrisbanes:PhotoView:2.3.0' implementation 'com.andrognito.patternlockview:patternlockview:1.0.0' implementation "ru.noties.markwon:core:${markwonVersion}" - kapt 'com.github.bumptech.glide:compiler:4.10.0' + kapt 'com.github.bumptech.glide:compiler:4.11.0' testImplementation 'junit:junit:4.13' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test:rules:1.2.0' diff --git a/app/src/main/java/xyz/quaver/pupil/util/saf/DocumentFileX.kt b/app/src/main/java/xyz/quaver/pupil/util/saf/DocumentFileX.kt new file mode 100644 index 00000000..776c4ea3 --- /dev/null +++ b/app/src/main/java/xyz/quaver/pupil/util/saf/DocumentFileX.kt @@ -0,0 +1,52 @@ +/* + * Pupil, Hitomi.la viewer for Android + * Copyright (C) 2020 tom5079 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package xyz.quaver.pupil.util.saf + +import android.content.Context +import android.net.Uri +import java.io.File + +abstract class DocumentFileX { + + abstract fun createFile(displayName: String): DocumentFileX? + abstract fun createDirectory(displayName: String): DocumentFileX? + abstract fun getUri(): Uri + abstract fun getName(): String + abstract fun getParentFile(): DocumentFileX? + abstract fun isDirectory(): Boolean + abstract fun isFile(): Boolean + abstract fun length(): Long + abstract fun canRead(): Boolean + abstract fun canWrite(): Boolean + abstract fun delete(): Boolean + abstract fun exists(): Boolean + abstract fun listFiles(): List? + abstract fun findFile(displayName: String): DocumentFileX? + + companion object { + fun fromFile(file: File): DocumentFileX { + return RawDocumentFileX(file) + } + + fun fromTreeUri(context: Context, uri: Uri): DocumentFileX { + return TreeDocumentFileX(context, uri) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/xyz/quaver/pupil/util/saf/RawDocumentFileX.kt b/app/src/main/java/xyz/quaver/pupil/util/saf/RawDocumentFileX.kt new file mode 100644 index 00000000..fa8d754e --- /dev/null +++ b/app/src/main/java/xyz/quaver/pupil/util/saf/RawDocumentFileX.kt @@ -0,0 +1,84 @@ +/* + * Pupil, Hitomi.la viewer for Android + * Copyright (C) 2020 tom5079 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package xyz.quaver.pupil.util.saf + +import android.net.Uri +import java.io.File + +class RawDocumentFileX(private var file: File) : DocumentFileX() { + + override fun createFile(displayName: String) = + File(file, displayName).let { + try { + it.createNewFile() + RawDocumentFileX(it) + } catch (e: Exception) { + null + } + } + + override fun createDirectory(displayName: String) = + File(file, displayName).let { + if (it.isDirectory || it.mkdir()) + RawDocumentFileX(it) + else + null + } + + override fun getUri() = Uri.fromFile(file)!! + + override fun getName() = file.name + + override fun getParentFile() = + file.parentFile.let { + if (it == null) + null + else + RawDocumentFileX(it) + } + + override fun isDirectory() = file.isDirectory + + override fun isFile() = file.isFile + + override fun length() = file.length() + + override fun canRead() = file.canRead() + + override fun canWrite() = file.canWrite() + + override fun delete() = + if (file.isDirectory) + file.deleteRecursively() + else + file.delete() + + override fun exists() = file.exists() + + override fun listFiles() = file.listFiles()?.map { RawDocumentFileX(it) } + + override fun findFile(displayName: String) = + File(file, displayName).let { + if (it.exists()) + RawDocumentFileX(it) + else + null + } + +} \ No newline at end of file diff --git a/app/src/main/java/xyz/quaver/pupil/util/saf/TreeDocumentFileX.kt b/app/src/main/java/xyz/quaver/pupil/util/saf/TreeDocumentFileX.kt new file mode 100644 index 00000000..08978165 --- /dev/null +++ b/app/src/main/java/xyz/quaver/pupil/util/saf/TreeDocumentFileX.kt @@ -0,0 +1,118 @@ +/* + * Pupil, Hitomi.la viewer for Android + * Copyright (C) 2020 tom5079 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package xyz.quaver.pupil.util.saf + +import android.annotation.TargetApi +import android.content.Context +import android.net.Uri +import android.provider.DocumentsContract + +@TargetApi(21) +class TreeDocumentFileX( + private val context: Context, + private val uri: Uri, + private var name: String? = null, + private var documentID: String? = null, + private var length: Long? = null +) : DocumentFileX() { + + init { + val projection = mutableListOf() + + if (name == null) + projection.add(DocumentsContract.Document.COLUMN_DISPLAY_NAME) + if (documentID == null) + projection.add(DocumentsContract.Document.COLUMN_DOCUMENT_ID) + if (length == null) + projection.add(DocumentsContract.Document.COLUMN_SIZE) + + if (projection.isNotEmpty()) { + val contentResolver = context.contentResolver + + contentResolver.query(uri, projection.toTypedArray(), null, null, null).use { cursor -> + while (cursor?.moveToNext() == true) { + cursor.columnNames.forEach { column -> + val index = cursor.getColumnIndex(column) + + when (column) { + DocumentsContract.Document.COLUMN_DISPLAY_NAME -> this.name = cursor.getString(index) + DocumentsContract.Document.COLUMN_DOCUMENT_ID -> this.documentID = cursor.getString(index) + DocumentsContract.Document.COLUMN_SIZE -> this.length = cursor.getLong(index) + } + } + } + } + } + } + + override fun createFile(displayName: String): DocumentFileX? { + val uri = kotlin.runCatching { + DocumentsContract.createDocument(context.contentResolver, uri, "null", displayName) + }.getOrNull() ?: return null + + return TreeDocumentFileX(context, uri, displayName, DocumentsContract.getDocumentId(uri), 0) + } + + override fun createDirectory(displayName: String): DocumentFileX? { + val uri = kotlin.runCatching { + DocumentsContract.createDocument(context.contentResolver, uri, "null", displayName) + }.getOrNull() ?: return null + } + + override fun getUri() = uri + + override fun getName() = name ?: "null" + + override fun getParentFile(): DocumentFileX? + + override fun isDirectory() = name?.contains('.') == false + override fun isFile() = name?.contains('.') == true + + override fun length() = length ?: -1 + + override fun canRead(): Boolean + override fun canWrite(): Boolean + + override fun delete() = + kotlin.runCatching { + DocumentsContract.deleteDocument(context.contentResolver, uri) + }.getOrElse { false } + + override fun exists() = documentID == null + + override fun listFiles(): List? { + val contentResolver = context.contentResolver + val children = DocumentsContract.buildChildDocumentsUriUsingTree(uri, DocumentsContract.getDocumentId(uri)) + + contentResolver.query( + children, + arrayOf( + DocumentsContract.Document.COLUMN_MIME_TYPE + ), + null, + null, + null + ).use { + + } + } + + override fun findFile(displayName: String): DocumentFileX? + +} \ No newline at end of file