pull/2448/head
kunfei 2 years ago
parent aaf369346e
commit e1f180f5f8
  1. 2
      app/src/main/java/io/legado/app/help/book/BookExtensions.kt
  2. 12
      app/src/main/java/io/legado/app/model/localBook/LocalBook.kt
  3. 2
      app/src/main/java/io/legado/app/ui/association/BaseAssociationViewModel.kt
  4. 2
      app/src/main/java/io/legado/app/ui/association/FileAssociationViewModel.kt
  5. 2
      app/src/main/java/io/legado/app/ui/association/ImportBookSourceViewModel.kt
  6. 13
      app/src/main/java/io/legado/app/ui/book/group/GroupEditDialog.kt
  7. 7
      app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditActivity.kt
  8. 7
      app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt
  9. 7
      app/src/main/java/io/legado/app/ui/config/CoverConfigFragment.kt
  10. 7
      app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt
  11. 7
      app/src/main/java/io/legado/app/ui/config/WelcomeConfigFragment.kt
  12. 21
      app/src/main/java/io/legado/app/utils/UriExtensions.kt

@ -69,7 +69,7 @@ fun Book.getLocalUri(): Uri {
Uri.fromFile(File(bookUrl)) Uri.fromFile(File(bookUrl))
} }
//先检测uri是否有效,这个比较快 //先检测uri是否有效,这个比较快
uri.inputStream(appCtx)?.use { uri.inputStream(appCtx).getOrNull()?.use {
localUriCache[bookUrl] = uri localUriCache[bookUrl] = uri
}?.let { }?.let {
return uri return uri

@ -43,7 +43,8 @@ object LocalBook {
fun getBookInputStream(book: Book): InputStream { fun getBookInputStream(book: Book): InputStream {
val uri = book.getLocalUri() val uri = book.getLocalUri()
//文件不存在 尝试下载webDav文件 //文件不存在 尝试下载webDav文件
val inputStream = uri.inputStream(appCtx) ?: let { val inputStream = uri.inputStream(appCtx).getOrNull()
?: let {
book.removeLocalUriCache() book.removeLocalUriCache()
downloadRemoteBook(book) downloadRemoteBook(book)
} }
@ -241,7 +242,12 @@ object LocalBook {
?: throw NoStackTraceException("没有设置书籍保存位置!") ?: throw NoStackTraceException("没有设置书籍保存位置!")
val bytes = when { val bytes = when {
str.isAbsUrl() -> AnalyzeUrl(str, source = source).getInputStream() str.isAbsUrl() -> AnalyzeUrl(str, source = source).getInputStream()
str.isDataUrl() -> ByteArrayInputStream(Base64.decode(str.substringAfter("base64,"), Base64.DEFAULT)) str.isDataUrl() -> ByteArrayInputStream(
Base64.decode(
str.substringAfter("base64,"),
Base64.DEFAULT
)
)
else -> throw NoStackTraceException("在线导入书籍支持http/https/DataURL") else -> throw NoStackTraceException("在线导入书籍支持http/https/DataURL")
} }
return saveBookFile(bytes, fileName) return saveBookFile(bytes, fileName)
@ -324,7 +330,7 @@ object LocalBook {
localBook.bookUrl = if (it.isContentScheme()) it.toString() else it.path!! localBook.bookUrl = if (it.isContentScheme()) it.toString() else it.path!!
localBook.save() localBook.save()
localBook.cacheLocalUri(it) localBook.cacheLocalUri(it)
it.inputStream(appCtx) it.inputStream(appCtx).getOrThrow()
} }
} catch (e: Exception) { } catch (e: Exception) {
e.printOnDebug() e.printOnDebug()

@ -15,7 +15,7 @@ abstract class BaseAssociationViewModel(application: Application) : BaseViewMode
fun importJson(uri: Uri) { fun importJson(uri: Uri) {
when { when {
uri.inputStream(context).contains("bookSourceUrl") -> uri.inputStream(context).getOrNull().contains("bookSourceUrl") ->
successLive.postValue(Pair("bookSource", uri.toString())) successLive.postValue(Pair("bookSource", uri.toString()))
else -> importJson(uri.readText(context)) else -> importJson(uri.readText(context))
} }

@ -23,7 +23,7 @@ class FileAssociationViewModel(application: Application) : BaseAssociationViewMo
val fileDoc = FileDoc.fromUri(uri, false) val fileDoc = FileDoc.fromUri(uri, false)
fileName = fileDoc.name fileName = fileDoc.name
kotlin.runCatching { kotlin.runCatching {
if (uri.inputStream(context).isJson()) { if (uri.inputStream(context).getOrNull().isJson()) {
importJson(uri) importJson(uri)
return@execute return@execute
} }

@ -112,7 +112,7 @@ class ImportBookSourceViewModel(app: Application) : BaseViewModel(app) {
} }
mText.isUri() -> { mText.isUri() -> {
val uri = Uri.parse(mText) val uri = Uri.parse(mText)
uri.inputStream(context)?.let { uri.inputStream(context).getOrThrow().let {
allSources.addAll(BookSource.fromJsonArray(it).getOrThrow()) allSources.addAll(BookSource.fromJsonArray(it).getOrThrow())
} }
} }

@ -12,6 +12,7 @@ import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.theme.primaryColor import io.legado.app.lib.theme.primaryColor
import io.legado.app.utils.* import io.legado.app.utils.*
import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.viewbindingdelegate.viewBinding
import splitties.init.appCtx
import splitties.views.onClick import splitties.views.onClick
import java.io.FileOutputStream import java.io.FileOutputStream
@ -27,17 +28,23 @@ class GroupEditDialog() : BaseDialogFragment(R.layout.dialog_book_group_edit) {
private val viewModel by viewModels<GroupViewModel>() private val viewModel by viewModels<GroupViewModel>()
private var bookGroup: BookGroup? = null private var bookGroup: BookGroup? = null
val selectImage = registerForActivityResult(SelectImageContract()) { val selectImage = registerForActivityResult(SelectImageContract()) {
readUri(it?.uri) { fileDoc, inputStream -> it ?: return@registerForActivityResult
it.uri ?: return@registerForActivityResult
readUri(it.uri) { fileDoc, inputStream ->
try {
var file = requireContext().externalFiles var file = requireContext().externalFiles
val suffix = fileDoc.name.substringAfterLast(".") val suffix = fileDoc.name.substringAfterLast(".")
val fileName = it.uri!!.inputStream(requireContext())!!.use { val fileName = it.uri.inputStream(requireContext()).getOrThrow().use { tmp ->
MD5Utils.md5Encode(it) + ".$suffix" MD5Utils.md5Encode(tmp) + ".$suffix"
} }
file = FileUtils.createFileIfNotExist(file, "covers", fileName) file = FileUtils.createFileIfNotExist(file, "covers", fileName)
FileOutputStream(file).use { outputStream -> FileOutputStream(file).use { outputStream ->
inputStream.copyTo(outputStream) inputStream.copyTo(outputStream)
} }
binding.ivCover.load(file.absolutePath) binding.ivCover.load(file.absolutePath)
} catch (e: Exception) {
appCtx.toastOnUi(e.localizedMessage)
}
} }
} }

@ -17,6 +17,7 @@ import io.legado.app.help.book.isLocal
import io.legado.app.ui.book.changecover.ChangeCoverDialog import io.legado.app.ui.book.changecover.ChangeCoverDialog
import io.legado.app.utils.* import io.legado.app.utils.*
import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.viewbindingdelegate.viewBinding
import splitties.init.appCtx
import java.io.FileOutputStream import java.io.FileOutputStream
class BookInfoEditActivity : class BookInfoEditActivity :
@ -120,10 +121,11 @@ class BookInfoEditActivity :
private fun coverChangeTo(uri: Uri) { private fun coverChangeTo(uri: Uri) {
readUri(uri) { fileDoc, inputStream -> readUri(uri) { fileDoc, inputStream ->
runCatching {
inputStream.use { inputStream.use {
var file = this.externalFiles var file = this.externalFiles
val suffix = fileDoc.name.substringAfterLast(".") val suffix = fileDoc.name.substringAfterLast(".")
val fileName = uri.inputStream(this)!!.use { val fileName = uri.inputStream(this).getOrThrow().use {
MD5Utils.md5Encode(it) + ".$suffix" MD5Utils.md5Encode(it) + ".$suffix"
} }
file = FileUtils.createFileIfNotExist(file, "covers", fileName) file = FileUtils.createFileIfNotExist(file, "covers", fileName)
@ -132,6 +134,9 @@ class BookInfoEditActivity :
} }
coverChangeTo(file.absolutePath) coverChangeTo(file.absolutePath)
} }
}.onFailure {
appCtx.toastOnUi(it.localizedMessage)
}
} }
} }

@ -34,6 +34,7 @@ import io.legado.app.ui.document.HandleFileContract
import io.legado.app.ui.widget.seekbar.SeekBarChangeListener import io.legado.app.ui.widget.seekbar.SeekBarChangeListener
import io.legado.app.utils.* import io.legado.app.utils.*
import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.viewbindingdelegate.viewBinding
import splitties.init.appCtx
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
@ -353,9 +354,10 @@ class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) {
private fun setBgFromUri(uri: Uri) { private fun setBgFromUri(uri: Uri) {
readUri(uri) { fileDoc, inputStream -> readUri(uri) { fileDoc, inputStream ->
kotlin.runCatching {
var file = requireContext().externalFiles var file = requireContext().externalFiles
val suffix = fileDoc.name.substringAfterLast(".") val suffix = fileDoc.name.substringAfterLast(".")
val fileName = uri.inputStream(requireContext())!!.use { val fileName = uri.inputStream(requireContext()).getOrThrow().use {
MD5Utils.md5Encode(it) + ".$suffix" MD5Utils.md5Encode(it) + ".$suffix"
} }
file = FileUtils.createFileIfNotExist(file, "bg", fileName) file = FileUtils.createFileIfNotExist(file, "bg", fileName)
@ -364,6 +366,9 @@ class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) {
} }
ReadBookConfig.durConfig.setCurBg(2, file.absolutePath) ReadBookConfig.durConfig.setCurBg(2, file.absolutePath)
postEvent(EventBus.UP_CONFIG, false) postEvent(EventBus.UP_CONFIG, false)
}.onFailure {
appCtx.toastOnUi(it.localizedMessage)
}
} }
} }
} }

@ -14,6 +14,7 @@ import io.legado.app.lib.prefs.fragment.PreferenceFragment
import io.legado.app.lib.theme.primaryColor import io.legado.app.lib.theme.primaryColor
import io.legado.app.model.BookCover import io.legado.app.model.BookCover
import io.legado.app.utils.* import io.legado.app.utils.*
import splitties.init.appCtx
import java.io.FileOutputStream import java.io.FileOutputStream
class CoverConfigFragment : PreferenceFragment(), class CoverConfigFragment : PreferenceFragment(),
@ -139,9 +140,10 @@ class CoverConfigFragment : PreferenceFragment(),
private fun setCoverFromUri(preferenceKey: String, uri: Uri) { private fun setCoverFromUri(preferenceKey: String, uri: Uri) {
readUri(uri) { fileDoc, inputStream -> readUri(uri) { fileDoc, inputStream ->
kotlin.runCatching {
var file = requireContext().externalFiles var file = requireContext().externalFiles
val suffix = fileDoc.name.substringAfterLast(".") val suffix = fileDoc.name.substringAfterLast(".")
val fileName = uri.inputStream(requireContext())!!.use { val fileName = uri.inputStream(requireContext()).getOrThrow().use {
MD5Utils.md5Encode(it) + ".$suffix" MD5Utils.md5Encode(it) + ".$suffix"
} }
file = FileUtils.createFileIfNotExist(file, "covers", fileName) file = FileUtils.createFileIfNotExist(file, "covers", fileName)
@ -150,6 +152,9 @@ class CoverConfigFragment : PreferenceFragment(),
} }
putPrefString(preferenceKey, file.absolutePath) putPrefString(preferenceKey, file.absolutePath)
BookCover.upDefaultCover() BookCover.upDefaultCover()
}.onFailure {
appCtx.toastOnUi(it.localizedMessage)
}
} }
} }

@ -30,6 +30,7 @@ import io.legado.app.lib.theme.primaryColor
import io.legado.app.ui.widget.number.NumberPickerDialog import io.legado.app.ui.widget.number.NumberPickerDialog
import io.legado.app.ui.widget.seekbar.SeekBarChangeListener import io.legado.app.ui.widget.seekbar.SeekBarChangeListener
import io.legado.app.utils.* import io.legado.app.utils.*
import splitties.init.appCtx
import java.io.FileOutputStream import java.io.FileOutputStream
@ -303,9 +304,10 @@ class ThemeConfigFragment : PreferenceFragment(),
private fun setBgFromUri(uri: Uri, preferenceKey: String, success: () -> Unit) { private fun setBgFromUri(uri: Uri, preferenceKey: String, success: () -> Unit) {
readUri(uri) { fileDoc, inputStream -> readUri(uri) { fileDoc, inputStream ->
kotlin.runCatching {
var file = requireContext().externalFiles var file = requireContext().externalFiles
val suffix = fileDoc.name.substringAfterLast(".") val suffix = fileDoc.name.substringAfterLast(".")
val fileName = uri.inputStream(requireContext())!!.use { val fileName = uri.inputStream(requireContext()).getOrThrow().use {
MD5Utils.md5Encode(it) + ".$suffix" MD5Utils.md5Encode(it) + ".$suffix"
} }
file = FileUtils.createFileIfNotExist(file, preferenceKey, fileName) file = FileUtils.createFileIfNotExist(file, preferenceKey, fileName)
@ -314,6 +316,9 @@ class ThemeConfigFragment : PreferenceFragment(),
} }
putPrefString(preferenceKey, file.absolutePath) putPrefString(preferenceKey, file.absolutePath)
success() success()
}.onFailure {
appCtx.toastOnUi(it.localizedMessage)
}
} }
} }

@ -13,6 +13,7 @@ import io.legado.app.lib.prefs.fragment.PreferenceFragment
import io.legado.app.lib.theme.primaryColor import io.legado.app.lib.theme.primaryColor
import io.legado.app.model.BookCover import io.legado.app.model.BookCover
import io.legado.app.utils.* import io.legado.app.utils.*
import splitties.init.appCtx
import java.io.FileOutputStream import java.io.FileOutputStream
class WelcomeConfigFragment : PreferenceFragment(), class WelcomeConfigFragment : PreferenceFragment(),
@ -119,9 +120,10 @@ class WelcomeConfigFragment : PreferenceFragment(),
private fun setCoverFromUri(preferenceKey: String, uri: Uri) { private fun setCoverFromUri(preferenceKey: String, uri: Uri) {
readUri(uri) { fileDoc, inputStream -> readUri(uri) { fileDoc, inputStream ->
kotlin.runCatching {
var file = requireContext().externalFiles var file = requireContext().externalFiles
val suffix = fileDoc.name.substringAfterLast(".") val suffix = fileDoc.name.substringAfterLast(".")
val fileName = uri.inputStream(requireContext())!!.use { val fileName = uri.inputStream(requireContext()).getOrThrow().use {
MD5Utils.md5Encode(it) + ".$suffix" MD5Utils.md5Encode(it) + ".$suffix"
} }
file = FileUtils.createFileIfNotExist(file, "covers", fileName) file = FileUtils.createFileIfNotExist(file, "covers", fileName)
@ -129,6 +131,9 @@ class WelcomeConfigFragment : PreferenceFragment(),
inputStream.copyTo(it) inputStream.copyTo(it)
} }
putPrefString(preferenceKey, file.absolutePath) putPrefString(preferenceKey, file.absolutePath)
}.onFailure {
appCtx.toastOnUi(it.localizedMessage)
}
} }
} }

@ -173,23 +173,28 @@ fun Uri.writeBytes(
return false return false
} }
fun Uri.inputStream(context: Context): InputStream? { fun Uri.inputStream(context: Context): Result<InputStream> {
val uri = this val uri = this
return kotlin.runCatching {
try { try {
if (isContentScheme()) { if (isContentScheme()) {
val doc = DocumentFile.fromSingleUri(context, uri) DocumentFile.fromSingleUri(context, uri)
doc ?: throw NoStackTraceException("未获取到文件") ?: throw NoStackTraceException("未获取到文件")
return context.contentResolver.openInputStream(uri)!! return@runCatching context.contentResolver.openInputStream(uri)!!
} else { } else {
RealPathUtil.getPath(context, uri)?.let { path -> val path = RealPathUtil.getPath(context, uri)
?: throw NoStackTraceException("未获取到文件")
val file = File(path) val file = File(path)
return FileInputStream(file) if (file.exists()) {
return@runCatching FileInputStream(file)
} else {
throw NoStackTraceException("文件不存在")
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
e.printOnDebug() e.printOnDebug()
context.toastOnUi("读取inputStream失败:${e.localizedMessage}")
AppLog.put("读取inputStream失败:${e.localizedMessage}", e) AppLog.put("读取inputStream失败:${e.localizedMessage}", e)
throw e
}
} }
return null
} }
Loading…
Cancel
Save