Przeglądaj źródła

Merge branch 'master' of https://github.com/52fisher/legado

fisher 4 lat temu
rodzic
commit
9eb8e2cf9e

BIN
app/cronetlib/cronet_api.jar


BIN
app/cronetlib/cronet_impl_common_java.jar


BIN
app/cronetlib/cronet_impl_native_java.jar


+ 1 - 1
app/src/main/assets/cronet.json

@@ -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"}

+ 1 - 1
app/src/main/assets/defaultData/txtTocRule.json

@@ -159,4 +159,4 @@
         "example": "标题后面数字没有括号124",
         "serialNumber": 18
     }
-]
+]

+ 3 - 1
app/src/main/assets/updateLog.md

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

+ 5 - 3
app/src/main/java/io/legado/app/constant/AppConst.kt

@@ -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"

+ 1 - 1
app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt

@@ -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 ->

+ 1 - 1
app/src/main/java/io/legado/app/lib/webdav/WebDav.kt

@@ -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)

+ 1 - 1
app/src/main/java/io/legado/app/ui/book/local/rule/TxtTocRuleActivity.kt

@@ -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(",")

+ 23 - 5
app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt

@@ -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()
         }

+ 34 - 4
app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt

@@ -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}")
+        }
+    }
+
     /**
      * 替换规则变化
      */

+ 29 - 0
app/src/main/java/io/legado/app/ui/book/source/debug/BookSourceDebugActivity.kt

@@ -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)
+                }
+            }
+        }
     }
 
     /**

+ 1 - 0
app/src/main/java/io/legado/app/ui/document/HandleFileActivity.kt

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

+ 7 - 4
app/src/main/java/io/legado/app/ui/document/HandleFileContract.kt

@@ -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?
     )
 
 }

+ 20 - 10
app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt

@@ -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
         }
     }
 

+ 1 - 1
app/src/main/java/io/legado/app/utils/DocumentExtensions.kt

@@ -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? {

+ 3 - 0
app/src/main/res/layout/activity_source_debug.xml

@@ -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"

+ 1 - 1
gradle.properties

@@ -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