diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md
index c327795f1..b7d51d201 100644
--- a/app/src/main/assets/updateLog.md
+++ b/app/src/main/assets/updateLog.md
@@ -3,6 +3,14 @@
* 关注合作公众号 **[小说拾遗]** 获取好看的小说。
* 旧版数据导入教程:先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】。
+**2021/02/26**
+* 添加反转内容功能
+* 更新章节是如果没有目录url自动加载详情页
+* 添加变量nextChapterUrl
+* 订阅跳转外部应用时提示
+* 修复恢复bug
+* 详情页拼接url改为重定向后的地址
+
**2021/02/21**
* 下一页规则改为在内容规则之后执行
* 书籍导出增加编码设置和导出文件夹设置,使用替换设置
diff --git a/app/src/main/java/io/legado/app/help/BookHelp.kt b/app/src/main/java/io/legado/app/help/BookHelp.kt
index fbf05f538..803d11a9a 100644
--- a/app/src/main/java/io/legado/app/help/BookHelp.kt
+++ b/app/src/main/java/io/legado/app/help/BookHelp.kt
@@ -191,6 +191,25 @@ object BookHelp {
return null
}
+ fun reverseContent(book: Book, bookChapter: BookChapter) {
+ if (!book.isLocalBook()) {
+ val file = FileUtils.getFile(
+ downloadDir,
+ cacheFolderName,
+ book.getFolderName(),
+ bookChapter.getFileName()
+ )
+ if (file.exists()) {
+ val text = file.readText()
+ val stringBuilder = StringBuilder()
+ text.toStringArray().forEach {
+ stringBuilder.insert(0, it)
+ }
+ file.writeText(stringBuilder.toString())
+ }
+ }
+ }
+
fun delContent(book: Book, bookChapter: BookChapter) {
if (book.isLocalBook()) {
return
diff --git a/app/src/main/java/io/legado/app/model/Debug.kt b/app/src/main/java/io/legado/app/model/Debug.kt
index 4697ae48b..d96aaa42b 100644
--- a/app/src/main/java/io/legado/app/model/Debug.kt
+++ b/app/src/main/java/io/legado/app/model/Debug.kt
@@ -186,6 +186,12 @@ object Debug {
}
private fun infoDebug(scope: CoroutineScope, webBook: WebBook, book: Book) {
+ if (book.tocUrl.isNotBlank()) {
+ log(debugSource, "目录url不为空,详情页已解析")
+ log(debugSource, showTime = false)
+ tocDebug(scope, webBook, book)
+ return
+ }
log(debugSource, "︾开始解析详情页")
val info = webBook.getBookInfo(scope, book)
.onSuccess {
diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt
index d316fcc08..b1dce05fa 100644
--- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt
+++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt
@@ -30,7 +30,7 @@ class AnalyzeRule(val ruleData: RuleDataInterface) : JsExtensions {
var nextChapterUrl: String? = null
private var content: Any? = null
private var baseUrl: String? = null
- private var baseURL: URL? = null
+ private var redirectUrl: URL? = null
private var isJSON: Boolean = false
private var isRegex: Boolean = false
@@ -63,11 +63,13 @@ class AnalyzeRule(val ruleData: RuleDataInterface) : JsExtensions {
fun setBaseUrl(baseUrl: String?): AnalyzeRule {
baseUrl?.let {
this.baseUrl = baseUrl
- kotlin.runCatching {
- baseURL = URL(baseUrl.substringBefore(","))
- }.onFailure {
- it.printStackTrace()
- }
+ }
+ return this
+ }
+
+ fun setRedirectUrl(url: String): AnalyzeRule {
+ kotlin.runCatching {
+ redirectUrl = URL(url.split(AnalyzeUrl.splitUrlRegex, 1)[0])
}
return this
}
@@ -170,7 +172,7 @@ class AnalyzeRule(val ruleData: RuleDataInterface) : JsExtensions {
val urlList = ArrayList()
if (result is List<*>) {
for (url in result as List<*>) {
- val absoluteURL = NetworkUtils.getAbsoluteURL(baseURL, url.toString())
+ val absoluteURL = NetworkUtils.getAbsoluteURL(redirectUrl, url.toString())
if (absoluteURL.isNotEmpty() && !urlList.contains(absoluteURL)) {
urlList.add(absoluteURL)
}
@@ -239,7 +241,7 @@ class AnalyzeRule(val ruleData: RuleDataInterface) : JsExtensions {
return if (str.isBlank()) {
baseUrl ?: ""
} else {
- NetworkUtils.getAbsoluteURL(baseURL, str)
+ NetworkUtils.getAbsoluteURL(redirectUrl, str)
}
}
return str
diff --git a/app/src/main/java/io/legado/app/model/rss/RssParserByRule.kt b/app/src/main/java/io/legado/app/model/rss/RssParserByRule.kt
index b162f37e1..e2b702cce 100644
--- a/app/src/main/java/io/legado/app/model/rss/RssParserByRule.kt
+++ b/app/src/main/java/io/legado/app/model/rss/RssParserByRule.kt
@@ -39,6 +39,7 @@ object RssParserByRule {
val articleList = mutableListOf()
val analyzeRule = AnalyzeRule(ruleData)
analyzeRule.setContent(body).setBaseUrl(sortUrl)
+ analyzeRule.setRedirectUrl(sortUrl)
var reverse = false
if (ruleArticles.startsWith("-")) {
reverse = true
diff --git a/app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt b/app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt
index ff37f6ffd..1fe21c3f8 100644
--- a/app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt
+++ b/app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt
@@ -24,7 +24,8 @@ object BookChapterList {
book: Book,
body: String?,
bookSource: BookSource,
- baseUrl: String
+ baseUrl: String,
+ redirectUrl: String
): List = suspendCancellableCoroutine { block ->
kotlin.runCatching {
val chapterList = ArrayList()
@@ -46,7 +47,15 @@ object BookChapterList {
}
var chapterData =
analyzeChapterList(
- scope, book, baseUrl, body, tocRule, listRule, bookSource, log = true
+ scope,
+ book,
+ baseUrl,
+ redirectUrl,
+ body,
+ tocRule,
+ listRule,
+ bookSource,
+ log = true
)
chapterData.chapterList?.let {
chapterList.addAll(it)
@@ -66,7 +75,14 @@ object BookChapterList {
headerMapF = bookSource.getHeaderMap()
).getStrResponse(bookSource.bookSourceUrl).body?.let { nextBody ->
chapterData = analyzeChapterList(
- this, book, nextUrl, nextBody, tocRule, listRule, bookSource
+ this,
+ book,
+ nextUrl,
+ nextUrl,
+ nextBody,
+ tocRule,
+ listRule,
+ bookSource
)
nextUrl = chapterData.nextUrl.firstOrNull() ?: ""
chapterData.chapterList?.let {
@@ -128,7 +144,15 @@ object BookChapterList {
).getStrResponse(bookSource.bookSourceUrl).body
?: throw Exception("${chapterData.nextUrl}, 下载失败")
val nextChapterData = analyzeChapterList(
- this, book, chapterData.nextUrl, nextBody, tocRule, listRule, bookSource, false
+ this,
+ book,
+ chapterData.nextUrl,
+ chapterData.nextUrl,
+ nextBody,
+ tocRule,
+ listRule,
+ bookSource,
+ false
)
synchronized(chapterDataList) {
val isFinished = addChapterListIsFinish(
@@ -195,6 +219,7 @@ object BookChapterList {
scope: CoroutineScope,
book: Book,
baseUrl: String,
+ redirectUrl: String,
body: String,
tocRule: TocRule,
listRule: String,
@@ -204,6 +229,7 @@ object BookChapterList {
): ChapterData> {
val analyzeRule = AnalyzeRule(book)
analyzeRule.setContent(body).setBaseUrl(baseUrl)
+ analyzeRule.setRedirectUrl(redirectUrl)
//获取目录列表
val chapterList = arrayListOf()
Debug.log(bookSource.bookSourceUrl, "┌获取目录列表", log)
diff --git a/app/src/main/java/io/legado/app/model/webBook/BookContent.kt b/app/src/main/java/io/legado/app/model/webBook/BookContent.kt
index e0aecc781..e305d1d4a 100644
--- a/app/src/main/java/io/legado/app/model/webBook/BookContent.kt
+++ b/app/src/main/java/io/legado/app/model/webBook/BookContent.kt
@@ -41,6 +41,7 @@ object BookContent {
val nextUrlList = arrayListOf(baseUrl)
val contentRule = bookSource.getContentRule()
val analyzeRule = AnalyzeRule(book).setContent(body, baseUrl)
+ analyzeRule.setRedirectUrl(baseUrl)
analyzeRule.nextChapterUrl = mNextChapterUrl
var contentData = analyzeContent(
book, baseUrl, body, contentRule, bookChapter, bookSource, mNextChapterUrl
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 c8bf93e71..aaabf18fa 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
@@ -22,6 +22,7 @@ object BookInfo {
body: String?,
bookSource: BookSource,
baseUrl: String,
+ redirectUrl: String,
canReName: Boolean,
) {
body ?: throw Exception(
@@ -31,6 +32,7 @@ object BookInfo {
val infoRule = bookSource.getBookInfoRule()
val analyzeRule = AnalyzeRule(book)
analyzeRule.setContent(body).setBaseUrl(baseUrl)
+ analyzeRule.setRedirectUrl(redirectUrl)
infoRule.init?.let {
if (it.isNotBlank()) {
scope.ensureActive()
@@ -84,7 +86,7 @@ object BookInfo {
scope.ensureActive()
Debug.log(bookSource.bookSourceUrl, "┌获取封面链接")
analyzeRule.getString(infoRule.coverUrl).let {
- if (it.isNotEmpty()) book.coverUrl = NetworkUtils.getAbsoluteURL(baseUrl, it)
+ if (it.isNotEmpty()) book.coverUrl = NetworkUtils.getAbsoluteURL(redirectUrl, it)
}
Debug.log(bookSource.bookSourceUrl, "└${book.coverUrl}")
scope.ensureActive()
diff --git a/app/src/main/java/io/legado/app/model/webBook/BookList.kt b/app/src/main/java/io/legado/app/model/webBook/BookList.kt
index 0dbde453e..c486c6e98 100644
--- a/app/src/main/java/io/legado/app/model/webBook/BookList.kt
+++ b/app/src/main/java/io/legado/app/model/webBook/BookList.kt
@@ -37,6 +37,7 @@ object BookList {
Debug.log(bookSource.bookSourceUrl, "≡获取成功:${analyzeUrl.ruleUrl}")
val analyzeRule = AnalyzeRule(variableBook)
analyzeRule.setContent(body).setBaseUrl(baseUrl)
+ analyzeRule.setRedirectUrl(baseUrl)
bookSource.bookUrlPattern?.let {
scope.ensureActive()
if (baseUrl.matches(it.toRegex())) {
diff --git a/app/src/main/java/io/legado/app/model/webBook/WebBook.kt b/app/src/main/java/io/legado/app/model/webBook/WebBook.kt
index bafc0ca0f..8e9e549ed 100644
--- a/app/src/main/java/io/legado/app/model/webBook/WebBook.kt
+++ b/app/src/main/java/io/legado/app/model/webBook/WebBook.kt
@@ -127,6 +127,7 @@ class WebBook(val bookSource: BookSource) {
book.infoHtml,
bookSource,
book.bookUrl,
+ book.bookUrl,
canReName
)
} else {
@@ -136,7 +137,15 @@ class WebBook(val bookSource: BookSource) {
headerMapF = bookSource.getHeaderMap(),
book = book
).getStrResponse(bookSource.bookSourceUrl)
- BookInfo.analyzeBookInfo(scope, book, res.body, bookSource, book.bookUrl, canReName)
+ BookInfo.analyzeBookInfo(
+ scope,
+ book,
+ res.body,
+ bookSource,
+ book.bookUrl,
+ res.url,
+ canReName
+ )
}
return book
}
@@ -160,7 +169,14 @@ class WebBook(val bookSource: BookSource) {
): List {
book.type = bookSource.bookSourceType
return if (book.bookUrl == book.tocUrl && !book.tocHtml.isNullOrEmpty()) {
- BookChapterList.analyzeChapterList(scope, book, book.tocHtml, bookSource, book.tocUrl)
+ BookChapterList.analyzeChapterList(
+ scope,
+ book,
+ book.tocHtml,
+ bookSource,
+ book.tocUrl,
+ book.tocUrl
+ )
} else {
val res = AnalyzeUrl(
book = book,
@@ -168,7 +184,14 @@ class WebBook(val bookSource: BookSource) {
baseUrl = book.bookUrl,
headerMapF = bookSource.getHeaderMap()
).getStrResponse(bookSource.bookSourceUrl)
- BookChapterList.analyzeChapterList(scope, book, res.body, bookSource, book.tocUrl)
+ BookChapterList.analyzeChapterList(
+ scope,
+ book,
+ res.body,
+ bookSource,
+ book.tocUrl,
+ res.url
+ )
}
}
diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt
index 9ec9fbaf3..732c1b902 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt
@@ -242,6 +242,9 @@ class ReadBookActivity : ReadBookBaseActivity(),
supportFragmentManager,
ReadBook.book?.tocUrl
)
+ R.id.menu_reverse_content -> ReadBook.book?.let {
+ viewModel.reverseContent(it)
+ }
R.id.menu_set_charset -> showCharsetConfig()
R.id.menu_get_progress -> ReadBook.book?.let {
viewModel.syncBookProgress(it) { progress ->
diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt
index 5fff40d5c..5b6281320 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt
@@ -295,6 +295,16 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
}
}
+ fun reverseContent(book: Book) {
+ execute {
+ appDb.bookChapterDao.getChapter(book.bookUrl, ReadBook.durChapterIndex)
+ ?.let { chapter ->
+ BookHelp.reverseContent(book, chapter)
+ ReadBook.loadContent(ReadBook.durChapterIndex, resetPageOffset = false)
+ }
+ }
+ }
+
/**
* 替换规则变化
*/
diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/GroupManageDialog.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/GroupManageDialog.kt
index 59344bfdc..c3fab473d 100644
--- a/app/src/main/java/io/legado/app/ui/book/source/manage/GroupManageDialog.kt
+++ b/app/src/main/java/io/legado/app/ui/book/source/manage/GroupManageDialog.kt
@@ -103,6 +103,7 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener {
alert(title = getString(R.string.group_edit)) {
val alertBinding = DialogEditTextBinding.inflate(layoutInflater)
alertBinding.editView.setHint(R.string.group_name)
+ alertBinding.editView.setText(group)
customView { alertBinding.root }
yesButton {
viewModel.upGroup(group, alertBinding.editView.text?.toString())
diff --git a/app/src/main/res/menu/book_read.xml b/app/src/main/res/menu/book_read.xml
index b34861c5a..e2cdb3f45 100644
--- a/app/src/main/res/menu/book_read.xml
+++ b/app/src/main/res/menu/book_read.xml
@@ -73,6 +73,11 @@
android:title="@string/get_book_progress"
app:showAsAction="never" />
+
+
- 导出文件夹
导出编码
导出到WebDav
+ 反转内容
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 762318f9f..0f4e05286 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -808,5 +808,6 @@
匯出資料夾
匯出編碼
匯出到WebDav
+ 反转内容
diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml
index d4dad82b7..cf60feffd 100644
--- a/app/src/main/res/values-zh/strings.xml
+++ b/app/src/main/res/values-zh/strings.xml
@@ -808,5 +808,6 @@
导出文件夹
导出编码
导出到WebDav
+ 反转内容
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 227aeb400..0e1c150cd 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -811,5 +811,6 @@
导出文件夹
导出编码
导出到WebDav
+ 反转内容
diff --git a/build.gradle b/build.gradle
index e4a3e9d2e..228c51fa0 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
- ext.kotlin_version = '1.4.30'
+ ext.kotlin_version = '1.4.31'
repositories {
google()
jcenter()