Merge branch 'master' of github.com:AndyBernie/legado into master

pull/341/head
AndyBernie 5 years ago
commit 12b17cc37f
  1. 24
      app/src/main/assets/httpTTS.json
  2. 5
      app/src/main/assets/updateLog.md
  3. 5
      app/src/main/java/io/legado/app/App.kt
  4. 9
      app/src/main/java/io/legado/app/data/dao/ReadRecordDao.kt
  5. 6
      app/src/main/java/io/legado/app/data/entities/ReadRecordShow.kt
  6. 19
      app/src/main/java/io/legado/app/help/DefaultValueHelp.kt
  7. 10
      app/src/main/java/io/legado/app/help/JsExtensions.kt
  8. 13
      app/src/main/java/io/legado/app/help/storage/Restore.kt
  9. 4
      app/src/main/java/io/legado/app/model/localBook/AnalyzeTxtFile.kt
  10. 5
      app/src/main/java/io/legado/app/model/webBook/BookList.kt
  11. 9
      app/src/main/java/io/legado/app/service/help/ReadBook.kt
  12. 2
      app/src/main/java/io/legado/app/ui/about/AboutFragment.kt
  13. 14
      app/src/main/java/io/legado/app/ui/about/ReadRecordActivity.kt
  14. 5
      app/src/main/java/io/legado/app/ui/association/FileAssociationActivity.kt
  15. 5
      app/src/main/java/io/legado/app/ui/association/ImportBookSourceActivity.kt
  16. 5
      app/src/main/java/io/legado/app/ui/association/ImportReplaceRuleActivity.kt
  17. 5
      app/src/main/java/io/legado/app/ui/association/ImportRssSourceActivity.kt
  18. 5
      app/src/main/java/io/legado/app/ui/audio/AudioPlayActivity.kt
  19. 5
      app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt
  20. 5
      app/src/main/java/io/legado/app/ui/book/changecover/ChangeCoverDialog.kt
  21. 5
      app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceDialog.kt
  22. 5
      app/src/main/java/io/legado/app/ui/book/chapterlist/BookmarkFragment.kt
  23. 11
      app/src/main/java/io/legado/app/ui/book/chapterlist/ChapterListAdapter.kt
  24. 5
      app/src/main/java/io/legado/app/ui/book/chapterlist/ChapterListFragment.kt
  25. 5
      app/src/main/java/io/legado/app/ui/book/download/DownloadActivity.kt
  26. 3
      app/src/main/java/io/legado/app/ui/book/explore/ExploreShowActivity.kt
  27. 3
      app/src/main/java/io/legado/app/ui/book/group/GroupManageDialog.kt
  28. 3
      app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt
  29. 5
      app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt
  30. 3
      app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditActivity.kt
  31. 3
      app/src/main/java/io/legado/app/ui/book/local/ImportBookActivity.kt
  32. 29
      app/src/main/java/io/legado/app/ui/book/read/Help.kt
  33. 15
      app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt
  34. 11
      app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineDialog.kt
  35. 34
      app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineViewModel.kt
  36. 3
      app/src/main/java/io/legado/app/ui/book/read/config/TocRegexDialog.kt
  37. 11
      app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt
  38. 5
      app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt
  39. 3
      app/src/main/java/io/legado/app/ui/book/source/manage/GroupManageDialog.kt
  40. 6
      app/src/main/java/io/legado/app/ui/main/MainActivity.kt
  41. 13
      app/src/main/java/io/legado/app/ui/main/MainViewModel.kt
  42. 7
      app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfFragment.kt
  43. 3
      app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksFragment.kt
  44. 5
      app/src/main/java/io/legado/app/ui/main/explore/ExploreFragment.kt
  45. 3
      app/src/main/java/io/legado/app/ui/main/rss/RssFragment.kt
  46. 3
      app/src/main/java/io/legado/app/ui/replacerule/GroupManageDialog.kt
  47. 5
      app/src/main/java/io/legado/app/ui/replacerule/ReplaceRuleActivity.kt
  48. 3
      app/src/main/java/io/legado/app/ui/replacerule/edit/ReplaceEditDialog.kt
  49. 5
      app/src/main/java/io/legado/app/ui/rss/article/RssArticlesFragment.kt
  50. 5
      app/src/main/java/io/legado/app/ui/rss/article/RssSortActivity.kt
  51. 3
      app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesActivity.kt
  52. 5
      app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt
  53. 3
      app/src/main/java/io/legado/app/ui/rss/source/manage/GroupManageDialog.kt
  54. 5
      app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceActivity.kt
  55. 31
      app/src/main/res/layout/item_chapter_list.xml
  56. 11
      app/src/main/res/menu/speak_engine.xml

@ -2,61 +2,61 @@
{ {
"id": 1598233029304, "id": 1598233029304,
"name": "度小美", "name": "度小美",
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{encodeURIComponent(encodeURIComponent(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=0&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" "url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=0&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}"
}, },
{ {
"id": 1598233029305, "id": 1598233029305,
"name": "度小宇", "name": "度小宇",
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{encodeURIComponent(encodeURIComponent(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=1&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" "url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=1&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}"
}, },
{ {
"id": 1598233029306, "id": 1598233029306,
"name": "度逍遥", "name": "度逍遥",
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{encodeURIComponent(encodeURIComponent(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=3&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" "url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=3&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}"
}, },
{ {
"id": 1598233029307, "id": 1598233029307,
"name": "度丫丫", "name": "度丫丫",
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{encodeURIComponent(encodeURIComponent(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=4&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" "url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=4&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}"
}, },
{ {
"id": 1598233029308, "id": 1598233029308,
"name": "度小娇", "name": "度小娇",
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{encodeURIComponent(encodeURIComponent(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=5&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" "url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=5&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}"
}, },
{ {
"id": 1598233029309, "id": 1598233029309,
"name": "度米朵", "name": "度米朵",
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{encodeURIComponent(encodeURIComponent(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=103&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" "url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=103&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}"
}, },
{ {
"id": 1598233029310, "id": 1598233029310,
"name": "度博文", "name": "度博文",
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{encodeURIComponent(encodeURIComponent(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=106&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" "url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=106&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}"
}, },
{ {
"id": 1598233029311, "id": 1598233029311,
"name": "度小童", "name": "度小童",
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{encodeURIComponent(encodeURIComponent(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=110&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" "url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=110&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}"
}, },
{ {
"id": 1598233029312, "id": 1598233029312,
"name": "度小萌", "name": "度小萌",
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{encodeURIComponent(encodeURIComponent(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=111&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" "url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=111&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}"
}, },
{ {
"id": 1598233029313, "id": 1598233029313,
"name": "百度骚男", "name": "百度骚男",
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{encodeURIComponent(encodeURIComponent(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=11&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" "url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=11&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}"
}, },
{ {
"id": 1598233029314, "id": 1598233029314,
"name": "百度评书", "name": "百度评书",
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{encodeURIComponent(encodeURIComponent(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=6&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" "url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=6&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}"
}, },
{ {
"id": 1598233029315, "id": 1598233029315,
"name": "百度主持", "name": "百度主持",
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{encodeURIComponent(encodeURIComponent(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=9&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" "url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=9&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}"
} }
] ]

@ -3,6 +3,11 @@
* 关注合作公众号 **[小说拾遗]()** 获取好看的小说。 * 关注合作公众号 **[小说拾遗]()** 获取好看的小说。
- 旧版数据导入教程:先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】。 - 旧版数据导入教程:先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】。
**2020/08/26**
* js添加java.encodeURI(speakText),用于解决js编码时有~的语句朗读不出来
* 修复书名太长删除阅读记录按钮不显示的bug
* 完成本地书籍编码选择
**2020/08/25** **2020/08/25**
* 阅读记录可以删除了 * 阅读记录可以删除了
* 修复翻页模式选择颜色问题 * 修复翻页模式选择颜色问题

@ -37,11 +37,10 @@ class App : MultiDexApplication() {
private set private set
lateinit var androidId: String lateinit var androidId: String
var versionCode = 0
var versionName = ""
} }
var versionCode = 0
var versionName = ""
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
INSTANCE = this INSTANCE = this

@ -2,6 +2,7 @@ package io.legado.app.data.dao
import androidx.room.* import androidx.room.*
import io.legado.app.data.entities.ReadRecord import io.legado.app.data.entities.ReadRecord
import io.legado.app.data.entities.ReadRecordShow
@Dao @Dao
interface ReadRecordDao { interface ReadRecordDao {
@ -9,12 +10,18 @@ interface ReadRecordDao {
@get:Query("select * from readRecord") @get:Query("select * from readRecord")
val all: List<ReadRecord> val all: List<ReadRecord>
@get:Query("select bookName, sum(readTime) as readTime from readRecord group by bookName")
val allShow: List<ReadRecordShow>
@get:Query("select sum(readTime) from readRecord") @get:Query("select sum(readTime) from readRecord")
val allTime: Long val allTime: Long
@Query("select sum(readTime) from readRecord where bookName = :bookName") @Query("select sum(readTime) from readRecord where bookName = :bookName")
fun getReadTime(bookName: String): Long? fun getReadTime(bookName: String): Long?
@Query("select readTime from readRecord where androidId = :androidId and bookName = :bookName")
fun getReadTime(androidId: String, bookName: String): Long?
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg readRecord: ReadRecord) fun insert(vararg readRecord: ReadRecord)
@ -24,4 +31,6 @@ interface ReadRecordDao {
@Delete @Delete
fun delete(vararg record: ReadRecord) fun delete(vararg record: ReadRecord)
@Query("delete from readRecord where bookName = :bookName")
fun deleteByName(bookName: String)
} }

@ -0,0 +1,6 @@
package io.legado.app.data.entities
data class ReadRecordShow(
var bookName: String = "",
var readTime: Long = 0L
)

@ -0,0 +1,19 @@
package io.legado.app.help
import io.legado.app.App
import io.legado.app.data.entities.HttpTTS
import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonArray
object DefaultValueHelp {
fun initHttpTTS() {
val json = String(App.INSTANCE.assets.open("httpTTS.json").readBytes())
GSON.fromJsonArray<HttpTTS>(json)?.let {
App.db.httpTTSDao().insert(*it.toTypedArray())
}
}
}

@ -6,6 +6,7 @@ import io.legado.app.constant.AppConst.dateFormat
import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.utils.EncoderUtils import io.legado.app.utils.EncoderUtils
import io.legado.app.utils.MD5Utils import io.legado.app.utils.MD5Utils
import java.net.URLEncoder
import java.util.* import java.util.*
@Keep @Keep
@ -52,10 +53,19 @@ interface JsExtensions {
fun timeFormat(time: Long): String { fun timeFormat(time: Long): String {
return dateFormat.format(Date(time)) return dateFormat.format(Date(time))
} }
//utf8编码转gbk编码 //utf8编码转gbk编码
fun utf8ToGbk(str: String): String { fun utf8ToGbk(str: String): String {
val utf8 = String(str.toByteArray(charset("UTF-8"))) val utf8 = String(str.toByteArray(charset("UTF-8")))
val unicode = String(utf8.toByteArray(), charset("UTF-8")) val unicode = String(utf8.toByteArray(), charset("UTF-8"))
return String(unicode.toByteArray(charset("GBK"))) return String(unicode.toByteArray(charset("GBK")))
} }
fun encodeURI(str: String): String {
return try {
URLEncoder.encode(str, "UTF-8")
} catch (e: Exception) {
""
}
}
} }

@ -135,7 +135,18 @@ object Restore {
App.db.txtTocRule().insert(*it.toTypedArray()) App.db.txtTocRule().insert(*it.toTypedArray())
} }
fileToListT<ReadRecord>(path, "readRecord.json")?.let { fileToListT<ReadRecord>(path, "readRecord.json")?.let {
App.db.readRecordDao().insert(*it.toTypedArray()) it.forEach { readRecord ->
//判断是不是本机记录
if (readRecord.androidId != App.androidId) {
App.db.readRecordDao().insert(readRecord)
} else {
val time = App.db.readRecordDao()
.getReadTime(readRecord.androidId, readRecord.bookName)
if (time == null || time < readRecord.readTime) {
App.db.readRecordDao().insert(readRecord)
}
}
}
} }
fileToListT<HttpTTS>(path, "httpTTS.json")?.let { fileToListT<HttpTTS>(path, "httpTTS.json")?.let {
App.db.httpTTSDao().insert(*it.toTypedArray()) App.db.httpTTSDao().insert(*it.toTypedArray())

@ -20,7 +20,9 @@ class AnalyzeTxtFile {
@Throws(Exception::class) @Throws(Exception::class)
fun analyze(book: Book): ArrayList<BookChapter> { fun analyze(book: Book): ArrayList<BookChapter> {
val bookFile = getBookFile(book) val bookFile = getBookFile(book)
book.charset = EncodingDetect.getEncode(bookFile) if (book.charset == null) {
book.charset = EncodingDetect.getEncode(bookFile)
}
charset = book.fileCharset() charset = book.fileCharset()
val rulePattern = if (book.tocUrl.isNotEmpty()) { val rulePattern = if (book.tocUrl.isNotEmpty()) {
Pattern.compile(book.tocUrl, Pattern.MULTILINE) Pattern.compile(book.tocUrl, Pattern.MULTILINE)

@ -11,6 +11,7 @@ import io.legado.app.model.analyzeRule.AnalyzeRule
import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.utils.NetworkUtils import io.legado.app.utils.NetworkUtils
import io.legado.app.utils.StringUtils.wordCountFormat import io.legado.app.utils.StringUtils.wordCountFormat
import io.legado.app.utils.htmlFormat
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.isActive import kotlinx.coroutines.isActive
@ -161,7 +162,7 @@ object BookList {
Debug.log(bookSource.bookSourceUrl, "${searchBook.latestChapterTitle}") Debug.log(bookSource.bookSourceUrl, "${searchBook.latestChapterTitle}")
if (!scope.isActive) throw CancellationException() if (!scope.isActive) throw CancellationException()
Debug.log(bookSource.bookSourceUrl, "┌获取简介") Debug.log(bookSource.bookSourceUrl, "┌获取简介")
searchBook.intro = analyzeRule.getString(intro) searchBook.intro = analyzeRule.getString(intro).htmlFormat()
Debug.log(bookSource.bookSourceUrl, "${searchBook.intro}", true) Debug.log(bookSource.bookSourceUrl, "${searchBook.intro}", true)
if (!scope.isActive) throw CancellationException() if (!scope.isActive) throw CancellationException()
Debug.log(bookSource.bookSourceUrl, "┌获取封面链接") Debug.log(bookSource.bookSourceUrl, "┌获取封面链接")
@ -221,7 +222,7 @@ object BookList {
Debug.log(bookSource.bookSourceUrl, "${searchBook.latestChapterTitle}", log) Debug.log(bookSource.bookSourceUrl, "${searchBook.latestChapterTitle}", log)
if (!scope.isActive) throw CancellationException() if (!scope.isActive) throw CancellationException()
Debug.log(bookSource.bookSourceUrl, "┌获取简介", log) Debug.log(bookSource.bookSourceUrl, "┌获取简介", log)
searchBook.intro = analyzeRule.getString(ruleIntro) searchBook.intro = analyzeRule.getString(ruleIntro).htmlFormat()
Debug.log(bookSource.bookSourceUrl, "${searchBook.intro}", log, true) Debug.log(bookSource.bookSourceUrl, "${searchBook.intro}", log, true)
if (!scope.isActive) throw CancellationException() if (!scope.isActive) throw CancellationException()
Debug.log(bookSource.bookSourceUrl, "┌获取封面链接", log) Debug.log(bookSource.bookSourceUrl, "┌获取封面链接", log)

@ -376,6 +376,14 @@ object ReadBook {
private val imageStyle get() = webBook?.bookSource?.ruleContent?.imageStyle private val imageStyle get() = webBook?.bookSource?.ruleContent?.imageStyle
fun setCharset(charset: String) {
book?.let {
it.charset = charset
callBack?.loadChapterList(it)
}
saveRead()
}
fun saveRead() { fun saveRead() {
Coroutine.async { Coroutine.async {
book?.let { book -> book?.let { book ->
@ -392,6 +400,7 @@ object ReadBook {
} }
interface CallBack { interface CallBack {
fun loadChapterList(book: Book)
fun upContent(relativePosition: Int = 0, resetPageOffset: Boolean = true) fun upContent(relativePosition: Int = 0, resetPageOffset: Boolean = true)
fun upView() fun upView()
fun pageChanged() fun pageChanged()

@ -34,7 +34,7 @@ class AboutFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.about) addPreferencesFromResource(R.xml.about)
findPreference<Preference>("check_update")?.summary = findPreference<Preference>("check_update")?.summary =
"${getString(R.string.version)} ${App.INSTANCE.versionName}" "${getString(R.string.version)} ${App.versionName}"
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

@ -8,7 +8,7 @@ import io.legado.app.R
import io.legado.app.base.BaseActivity import io.legado.app.base.BaseActivity
import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.ItemViewHolder
import io.legado.app.base.adapter.SimpleRecyclerAdapter import io.legado.app.base.adapter.SimpleRecyclerAdapter
import io.legado.app.data.entities.ReadRecord import io.legado.app.data.entities.ReadRecordShow
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.dialogs.noButton import io.legado.app.lib.dialogs.noButton
import io.legado.app.lib.dialogs.okButton import io.legado.app.lib.dialogs.okButton
@ -45,7 +45,7 @@ class ReadRecordActivity : BaseActivity(R.layout.activity_read_record) {
withContext(Main) { withContext(Main) {
tv_read_time.text = formatDuring(allTime) tv_read_time.text = formatDuring(allTime)
} }
val readRecords = App.db.readRecordDao().all val readRecords = App.db.readRecordDao().allShow
withContext(Main) { withContext(Main) {
adapter.setItems(readRecords) adapter.setItems(readRecords)
} }
@ -53,9 +53,13 @@ class ReadRecordActivity : BaseActivity(R.layout.activity_read_record) {
} }
inner class RecordAdapter(context: Context) : inner class RecordAdapter(context: Context) :
SimpleRecyclerAdapter<ReadRecord>(context, R.layout.item_read_record) { SimpleRecyclerAdapter<ReadRecordShow>(context, R.layout.item_read_record) {
override fun convert(holder: ItemViewHolder, item: ReadRecord, payloads: MutableList<Any>) { override fun convert(
holder: ItemViewHolder,
item: ReadRecordShow,
payloads: MutableList<Any>
) {
holder.itemView.apply { holder.itemView.apply {
tv_book_name.text = item.bookName tv_book_name.text = item.bookName
tv_read_time.text = formatDuring(item.readTime) tv_read_time.text = formatDuring(item.readTime)
@ -69,7 +73,7 @@ class ReadRecordActivity : BaseActivity(R.layout.activity_read_record) {
alert(R.string.delete, R.string.sure_del) { alert(R.string.delete, R.string.sure_del) {
okButton { okButton {
getItem(holder.layoutPosition)?.let { getItem(holder.layoutPosition)?.let {
App.db.readRecordDao().delete(it) App.db.readRecordDao().deleteByName(it.bookName)
initData() initData()
} }
} }

@ -2,7 +2,6 @@ package io.legado.app.ui.association
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import androidx.lifecycle.Observer
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.Theme import io.legado.app.constant.Theme
@ -23,12 +22,12 @@ class FileAssociationActivity : VMBaseActivity<FileAssociationViewModel>(
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
rotate_loading.show() rotate_loading.show()
viewModel.errorLiveData.observe(this, Observer { viewModel.errorLiveData.observe(this, {
rotate_loading.hide() rotate_loading.hide()
toast(it) toast(it)
finish() finish()
}) })
viewModel.successLiveData.observe(this, Observer { viewModel.successLiveData.observe(this, {
rotate_loading.hide() rotate_loading.hide()
startActivity(it) startActivity(it)
finish() finish()

@ -9,7 +9,6 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseDialogFragment import io.legado.app.base.BaseDialogFragment
@ -41,11 +40,11 @@ class ImportBookSourceActivity : VMBaseActivity<ImportBookSourceViewModel>(
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
rotate_loading.show() rotate_loading.show()
viewModel.errorLiveData.observe(this, Observer { viewModel.errorLiveData.observe(this, {
rotate_loading.hide() rotate_loading.hide()
errorDialog(it) errorDialog(it)
}) })
viewModel.successLiveData.observe(this, Observer { viewModel.successLiveData.observe(this, {
rotate_loading.hide() rotate_loading.hide()
if (it > 0) { if (it > 0) {
successDialog() successDialog()

@ -1,7 +1,6 @@
package io.legado.app.ui.association package io.legado.app.ui.association
import android.os.Bundle import android.os.Bundle
import androidx.lifecycle.Observer
import io.legado.app.App import io.legado.app.App
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
@ -26,11 +25,11 @@ class ImportReplaceRuleActivity : VMBaseActivity<ImportReplaceRuleViewModel>(
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
rotate_loading.show() rotate_loading.show()
viewModel.errorLiveData.observe(this, Observer { viewModel.errorLiveData.observe(this, {
rotate_loading.hide() rotate_loading.hide()
errorDialog(it) errorDialog(it)
}) })
viewModel.successLiveData.observe(this, Observer { viewModel.successLiveData.observe(this, {
rotate_loading.hide() rotate_loading.hide()
if (it.size > 0) { if (it.size > 0) {
successDialog(it) successDialog(it)

@ -9,7 +9,6 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseDialogFragment import io.legado.app.base.BaseDialogFragment
@ -41,11 +40,11 @@ class ImportRssSourceActivity : VMBaseActivity<ImportRssSourceViewModel>(
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
rotate_loading.show() rotate_loading.show()
viewModel.errorLiveData.observe(this, Observer { viewModel.errorLiveData.observe(this, {
rotate_loading.hide() rotate_loading.hide()
errorDialog(it) errorDialog(it)
}) })
viewModel.successLiveData.observe(this, Observer { viewModel.successLiveData.observe(this, {
rotate_loading.hide() rotate_loading.hide()
if (it > 0) { if (it > 0) {
successDialog() successDialog()

@ -8,7 +8,6 @@ import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.widget.SeekBar import android.widget.SeekBar
import androidx.lifecycle.Observer
import com.bumptech.glide.RequestBuilder import com.bumptech.glide.RequestBuilder
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestOptions.bitmapTransform import com.bumptech.glide.request.RequestOptions.bitmapTransform
@ -48,8 +47,8 @@ class AudioPlayActivity :
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
title_bar.transparent() title_bar.transparent()
AudioPlay.titleData.observe(this, Observer { title_bar.title = it }) AudioPlay.titleData.observe(this, { title_bar.title = it })
AudioPlay.coverData.observe(this, Observer { upCover(it) }) AudioPlay.coverData.observe(this, { upCover(it) })
viewModel.initData(intent) viewModel.initData(intent)
initView() initView()
} }

@ -5,7 +5,6 @@ import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.App import io.legado.app.App
@ -94,7 +93,7 @@ class ArrangeBookActivity : VMBaseActivity<ArrangeBookViewModel>(R.layout.activi
private fun initGroupData() { private fun initGroupData() {
groupLiveData?.removeObservers(this) groupLiveData?.removeObservers(this)
groupLiveData = App.db.bookGroupDao().liveDataAll() groupLiveData = App.db.bookGroupDao().liveDataAll()
groupLiveData?.observe(this, Observer { groupLiveData?.observe(this, {
groupList.clear() groupList.clear()
groupList.addAll(it) groupList.addAll(it)
adapter.notifyDataSetChanged() adapter.notifyDataSetChanged()
@ -112,7 +111,7 @@ class ArrangeBookActivity : VMBaseActivity<ArrangeBookViewModel>(R.layout.activi
AppConst.bookGroupNone.groupId -> App.db.bookDao().observeNoGroup() AppConst.bookGroupNone.groupId -> App.db.bookDao().observeNoGroup()
else -> App.db.bookDao().observeByGroup(groupId) else -> App.db.bookDao().observeByGroup(groupId)
} }
booksLiveData?.observe(this, Observer { list -> booksLiveData?.observe(this, { list ->
val books = when (getPrefInt(PreferKey.bookshelfSort)) { val books = when (getPrefInt(PreferKey.bookshelfSort)) {
1 -> list.sortedByDescending { it.latestChapterTime } 1 -> list.sortedByDescending { it.latestChapterTime }
2 -> list.sortedBy { it.name } 2 -> list.sortedBy { it.name }

@ -8,7 +8,6 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import io.legado.app.R import io.legado.app.R
@ -83,7 +82,7 @@ class ChangeCoverDialog : BaseDialogFragment(),
override fun observeLiveBus() { override fun observeLiveBus() {
super.observeLiveBus() super.observeLiveBus()
viewModel.searchStateData.observe(viewLifecycleOwner, Observer { viewModel.searchStateData.observe(viewLifecycleOwner, {
refresh_progress_bar.isAutoLoading = it refresh_progress_bar.isAutoLoading = it
if (it) { if (it) {
stopMenuItem?.setIcon(R.drawable.ic_stop_black_24dp) stopMenuItem?.setIcon(R.drawable.ic_stop_black_24dp)
@ -92,7 +91,7 @@ class ChangeCoverDialog : BaseDialogFragment(),
} }
tool_bar.menu.applyTint(requireContext(), Theme.getTheme()) tool_bar.menu.applyTint(requireContext(), Theme.getTheme())
}) })
viewModel.searchBooksLiveData.observe(viewLifecycleOwner, Observer { viewModel.searchBooksLiveData.observe(viewLifecycleOwner, {
val diffResult = DiffUtil.calculateDiff(DiffCallBack(adapter.getItems(), it)) val diffResult = DiffUtil.calculateDiff(DiffCallBack(adapter.getItems(), it))
adapter.setItems(it) adapter.setItems(it)
diffResult.dispatchUpdatesTo(adapter) diffResult.dispatchUpdatesTo(adapter)

@ -9,7 +9,6 @@ import android.view.ViewGroup
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -135,7 +134,7 @@ class ChangeSourceDialog : BaseDialogFragment(),
} }
private fun initLiveData() { private fun initLiveData() {
viewModel.searchStateData.observe(viewLifecycleOwner, Observer { viewModel.searchStateData.observe(viewLifecycleOwner, {
refresh_progress_bar.isAutoLoading = it refresh_progress_bar.isAutoLoading = it
if (it) { if (it) {
stopMenuItem?.setIcon(R.drawable.ic_stop_black_24dp) stopMenuItem?.setIcon(R.drawable.ic_stop_black_24dp)
@ -144,7 +143,7 @@ class ChangeSourceDialog : BaseDialogFragment(),
} }
tool_bar.menu.applyTint(requireContext()) tool_bar.menu.applyTint(requireContext())
}) })
viewModel.searchBooksLiveData.observe(viewLifecycleOwner, Observer { viewModel.searchBooksLiveData.observe(viewLifecycleOwner, {
val diffResult = DiffUtil.calculateDiff(DiffCallBack(adapter.getItems(), it)) val diffResult = DiffUtil.calculateDiff(DiffCallBack(adapter.getItems(), it))
adapter.setItems(it) adapter.setItems(it)
diffResult.dispatchUpdatesTo(adapter) diffResult.dispatchUpdatesTo(adapter)

@ -8,7 +8,6 @@ import android.os.Bundle
import android.view.View import android.view.View
import android.widget.EditText import android.widget.EditText
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.paging.LivePagedListBuilder import androidx.paging.LivePagedListBuilder
import androidx.paging.PagedList import androidx.paging.PagedList
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@ -59,7 +58,7 @@ class BookmarkFragment : VMBaseFragment<ChapterListViewModel>(R.layout.fragment_
LivePagedListBuilder( LivePagedListBuilder(
App.db.bookmarkDao().observeByBook(book.bookUrl, book.name, book.author), 20 App.db.bookmarkDao().observeByBook(book.bookUrl, book.name, book.author), 20
).build() ).build()
bookmarkLiveData?.observe(viewLifecycleOwner, Observer { adapter.submitList(it) }) bookmarkLiveData?.observe(viewLifecycleOwner, { adapter.submitList(it) })
} }
} }
@ -74,7 +73,7 @@ class BookmarkFragment : VMBaseFragment<ChapterListViewModel>(R.layout.fragment_
newText newText
), 20 ), 20
).build() ).build()
bookmarkLiveData?.observe(viewLifecycleOwner, Observer { adapter.submitList(it) }) bookmarkLiveData?.observe(viewLifecycleOwner, { adapter.submitList(it) })
} }
} }

@ -1,7 +1,7 @@
package io.legado.app.ui.book.chapterlist package io.legado.app.ui.book.chapterlist
import android.content.Context import android.content.Context
import android.widget.TextView import android.view.View
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.ItemViewHolder
import io.legado.app.base.adapter.SimpleRecyclerAdapter import io.legado.app.base.adapter.SimpleRecyclerAdapter
@ -33,12 +33,12 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
tv_tag.visible() tv_tag.visible()
} }
upHasCache( upHasCache(
tv_chapter_name, this,
cacheFileNames.contains(BookHelp.formatChapterName(item)) cacheFileNames.contains(BookHelp.formatChapterName(item))
) )
} else { } else {
upHasCache( upHasCache(
tv_chapter_name, this,
cacheFileNames.contains(BookHelp.formatChapterName(item)) cacheFileNames.contains(BookHelp.formatChapterName(item))
) )
} }
@ -53,8 +53,9 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
} }
} }
private fun upHasCache(textView: TextView, contains: Boolean) { private fun upHasCache(itemView: View, contains: Boolean) = itemView.apply {
textView.paint.isFakeBoldText = contains tv_chapter_name.paint.isFakeBoldText = contains
iv_checked.visible(contains)
} }
interface Callback { interface Callback {

@ -6,7 +6,6 @@ import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import io.legado.app.App import io.legado.app.App
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseFragment import io.legado.app.base.VMBaseFragment
@ -89,7 +88,7 @@ class ChapterListFragment : VMBaseFragment<ChapterListViewModel>(R.layout.fragme
private fun initDoc() { private fun initDoc() {
tocLiveData?.removeObservers(this@ChapterListFragment) tocLiveData?.removeObservers(this@ChapterListFragment)
tocLiveData = App.db.bookChapterDao().observeByBook(viewModel.bookUrl) tocLiveData = App.db.bookChapterDao().observeByBook(viewModel.bookUrl)
tocLiveData?.observe(viewLifecycleOwner, Observer { tocLiveData?.observe(viewLifecycleOwner, {
adapter.setItems(it) adapter.setItems(it)
if (!scrollToDurChapter) { if (!scrollToDurChapter) {
mLayoutManager.scrollToPositionWithOffset(durChapterIndex, 0) mLayoutManager.scrollToPositionWithOffset(durChapterIndex, 0)
@ -124,7 +123,7 @@ class ChapterListFragment : VMBaseFragment<ChapterListViewModel>(R.layout.fragme
} else { } else {
tocLiveData?.removeObservers(this) tocLiveData?.removeObservers(this)
tocLiveData = App.db.bookChapterDao().liveDataSearch(viewModel.bookUrl, newText) tocLiveData = App.db.bookChapterDao().liveDataSearch(viewModel.bookUrl, newText)
tocLiveData?.observe(viewLifecycleOwner, Observer { tocLiveData?.observe(viewLifecycleOwner, {
adapter.setItems(it) adapter.setItems(it)
}) })
} }

@ -6,7 +6,6 @@ import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import io.legado.app.App import io.legado.app.App
@ -129,7 +128,7 @@ class DownloadActivity : VMBaseActivity<DownloadViewModel>(R.layout.activity_dow
AppConst.bookGroupNone.groupId -> App.db.bookDao().observeNoGroup() AppConst.bookGroupNone.groupId -> App.db.bookDao().observeNoGroup()
else -> App.db.bookDao().observeByGroup(groupId) else -> App.db.bookDao().observeByGroup(groupId)
} }
booksLiveData?.observe(this, Observer { list -> booksLiveData?.observe(this, { list ->
val booksDownload = list.filter { val booksDownload = list.filter {
it.isOnLineTxt() it.isOnLineTxt()
} }
@ -147,7 +146,7 @@ class DownloadActivity : VMBaseActivity<DownloadViewModel>(R.layout.activity_dow
private fun initGroupData() { private fun initGroupData() {
groupLiveData?.removeObservers(this) groupLiveData?.removeObservers(this)
groupLiveData = App.db.bookGroupDao().liveDataAll() groupLiveData = App.db.bookGroupDao().liveDataAll()
groupLiveData?.observe(this, Observer { groupLiveData?.observe(this, {
groupList.clear() groupList.clear()
groupList.addAll(it) groupList.addAll(it)
adapter.notifyDataSetChanged() adapter.notifyDataSetChanged()

@ -1,7 +1,6 @@
package io.legado.app.ui.book.explore package io.legado.app.ui.book.explore
import android.os.Bundle import android.os.Bundle
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import io.legado.app.R import io.legado.app.R
@ -27,7 +26,7 @@ class ExploreShowActivity : VMBaseActivity<ExploreShowViewModel>(R.layout.activi
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
title_bar.title = intent.getStringExtra("exploreName") title_bar.title = intent.getStringExtra("exploreName")
initRecyclerView() initRecyclerView()
viewModel.booksData.observe(this, Observer { upData(it) }) viewModel.booksData.observe(this, { upData(it) })
viewModel.initData(intent) viewModel.initData(intent)
} }

@ -10,7 +10,6 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.EditText import android.widget.EditText
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@ -78,7 +77,7 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener
tv_ok.setTextColor(requireContext().accentColor) tv_ok.setTextColor(requireContext().accentColor)
tv_ok.visible() tv_ok.visible()
tv_ok.onClick { dismiss() } tv_ok.onClick { dismiss() }
App.db.bookGroupDao().liveDataAll().observe(viewLifecycleOwner, Observer { App.db.bookGroupDao().liveDataAll().observe(viewLifecycleOwner, {
val diffResult = val diffResult =
DiffUtil.calculateDiff(GroupDiffCallBack(ArrayList(adapter.getItems()), it)) DiffUtil.calculateDiff(GroupDiffCallBack(ArrayList(adapter.getItems()), it))
adapter.setItems(it, diffResult) adapter.setItems(it, diffResult)

@ -11,7 +11,6 @@ import android.view.ViewGroup
import android.widget.EditText import android.widget.EditText
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -113,7 +112,7 @@ class GroupSelectDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener
} }
private fun initData() { private fun initData() {
App.db.bookGroupDao().liveDataAll().observe(viewLifecycleOwner, Observer { App.db.bookGroupDao().liveDataAll().observe(viewLifecycleOwner, {
adapter.setItems(it) adapter.setItems(it)
}) })
} }

@ -9,7 +9,6 @@ import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.widget.CheckBox import android.widget.CheckBox
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.lifecycle.Observer
import com.bumptech.glide.RequestBuilder import com.bumptech.glide.RequestBuilder
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestOptions.bitmapTransform import com.bumptech.glide.request.RequestOptions.bitmapTransform
@ -66,8 +65,8 @@ class BookInfoActivity :
scroll_view.setBackgroundColor(backgroundColor) scroll_view.setBackgroundColor(backgroundColor)
fl_action.setBackgroundColor(bottomBackground) fl_action.setBackgroundColor(bottomBackground)
tv_shelf.setTextColor(getPrimaryTextColor(ColorUtils.isColorLight(bottomBackground))) tv_shelf.setTextColor(getPrimaryTextColor(ColorUtils.isColorLight(bottomBackground)))
viewModel.bookData.observe(this, Observer { showBook(it) }) viewModel.bookData.observe(this, { showBook(it) })
viewModel.chapterListData.observe(this, Observer { upLoading(false, it) }) viewModel.chapterListData.observe(this, { upLoading(false, it) })
viewModel.initData(intent) viewModel.initData(intent)
initOnClick() initOnClick()
} }

@ -7,7 +7,6 @@ import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.Observer
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
@ -30,7 +29,7 @@ class BookInfoEditActivity :
get() = getViewModel(BookInfoEditViewModel::class.java) get() = getViewModel(BookInfoEditViewModel::class.java)
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
viewModel.bookData.observe(this, Observer { upView(it) }) viewModel.bookData.observe(this, { upView(it) })
if (viewModel.bookData.value == null) { if (viewModel.bookData.value == null) {
intent.getStringExtra("bookUrl")?.let { intent.getStringExtra("bookUrl")?.let {
viewModel.loadBook(it) viewModel.loadBook(it)

@ -12,7 +12,6 @@ import android.view.View
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.App import io.legado.app.App
import io.legado.app.R import io.legado.app.R
@ -114,7 +113,7 @@ class ImportBookActivity : VMBaseActivity<ImportBookViewModel>(R.layout.activity
private fun initData() { private fun initData() {
localUriLiveData?.removeObservers(this) localUriLiveData?.removeObservers(this)
localUriLiveData = App.db.bookDao().observeLocalUri() localUriLiveData = App.db.bookDao().observeLocalUri()
localUriLiveData?.observe(this, Observer { localUriLiveData?.observe(this, {
adapter.upBookHas(it) adapter.upBookHas(it)
}) })
} }

@ -14,15 +14,13 @@ import io.legado.app.R
import io.legado.app.data.entities.Bookmark import io.legado.app.data.entities.Bookmark
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.ReadBookConfig import io.legado.app.help.ReadBookConfig
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.*
import io.legado.app.lib.dialogs.customView
import io.legado.app.lib.dialogs.noButton
import io.legado.app.lib.dialogs.yesButton
import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.ATH
import io.legado.app.lib.theme.ThemeStore import io.legado.app.lib.theme.ThemeStore
import io.legado.app.lib.theme.backgroundColor import io.legado.app.lib.theme.backgroundColor
import io.legado.app.service.help.Download import io.legado.app.service.help.Download
import io.legado.app.service.help.ReadBook import io.legado.app.service.help.ReadBook
import io.legado.app.ui.widget.text.AutoCompleteTextView
import io.legado.app.utils.applyTint import io.legado.app.utils.applyTint
import io.legado.app.utils.requestInputMethod import io.legado.app.utils.requestInputMethod
import kotlinx.android.synthetic.main.dialog_download_choice.view.* import kotlinx.android.synthetic.main.dialog_download_choice.view.*
@ -181,4 +179,27 @@ object Help {
noButton() noButton()
}.show().applyTint().requestInputMethod() }.show().applyTint().requestInputMethod()
} }
@SuppressLint("InflateParams")
fun showCharsetConfig(context: Context) = with(context) {
val charsets =
arrayListOf("UTF-8", "GB2312", "GBK", "Unicode", "UTF-16", "UTF-16LE", "ASCII")
alert(R.string.set_charset) {
var editText: AutoCompleteTextView? = null
customView {
layoutInflater.inflate(R.layout.dialog_edit_text, null).apply {
editText = edit_view
edit_view.setFilterValues(charsets)
edit_view.setText(ReadBook.book?.charset)
}
}
okButton {
val text = editText?.text?.toString()
text?.let {
ReadBook.setCharset(it)
}
}
cancelButton()
}.show().applyTint()
}
} }

@ -14,7 +14,6 @@ import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import androidx.core.view.get import androidx.core.view.get
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.size import androidx.core.view.size
import androidx.lifecycle.Observer
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
import io.legado.app.BuildConfig import io.legado.app.BuildConfig
import io.legado.app.R import io.legado.app.R
@ -108,11 +107,11 @@ class ReadBookActivity : VMBaseActivity<ReadBookViewModel>(R.layout.activity_boo
initView() initView()
upScreenTimeOut() upScreenTimeOut()
ReadBook.callBack = this ReadBook.callBack = this
ReadBook.titleDate.observe(this, Observer { ReadBook.titleDate.observe(this) {
title_bar.title = it title_bar.title = it
upMenu() upMenu()
upView() upView()
}) }
viewModel.initData(intent) viewModel.initData(intent)
} }
@ -128,6 +127,7 @@ class ReadBookActivity : VMBaseActivity<ReadBookViewModel>(R.layout.activity_boo
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
ReadBook.readStartTime = System.currentTimeMillis()
upSystemUiVisibility() upSystemUiVisibility()
timeBatteryReceiver = TimeBatteryReceiver.register(this) timeBatteryReceiver = TimeBatteryReceiver.register(this)
page_view.upTime() page_view.upTime()
@ -251,8 +251,7 @@ class ReadBookActivity : VMBaseActivity<ReadBookViewModel>(R.layout.activity_boo
R.id.menu_copy_text -> R.id.menu_copy_text ->
TextDialog.show(supportFragmentManager, ReadBook.curTextChapter?.getContent()) TextDialog.show(supportFragmentManager, ReadBook.curTextChapter?.getContent())
R.id.menu_update_toc -> ReadBook.book?.let { R.id.menu_update_toc -> ReadBook.book?.let {
ReadBook.upMsg(getString(R.string.toc_updateing)) loadChapterList(it)
viewModel.loadChapterList(it)
} }
R.id.menu_enable_replace -> ReadBook.book?.let { R.id.menu_enable_replace -> ReadBook.book?.let {
it.useReplaceRule = !it.useReplaceRule it.useReplaceRule = !it.useReplaceRule
@ -275,6 +274,7 @@ class ReadBookActivity : VMBaseActivity<ReadBookViewModel>(R.layout.activity_boo
Pair("loginUrl", it.loginUrl) Pair("loginUrl", it.loginUrl)
) )
} }
R.id.menu_set_charset -> Help.showCharsetConfig(this)
} }
return super.onCompatOptionsItemSelected(item) return super.onCompatOptionsItemSelected(item)
} }
@ -515,6 +515,11 @@ class ReadBookActivity : VMBaseActivity<ReadBookViewModel>(R.layout.activity_boo
return false return false
} }
override fun loadChapterList(book: Book) {
ReadBook.upMsg(getString(R.string.toc_updateing))
viewModel.loadChapterList(book)
}
/** /**
* 内容加载完成 * 内容加载完成
*/ */

@ -39,18 +39,20 @@ class SpeakEngineDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener
dialog?.window?.setLayout((dm.widthPixels * 0.9).toInt(), (dm.heightPixels * 0.9).toInt()) dialog?.window?.setLayout((dm.widthPixels * 0.9).toInt(), (dm.heightPixels * 0.9).toInt())
} }
lateinit var adapter: Adapter
lateinit var viewModel: SpeakEngineViewModel
private var httpTTSData: LiveData<List<HttpTTS>>? = null
var engineId = App.INSTANCE.getPrefLong(PreferKey.speakEngine)
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
viewModel = getViewModel(SpeakEngineViewModel::class.java)
return inflater.inflate(R.layout.dialog_recycler_view, container) return inflater.inflate(R.layout.dialog_recycler_view, container)
} }
lateinit var adapter: Adapter
private var httpTTSData: LiveData<List<HttpTTS>>? = null
var engineId = App.INSTANCE.getPrefLong(PreferKey.speakEngine)
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
initView() initView()
initMenu() initMenu()
@ -97,6 +99,7 @@ class SpeakEngineDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener
override fun onMenuItemClick(item: MenuItem?): Boolean { override fun onMenuItemClick(item: MenuItem?): Boolean {
when (item?.itemId) { when (item?.itemId) {
R.id.menu_add -> editHttpTTS() R.id.menu_add -> editHttpTTS()
R.id.menu_default -> viewModel.importDefault()
} }
return true return true
} }

@ -0,0 +1,34 @@
package io.legado.app.ui.book.read.config
import android.app.Application
import io.legado.app.App
import io.legado.app.base.BaseViewModel
import io.legado.app.data.entities.TxtTocRule
import io.legado.app.help.DefaultValueHelp
import io.legado.app.help.http.HttpHelper
import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonArray
class SpeakEngineViewModel(application: Application) : BaseViewModel(application) {
fun importDefault() {
execute {
DefaultValueHelp.initHttpTTS()
}
}
fun importOnLine(url: String, finally: (msg: String) -> Unit) {
execute {
HttpHelper.simpleGetAsync(url)?.let { json ->
GSON.fromJsonArray<TxtTocRule>(json)?.let {
App.db.txtTocRule().insert(*it.toTypedArray())
}
}
}.onSuccess {
finally("导入成功")
}.onError {
finally("导入失败")
}
}
}

@ -11,7 +11,6 @@ import android.view.ViewGroup
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -104,7 +103,7 @@ class TocRegexDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener {
private fun initData() { private fun initData() {
tocRegexLiveData?.removeObservers(viewLifecycleOwner) tocRegexLiveData?.removeObservers(viewLifecycleOwner)
tocRegexLiveData = App.db.txtTocRule().observeAll() tocRegexLiveData = App.db.txtTocRule().observeAll()
tocRegexLiveData?.observe(viewLifecycleOwner, Observer { tocRules -> tocRegexLiveData?.observe(viewLifecycleOwner, { tocRules ->
initSelectedName(tocRules) initSelectedName(tocRules)
adapter.setItems(tocRules) adapter.setItems(tocRules)
}) })

@ -7,7 +7,6 @@ import android.view.View.GONE
import android.view.View.VISIBLE import android.view.View.VISIBLE
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.flexbox.FlexboxLayoutManager import com.google.android.flexbox.FlexboxLayoutManager
@ -176,17 +175,17 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
} }
private fun initLiveData() { private fun initLiveData() {
App.db.bookSourceDao().liveGroupEnabled().observe(this, Observer { App.db.bookSourceDao().liveGroupEnabled().observe(this, {
groups.clear() groups.clear()
it.map { group -> it.map { group ->
groups.addAll(group.splitNotBlank(",", ";")) groups.addAll(group.splitNotBlank(",", ";"))
} }
upGroupMenu() upGroupMenu()
}) })
viewModel.searchBookLiveData.observe(this, Observer { viewModel.searchBookLiveData.observe(this, {
upSearchItems(it) upSearchItems(it)
}) })
viewModel.isSearchLiveData.observe(this, Observer { viewModel.isSearchLiveData.observe(this, {
if (it) { if (it) {
startSearch() startSearch()
} else { } else {
@ -254,7 +253,7 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
rv_bookshelf_search.gone() rv_bookshelf_search.gone()
} else { } else {
bookData = App.db.bookDao().liveDataSearch(key) bookData = App.db.bookDao().liveDataSearch(key)
bookData?.observe(this, Observer { bookData?.observe(this, {
if (it.isEmpty()) { if (it.isEmpty()) {
tv_book_show.gone() tv_book_show.gone()
rv_bookshelf_search.gone() rv_bookshelf_search.gone()
@ -272,7 +271,7 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
} else { } else {
App.db.searchKeywordDao().liveDataSearch(key) App.db.searchKeywordDao().liveDataSearch(key)
} }
historyData?.observe(this, Observer { historyData?.observe(this, {
historyKeyAdapter.setItems(it) historyKeyAdapter.setItems(it)
if (it.isEmpty()) { if (it.isEmpty()) {
tv_clear_history.invisible() tv_clear_history.invisible()

@ -11,7 +11,6 @@ import androidx.appcompat.widget.PopupMenu
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@ -164,7 +163,7 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
App.db.bookSourceDao().liveDataSearch("%$searchKey%") App.db.bookSourceDao().liveDataSearch("%$searchKey%")
} }
} }
bookSourceLiveDate?.observe(this, Observer { data -> bookSourceLiveDate?.observe(this, { data ->
val sourceList = when (sort) { val sourceList = when (sort) {
1 -> data.sortedBy { it.weight } 1 -> data.sortedBy { it.weight }
2 -> data.sortedBy { it.bookSourceName } 2 -> data.sortedBy { it.bookSourceName }
@ -179,7 +178,7 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
} }
private fun initLiveDataGroup() { private fun initLiveDataGroup() {
App.db.bookSourceDao().liveGroup().observe(this, Observer { App.db.bookSourceDao().liveGroup().observe(this, {
groups.clear() groups.clear()
it.map { group -> it.map { group ->
groups.addAll(group.splitNotBlank(",", ";")) groups.addAll(group.splitNotBlank(",", ";"))

@ -11,7 +11,6 @@ import android.view.ViewGroup
import android.widget.EditText import android.widget.EditText
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.App import io.legado.app.App
import io.legado.app.R import io.legado.app.R
@ -69,7 +68,7 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener {
} }
private fun initData() { private fun initData() {
App.db.bookSourceDao().liveGroup().observe(viewLifecycleOwner, Observer { App.db.bookSourceDao().liveGroup().observe(viewLifecycleOwner, {
val groups = linkedSetOf<String>() val groups = linkedSetOf<String>()
it.map { group -> it.map { group ->
groups.addAll(group.splitNotBlank(",", ";")) groups.addAll(group.splitNotBlank(",", ";"))

@ -93,8 +93,8 @@ class MainActivity : VMBaseActivity<MainViewModel>(R.layout.activity_main),
} }
private fun upVersion() { private fun upVersion() {
if (getPrefInt(PreferKey.versionCode) != App.INSTANCE.versionCode) { if (getPrefInt(PreferKey.versionCode) != App.versionCode) {
putPrefInt(PreferKey.versionCode, App.INSTANCE.versionCode) putPrefInt(PreferKey.versionCode, App.versionCode)
if (!BuildConfig.DEBUG) { if (!BuildConfig.DEBUG) {
val log = String(assets.open("updateLog.md").readBytes()) val log = String(assets.open("updateLog.md").readBytes())
TextDialog.show(supportFragmentManager, log, TextDialog.MD, 5000, true) TextDialog.show(supportFragmentManager, log, TextDialog.MD, 5000, true)
@ -168,7 +168,7 @@ class MainActivity : VMBaseActivity<MainViewModel>(R.layout.activity_main),
} }
} }
private inner class TabFragmentPageAdapter internal constructor(fm: FragmentManager) : private inner class TabFragmentPageAdapter(fm: FragmentManager) :
FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getItemPosition(`object`: Any): Int { override fun getItemPosition(`object`: Any): Int {

@ -6,13 +6,16 @@ import io.legado.app.base.BaseViewModel
import io.legado.app.constant.BookType import io.legado.app.constant.BookType
import io.legado.app.constant.EventBus import io.legado.app.constant.EventBus
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
import io.legado.app.data.entities.HttpTTS
import io.legado.app.data.entities.RssSource import io.legado.app.data.entities.RssSource
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.DefaultValueHelp
import io.legado.app.help.http.HttpHelper import io.legado.app.help.http.HttpHelper
import io.legado.app.help.storage.Restore import io.legado.app.help.storage.Restore
import io.legado.app.model.WebBook import io.legado.app.model.WebBook
import io.legado.app.utils.* import io.legado.app.utils.FileUtils
import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonObject
import io.legado.app.utils.postEvent
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -96,11 +99,7 @@ class MainViewModel(application: Application) : BaseViewModel(application) {
execute { execute {
FileUtils.deleteFile(FileUtils.getPath(context.cacheDir, "Fonts")) FileUtils.deleteFile(FileUtils.getPath(context.cacheDir, "Fonts"))
if (App.db.httpTTSDao().count == 0) { if (App.db.httpTTSDao().count == 0) {
@Suppress("BlockingMethodInNonBlockingContext") DefaultValueHelp.initHttpTTS()
val json = String(App.INSTANCE.assets.open("httpTTS.json").readBytes())
GSON.fromJsonArray<HttpTTS>(json)?.let {
App.db.httpTTSDao().insert(*it.toTypedArray())
}
} }
} }
} }

@ -11,7 +11,6 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import io.legado.app.App import io.legado.app.App
import io.legado.app.R import io.legado.app.R
@ -114,7 +113,7 @@ class BookshelfFragment : VMBaseFragment<BookshelfViewModel>(R.layout.fragment_b
private fun initBookGroupData() { private fun initBookGroupData() {
bookGroupLiveData?.removeObservers(viewLifecycleOwner) bookGroupLiveData?.removeObservers(viewLifecycleOwner)
bookGroupLiveData = App.db.bookGroupDao().liveDataAll() bookGroupLiveData = App.db.bookGroupDao().liveDataAll()
bookGroupLiveData?.observe(viewLifecycleOwner, Observer { bookGroupLiveData?.observe(viewLifecycleOwner, {
viewModel.checkGroup(it) viewModel.checkGroup(it)
launch { launch {
synchronized(this) { synchronized(this) {
@ -152,7 +151,7 @@ class BookshelfFragment : VMBaseFragment<BookshelfViewModel>(R.layout.fragment_b
}) })
noGroupLiveData?.removeObservers(viewLifecycleOwner) noGroupLiveData?.removeObservers(viewLifecycleOwner)
noGroupLiveData = App.db.bookDao().observeNoGroupSize() noGroupLiveData = App.db.bookDao().observeNoGroupSize()
noGroupLiveData?.observe(viewLifecycleOwner, Observer { noGroupLiveData?.observe(viewLifecycleOwner, {
if (it > 0 && !showGroupNone && AppConfig.bookGroupNoneShow) { if (it > 0 && !showGroupNone && AppConfig.bookGroupNoneShow) {
showGroupNone = true showGroupNone = true
upGroup() upGroup()
@ -270,7 +269,7 @@ class BookshelfFragment : VMBaseFragment<BookshelfViewModel>(R.layout.fragment_b
fragmentMap[selectedGroup?.groupId]?.gotoTop() fragmentMap[selectedGroup?.groupId]?.gotoTop()
} }
private inner class TabFragmentPageAdapter internal constructor(fm: FragmentManager) : private inner class TabFragmentPageAdapter(fm: FragmentManager) :
FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getPageTitle(position: Int): CharSequence? { override fun getPageTitle(position: Int): CharSequence? {

@ -3,7 +3,6 @@ package io.legado.app.ui.main.bookshelf.books
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@ -106,7 +105,7 @@ class BooksFragment : BaseFragment(R.layout.fragment_books),
AppConst.bookGroupNone.groupId -> App.db.bookDao().observeNoGroup() AppConst.bookGroupNone.groupId -> App.db.bookDao().observeNoGroup()
else -> App.db.bookDao().observeByGroup(groupId) else -> App.db.bookDao().observeByGroup(groupId)
} }
bookshelfLiveData?.observe(this, Observer { list -> bookshelfLiveData?.observe(this, { list ->
val books = when (getPrefInt(PreferKey.bookshelfSort)) { val books = when (getPrefInt(PreferKey.bookshelfSort)) {
1 -> list.sortedByDescending { it.latestChapterTime } 1 -> list.sortedByDescending { it.latestChapterTime }
2 -> list.sortedBy { it.name } 2 -> list.sortedBy { it.name }

@ -7,7 +7,6 @@ import android.view.SubMenu
import android.view.View import android.view.View
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -93,7 +92,7 @@ class ExploreFragment : VMBaseFragment<ExploreViewModel>(R.layout.fragment_find_
private fun initGroupData() { private fun initGroupData() {
liveGroup?.removeObservers(viewLifecycleOwner) liveGroup?.removeObservers(viewLifecycleOwner)
liveGroup = App.db.bookSourceDao().liveGroupExplore() liveGroup = App.db.bookSourceDao().liveGroupExplore()
liveGroup?.observe(viewLifecycleOwner, Observer { liveGroup?.observe(viewLifecycleOwner, {
groups.clear() groups.clear()
it.map { group -> it.map { group ->
groups.addAll(group.splitNotBlank(",", ";")) groups.addAll(group.splitNotBlank(",", ";"))
@ -109,7 +108,7 @@ class ExploreFragment : VMBaseFragment<ExploreViewModel>(R.layout.fragment_find_
} else { } else {
App.db.bookSourceDao().liveExplore("%$key%") App.db.bookSourceDao().liveExplore("%$key%")
} }
liveExplore?.observe(viewLifecycleOwner, Observer { liveExplore?.observe(viewLifecycleOwner, {
val diffResult = DiffUtil val diffResult = DiffUtil
.calculateDiff(ExploreDiffCallBack(ArrayList(adapter.getItems()), it)) .calculateDiff(ExploreDiffCallBack(ArrayList(adapter.getItems()), it))
adapter.setItems(it) adapter.setItems(it)

@ -4,7 +4,6 @@ import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import io.legado.app.App import io.legado.app.App
import io.legado.app.R import io.legado.app.R
@ -56,7 +55,7 @@ class RssFragment : VMBaseFragment<RssSourceViewModel>(R.layout.fragment_rss),
} }
private fun initData() { private fun initData() {
App.db.rssSourceDao().liveEnabled().observe(viewLifecycleOwner, Observer { App.db.rssSourceDao().liveEnabled().observe(viewLifecycleOwner, {
if (it.isEmpty()) { if (it.isEmpty()) {
getViewModelOfActivity(MainViewModel::class.java).initRss() getViewModelOfActivity(MainViewModel::class.java).initRss()
} }

@ -11,7 +11,6 @@ import android.view.ViewGroup
import android.widget.EditText import android.widget.EditText
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.App import io.legado.app.App
import io.legado.app.R import io.legado.app.R
@ -69,7 +68,7 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener {
recycler_view.layoutManager = LinearLayoutManager(requireContext()) recycler_view.layoutManager = LinearLayoutManager(requireContext())
recycler_view.addItemDecoration(VerticalDivider(requireContext())) recycler_view.addItemDecoration(VerticalDivider(requireContext()))
recycler_view.adapter = adapter recycler_view.adapter = adapter
App.db.replaceRuleDao().liveGroup().observe(viewLifecycleOwner, Observer { App.db.replaceRuleDao().liveGroup().observe(viewLifecycleOwner, {
val groups = linkedSetOf<String>() val groups = linkedSetOf<String>()
it.map { group -> it.map { group ->
groups.addAll(group.splitNotBlank(",", ";")) groups.addAll(group.splitNotBlank(",", ";"))

@ -11,7 +11,6 @@ import androidx.appcompat.widget.PopupMenu
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@ -133,7 +132,7 @@ class ReplaceRuleActivity : VMBaseActivity<ReplaceRuleViewModel>(R.layout.activi
} else { } else {
App.db.replaceRuleDao().liveDataSearch(key) App.db.replaceRuleDao().liveDataSearch(key)
} }
replaceRuleLiveData?.observe(this, Observer { replaceRuleLiveData?.observe(this, {
if (dataInit) { if (dataInit) {
setResult(Activity.RESULT_OK) setResult(Activity.RESULT_OK)
} }
@ -146,7 +145,7 @@ class ReplaceRuleActivity : VMBaseActivity<ReplaceRuleViewModel>(R.layout.activi
} }
private fun observeGroupData() { private fun observeGroupData() {
App.db.replaceRuleDao().liveGroup().observe(this, Observer { App.db.replaceRuleDao().liveGroup().observe(this, {
groups.clear() groups.clear()
it.map { group -> it.map { group ->
groups.addAll(group.splitNotBlank(",", ";")) groups.addAll(group.splitNotBlank(",", ";"))

@ -11,7 +11,6 @@ import android.widget.EditText
import android.widget.PopupWindow import android.widget.PopupWindow
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Observer
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.constant.AppConst import io.legado.app.constant.AppConst
@ -71,7 +70,7 @@ class ReplaceEditDialog : BaseDialogFragment(),
tool_bar.inflateMenu(R.menu.replace_edit) tool_bar.inflateMenu(R.menu.replace_edit)
tool_bar.menu.applyTint(requireContext()) tool_bar.menu.applyTint(requireContext())
tool_bar.setOnMenuItemClickListener(this) tool_bar.setOnMenuItemClickListener(this)
viewModel.replaceRuleData.observe(viewLifecycleOwner, Observer { viewModel.replaceRuleData.observe(viewLifecycleOwner, {
upReplaceView(it) upReplaceView(it)
}) })
arguments?.let { arguments?.let {

@ -3,7 +3,6 @@ package io.legado.app.ui.rss.article
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -87,7 +86,7 @@ class RssArticlesFragment : VMBaseFragment<RssArticlesViewModel>(R.layout.fragme
activityViewModel.url?.let { activityViewModel.url?.let {
rssArticlesData?.removeObservers(this) rssArticlesData?.removeObservers(this)
rssArticlesData = App.db.rssArticleDao().liveByOriginSort(it, viewModel.sortName) rssArticlesData = App.db.rssArticleDao().liveByOriginSort(it, viewModel.sortName)
rssArticlesData?.observe(viewLifecycleOwner, Observer { list -> rssArticlesData?.observe(viewLifecycleOwner, { list ->
adapter.setItems(list) adapter.setItems(list)
}) })
} }
@ -104,7 +103,7 @@ class RssArticlesFragment : VMBaseFragment<RssArticlesViewModel>(R.layout.fragme
} }
override fun observeLiveBus() { override fun observeLiveBus() {
viewModel.loadFinally.observe(viewLifecycleOwner, Observer { viewModel.loadFinally.observe(viewLifecycleOwner, {
refresh_recycler_view.stopLoading() refresh_recycler_view.stopLoading()
if (it) { if (it) {
loadMoreView.startLoad() loadMoreView.startLoad()

@ -8,7 +8,6 @@ import android.view.MenuItem
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.lifecycle.Observer
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.ui.rss.source.edit.RssSourceEditActivity import io.legado.app.ui.rss.source.edit.RssSourceEditActivity
@ -30,7 +29,7 @@ class RssSortActivity : VMBaseActivity<RssSortViewModel>(R.layout.activity_rss_a
adapter = TabFragmentPageAdapter(supportFragmentManager) adapter = TabFragmentPageAdapter(supportFragmentManager)
tab_layout.setupWithViewPager(view_pager) tab_layout.setupWithViewPager(view_pager)
view_pager.adapter = adapter view_pager.adapter = adapter
viewModel.titleLiveData.observe(this, Observer { viewModel.titleLiveData.observe(this, {
title_bar.title = it title_bar.title = it
}) })
viewModel.initData(intent) { viewModel.initData(intent) {
@ -85,7 +84,7 @@ class RssSortActivity : VMBaseActivity<RssSortViewModel>(R.layout.activity_rss_a
} }
} }
private inner class TabFragmentPageAdapter internal constructor(fm: FragmentManager) : private inner class TabFragmentPageAdapter(fm: FragmentManager) :
FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getItemPosition(`object`: Any): Int { override fun getItemPosition(`object`: Any): Int {

@ -2,7 +2,6 @@ package io.legado.app.ui.rss.favorites
import android.os.Bundle import android.os.Bundle
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.App import io.legado.app.App
import io.legado.app.R import io.legado.app.R
@ -37,7 +36,7 @@ class RssFavoritesActivity : BaseActivity(R.layout.activity_rss_favorites),
private fun initData() { private fun initData() {
liveData?.removeObservers(this) liveData?.removeObservers(this)
liveData = App.db.rssStarDao().liveAll() liveData = App.db.rssStarDao().liveAll()
liveData?.observe(this, Observer { liveData?.observe(this, {
adapter.setItems(it) adapter.setItems(it)
}) })
} }

@ -8,7 +8,6 @@ import android.os.Bundle
import android.view.* import android.view.*
import android.webkit.* import android.webkit.*
import androidx.core.view.size import androidx.core.view.size
import androidx.lifecycle.Observer
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.lib.theme.DrawableUtils import io.legado.app.lib.theme.DrawableUtils
@ -155,7 +154,7 @@ class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_r
@SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled")
private fun initLiveData() { private fun initLiveData() {
viewModel.contentLiveData.observe(this, Observer { content -> viewModel.contentLiveData.observe(this, { content ->
viewModel.rssArticle?.let { viewModel.rssArticle?.let {
upJavaScriptEnable() upJavaScriptEnable()
val url = NetworkUtils.getAbsoluteURL(it.origin, it.link) val url = NetworkUtils.getAbsoluteURL(it.origin, it.link)
@ -179,7 +178,7 @@ class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_r
} }
} }
}) })
viewModel.urlLiveData.observe(this, Observer { viewModel.urlLiveData.observe(this, {
upJavaScriptEnable() upJavaScriptEnable()
web_view.loadUrl(it.url, it.headerMap) web_view.loadUrl(it.url, it.headerMap)
}) })

@ -10,7 +10,6 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.EditText import android.widget.EditText
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.App import io.legado.app.App
import io.legado.app.R import io.legado.app.R
@ -63,7 +62,7 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener
tv_ok.setTextColor(requireContext().accentColor) tv_ok.setTextColor(requireContext().accentColor)
tv_ok.visible() tv_ok.visible()
tv_ok.onClick { dismiss() } tv_ok.onClick { dismiss() }
App.db.rssSourceDao().liveGroup().observe(viewLifecycleOwner, Observer { App.db.rssSourceDao().liveGroup().observe(viewLifecycleOwner, {
val groups = linkedSetOf<String>() val groups = linkedSetOf<String>()
it.map { group -> it.map { group ->
groups.addAll(group.splitNotBlank(",", ";")) groups.addAll(group.splitNotBlank(",", ";"))

@ -11,7 +11,6 @@ import androidx.appcompat.widget.PopupMenu
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@ -142,7 +141,7 @@ class RssSourceActivity : VMBaseActivity<RssSourceViewModel>(R.layout.activity_r
} }
private fun initLiveDataGroup() { private fun initLiveDataGroup() {
App.db.rssSourceDao().liveGroup().observe(this, Observer { App.db.rssSourceDao().liveGroup().observe(this, {
groups.clear() groups.clear()
it.map { group -> it.map { group ->
groups.addAll(group.splitNotBlank(",", ";")) groups.addAll(group.splitNotBlank(",", ";"))
@ -195,7 +194,7 @@ class RssSourceActivity : VMBaseActivity<RssSourceViewModel>(R.layout.activity_r
} else { } else {
App.db.rssSourceDao().liveSearch("%$key%") App.db.rssSourceDao().liveSearch("%$key%")
} }
sourceLiveData?.observe(this, Observer { sourceLiveData?.observe(this, {
val diffResult = DiffUtil val diffResult = DiffUtil
.calculateDiff(DiffCallBack(adapter.getItems(), it)) .calculateDiff(DiffCallBack(adapter.getItems(), it))
adapter.setItems(it, diffResult) adapter.setItems(it, diffResult)

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -8,16 +9,34 @@
<TextView <TextView
android:id="@+id/tv_chapter_name" android:id="@+id/tv_chapter_name"
android:layout_width="match_parent" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:singleLine="true" /> android:singleLine="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/iv_checked" />
<TextView <TextView
android:id="@+id/tv_tag" android:id="@+id/tv_tag"
android:layout_width="match_parent" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="12sp" android:textSize="12sp"
android:visibility="gone" android:visibility="gone"
android:singleLine="true" /> android:singleLine="true"
app:layout_constraintTop_toBottomOf="@+id/tv_chapter_name"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/iv_checked" />
</LinearLayout> <ImageView
android:id="@+id/iv_checked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_check"
android:visibility="invisible"
android:contentDescription="@string/success"
app:tint="@color/primaryText"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -1,11 +1,18 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<item <item
android:id="@+id/menu_add" android:id="@+id/menu_add"
android:icon="@drawable/ic_add" android:icon="@drawable/ic_add"
android:title="@string/add" android:title="@string/add"
app:showAsAction="always" /> app:showAsAction="always"
tools:ignore="AlwaysShowAction" />
<item
android:id="@+id/menu_default"
android:title="@string/import_default_rule"
app:showAsAction="never" />
</menu> </menu>
Loading…
Cancel
Save