Merge branch 'master' into master
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
* 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则或简繁转换出现问题。
|
* 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则或简繁转换出现问题。
|
||||||
* 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源!
|
* 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源!
|
||||||
|
|
||||||
**2022/09/19**
|
**2022/09/20**
|
||||||
|
|
||||||
* 发现为空时不校验
|
* 发现为空时不校验
|
||||||
* 订阅添加刷新分类功能,菜单中
|
* 订阅添加刷新分类功能,菜单中
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import io.legado.app.help.http.newCallStrResponse
|
|||||||
import io.legado.app.help.http.okHttpClient
|
import io.legado.app.help.http.okHttpClient
|
||||||
import io.legado.app.utils.jsonPath
|
import io.legado.app.utils.jsonPath
|
||||||
import io.legado.app.utils.readString
|
import io.legado.app.utils.readString
|
||||||
import io.legado.app.utils.toastOnUi
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import splitties.init.appCtx
|
import splitties.init.appCtx
|
||||||
|
|
||||||
@@ -16,10 +15,8 @@ object AppUpdate {
|
|||||||
|
|
||||||
fun checkFromGitHub(
|
fun checkFromGitHub(
|
||||||
scope: CoroutineScope,
|
scope: CoroutineScope,
|
||||||
showErrorMsg: Boolean = true,
|
): Coroutine<UpdateInfo> {
|
||||||
callback: (newVersion: String, updateBody: String, url: String, fileName: String) -> Unit
|
return Coroutine.async(scope) {
|
||||||
) {
|
|
||||||
Coroutine.async(scope) {
|
|
||||||
val lastReleaseUrl = appCtx.getString(R.string.latest_release_api)
|
val lastReleaseUrl = appCtx.getString(R.string.latest_release_api)
|
||||||
val body = okHttpClient.newCallStrResponse {
|
val body = okHttpClient.newCallStrResponse {
|
||||||
url(lastReleaseUrl)
|
url(lastReleaseUrl)
|
||||||
@@ -37,18 +34,18 @@ object AppUpdate {
|
|||||||
?: throw NoStackTraceException("获取新版本出错")
|
?: throw NoStackTraceException("获取新版本出错")
|
||||||
val fileName = rootDoc.readString("$.assets[0].name")
|
val fileName = rootDoc.readString("$.assets[0].name")
|
||||||
?: throw NoStackTraceException("获取新版本出错")
|
?: throw NoStackTraceException("获取新版本出错")
|
||||||
return@async arrayOf(tagName, updateBody, downloadUrl, fileName)
|
return@async UpdateInfo(tagName, updateBody, downloadUrl, fileName)
|
||||||
} else {
|
} else {
|
||||||
throw NoStackTraceException("已是最新版本")
|
throw NoStackTraceException("已是最新版本")
|
||||||
}
|
}
|
||||||
}.timeout(10000)
|
}.timeout(10000)
|
||||||
.onSuccess {
|
|
||||||
callback.invoke(it[0], it[1], it[2], it[3])
|
|
||||||
}.onError {
|
|
||||||
if (showErrorMsg) {
|
|
||||||
appCtx.toastOnUi("检测更新\n${it.localizedMessage}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class UpdateInfo(
|
||||||
|
val tagName: String,
|
||||||
|
val updateLog: String,
|
||||||
|
val downloadUrl: String,
|
||||||
|
val fileName: String
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,6 @@ object AppWebDav {
|
|||||||
authorization?.let {
|
authorization?.let {
|
||||||
val webDav = WebDav(rootWebDavUrl + name, it)
|
val webDav = WebDav(rootWebDavUrl + name, it)
|
||||||
webDav.downloadTo(zipFilePath, true)
|
webDav.downloadTo(zipFilePath, true)
|
||||||
@Suppress("BlockingMethodInNonBlockingContext")
|
|
||||||
ZipUtils.unzipFile(zipFilePath, Backup.backupPath)
|
ZipUtils.unzipFile(zipFilePath, Backup.backupPath)
|
||||||
Restore.restoreDatabase()
|
Restore.restoreDatabase()
|
||||||
Restore.restoreConfig()
|
Restore.restoreConfig()
|
||||||
|
|||||||
@@ -311,7 +311,7 @@ object BookHelp {
|
|||||||
newChapterList: List<BookChapter>,
|
newChapterList: List<BookChapter>,
|
||||||
oldChapterListSize: Int = 0
|
oldChapterListSize: Int = 0
|
||||||
): Int {
|
): Int {
|
||||||
if (oldDurChapterIndex == 0) return oldDurChapterIndex
|
if (oldDurChapterIndex == 0) return 0
|
||||||
if (newChapterList.isEmpty()) return oldDurChapterIndex
|
if (newChapterList.isEmpty()) return oldDurChapterIndex
|
||||||
val oldChapterNum = getChapterNum(oldDurChapterName)
|
val oldChapterNum = getChapterNum(oldDurChapterName)
|
||||||
val oldName = getPureChapterName(oldDurChapterName)
|
val oldName = getPureChapterName(oldDurChapterName)
|
||||||
@@ -358,6 +358,7 @@ object BookHelp {
|
|||||||
Pattern.compile(".*?第([\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+)[章节篇回集话]")
|
Pattern.compile(".*?第([\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+)[章节篇回集话]")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("RegExpSimplifiable")
|
||||||
private val chapterNamePattern2 by lazy {
|
private val chapterNamePattern2 by lazy {
|
||||||
Pattern.compile("^(?:[\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+[,:、])*([\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+)(?:[,:、]|\\.[^\\d])")
|
Pattern.compile("^(?:[\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+[,:、])*([\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+)(?:[,:、]|\\.[^\\d])")
|
||||||
}
|
}
|
||||||
@@ -385,7 +386,7 @@ object BookHelp {
|
|||||||
return@lazy "[^\\w\\u4E00-\\u9FEF〇\\u3400-\\u4DBF\\u20000-\\u2A6DF\\u2A700-\\u2EBEF]".toRegex()
|
return@lazy "[^\\w\\u4E00-\\u9FEF〇\\u3400-\\u4DBF\\u20000-\\u2A6DF\\u2A700-\\u2EBEF]".toRegex()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("RegExpUnnecessaryNonCapturingGroup")
|
@Suppress("RegExpUnnecessaryNonCapturingGroup", "RegExpSimplifiable")
|
||||||
private val regexB by lazy {
|
private val regexB by lazy {
|
||||||
//章节序号,排除处于结尾的状况,避免将章节名替换为空字串
|
//章节序号,排除处于结尾的状况,避免将章节名替换为空字串
|
||||||
return@lazy "^.*?第(?:[\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+)[章节篇回集话](?!$)|^(?:[\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+[,:、])*(?:[\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+)(?:[,:、](?!$)|\\.(?=[^\\d]))".toRegex()
|
return@lazy "^.*?第(?:[\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+)[章节篇回集话](?!$)|^(?:[\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+[,:、])*(?:[\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+)(?:[,:、](?!$)|\\.(?=[^\\d]))".toRegex()
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import io.legado.app.lib.dialogs.alert
|
|||||||
import io.legado.app.lib.dialogs.selector
|
import io.legado.app.lib.dialogs.selector
|
||||||
import io.legado.app.ui.widget.dialog.TextDialog
|
import io.legado.app.ui.widget.dialog.TextDialog
|
||||||
import io.legado.app.utils.*
|
import io.legado.app.utils.*
|
||||||
|
import splitties.init.appCtx
|
||||||
|
|
||||||
class AboutFragment : PreferenceFragmentCompat() {
|
class AboutFragment : PreferenceFragmentCompat() {
|
||||||
|
|
||||||
@@ -80,14 +81,23 @@ class AboutFragment : PreferenceFragmentCompat() {
|
|||||||
showDialogFragment(TextDialog(mdText, TextDialog.Mode.MD))
|
showDialogFragment(TextDialog(mdText, TextDialog.Mode.MD))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测更新
|
||||||
|
*/
|
||||||
private fun checkUpdate() {
|
private fun checkUpdate() {
|
||||||
AppUpdate.checkFromGitHub(lifecycleScope) { newVersion, updateBody, url, name ->
|
AppUpdate.checkFromGitHub(lifecycleScope)
|
||||||
showDialogFragment(
|
.onSuccess {
|
||||||
UpdateDialog(newVersion, updateBody, url, name)
|
showDialogFragment(
|
||||||
)
|
UpdateDialog(it)
|
||||||
}
|
)
|
||||||
|
}.onError {
|
||||||
|
appCtx.toastOnUi("${getString(R.string.check_update)}\n${it.localizedMessage}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示qq群
|
||||||
|
*/
|
||||||
private fun showQqGroups() {
|
private fun showQqGroups() {
|
||||||
alert(titleResource = R.string.join_qq_group) {
|
alert(titleResource = R.string.join_qq_group) {
|
||||||
val names = arrayListOf<String>()
|
val names = arrayListOf<String>()
|
||||||
@@ -104,6 +114,9 @@ class AboutFragment : PreferenceFragmentCompat() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加入qq群
|
||||||
|
*/
|
||||||
private fun joinQQGroup(key: String): Boolean {
|
private fun joinQQGroup(key: String): Boolean {
|
||||||
val intent = Intent()
|
val intent = Intent()
|
||||||
intent.data =
|
intent.data =
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import android.view.ViewGroup
|
|||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.base.BaseDialogFragment
|
import io.legado.app.base.BaseDialogFragment
|
||||||
import io.legado.app.databinding.DialogUpdateBinding
|
import io.legado.app.databinding.DialogUpdateBinding
|
||||||
|
import io.legado.app.help.AppUpdate
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
import io.legado.app.lib.theme.primaryColor
|
import io.legado.app.lib.theme.primaryColor
|
||||||
import io.legado.app.model.Download
|
import io.legado.app.model.Download
|
||||||
@@ -19,12 +20,12 @@ import io.noties.markwon.image.glide.GlideImagesPlugin
|
|||||||
|
|
||||||
class UpdateDialog() : BaseDialogFragment(R.layout.dialog_update) {
|
class UpdateDialog() : BaseDialogFragment(R.layout.dialog_update) {
|
||||||
|
|
||||||
constructor(newVersion: String, updateBody: String, url: String, name: String) : this() {
|
constructor(updateInfo: AppUpdate.UpdateInfo) : this() {
|
||||||
arguments = Bundle().apply {
|
arguments = Bundle().apply {
|
||||||
putString("newVersion", newVersion)
|
putString("newVersion", updateInfo.tagName)
|
||||||
putString("updateBody", updateBody)
|
putString("updateBody", updateInfo.updateLog)
|
||||||
putString("url", url)
|
putString("url", updateInfo.downloadUrl)
|
||||||
putString("name", name)
|
putString("name", updateInfo.fileName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,6 +62,7 @@ class UpdateDialog() : BaseDialogFragment(R.layout.dialog_update) {
|
|||||||
val name = arguments?.getString("name")
|
val name = arguments?.getString("name")
|
||||||
if (url != null && name != null) {
|
if (url != null && name != null) {
|
||||||
Download.start(requireContext(), url, name)
|
Download.start(requireContext(), url, name)
|
||||||
|
toastOnUi(R.string.download_start)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -779,7 +779,7 @@ class ReadBookActivity : BaseReadBookActivity(),
|
|||||||
|
|
||||||
override fun changeTo(source: BookSource, book: Book, toc: List<BookChapter>) {
|
override fun changeTo(source: BookSource, book: Book, toc: List<BookChapter>) {
|
||||||
if (book.type != BookType.audio) {
|
if (book.type != BookType.audio) {
|
||||||
viewModel.changeTo(source, book, toc)
|
viewModel.changeTo(book, toc)
|
||||||
} else {
|
} else {
|
||||||
ReadAloud.stop(this)
|
ReadAloud.stop(this)
|
||||||
launch {
|
launch {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import io.legado.app.data.appDb
|
|||||||
import io.legado.app.data.entities.Book
|
import io.legado.app.data.entities.Book
|
||||||
import io.legado.app.data.entities.BookChapter
|
import io.legado.app.data.entities.BookChapter
|
||||||
import io.legado.app.data.entities.BookProgress
|
import io.legado.app.data.entities.BookProgress
|
||||||
import io.legado.app.data.entities.BookSource
|
|
||||||
import io.legado.app.exception.NoStackTraceException
|
import io.legado.app.exception.NoStackTraceException
|
||||||
import io.legado.app.help.AppWebDav
|
import io.legado.app.help.AppWebDav
|
||||||
import io.legado.app.help.BookHelp
|
import io.legado.app.help.BookHelp
|
||||||
@@ -93,7 +92,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
if (ReadBook.durChapterIndex > ReadBook.chapterSize - 1) {
|
if (ReadBook.durChapterIndex > ReadBook.chapterSize - 1) {
|
||||||
ReadBook.durChapterIndex = ReadBook.chapterSize - 1
|
ReadBook.durChapterIndex = ReadBook.chapterSize - 1
|
||||||
}
|
}
|
||||||
ReadBook.loadContent(resetPageOffset = isSameBook)
|
ReadBook.loadContent(resetPageOffset = false)
|
||||||
}
|
}
|
||||||
if (!isSameBook || !BaseReadAloudService.isRun) {
|
if (!isSameBook || !BaseReadAloudService.isRun) {
|
||||||
syncBookProgress(book)
|
syncBookProgress(book)
|
||||||
@@ -210,20 +209,11 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
/**
|
/**
|
||||||
* 换源
|
* 换源
|
||||||
*/
|
*/
|
||||||
fun changeTo(source: BookSource, book: Book, toc: List<BookChapter>) {
|
fun changeTo(book: Book, toc: List<BookChapter>) {
|
||||||
changeSourceCoroutine?.cancel()
|
changeSourceCoroutine?.cancel()
|
||||||
changeSourceCoroutine = execute {
|
changeSourceCoroutine = execute {
|
||||||
ReadBook.upMsg(context.getString(R.string.loading))
|
ReadBook.upMsg(context.getString(R.string.loading))
|
||||||
ReadBook.book?.changeTo(book, toc)
|
ReadBook.book?.changeTo(book, toc)
|
||||||
val nextChapter = toc.getOrElse(book.durChapterIndex) {
|
|
||||||
toc.first()
|
|
||||||
}
|
|
||||||
WebBook.getContentAwait(
|
|
||||||
bookSource = source,
|
|
||||||
book = book,
|
|
||||||
bookChapter = toc[book.durChapterIndex],
|
|
||||||
nextChapterUrl = nextChapter.url
|
|
||||||
)
|
|
||||||
appDb.bookDao.insert(book)
|
appDb.bookDao.insert(book)
|
||||||
appDb.bookChapterDao.insert(*toc.toTypedArray())
|
appDb.bookChapterDao.insert(*toc.toTypedArray())
|
||||||
ReadBook.resetData(book)
|
ReadBook.resetData(book)
|
||||||
@@ -250,11 +240,25 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
WebBook.getBookInfoAwait(source, book)
|
WebBook.getBookInfoAwait(source, book)
|
||||||
}
|
}
|
||||||
val toc = WebBook.getChapterListAwait(source, book).getOrThrow()
|
val toc = WebBook.getChapterListAwait(source, book).getOrThrow()
|
||||||
changeTo(source, book, toc)
|
val chapter = toc.getOrElse(book.durChapterIndex) {
|
||||||
return@execute
|
toc.last()
|
||||||
|
}
|
||||||
|
val nextChapter = toc.getOrElse(chapter.index) {
|
||||||
|
toc.first()
|
||||||
|
}
|
||||||
|
kotlin.runCatching {
|
||||||
|
WebBook.getContentAwait(
|
||||||
|
bookSource = source,
|
||||||
|
book = book,
|
||||||
|
bookChapter = chapter,
|
||||||
|
nextChapterUrl = nextChapter.url
|
||||||
|
)
|
||||||
|
changeTo(book, toc)
|
||||||
|
return@execute
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw NoStackTraceException("没有搜索到 ${name}(${author})")
|
throw NoStackTraceException("没有合适书源")
|
||||||
}.onStart {
|
}.onStart {
|
||||||
ReadBook.upMsg(context.getString(R.string.source_auto_changing))
|
ReadBook.upMsg(context.getString(R.string.source_auto_changing))
|
||||||
}.onError {
|
}.onError {
|
||||||
|
|||||||
Reference in New Issue
Block a user