优化
This commit is contained in:
@@ -102,41 +102,38 @@ class FileAssociationActivity :
|
||||
private fun importBook(treeUri: Uri, uri: Uri) {
|
||||
launch {
|
||||
runCatching {
|
||||
if (treeUri.isContentScheme()) {
|
||||
val treeDoc = DocumentFile.fromTreeUri(this@FileAssociationActivity, treeUri)
|
||||
val bookDoc = DocumentFile.fromSingleUri(this@FileAssociationActivity, uri)
|
||||
withContext(IO) {
|
||||
val name = bookDoc?.name!!
|
||||
var doc = treeDoc!!.findFile(name)
|
||||
if (doc == null || bookDoc.lastModified() > doc.lastModified()) {
|
||||
if (doc == null) {
|
||||
doc = treeDoc.createFile(FileUtils.getMimeType(name), name)
|
||||
?: throw SecurityException("Permission Denial")
|
||||
}
|
||||
contentResolver.openOutputStream(doc.uri)!!.use { oStream ->
|
||||
contentResolver.openInputStream(bookDoc.uri)!!.use { iStream ->
|
||||
iStream.copyTo(oStream)
|
||||
withContext(IO) {
|
||||
if (treeUri.isContentScheme()) {
|
||||
val treeDoc =
|
||||
DocumentFile.fromTreeUri(this@FileAssociationActivity, treeUri)
|
||||
readUri(uri) { fileDoc, inputStream ->
|
||||
val name = fileDoc.name
|
||||
var doc = treeDoc!!.findFile(name)
|
||||
if (doc == null || fileDoc.lastModified > doc.lastModified()) {
|
||||
if (doc == null) {
|
||||
doc = treeDoc.createFile(FileUtils.getMimeType(name), name)
|
||||
?: throw SecurityException("Permission Denial")
|
||||
}
|
||||
contentResolver.openOutputStream(doc.uri)!!.use { oStream ->
|
||||
inputStream.copyTo(oStream)
|
||||
oStream.flush()
|
||||
}
|
||||
}
|
||||
viewModel.importBook(doc.uri)
|
||||
}
|
||||
viewModel.importBook(doc.uri)
|
||||
}
|
||||
} else {
|
||||
val treeFile = File(treeUri.path!!)
|
||||
val bookDoc = DocumentFile.fromSingleUri(this@FileAssociationActivity, uri)
|
||||
withContext(IO) {
|
||||
val name = bookDoc?.name!!
|
||||
val file = treeFile.getFile(name)
|
||||
if (!file.exists() || file.lastModified() < bookDoc.lastModified()) {
|
||||
FileOutputStream(file).use { oStream ->
|
||||
contentResolver.openInputStream(bookDoc.uri)!!.use { iStream ->
|
||||
iStream.copyTo(oStream)
|
||||
} else {
|
||||
val treeFile = File(treeUri.path ?: treeUri.toString())
|
||||
readUri(uri) { fileDoc, inputStream ->
|
||||
val name = fileDoc.name
|
||||
val file = treeFile.getFile(name)
|
||||
if (!file.exists() || fileDoc.lastModified > file.lastModified()) {
|
||||
FileOutputStream(file).use { oStream ->
|
||||
inputStream.copyTo(oStream)
|
||||
oStream.flush()
|
||||
}
|
||||
}
|
||||
viewModel.importBook(Uri.fromFile(file))
|
||||
}
|
||||
viewModel.importBook(Uri.fromFile(file))
|
||||
}
|
||||
}
|
||||
}.onFailure {
|
||||
|
||||
@@ -13,6 +13,7 @@ import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.utils.*
|
||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||
import splitties.views.onClick
|
||||
import java.io.FileOutputStream
|
||||
|
||||
class GroupEditDialog() : BaseDialogFragment(R.layout.dialog_book_group_edit) {
|
||||
|
||||
@@ -26,10 +27,12 @@ class GroupEditDialog() : BaseDialogFragment(R.layout.dialog_book_group_edit) {
|
||||
private val viewModel by viewModels<GroupViewModel>()
|
||||
private var bookGroup: BookGroup? = null
|
||||
val selectImage = registerForActivityResult(SelectImageContract()) {
|
||||
readUri(it?.uri) { name, bytes ->
|
||||
readUri(it?.uri) { fileDoc, inputStream ->
|
||||
var file = requireContext().externalFiles
|
||||
file = FileUtils.createFileIfNotExist(file, "covers", name)
|
||||
file.writeBytes(bytes)
|
||||
file = FileUtils.createFileIfNotExist(file, "covers", fileDoc.name)
|
||||
FileOutputStream(file).use { outputStream ->
|
||||
inputStream.copyTo(outputStream)
|
||||
}
|
||||
binding.ivCover.load(file.absolutePath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import io.legado.app.databinding.ActivityBookInfoEditBinding
|
||||
import io.legado.app.ui.book.changecover.ChangeCoverDialog
|
||||
import io.legado.app.utils.*
|
||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||
import java.io.FileOutputStream
|
||||
|
||||
class BookInfoEditActivity :
|
||||
VMBaseActivity<ActivityBookInfoEditBinding, BookInfoEditViewModel>(),
|
||||
@@ -101,11 +102,15 @@ class BookInfoEditActivity :
|
||||
}
|
||||
|
||||
private fun coverChangeTo(uri: Uri) {
|
||||
readUri(uri) { name, bytes ->
|
||||
var file = this.externalFiles
|
||||
file = FileUtils.createFileIfNotExist(file, "covers", name)
|
||||
file.writeBytes(bytes)
|
||||
coverChangeTo(file.absolutePath)
|
||||
readUri(uri) { fileDoc, inputStream ->
|
||||
inputStream.use {
|
||||
var file = this.externalFiles
|
||||
file = FileUtils.createFileIfNotExist(file, "covers", fileDoc.name)
|
||||
FileOutputStream(file).use { outputStream ->
|
||||
inputStream.copyTo(outputStream)
|
||||
}
|
||||
coverChangeTo(file.absolutePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
|
||||
llBrief.visible()
|
||||
tvTag.text = item.name.substringAfterLast(".")
|
||||
tvSize.text = ConvertUtils.formatFileSize(item.size)
|
||||
tvDate.text = AppConst.dateFormat.format(item.date)
|
||||
tvDate.text = AppConst.dateFormat.format(item.lastModified)
|
||||
cbSelect.isChecked = selectedUris.contains(item.toString())
|
||||
}
|
||||
tvName.text = item.name
|
||||
|
||||
@@ -59,7 +59,7 @@ class ImportBookViewModel(application: Application) : BaseViewModel(application)
|
||||
}.map { docList ->
|
||||
when (sort) {
|
||||
2 -> docList.sortedWith(
|
||||
compareBy({ !it.isDir }, { it.date }, { it.name })
|
||||
compareBy({ !it.isDir }, { it.lastModified }, { it.name })
|
||||
)
|
||||
1 -> docList.sortedWith(
|
||||
compareBy({ !it.isDir }, { it.size }, { it.name })
|
||||
|
||||
@@ -35,6 +35,7 @@ import io.legado.app.utils.*
|
||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
|
||||
class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) {
|
||||
|
||||
@@ -350,10 +351,12 @@ class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) {
|
||||
}
|
||||
|
||||
private fun setBgFromUri(uri: Uri) {
|
||||
readUri(uri) { name, bytes ->
|
||||
readUri(uri) { fileDoc, inputStream ->
|
||||
var file = requireContext().externalFiles
|
||||
file = FileUtils.createFileIfNotExist(file, "bg", name)
|
||||
file.writeBytes(bytes)
|
||||
file = FileUtils.createFileIfNotExist(file, "bg", fileDoc.name)
|
||||
FileOutputStream(file).use { outputStream ->
|
||||
inputStream.copyTo(outputStream)
|
||||
}
|
||||
ReadBookConfig.durConfig.setCurBg(2, file.absolutePath)
|
||||
ReadBookConfig.upBg()
|
||||
postEvent(EventBus.UP_CONFIG, false)
|
||||
|
||||
@@ -14,6 +14,7 @@ import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.model.BookCover
|
||||
import io.legado.app.ui.widget.prefs.SwitchPreference
|
||||
import io.legado.app.utils.*
|
||||
import java.io.FileOutputStream
|
||||
|
||||
class CoverConfigFragment : BasePreferenceFragment(),
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
@@ -138,10 +139,12 @@ class CoverConfigFragment : BasePreferenceFragment(),
|
||||
}
|
||||
|
||||
private fun setCoverFromUri(preferenceKey: String, uri: Uri) {
|
||||
readUri(uri) { name, bytes ->
|
||||
readUri(uri) { fileDoc, inputStream ->
|
||||
var file = requireContext().externalFiles
|
||||
file = FileUtils.createFileIfNotExist(file, "covers", name)
|
||||
file.writeBytes(bytes)
|
||||
file = FileUtils.createFileIfNotExist(file, "covers", fileDoc.name)
|
||||
FileOutputStream(file).use {
|
||||
inputStream.copyTo(it)
|
||||
}
|
||||
putPrefString(preferenceKey, file.absolutePath)
|
||||
BookCover.upDefaultCover()
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import io.legado.app.ui.widget.number.NumberPickerDialog
|
||||
import io.legado.app.ui.widget.prefs.ColorPreference
|
||||
import io.legado.app.ui.widget.seekbar.SeekBarChangeListener
|
||||
import io.legado.app.utils.*
|
||||
import java.io.FileOutputStream
|
||||
|
||||
|
||||
@Suppress("SameParameterValue")
|
||||
@@ -298,10 +299,12 @@ class ThemeConfigFragment : BasePreferenceFragment(),
|
||||
}
|
||||
|
||||
private fun setBgFromUri(uri: Uri, preferenceKey: String, success: () -> Unit) {
|
||||
readUri(uri) { name, bytes ->
|
||||
readUri(uri) { fileDoc, inputStream ->
|
||||
var file = requireContext().externalFiles
|
||||
file = FileUtils.createFileIfNotExist(file, preferenceKey, name)
|
||||
file.writeBytes(bytes)
|
||||
file = FileUtils.createFileIfNotExist(file, preferenceKey, fileDoc.name)
|
||||
FileOutputStream(file).use {
|
||||
inputStream.copyTo(it)
|
||||
}
|
||||
putPrefString(preferenceKey, file.absolutePath)
|
||||
success()
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import io.legado.app.lib.dialogs.selector
|
||||
import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.model.BookCover
|
||||
import io.legado.app.utils.*
|
||||
import java.io.FileOutputStream
|
||||
|
||||
class WelcomeConfigFragment : BasePreferenceFragment(),
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
@@ -118,10 +119,12 @@ class WelcomeConfigFragment : BasePreferenceFragment(),
|
||||
}
|
||||
|
||||
private fun setCoverFromUri(preferenceKey: String, uri: Uri) {
|
||||
readUri(uri) { name, bytes ->
|
||||
readUri(uri) { fileDoc, inputStream ->
|
||||
var file = requireContext().externalFiles
|
||||
file = FileUtils.createFileIfNotExist(file, "covers", name)
|
||||
file.writeBytes(bytes)
|
||||
file = FileUtils.createFileIfNotExist(file, "covers", fileDoc.name)
|
||||
FileOutputStream(file).use {
|
||||
inputStream.copyTo(it)
|
||||
}
|
||||
putPrefString(preferenceKey, file.absolutePath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import io.legado.app.exception.NoStackTraceException
|
||||
import splitties.init.appCtx
|
||||
import java.io.File
|
||||
import java.nio.charset.Charset
|
||||
import java.util.*
|
||||
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
@@ -125,7 +124,7 @@ object DocumentUtils {
|
||||
name = cursor.getString(nci),
|
||||
isDir = cursor.getString(mci) == DocumentsContract.Document.MIME_TYPE_DIR,
|
||||
size = cursor.getLong(sci),
|
||||
date = Date(cursor.getLong(dci)),
|
||||
lastModified = cursor.getLong(dci),
|
||||
uri = DocumentsContract
|
||||
.buildDocumentUriUsingTree(uri, cursor.getString(ici))
|
||||
)
|
||||
@@ -150,7 +149,7 @@ object DocumentUtils {
|
||||
it.name,
|
||||
it.isDirectory,
|
||||
it.length(),
|
||||
Date(it.lastModified()),
|
||||
it.lastModified(),
|
||||
Uri.fromFile(it)
|
||||
)
|
||||
if (filter == null || filter.invoke(item)) {
|
||||
@@ -166,7 +165,7 @@ data class FileDoc(
|
||||
val name: String,
|
||||
val isDir: Boolean,
|
||||
val size: Long,
|
||||
val date: Date,
|
||||
val lastModified: Long,
|
||||
val uri: Uri
|
||||
) {
|
||||
|
||||
@@ -187,7 +186,7 @@ data class FileDoc(
|
||||
name = doc.name ?: "",
|
||||
isDir = doc.isDirectory,
|
||||
size = doc.length(),
|
||||
date = Date(doc.lastModified()),
|
||||
lastModified = doc.lastModified(),
|
||||
uri = doc.uri
|
||||
)
|
||||
}
|
||||
@@ -197,7 +196,7 @@ data class FileDoc(
|
||||
name = file.name,
|
||||
isDir = file.isDirectory,
|
||||
size = file.length(),
|
||||
date = Date(file.lastModified()),
|
||||
lastModified = file.lastModified(),
|
||||
uri = Uri.fromFile(file)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,32 +10,41 @@ import io.legado.app.exception.NoStackTraceException
|
||||
import io.legado.app.lib.permission.Permissions
|
||||
import io.legado.app.lib.permission.PermissionsCompat
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.InputStream
|
||||
|
||||
fun Uri.isContentScheme() = this.scheme == "content"
|
||||
|
||||
/**
|
||||
* 读取URI
|
||||
*/
|
||||
fun AppCompatActivity.readUri(uri: Uri?, success: (name: String, bytes: ByteArray) -> Unit) {
|
||||
fun AppCompatActivity.readUri(
|
||||
uri: Uri?,
|
||||
success: (fileDoc: FileDoc, inputStream: InputStream) -> Unit
|
||||
) {
|
||||
uri ?: return
|
||||
try {
|
||||
if (uri.isContentScheme()) {
|
||||
val doc = DocumentFile.fromSingleUri(this, uri)
|
||||
doc ?: throw NoStackTraceException("未获取到文件")
|
||||
val name = doc.name ?: throw NoStackTraceException("未获取到文件名")
|
||||
val fileBytes = DocumentUtils.readBytes(this, doc.uri)
|
||||
success.invoke(name, fileBytes)
|
||||
val fileDoc = FileDoc.fromDocumentFile(doc)
|
||||
contentResolver.openInputStream(uri)!!.use { inputStream ->
|
||||
success.invoke(fileDoc, inputStream)
|
||||
}
|
||||
} else {
|
||||
PermissionsCompat.Builder(this)
|
||||
.addPermissions(
|
||||
Permissions.READ_EXTERNAL_STORAGE,
|
||||
Permissions.WRITE_EXTERNAL_STORAGE
|
||||
)
|
||||
.rationale(R.string.bg_image_per)
|
||||
.rationale(R.string.get_storage_per)
|
||||
.onGranted {
|
||||
RealPathUtil.getPath(this, uri)?.let { path ->
|
||||
val imgFile = File(path)
|
||||
success.invoke(imgFile.name, imgFile.readBytes())
|
||||
val file = File(path)
|
||||
val fileDoc = FileDoc.fromFile(file)
|
||||
FileInputStream(file).use { inputStream ->
|
||||
success.invoke(fileDoc, inputStream)
|
||||
}
|
||||
}
|
||||
}
|
||||
.request()
|
||||
@@ -49,26 +58,31 @@ fun AppCompatActivity.readUri(uri: Uri?, success: (name: String, bytes: ByteArra
|
||||
/**
|
||||
* 读取URI
|
||||
*/
|
||||
fun Fragment.readUri(uri: Uri?, success: (name: String, bytes: ByteArray) -> Unit) {
|
||||
fun Fragment.readUri(uri: Uri?, success: (fileDoc: FileDoc, inputStream: InputStream) -> Unit) {
|
||||
uri ?: return
|
||||
try {
|
||||
if (uri.isContentScheme()) {
|
||||
val doc = DocumentFile.fromSingleUri(requireContext(), uri)
|
||||
doc ?: throw NoStackTraceException("未获取到文件")
|
||||
val name = doc.name ?: throw NoStackTraceException("未获取到文件名")
|
||||
val fileBytes = DocumentUtils.readBytes(requireContext(), doc.uri)
|
||||
success.invoke(name, fileBytes)
|
||||
val fileDoc = FileDoc.fromDocumentFile(doc)
|
||||
requireContext().contentResolver.openInputStream(uri)!!.use { inputStream ->
|
||||
success.invoke(fileDoc, inputStream)
|
||||
}
|
||||
} else {
|
||||
PermissionsCompat.Builder(this)
|
||||
.addPermissions(
|
||||
Permissions.READ_EXTERNAL_STORAGE,
|
||||
Permissions.WRITE_EXTERNAL_STORAGE
|
||||
)
|
||||
.rationale(R.string.bg_image_per)
|
||||
.rationale(R.string.get_storage_per)
|
||||
.onGranted {
|
||||
RealPathUtil.getPath(requireContext(), uri)?.let { path ->
|
||||
val imgFile = File(path)
|
||||
success.invoke(imgFile.name, imgFile.readBytes())
|
||||
val file = File(path)
|
||||
val fileDoc = FileDoc.fromFile(file)
|
||||
FileInputStream(file).use { inputStream ->
|
||||
success.invoke(fileDoc, inputStream)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
.request()
|
||||
|
||||
Reference in New Issue
Block a user