diff --git a/.github/scripts/cronet.sh b/.github/scripts/cronet.sh
index 95e471f83..2a6b865d2 100644
--- a/.github/scripts/cronet.sh
+++ b/.github/scripts/cronet.sh
@@ -1,14 +1,16 @@
#!/usr/bin/env bash
-echo "fetch release info from https://chromiumdash.appspot.com ..."
-
-branch="Stable"
+branch=$1
+[ -z $1 ] && branch=Stable
+[ -z $GITHUB_ENV ] && echo "Error: Unexpected github workflow environment" && exit
+# 获取最新cronet版本
+echo "fetch $branch release info from https://chromiumdash.appspot.com ..."
lastest_cronet_version=`curl -s "https://chromiumdash.appspot.com/fetch_releases?channel=$branch&platform=Android&num=1&offset=0" | jq .[0].version -r`
echo "lastest_cronet_version: $lastest_cronet_version"
#lastest_cronet_version=100.0.4845.0
lastest_cronet_main_version=${lastest_cronet_version%%\.*}.0.0.0
-
+# 检查版本是否存在
function checkVersionExit() {
local jar_url="https://storage.googleapis.com/chromium-cronet/android/$lastest_cronet_version/Release/cronet/cronet_api.jar"
statusCode=$(curl -s -I -w %{http_code} "$jar_url" -o /dev/null)
@@ -17,18 +19,25 @@ function checkVersionExit() {
exit
fi
}
-
+# 添加变量到github env
+function writeVariableToGithubEnv() {
+ echo "$1=$2" >> $GITHUB_ENV
+}
+# 获取本地cronet版本
path=$GITHUB_WORKSPACE/gradle.properties
current_cronet_version=`cat $path | grep CronetVersion | sed s/CronetVersion=//`
echo "current_cronet_version: $current_cronet_version"
if [[ $current_cronet_version < $lastest_cronet_version ]];then
checkVersionExit
+ # 更新gradle.properties
sed -i s/CronetVersion=.*/CronetVersion=$lastest_cronet_version/ $path
sed -i s/CronetMainVersion=.*/CronetMainVersion=$lastest_cronet_main_version/ $path
+ # 添加更新日志
sed "15a* 更新cronet: $lastest_cronet_version" -i $GITHUB_WORKSPACE/app/src/main/assets/updateLog.md
- echo "start download latest cronet"
- chmod +x gradlew
- ./gradlew app:downloadCronet
-fi
-
+ # 生成pull request信息
+ writeVariableToGithubEnv PR_TITLE "Bump cronet from $current_cronet_version to $lastest_cronet_version"
+ writeVariableToGithubEnv PR_BODY "Changes in the [Git log](https://chromium.googlesource.com/chromium/src/+log/$current_cronet_version..$lastest_cronet_version)"
+ # 生成cronet flag
+ writeVariableToGithubEnv cronet ok
+fi
\ No newline at end of file
diff --git a/.github/workflows/cronet.yml b/.github/workflows/cronet.yml
index 341c3afae..3280eb0cc 100644
--- a/.github/workflows/cronet.yml
+++ b/.github/workflows/cronet.yml
@@ -11,17 +11,19 @@ jobs:
if: ${{ github.repository == 'gedoor/legado' }}
steps:
- uses: actions/checkout@v3
- - name: Set up Gradle
- uses: gradle/gradle-build-action@v2
-
- name: Check Cronet Updates
+ run: source .github/scripts/cronet.sh
+
+ - uses: gradle/gradle-build-action@v2
+ if: ${{ env.cronet == 'ok' }}
+ - name: Download Cronet
+ if: ${{ env.cronet == 'ok' }}
run: |
- echo "获取cronet最新版本"
- source .github/scripts/cronet.sh
- echo "PR_TITLE=Bump cronet from $current_cronet_version to $lastest_cronet_version " >> $GITHUB_ENV
- echo "PR_BODY=Changes in the [Git log](https://chromium.googlesource.com/chromium/src/+log/$current_cronet_version..$lastest_cronet_version)" >> $GITHUB_ENV
+ chmod +x gradlew
+ ./gradlew app:downloadCronet
- name: Create Pull Request
+ if: ${{ env.cronet == 'ok' }}
uses: peter-evans/create-pull-request@v4
continue-on-error: true
with:
@@ -38,4 +40,3 @@ jobs:
*cronet.json
*updateLog.md
gradle.properties
-
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index f20d04360..8fe406da8 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -60,6 +60,8 @@ jobs:
VERSIONL: ${{ needs.prepare.outputs.versionL }}
steps:
- uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
- name: Clear 18PlusList.txt
run: |
echo "清空18PlusList.txt"
diff --git a/app/build.gradle b/app/build.gradle
index 38a6294a3..0be48cbec 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -172,7 +172,7 @@ dependencies {
implementation('com.google.code.gson:gson:2.10.1')
//lifecycle
- def lifecycle_version = '2.5.1'
+ def lifecycle_version = '2.6.0'
implementation("androidx.lifecycle:lifecycle-common-java8:$lifecycle_version")
implementation("androidx.lifecycle:lifecycle-service:$lifecycle_version")
@@ -246,7 +246,7 @@ dependencies {
//加解密类库,有些书源使用
//noinspection GradleDependency,GradlePackageUpdate
- implementation('cn.hutool:hutool-crypto:5.8.14')
+ implementation('cn.hutool:hutool-crypto:5.8.15')
//firebase, 崩溃统计和性能统计, 会导致共存版本崩溃
//implementation platform('com.google.firebase:firebase-bom:30.0.1')
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index d775b2ee4..a02240357 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -392,6 +392,7 @@
-keep class io.legado.app.lib.cronet.CronetInterceptor{*;}
-keep class io.legado.app.lib.cronet.CronetLoader{*;}
-keep class io.legado.app.help.AppUpdateGitHub{*;}
+-keep class io.legado.app.help.AppIntentType{*;}
# Error Exception
-keep class * extends java.lang.Exception
-keep class * extends java.lang.Error
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7c8235082..1436fb3b0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -381,12 +381,20 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/io/legado/app/help/CrashHandler.kt b/app/src/main/java/io/legado/app/help/CrashHandler.kt
index b72d9c944..684bac9d4 100644
--- a/app/src/main/java/io/legado/app/help/CrashHandler.kt
+++ b/app/src/main/java/io/legado/app/help/CrashHandler.kt
@@ -3,6 +3,7 @@ package io.legado.app.help
import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
+import android.webkit.WebSettings
import io.legado.app.constant.AppConst
import io.legado.app.model.ReadAloud
import io.legado.app.utils.FileUtils
@@ -65,6 +66,7 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
map["MODEL"] = Build.MODEL
map["SDK_INT"] = Build.VERSION.SDK_INT.toString()
map["RELEASE"] = Build.VERSION.RELEASE
+ map["WebViewUserAgent"] = WebSettings.getDefaultUserAgent(appCtx)
//获取app版本信息
AppConst.appInfo.let {
map["versionName"] = it.versionName
diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt
index 525d7d935..0033213be 100644
--- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt
+++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt
@@ -585,16 +585,18 @@ class AnalyzeUrl(
/**
* 设置cookie 优先级
- * urlOption临时cookie > 数据库cookie = okhttp CookieJar保存在内存中的cookie
+ * urlOption临时cookie > 数据库cookie
*/
private fun setCookie() {
val cookie = kotlin.run {
+ /* 每次调用getXX cookieJar已经保存过了
if (enabledCookieJar) {
val key = "${domain}_cookieJar"
CacheManager.getFromMemory(key)?.let {
return@run it
}
}
+ */
CookieStore.getCookie(domain)
}
if (cookie.isNotEmpty()) {
@@ -608,7 +610,7 @@ class AnalyzeUrl(
}
/**
- * 保存cookie在访问结束时就保存,不等到下次访问
+ * 保存cookieJar中的cookie在访问结束时就保存,不等到下次访问
*/
private fun saveCookie() {
//书源启用保存cookie时 添加内存中的cookie到数据库
diff --git a/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt b/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt
index a98c76562..4660928da 100644
--- a/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt
+++ b/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt
@@ -151,7 +151,7 @@ object BookInfo {
coroutineContext.ensureActive()
Debug.log(bookSource.bookSourceUrl, "┌获取文件下载链接")
book.downloadUrls = analyzeRule.getStringList(infoRule.downloadUrls, isUrl = true)
- if (book.downloadUrls == null) {
+ if (book.downloadUrls.isNullOrEmpty()) {
Debug.log(bookSource.bookSourceUrl, "└")
throw NoStackTraceException("下载链接为空")
} else {
diff --git a/app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt b/app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt
index 722856ddb..ebbf1a98c 100644
--- a/app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt
+++ b/app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt
@@ -45,7 +45,7 @@ class GroupSelectDialog() : BaseDialogFragment(R.layout.dialog_book_group_picker
private var requestCode: Int = -1
private val viewModel: GroupViewModel by viewModels()
private val adapter by lazy { GroupAdapter(requireContext()) }
- private var callBack = (activity as? CallBack)
+ private val callBack get() = (activity as? CallBack)
private var groupId: Long = 0
override fun onStart() {
diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt
index e5691959e..8e6a3d188 100644
--- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt
+++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt
@@ -52,8 +52,7 @@ class BookInfoActivity :
VMBaseActivity(toolBarTheme = Theme.Dark),
GroupSelectDialog.CallBack,
ChangeBookSourceDialog.CallBack,
- ChangeCoverDialog.CallBack,
- BookInfoViewModel.CallBack {
+ ChangeCoverDialog.CallBack {
private val tocActivityResult = registerForActivityResult(TocActivityResult()) {
it?.let {
@@ -108,10 +107,9 @@ class BookInfoActivity :
binding.flAction.setBackgroundColor(bottomBackground)
binding.tvShelf.setTextColor(getPrimaryTextColor(ColorUtils.isColorLight(bottomBackground)))
binding.tvToc.text = getString(R.string.toc_s, getString(R.string.loading))
- viewModel.callBack = this
viewModel.bookData.observe(this) { showBook(it) }
viewModel.chapterListData.observe(this) { upLoading(false, it) }
- //viewModel.webFileData.observe(this) { showWebFileDownloadAlert() }
+ viewModel.waitDialogData.observe(this) { upWaitDialogStatus(it) }
viewModel.initData(intent)
initViewEvent()
}
@@ -499,31 +497,34 @@ class BookInfoActivity :
private fun showWebFileDownloadAlert(
onClick: ((Book) -> Unit)? = null
) {
- viewModel.webFileData.value?.let {
- alert(titleResource = R.string.download_and_import_file) {
- items(it) { _, webFile, _ ->
- if (webFile.isSupported) {
- /* import */
- viewModel.importOrDownloadWebFile(webFile) {
- onClick?.invoke(it)
- }
- } else {
- alert(
- title = getString(R.string.draw),
- message = getString(R.string.file_not_supported, webFile.name)
- ) {
- neutralButton(R.string.open_fun) {
- /* download only */
- viewModel.importOrDownloadWebFile(webFile) { uri ->
- openFileUri(uri, "*/*")
- }
+ val webFiles = viewModel.webFiles
+ if (webFiles.isEmpty()) {
+ toastOnUi("Unexpected webFileData")
+ return
+ }
+ alert(titleResource = R.string.download_and_import_file) {
+ items(webFiles) { _, webFile, _ ->
+ if (webFile.isSupported) {
+ /* import */
+ viewModel.importOrDownloadWebFile(webFile) {
+ onClick?.invoke(it)
+ }
+ } else {
+ alert(
+ title = getString(R.string.draw),
+ message = getString(R.string.file_not_supported, webFile.name)
+ ) {
+ neutralButton(R.string.open_fun) {
+ /* download only */
+ viewModel.importOrDownloadWebFile(webFile) { uri ->
+ openFileUri(uri, "*/*")
}
- noButton()
}
+ noButton()
}
}
}
- } ?: toastOnUi("Unexpected webFileData")
+ }
}
private fun readBook(book: Book) {
@@ -588,14 +589,15 @@ class BookInfoActivity :
}
}
- override fun onWebFileProcessFinally() {
- waitDialog.dismiss()
- }
-
- override fun onWebFileProcessStart() {
- waitDialog.run {
- setText("Loading.....")
- show()
+ private fun upWaitDialogStatus(isShow: Boolean) {
+ val showText = "Loading....."
+ if (isShow) {
+ waitDialog.run {
+ setText(showText)
+ show()
+ }
+ } else {
+ waitDialog.dismiss()
}
}
diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt
index ba8546c68..633105d7e 100644
--- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt
+++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt
@@ -21,8 +21,6 @@ import io.legado.app.help.AppWebDav
import io.legado.app.help.book.*
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.lib.webdav.ObjectNotFoundException
-import io.legado.app.model.analyzeRule.AnalyzeRule
-import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.model.BookCover
import io.legado.app.model.ReadBook
import io.legado.app.model.localBook.LocalBook
@@ -30,18 +28,17 @@ import io.legado.app.model.webBook.WebBook
import io.legado.app.utils.isContentScheme
import io.legado.app.utils.postEvent
import io.legado.app.utils.toastOnUi
-import io.legado.app.utils.runOnUI
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO
class BookInfoViewModel(application: Application) : BaseViewModel(application) {
val bookData = MutableLiveData()
val chapterListData = MutableLiveData>()
- val webFileData = MutableLiveData>()
+ val webFiles = mutableListOf()
var inBookshelf = false
var bookSource: BookSource? = null
private var changeSourceCoroutine: Coroutine<*>? = null
- var callBack: CallBack? = null
+ val waitDialogData = MutableLiveData()
fun initData(intent: Intent) {
execute {
@@ -241,45 +238,24 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
scope: CoroutineScope = viewModelScope
) {
execute(scope) {
+ webFiles.clear()
val fileName = "${book.name} 作者:${book.author}"
- if (book.downloadUrls.isNullOrEmpty()) {
- val ruleDownloadUrls = bookSource.getBookInfoRule().downloadUrls
- val content = AnalyzeUrl(book.bookUrl, source = bookSource).getStrResponse().body
- val analyzeRule = AnalyzeRule(book, bookSource)
- analyzeRule.setContent(content).setBaseUrl(book.bookUrl)
- analyzeRule.getStringList(ruleDownloadUrls, isUrl = true)?.let {
- parseDownloadUrls(it, fileName)
- } ?: throw NoStackTraceException("Unexpected ruleDownloadUrls")
- } else {
- parseDownloadUrls(book.downloadUrls, fileName)
+ book.downloadUrls!!.map {
+ val mFileName = "${fileName}.${LocalBook.parseFileSuffix(it)}"
+ val isSupportedFile = AppPattern.bookFileRegex.matches(mFileName)
+ WebFile(it, mFileName, isSupportedFile)
}
}.onError {
context.toastOnUi("LoadWebFileError\n${it.localizedMessage}")
}.onSuccess {
- webFileData.postValue(it)
- }
- }
-
- private fun parseDownloadUrls(
- downloadUrls: List?,
- fileName: String
- ): List? {
- val urls = downloadUrls
- return urls?.map {
- val mFileName = "${fileName}.${LocalBook.parseFileSuffix(it)}"
- val isSupportedFile = AppPattern.bookFileRegex.matches(mFileName)
- WebFile(it, mFileName, isSupportedFile)
+ webFiles.addAll(it)
}
}
fun importOrDownloadWebFile(webFile: WebFile, success: ((T) -> Unit)?) {
bookSource ?: return
execute {
- callBack?.run {
- runOnUI {
- onWebFileProcessStart()
- }
- }
+ waitDialogData.postValue(true)
if (webFile.isSupported) {
val book = LocalBook.importFileOnLine(webFile.url, webFile.name, bookSource)
changeToLocalBook(book)
@@ -291,12 +267,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
}.onError {
context.toastOnUi("ImportWebFileError\n${it.localizedMessage}")
}.onFinally {
- callBack?.run {
- runOnUI {
- onWebFileProcessFinally()
- }
- }
-
+ waitDialogData.postValue(false)
}
}
@@ -433,9 +404,4 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
}
}
- interface CallBack {
- fun onWebFileProcessStart()
- fun onWebFileProcessFinally()
- }
-
}
diff --git a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt
index 1d409cb1d..75184a3c0 100644
--- a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt
+++ b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt
@@ -34,8 +34,7 @@ import java.net.URLDecoder
/**
* rss阅读界面
*/
-class ReadRssActivity : VMBaseActivity(false),
- ReadRssViewModel.CallBack {
+class ReadRssActivity : VMBaseActivity(false) {
override val binding by viewBinding(ActivityRssReadBinding::inflate)
override val viewModel by viewModels()
@@ -50,7 +49,8 @@ class ReadRssActivity : VMBaseActivity
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
- viewModel.callBack = this
+ viewModel.upStarMenuData.observe(this) { upStarMenu() }
+ viewModel.upTtsMenuData.observe(this) { upTtsMenu(it) }
binding.titleBar.title = intent.getStringExtra("title")
initWebView()
initLiveData()
@@ -223,7 +223,7 @@ class ReadRssActivity : VMBaseActivity
}
}
- override fun upStarMenu() {
+ private fun upStarMenu() {
starMenuItem?.isVisible = viewModel.rssArticle != null
if (viewModel.rssStar != null) {
starMenuItem?.setIcon(R.drawable.ic_star)
@@ -235,7 +235,7 @@ class ReadRssActivity : VMBaseActivity
starMenuItem?.icon?.setTintMutate(primaryTextColor)
}
- override fun upTtsMenu(isPlaying: Boolean) {
+ private fun upTtsMenu(isPlaying: Boolean) {
launch {
if (isPlaying) {
ttsMenuItem?.setIcon(R.drawable.ic_stop_black_24dp)
diff --git a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt
index 193e601fa..274117165 100644
--- a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt
+++ b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt
@@ -27,13 +27,14 @@ import java.util.*
class ReadRssViewModel(application: Application) : BaseViewModel(application) {
- var callBack: CallBack? = null
var rssSource: RssSource? = null
var rssArticle: RssArticle? = null
var tts: TTS? = null
val contentLiveData = MutableLiveData()
val urlLiveData = MutableLiveData()
var rssStar: RssStar? = null
+ val upTtsMenuData = MutableLiveData()
+ val upStarMenuData = MutableLiveData()
fun initData(intent: Intent) {
execute {
@@ -72,7 +73,7 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application) {
}
}
}.onFinally {
- callBack?.upStarMenu()
+ upStarMenuData.postValue(true)
}
}
@@ -126,7 +127,7 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application) {
rssStar = it
}
}.onSuccess {
- callBack?.upStarMenu()
+ upStarMenuData.postValue(true)
}
}
@@ -196,11 +197,11 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application) {
tts = TTS().apply {
setSpeakStateListener(object : TTS.SpeakStateListener {
override fun onStart() {
- callBack?.upTtsMenu(true)
+ upTtsMenuData.postValue(true)
}
override fun onDone() {
- callBack?.upTtsMenu(false)
+ upTtsMenuData.postValue(false)
}
})
}
@@ -213,8 +214,4 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application) {
tts?.clearTts()
}
- interface CallBack {
- fun upStarMenu()
- fun upTtsMenu(isPlaying: Boolean)
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/utils/CookieManagerExtensions.kt b/app/src/main/java/io/legado/app/utils/CookieManagerExtensions.kt
index f9d0b9b84..f93e299b8 100644
--- a/app/src/main/java/io/legado/app/utils/CookieManagerExtensions.kt
+++ b/app/src/main/java/io/legado/app/utils/CookieManagerExtensions.kt
@@ -11,8 +11,8 @@ fun CookieManager.removeCookie(domain: String) {
"https://$domain"
)
urls.forEach { url ->
- val cookieGlob = cm.getCookie(url)
- cookieGlob.splitNotBlank(";").forEach {
+ val cookieGlob: String? = cm.getCookie(url)
+ cookieGlob?.splitNotBlank(";")?.forEach {
val cookieName = it.substringBefore("=")
cm.setCookie(url, "$cookieName=; Expires=Wed, 31 Dec 2000 23:59:59 GMT")
}