pull/2130/head
fisher 2 years ago
commit 6be0cb9884
  1. BIN
      app/cronetlib/cronet_api.jar
  2. BIN
      app/cronetlib/cronet_impl_common_java.jar
  3. BIN
      app/cronetlib/cronet_impl_native_java.jar
  4. 2
      app/src/main/assets/cronet.json
  5. 4
      app/src/main/assets/updateLog.md
  6. 8
      app/src/main/java/io/legado/app/constant/AppConst.kt
  7. 2
      app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt
  8. 2
      app/src/main/java/io/legado/app/lib/webdav/WebDav.kt
  9. 2
      app/src/main/java/io/legado/app/ui/book/local/rule/TxtTocRuleActivity.kt
  10. 28
      app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt
  11. 38
      app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt
  12. 29
      app/src/main/java/io/legado/app/ui/book/source/debug/BookSourceDebugActivity.kt
  13. 1
      app/src/main/java/io/legado/app/ui/document/HandleFileActivity.kt
  14. 11
      app/src/main/java/io/legado/app/ui/document/HandleFileContract.kt
  15. 30
      app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt
  16. 2
      app/src/main/java/io/legado/app/utils/DocumentExtensions.kt
  17. 3
      app/src/main/res/layout/activity_source_debug.xml
  18. 2
      gradle.properties

Binary file not shown.

@ -1 +1 @@
{"armeabi-v7a":"2001ec065243c76166fe5cc3c7ee2657","x86":"6d1301e1dc1c63eedd6ad9d57716972f","arm64-v8a":"ff861c88eaa622eba7f8a7af0672352b","x86_64":"5eb49453ef59221deaee4913a0d693b6","version":"103.0.5060.129"}
{"armeabi-v7a":"a36bb21eec579e2c4bed0009eb0f1587","x86":"afce9bdd790c215374bb906919179ca5","arm64-v8a":"3ea9fa21d9b18860cfa12957c39dded1","x86_64":"717c1ebe0d1d3562f5c91c2b2606d2c2","version":"104.0.5112.69"}

@ -11,11 +11,13 @@
* 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则或简繁转换出现问题。
* 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源!
**2022/07/31**
**2022/08/02**
* 更新cronet: 104.0.5112.69
* 修复一些bug by 821938089
* 备份自定义直链上传规则
* 尝试修复epub加载OOM的问题
* 图片添加保存按钮
* 一些优化
**2022/07/21**

@ -50,15 +50,17 @@ object AppConst {
const val notificationIdDownload = -1122395
const val notificationIdCheckSource = -1122395
const val imagePathKey = "imagePath"
val menuViewNames = arrayOf(
"com.android.internal.view.menu.ListMenuItemView",
"androidx.appcompat.view.menu.ListMenuItemView"
)
@SuppressLint("PrivateResource")
val sysElevation =
appCtx.resources.getDimension(com.google.android.material.R.dimen.design_appbar_elevation)
.toInt()
val sysElevation = appCtx.resources
.getDimension(com.google.android.material.R.dimen.design_appbar_elevation)
.toInt()
val androidId: String by lazy {
Settings.System.getString(appCtx.contentResolver, Settings.Secure.ANDROID_ID) ?: "null"

@ -148,7 +148,7 @@ class Coroutine<T>(
success?.let { dispatchCallback(this, value, it) }
} catch (e: Throwable) {
e.printOnDebug()
if (e is CancellationException && !isActive && e !is ActivelyCancelException) {
if (e is CancellationException && e !is ActivelyCancelException && isCancelled) {
this@Coroutine.cancel()
}
val consume: Boolean = errorReturn?.value?.let { value ->

@ -71,7 +71,7 @@ open class WebDav(val path: String, val authorization: Authorization) {
private val webDavClient by lazy {
val authInterceptor = Interceptor { chain ->
var request = chain.request()
if (request.url.host == host) {
if (request.url.host.equals(host, true)) {
request = request
.newBuilder()
.header(authorization.name, authorization.data)

@ -159,7 +159,7 @@ class TxtTocRuleActivity : VMBaseActivity<ActivityTxtTocRuleBinding, TxtTocRuleV
@SuppressLint("InflateParams")
private fun showImportDialog() {
val aCache = ACache.get(cacheDir = false)
val defaultUrl = "https://raw.githubusercontent.com/52fisher/YueDuJson/master/myTxtChapterRule.json"
val defaultUrl = "https://gitee.com/fisher52/YueDuJson/raw/master/myTxtChapterRule.json"
val cacheUrls: MutableList<String> = aCache
.getAsString(importTocRuleKey)
?.splitNotBlank(",")

@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.content.res.Configuration
import android.net.Uri
import android.os.Bundle
import android.view.*
import androidx.activity.result.contract.ActivityResultContracts
@ -14,10 +15,7 @@ import androidx.core.view.size
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
import io.legado.app.BuildConfig
import io.legado.app.R
import io.legado.app.constant.BookType
import io.legado.app.constant.EventBus
import io.legado.app.constant.PreferKey
import io.legado.app.constant.Status
import io.legado.app.constant.*
import io.legado.app.data.appDb
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter
@ -58,6 +56,7 @@ import io.legado.app.ui.book.source.edit.BookSourceEditActivity
import io.legado.app.ui.book.toc.TocActivityResult
import io.legado.app.ui.browser.WebViewActivity
import io.legado.app.ui.dict.DictDialog
import io.legado.app.ui.document.HandleFileContract
import io.legado.app.ui.login.SourceLoginActivity
import io.legado.app.ui.replace.ReplaceRuleActivity
import io.legado.app.ui.replace.edit.ReplaceEditActivity
@ -129,6 +128,12 @@ class ReadBookActivity : BaseReadBookActivity(),
}
}
}
private val selectImageDir = registerForActivityResult(HandleFileContract()) {
it.uri?.let { uri ->
ACache.get().put(AppConst.imagePathKey, uri.toString())
viewModel.saveImage(it.value, uri)
}
}
private var menu: Menu? = null
private var autoPageJob: Job? = null
private var backupJob: Job? = null
@ -1001,13 +1006,26 @@ class ReadBookActivity : BaseReadBookActivity(),
popupAction.setItems(
listOf(
SelectItem(getString(R.string.show), "show"),
SelectItem(getString(R.string.refresh), "refresh")
SelectItem(getString(R.string.refresh), "refresh"),
SelectItem(getString(R.string.action_save), "save"),
SelectItem(getString(R.string.select_folder), "selectFolder")
)
)
popupAction.onActionClick = {
when (it) {
"show" -> showDialogFragment(PhotoDialog(src))
"refresh" -> viewModel.refreshImage(src)
"save" -> {
val path = ACache.get().getAsString(AppConst.imagePathKey)
if (path.isNullOrEmpty()) {
selectImageDir.launch {
value = src
}
} else {
viewModel.saveImage(src, Uri.parse(path))
}
}
"selectFolder" -> selectImageDir.launch()
}
popupAction.dismiss()
}

@ -2,6 +2,8 @@ package io.legado.app.ui.book.read
import android.app.Application
import android.content.Intent
import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import io.legado.app.R
@ -28,12 +30,12 @@ import io.legado.app.service.BaseReadAloudService
import io.legado.app.ui.book.read.page.entities.TextChapter
import io.legado.app.ui.book.read.page.provider.ImageProvider
import io.legado.app.ui.book.searchContent.SearchResult
import io.legado.app.utils.msg
import io.legado.app.utils.postEvent
import io.legado.app.utils.toStringArray
import io.legado.app.utils.toastOnUi
import io.legado.app.utils.*
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
/**
* 阅读界面数据处理
@ -425,6 +427,34 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
}
}
@Suppress("BlockingMethodInNonBlockingContext")
fun saveImage(src: String?, uri: Uri) {
src ?: return
val book = ReadBook.book ?: return
execute {
val image = BookHelp.getImage(book, src)
FileInputStream(image).use { input ->
if (uri.isContentScheme()) {
DocumentFile.fromTreeUri(context, uri)?.let { doc ->
val imageDoc = DocumentUtils.createFileIfNotExist(doc, image.name)!!
context.contentResolver.openOutputStream(imageDoc.uri)!!.use { output ->
input.copyTo(output)
}
}
} else {
val dir = File(uri.path ?: uri.toString())
val file = FileUtils.createFileIfNotExist(dir, image.name)
FileOutputStream(file).use { output ->
input.copyTo(output)
}
}
}
}.onError {
AppLog.put("保存图片出错\n${it.localizedMessage}", it)
context.toastOnUi("保存图片出错\n${it.localizedMessage}")
}
}
/**
* 替换规则变化
*/

@ -109,6 +109,35 @@ class BookSourceDebugActivity : VMBaseActivity<ActivitySourceDebugBinding, BookS
searchView.setQuery(binding.textFx.text, true)
}
}
binding.textInfo.onClick {
if (!searchView.query.isNullOrBlank()) {
searchView.setQuery(searchView.query, true)
}
}
binding.textToc.onClick {
val query = searchView.query
if (query.isNullOrBlank() || query.length <= 2) {
searchView.setQuery("++", false)
} else {
if (!query.startsWith("++")) {
searchView.setQuery("++$query", true)
} else {
searchView.setQuery(query, true)
}
}
}
binding.textContent.onClick {
val query = searchView.query
if (query.isNullOrBlank() || query.length <= 2) {
searchView.setQuery("--", false)
} else {
if (!query.startsWith("--")) {
searchView.setQuery("--$query", true)
} else {
searchView.setQuery(query, true)
}
}
}
}
/**

@ -223,6 +223,7 @@ class HandleFileActivity :
}
}
} else {
data.putExtra("value", intent.getStringExtra("value"))
setResult(RESULT_OK, data)
finish()
}

@ -32,15 +32,16 @@ class HandleFileContract :
intent.putExtra("fileKey", IntentData.put(fileData.second))
intent.putExtra("contentType", fileData.third)
}
intent.putExtra("value", it.value)
}
return intent
}
override fun parseResult(resultCode: Int, intent: Intent?): Result {
if (resultCode == RESULT_OK) {
return Result(intent?.data, requestCode)
return Result(intent?.data, requestCode, intent?.getStringExtra("value"))
}
return Result(null, requestCode)
return Result(null, requestCode, intent?.getStringExtra("value"))
}
companion object {
@ -57,12 +58,14 @@ class HandleFileContract :
var allowExtensions: Array<String> = arrayOf(),
var otherActions: ArrayList<SelectItem<Int>>? = null,
var fileData: Triple<String, Any, String>? = null,
var requestCode: Int = 0
var requestCode: Int = 0,
var value: String? = null
)
data class Result(
val uri: Uri?,
val requestCode: Int
val requestCode: Int,
val value: String?
)
}

@ -14,9 +14,11 @@ import androidx.webkit.WebViewFeature
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.AppConst
import io.legado.app.constant.AppConst.imagePathKey
import io.legado.app.databinding.ActivityRssReadBinding
import io.legado.app.help.config.AppConfig
import io.legado.app.lib.dialogs.SelectItem
import io.legado.app.lib.dialogs.selector
import io.legado.app.lib.theme.accentColor
import io.legado.app.lib.theme.primaryTextColor
import io.legado.app.model.Download
@ -38,15 +40,13 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
override val binding by viewBinding(ActivityRssReadBinding::inflate)
override val viewModel by viewModels<ReadRssViewModel>()
private val imagePathKey = "imagePath"
private var starMenuItem: MenuItem? = null
private var ttsMenuItem: MenuItem? = null
private var customWebViewCallback: WebChromeClient.CustomViewCallback? = null
private var webPic: String? = null
private val saveImage = registerForActivityResult(HandleFileContract()) {
private val selectImageDir = registerForActivityResult(HandleFileContract()) {
it.uri?.let { uri ->
ACache.get().put(imagePathKey, uri.toString())
viewModel.saveImage(webPic, uri)
viewModel.saveImage(it.value, uri)
}
}
@ -135,8 +135,18 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
if (hitTestResult.type == WebView.HitTestResult.IMAGE_TYPE ||
hitTestResult.type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE
) {
hitTestResult.extra?.let {
saveImage(it)
hitTestResult.extra?.let { webPic ->
selector(
arrayListOf(
SelectItem(getString(R.string.action_save), "save"),
SelectItem(getString(R.string.select_folder), "selectFolder")
)
) { _, charSequence, i ->
when (charSequence.value) {
"save" -> saveImage(webPic)
"selectFolder" -> selectSaveFolder(null)
}
}
return@setOnLongClickListener true
}
}
@ -153,23 +163,23 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
}
private fun saveImage(webPic: String) {
this.webPic = webPic
val path = ACache.get().getAsString(imagePathKey)
if (path.isNullOrEmpty()) {
selectSaveFolder()
selectSaveFolder(webPic)
} else {
viewModel.saveImage(webPic, Uri.parse(path))
}
}
private fun selectSaveFolder() {
private fun selectSaveFolder(webPic: String?) {
val default = arrayListOf<SelectItem<Int>>()
val path = ACache.get().getAsString(imagePathKey)
if (!path.isNullOrEmpty()) {
default.add(SelectItem(path, -1))
}
saveImage.launch {
selectImageDir.launch {
otherActions = default
value = webPic
}
}

@ -31,7 +31,7 @@ object DocumentUtils {
vararg subDirs: String
): DocumentFile? {
val parent: DocumentFile? = createFolderIfNotExist(root, *subDirs)
return parent?.createFile(mimeType, fileName)
return parent?.findFile(fileName) ?: parent?.createFile(mimeType, fileName)
}
fun createFolderIfNotExist(root: DocumentFile, vararg subDirs: String): DocumentFile? {

@ -132,6 +132,7 @@
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/text_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="3dp"
@ -156,6 +157,7 @@
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/text_toc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="3dp"
@ -180,6 +182,7 @@
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/text_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="3dp"

@ -26,4 +26,4 @@ android.experimental.enableNewResourceShrinker.preciseShrinking=true
# and none from the library's dependencies, thereby reducing the size of the R class for that library.
android.nonTransitiveRClass=true
#https://chromiumdash.appspot.com/releases?platform=Android
CronetVersion=103.0.5060.129
CronetVersion=104.0.5112.69

Loading…
Cancel
Save