diff --git a/app/build.gradle b/app/build.gradle
index 9175af2d1..844f12227 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -2,7 +2,7 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
-apply plugin: "de.timfreiheit.resourceplaceholders"
+apply plugin: 'de.timfreiheit.resourceplaceholders'
apply plugin: 'io.fabric'
androidExtensions {
@@ -19,6 +19,7 @@ def gitCommits = Integer.parseInt('git rev-list --count HEAD'.execute([], projec
android {
compileSdkVersion 29
+ flavorDimensions ("version")
signingConfigs {
if (project.hasProperty("RELEASE_STORE_FILE")) {
myConfig {
@@ -37,7 +38,6 @@ android {
targetSdkVersion 29
versionCode gitCommits
versionName version
- flavorDimensions "versionCode"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
project.ext.set("archivesBaseName", name + "_" + version)
multiDexEnabled true
@@ -74,13 +74,15 @@ android {
}
}
}
- productFlavors{
- app{
- manifestPlaceholders = [APP_CHANNEL_VALUE:"app"]
+ productFlavors {
+ app {
+ dimension "version"
+ manifestPlaceholders = [APP_CHANNEL_VALUE: "app"]
}
- google{
+ google {
+ dimension "version"
applicationId "io.legado.play"
- manifestPlaceholders = [APP_CHANNEL_VALUE:"google"]
+ manifestPlaceholders = [APP_CHANNEL_VALUE: "google"]
}
}
compileOptions {
@@ -115,14 +117,14 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
//fireBase
- implementation 'com.google.firebase:firebase-core:17.2.3'
+ implementation 'com.google.firebase:firebase-core:17.3.0'
implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
//androidX
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.media:media:1.1.0'
- implementation 'androidx.preference:preference:1.1.0'
+ implementation 'androidx.preference:preference:1.1.1'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'
implementation 'androidx.viewpager2:viewpager2:1.0.0'
@@ -182,14 +184,14 @@ dependencies {
implementation 'com.jaredrummler:colorpicker:1.1.0'
//apache
- implementation 'org.apache.commons:commons-lang3:3.9'
+ implementation 'org.apache.commons:commons-lang3:3.10'
implementation 'org.apache.commons:commons-text:1.8'
//MarkDown
implementation 'ru.noties.markwon:core:3.1.0'
//转换繁体
- implementation 'com.github.houbb:opencc4j:1.4.0'
+ implementation 'com.hankcs:hanlp:portable-1.7.7'
}
diff --git a/app/src/google/res/values-zh-rHK/strings.xml b/app/src/google/res/values-zh-rHK/strings.xml
new file mode 100644
index 000000000..daa6a610a
--- /dev/null
+++ b/app/src/google/res/values-zh-rHK/strings.xml
@@ -0,0 +1,6 @@
+
+
+
+ 閱讀Pro
+
+
\ No newline at end of file
diff --git a/app/src/google/res/values/strings.xml b/app/src/google/res/values/strings.xml
new file mode 100644
index 000000000..ed2d735c4
--- /dev/null
+++ b/app/src/google/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+
+
+ 阅读Pro
+
+
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 97b4132cb..b33892324 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -257,7 +257,7 @@
android:launchMode="singleTop" />
【备份与恢复】,选择【导入旧版本数据】。
-* 请关注[开源阅读]()支持我,同时关注合作公众号[小说拾遗](),阅读公众号小编。
-* 弄了个企业公众号[开源阅读](),后面弄好后会把原来的[开源阅读软件]()迁移过来
+* 请关注公众号[开源阅读]()支持我,同时关注合作公众号[小说拾遗](),阅读公众号小编。
+* 新公众号[开源阅读]()已启用,[开源阅读软件]()备用
+
+**2020/04/20**
+* 优化阅读界面信息显示
+
+**2020/04/19**
+* 添加阅读界面各种信息设置
+
+**2020/04/18**
+* feat: 中文简繁处理库换成 HanLP, 中文增加 zh-rHK 翻译, hingbong
+* 修复更新时间不对的bug
+
+**2020/04/13**
+* 去除rss朗读时的引号
+
+**2020/04/13**
+* 修复调用webView返回结果多了引号的bug
+
+**2020/04/12**
+* 解决无法取消加粗的bug
+* 修复换源自动加入书架的bug
+
+**2020/04/09**
+* 修复书架刷新闪烁
+
+**2020/04/08**
+* 可以隐藏书架未分组
+
+**2020/04/07**
+* 书架添加未分组,有未分组书籍时自动显示
+* 其它一些优化
+
+**2020/04/04**
+* 优化备份逻辑
+* 修复订阅分类太多显示不全的bug
+* 修复一些分类要手动刷新的问题
+
+**2020/04/02**
+* 书架书名和作者作为唯一值
+* 添加订阅分类,分类规则和发现一样,分类一::url1 && 分类2::url2
+
+**2020/03/29**
+* 添加退出软件后是否响应耳机按键的开关
+* 优化书源校验
+
+**2020/03/26**
+* 修复txt目录bug
+* 最近工作比较忙,只有晚上有时间写软件,bug之类的不要催,白天不回消息
**2020/03/25**
* 修复7.1.1的网络问题,是retrofit2库最新版本的bug,暂时退回上版本
diff --git a/app/src/main/java/io/legado/app/App.kt b/app/src/main/java/io/legado/app/App.kt
index 7cb9eff1f..5c4c02964 100644
--- a/app/src/main/java/io/legado/app/App.kt
+++ b/app/src/main/java/io/legado/app/App.kt
@@ -73,7 +73,7 @@ class App : Application() {
.primaryColor(
getPrefInt("colorPrimaryNight", getCompatColor(R.color.md_blue_grey_600))
).accentColor(
- getPrefInt("colorAccentNight", getCompatColor(R.color.md_brown_800))
+ getPrefInt("colorAccentNight", getCompatColor(R.color.md_deep_orange_800))
).backgroundColor(
getPrefInt("colorBackgroundNight", getCompatColor(R.color.shine_color))
).bottomBackground(
diff --git a/app/src/main/java/io/legado/app/constant/AppConst.kt b/app/src/main/java/io/legado/app/constant/AppConst.kt
index 810e6deb2..57724c62f 100644
--- a/app/src/main/java/io/legado/app/constant/AppConst.kt
+++ b/app/src/main/java/io/legado/app/constant/AppConst.kt
@@ -49,6 +49,7 @@ object AppConst {
val bookGroupAll = BookGroup(-1, App.INSTANCE.getString(R.string.all))
val bookGroupLocal = BookGroup(-2, App.INSTANCE.getString(R.string.local))
val bookGroupAudio = BookGroup(-3, App.INSTANCE.getString(R.string.audio))
+ val bookGroupNone = BookGroup(-4, App.INSTANCE.getString(R.string.no_group))
const val notificationIdRead = 1144771
const val notificationIdAudio = 1144772
diff --git a/app/src/main/java/io/legado/app/constant/PreferKey.kt b/app/src/main/java/io/legado/app/constant/PreferKey.kt
index e14ec42f6..8913956d3 100644
--- a/app/src/main/java/io/legado/app/constant/PreferKey.kt
+++ b/app/src/main/java/io/legado/app/constant/PreferKey.kt
@@ -42,4 +42,5 @@ object PreferKey {
const val shareLayout = "shareLayout"
const val readStyleSelect = "readStyleSelect"
const val systemTypefaces = "system_typefaces"
+ const val readBodyToLh = "readBodyToLh"
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/data/AppDatabase.kt b/app/src/main/java/io/legado/app/data/AppDatabase.kt
index f32d6a199..f7eabc4b9 100644
--- a/app/src/main/java/io/legado/app/data/AppDatabase.kt
+++ b/app/src/main/java/io/legado/app/data/AppDatabase.kt
@@ -18,7 +18,7 @@ import kotlinx.coroutines.launch
ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class,
RssSource::class, Bookmark::class, RssArticle::class, RssReadRecord::class,
RssStar::class, TxtTocRule::class],
- version = 8,
+ version = 10,
exportSchema = true
)
abstract class AppDatabase : RoomDatabase() {
diff --git a/app/src/main/java/io/legado/app/data/dao/BookChapterDao.kt b/app/src/main/java/io/legado/app/data/dao/BookChapterDao.kt
index 38cc452f2..d0588bec8 100644
--- a/app/src/main/java/io/legado/app/data/dao/BookChapterDao.kt
+++ b/app/src/main/java/io/legado/app/data/dao/BookChapterDao.kt
@@ -10,16 +10,16 @@ import io.legado.app.data.entities.BookChapter
@Dao
interface BookChapterDao {
- @Query("select * from chapters where bookUrl = :bookUrl")
+ @Query("select * from chapters where bookUrl = :bookUrl order by `index`")
fun observeByBook(bookUrl: String): LiveData>
- @Query("SELECT * FROM chapters where bookUrl = :bookUrl and title like '%'||:key||'%'")
+ @Query("SELECT * FROM chapters where bookUrl = :bookUrl and title like '%'||:key||'%' order by `index`")
fun liveDataSearch(bookUrl: String, key: String): LiveData>
- @Query("select * from chapters where bookUrl = :bookUrl")
+ @Query("select * from chapters where bookUrl = :bookUrl order by `index`")
fun getChapterList(bookUrl: String): List
- @Query("select * from chapters where bookUrl = :bookUrl and `index` >= :start and `index` <= :end")
+ @Query("select * from chapters where bookUrl = :bookUrl and `index` >= :start and `index` <= :end order by `index`")
fun getChapterList(bookUrl: String, start: Int, end: Int): List
@Query("select * from chapters where bookUrl = :bookUrl and `index` = :index")
diff --git a/app/src/main/java/io/legado/app/data/dao/BookDao.kt b/app/src/main/java/io/legado/app/data/dao/BookDao.kt
index d8d960df3..c91e01648 100644
--- a/app/src/main/java/io/legado/app/data/dao/BookDao.kt
+++ b/app/src/main/java/io/legado/app/data/dao/BookDao.kt
@@ -30,6 +30,9 @@ interface BookDao {
@Query("select * from books where (SELECT sum(groupId) FROM book_groups) & `group` = 0")
fun observeNoGroup(): LiveData>
+ @Query("select count(bookUrl) from books where (SELECT sum(groupId) FROM book_groups) & `group` = 0")
+ fun observeNoGroupSize(): LiveData
+
@Query("SELECT * FROM books WHERE name like '%'||:key||'%' or author like '%'||:key||'%'")
fun liveDataSearch(key: String): LiveData>
@@ -42,6 +45,12 @@ interface BookDao {
@Query("SELECT * FROM books WHERE bookUrl = :bookUrl")
fun getBook(bookUrl: String): Book?
+ @Query("SELECT * FROM books WHERE name = :name and author = :author")
+ fun getBook(name: String, author: String): Book?
+
+ @get:Query("select count(bookUrl) from books where (SELECT sum(groupId) FROM book_groups) & `group` = 0")
+ val noGroupSize: Int
+
@get:Query("SELECT * FROM books where origin <> '${BookType.local}' and type = 0")
val webBooks: List
diff --git a/app/src/main/java/io/legado/app/data/dao/RssArticleDao.kt b/app/src/main/java/io/legado/app/data/dao/RssArticleDao.kt
index fbf3c3611..10bf63933 100644
--- a/app/src/main/java/io/legado/app/data/dao/RssArticleDao.kt
+++ b/app/src/main/java/io/legado/app/data/dao/RssArticleDao.kt
@@ -12,17 +12,18 @@ interface RssArticleDao {
fun get(origin: String, link: String): RssArticle?
@Query(
- """select t1.link, t1.origin, t1.`order`, t1.title, t1.content, t1.description, t1.image, t1.pubDate, ifNull(t2.read, 0) as read
+ """select t1.link, t1.sort, t1.origin, t1.`order`, t1.title, t1.content, t1.description, t1.image, t1.pubDate, ifNull(t2.read, 0) as read
from rssArticles as t1 left join rssReadRecords as t2
- on t1.link = t2.record where origin = :origin order by `order` desc"""
+ on t1.link = t2.record where origin = :origin and sort = :sort
+ order by `order` desc"""
)
- fun liveByOrigin(origin: String): LiveData>
+ fun liveByOriginSort(origin: String, sort: String): LiveData>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg rssArticle: RssArticle)
- @Query("delete from rssArticles where origin = :origin and `order` < :order")
- fun clearOld(origin: String, order: Long)
+ @Query("delete from rssArticles where origin = :origin and sort = :sort and `order` < :order")
+ fun clearOld(origin: String, sort: String, order: Long)
@Update
fun update(vararg rssArticle: RssArticle)
diff --git a/app/src/main/java/io/legado/app/data/entities/Book.kt b/app/src/main/java/io/legado/app/data/entities/Book.kt
index 0dd5cab9e..fd96d137b 100644
--- a/app/src/main/java/io/legado/app/data/entities/Book.kt
+++ b/app/src/main/java/io/legado/app/data/entities/Book.kt
@@ -4,7 +4,6 @@ import android.os.Parcelable
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.Index
-import androidx.room.PrimaryKey
import io.legado.app.constant.AppPattern
import io.legado.app.constant.BookType
import io.legado.app.utils.GSON
@@ -15,9 +14,12 @@ import java.nio.charset.Charset
import kotlin.math.max
@Parcelize
-@Entity(tableName = "books", indices = [(Index(value = ["bookUrl"], unique = true))])
+@Entity(
+ tableName = "books",
+ primaryKeys = ["name", "author"],
+ indices = [(Index(value = ["bookUrl"], unique = true))]
+)
data class Book(
- @PrimaryKey
override var bookUrl: String = "", // 详情页Url(本地书源存储完整文件路径)
var tocUrl: String = "", // 目录页Url (toc=table of Contents)
var origin: String = BookType.local, // 书源URL(默认BookType.local)
diff --git a/app/src/main/java/io/legado/app/data/entities/BookSource.kt b/app/src/main/java/io/legado/app/data/entities/BookSource.kt
index 78852a4ec..ad16bf99f 100644
--- a/app/src/main/java/io/legado/app/data/entities/BookSource.kt
+++ b/app/src/main/java/io/legado/app/data/entities/BookSource.kt
@@ -169,7 +169,7 @@ data class BookSource(
}
}
val b = a.split("(&&|\n)+".toRegex())
- b.map { c ->
+ b.forEach { c ->
val d = c.split("::")
if (d.size > 1)
exploreKinds.add(ExploreKind(d[0], d[1]))
diff --git a/app/src/main/java/io/legado/app/data/entities/RssArticle.kt b/app/src/main/java/io/legado/app/data/entities/RssArticle.kt
index c74597e74..15dafa3ab 100644
--- a/app/src/main/java/io/legado/app/data/entities/RssArticle.kt
+++ b/app/src/main/java/io/legado/app/data/entities/RssArticle.kt
@@ -9,6 +9,7 @@ import androidx.room.Entity
)
data class RssArticle(
var origin: String = "",
+ var sort: String = "",
var title: String = "",
var order: Long = 0,
var link: String = "",
@@ -36,6 +37,7 @@ data class RssArticle(
fun toStar(): RssStar {
return RssStar(
origin = origin,
+ sort = sort,
title = title,
starTime = System.currentTimeMillis(),
link = link,
diff --git a/app/src/main/java/io/legado/app/data/entities/RssSource.kt b/app/src/main/java/io/legado/app/data/entities/RssSource.kt
index 999b12523..e9a58ee98 100644
--- a/app/src/main/java/io/legado/app/data/entities/RssSource.kt
+++ b/app/src/main/java/io/legado/app/data/entities/RssSource.kt
@@ -23,6 +23,7 @@ data class RssSource(
var sourceIcon: String = "",
var sourceGroup: String? = null,
var enabled: Boolean = true,
+ var sortUrl: String? = null,
//列表规则
var ruleArticles: String? = null,
var ruleNextPage: String? = null,
@@ -99,4 +100,16 @@ data class RssSource(
return a == b || (a.isNullOrEmpty() && b.isNullOrEmpty())
}
+ fun sortUrls(): LinkedHashMap {
+ val sortMap = linkedMapOf()
+ sortUrl?.split("(&&|\n)+".toRegex())?.forEach { c ->
+ val d = c.split("::")
+ if (d.size > 1)
+ sortMap[d[0]] = d[1]
+ }
+ if (sortMap.isEmpty()) {
+ sortMap[""] = sourceUrl
+ }
+ return sortMap
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/data/entities/RssStar.kt b/app/src/main/java/io/legado/app/data/entities/RssStar.kt
index 1d0c266f8..94196416b 100644
--- a/app/src/main/java/io/legado/app/data/entities/RssStar.kt
+++ b/app/src/main/java/io/legado/app/data/entities/RssStar.kt
@@ -9,6 +9,7 @@ import androidx.room.Entity
)
data class RssStar(
var origin: String = "",
+ var sort: String = "",
var title: String = "",
var starTime: Long = 0,
var link: String = "",
@@ -20,6 +21,7 @@ data class RssStar(
fun toRssArticle(): RssArticle {
return RssArticle(
origin = origin,
+ sort = sort,
title = title,
link = link,
pubDate = pubDate,
diff --git a/app/src/main/java/io/legado/app/help/AppConfig.kt b/app/src/main/java/io/legado/app/help/AppConfig.kt
index f2e34c3b6..9d2a3f679 100644
--- a/app/src/main/java/io/legado/app/help/AppConfig.kt
+++ b/app/src/main/java/io/legado/app/help/AppConfig.kt
@@ -115,13 +115,19 @@ object AppConfig {
App.INSTANCE.putPrefBoolean("bookGroupAudio", value)
}
+ var bookGroupNoneShow: Boolean
+ get() = App.INSTANCE.getPrefBoolean("bookGroupNone", false)
+ set(value) {
+ App.INSTANCE.putPrefBoolean("bookGroupNone", value)
+ }
+
var elevation: Int
get() = App.INSTANCE.getPrefInt("elevation", -1)
set(value) {
App.INSTANCE.putPrefInt("elevation", value)
}
- val readBodyToLh: Boolean get() = App.INSTANCE.getPrefBoolean("readBodyToLh", true)
+ val readBodyToLh: Boolean get() = App.INSTANCE.getPrefBoolean(PreferKey.readBodyToLh, true)
val isGooglePlay: Boolean get() = App.INSTANCE.channel == "google"
}
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 a147e140d..514c5327c 100644
--- a/app/src/main/java/io/legado/app/help/BookHelp.kt
+++ b/app/src/main/java/io/legado/app/help/BookHelp.kt
@@ -1,6 +1,6 @@
package io.legado.app.help
-import com.github.houbb.opencc4j.core.impl.ZhConvertBootstrap
+import com.hankcs.hanlp.HanLP
import io.legado.app.App
import io.legado.app.constant.EventBus
import io.legado.app.data.entities.Book
@@ -231,12 +231,17 @@ object BookHelp {
if (!c.substringBefore("\n").contains(title)) {
c = "$title\n$c"
}
- when (AppConfig.chineseConverterType) {
- 1 -> c = ZhConvertBootstrap.newInstance().toSimple(c)
- 2 -> c = ZhConvertBootstrap.newInstance().toTraditional(c)
+ try {
+ when (AppConfig.chineseConverterType) {
+ 1 -> c = HanLP.convertToSimplifiedChinese(c)
+ 2 -> c = HanLP.convertToTraditionalChinese(c)
+ }
+ } catch (e: Exception) {
+ withContext(Main) {
+ App.INSTANCE.toast("简繁转换出错")
+ }
}
return c
.replace("\\s*\\n+\\s*".toRegex(), "\n${ReadBookConfig.bodyIndent}")
- .replace("[\\n\\s]+$".toRegex(), "") //移除尾部空行
}
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/help/ReadBookConfig.kt b/app/src/main/java/io/legado/app/help/ReadBookConfig.kt
index d0e67e901..ff4180081 100644
--- a/app/src/main/java/io/legado/app/help/ReadBookConfig.kt
+++ b/app/src/main/java/io/legado/app/help/ReadBookConfig.kt
@@ -27,7 +27,6 @@ object ReadBookConfig {
GSON.fromJsonArray(json)!!
}
val durConfig get() = getConfig(styleSelect)
- private val shareConfig get() = getConfig(5)
var bg: Drawable? = null
var bgMeanColor: Int = 0
@@ -139,129 +138,145 @@ object ReadBookConfig {
var bodyIndent = " ".repeat(bodyIndentCount)
var hideStatusBar = App.INSTANCE.getPrefBoolean(PreferKey.hideStatusBar)
var hideNavigationBar = App.INSTANCE.getPrefBoolean(PreferKey.hideNavigationBar)
+
+ private val config get() = if (shareLayout) getConfig(5) else durConfig
+
var textBold: Boolean
- get() = if (shareLayout) shareConfig.textBold else durConfig.textBold
- set(value) = if (shareLayout) shareConfig.textBold = value else durConfig.textBold = value
+ get() = config.textBold
+ set(value) {
+ config.textBold = value
+ }
var textSize: Int
- get() = if (shareLayout) shareConfig.textSize else durConfig.textSize
- set(value) = if (shareLayout) shareConfig.textSize = value else durConfig.textSize = value
+ get() = config.textSize
+ set(value) {
+ config.textSize = value
+ }
var letterSpacing: Float
- get() = if (shareLayout) shareConfig.letterSpacing else durConfig.letterSpacing
- set(value) =
- if (shareLayout) shareConfig.letterSpacing = value else durConfig.letterSpacing = value
+ get() = config.letterSpacing
+ set(value) {
+ config.letterSpacing = value
+ }
var lineSpacingExtra: Int
- get() = if (shareLayout) shareConfig.lineSpacingExtra else durConfig.lineSpacingExtra
- set(value) =
- if (shareLayout) shareConfig.lineSpacingExtra = value
- else durConfig.lineSpacingExtra = value
+ get() = config.lineSpacingExtra
+ set(value) {
+ config.lineSpacingExtra = value
+ }
var paragraphSpacing: Int
- get() = if (shareLayout) shareConfig.paragraphSpacing else durConfig.paragraphSpacing
- set(value) =
- if (shareLayout) shareConfig.paragraphSpacing = value
- else durConfig.paragraphSpacing = value
+ get() = config.paragraphSpacing
+ set(value) {
+ config.paragraphSpacing = value
+ }
var titleMode: Int
- get() = if (shareLayout) shareConfig.titleMode else durConfig.titleMode
- set(value) =
- if (shareLayout) shareConfig.titleMode = value else durConfig.titleMode = value
+ get() = config.titleMode
+ set(value) {
+ config.titleMode = value
+ }
var titleSize: Int
- get() = if (shareLayout) shareConfig.titleSize else durConfig.titleSize
- set(value) =
- if (shareLayout) shareConfig.titleSize = value else durConfig.titleSize = value
+ get() = config.titleSize
+ set(value) {
+ config.titleSize = value
+ }
+
var titleTopSpacing: Int
- get() = if (shareLayout) shareConfig.titleTopSpacing else durConfig.titleTopSpacing
- set(value) =
- if (shareLayout) shareConfig.titleTopSpacing = value
- else durConfig.titleTopSpacing = value
+ get() = config.titleTopSpacing
+ set(value) {
+ config.titleTopSpacing = value
+ }
+
var titleBottomSpacing: Int
- get() = if (shareLayout) shareConfig.titleBottomSpacing else durConfig.titleBottomSpacing
- set(value) =
- if (shareLayout) shareConfig.titleBottomSpacing = value
- else durConfig.titleBottomSpacing = value
+ get() = config.titleBottomSpacing
+ set(value) {
+ config.titleBottomSpacing = value
+ }
var paddingBottom: Int
- get() = if (shareLayout) shareConfig.paddingBottom else durConfig.paddingBottom
- set(value) =
- if (shareLayout) shareConfig.paddingBottom = value else durConfig.paddingBottom = value
+ get() = config.paddingBottom
+ set(value) {
+ config.paddingBottom = value
+ }
var paddingLeft: Int
- get() = if (shareLayout) shareConfig.paddingLeft else durConfig.paddingLeft
- set(value) =
- if (shareLayout) shareConfig.paddingLeft = value else durConfig.paddingLeft = value
+ get() = config.paddingLeft
+ set(value) {
+ config.paddingLeft = value
+ }
var paddingRight: Int
- get() = if (shareLayout) shareConfig.paddingRight else durConfig.paddingRight
- set(value) =
- if (shareLayout) shareConfig.paddingRight = value else durConfig.paddingRight = value
+ get() = config.paddingRight
+ set(value) {
+ config.paddingRight = value
+ }
var paddingTop: Int
- get() = if (shareLayout) shareConfig.paddingTop else durConfig.paddingTop
- set(value) =
- if (shareLayout) shareConfig.paddingTop = value else durConfig.paddingTop = value
+ get() = config.paddingTop
+ set(value) {
+ config.paddingTop = value
+ }
var headerPaddingBottom: Int
- get() = if (shareLayout) shareConfig.headerPaddingBottom else durConfig.headerPaddingBottom
- set(value) =
- if (shareLayout) shareConfig.headerPaddingBottom = value
- else durConfig.headerPaddingBottom = value
+ get() = config.headerPaddingBottom
+ set(value) {
+ config.headerPaddingBottom = value
+ }
var headerPaddingLeft: Int
- get() = if (shareLayout) shareConfig.headerPaddingLeft else durConfig.headerPaddingLeft
- set(value) =
- if (shareLayout) shareConfig.headerPaddingLeft = value
- else durConfig.headerPaddingLeft = value
+ get() = config.headerPaddingLeft
+ set(value) {
+ config.headerPaddingLeft = value
+ }
var headerPaddingRight: Int
- get() = if (shareLayout) shareConfig.headerPaddingRight else durConfig.headerPaddingRight
- set(value) =
- if (shareLayout) shareConfig.headerPaddingRight = value
- else durConfig.headerPaddingRight = value
+ get() = config.headerPaddingRight
+ set(value) {
+ config.headerPaddingRight = value
+ }
var headerPaddingTop: Int
- get() = if (shareLayout) shareConfig.headerPaddingTop else durConfig.headerPaddingTop
- set(value) =
- if (shareLayout) shareConfig.headerPaddingTop = value
- else durConfig.headerPaddingTop = value
+ get() = config.headerPaddingTop
+ set(value) {
+ config.headerPaddingTop = value
+ }
var footerPaddingBottom: Int
- get() = if (shareLayout) shareConfig.footerPaddingBottom else durConfig.footerPaddingBottom
- set(value) =
- if (shareLayout) shareConfig.footerPaddingBottom = value
- else durConfig.footerPaddingBottom = value
+ get() = config.footerPaddingBottom
+ set(value) {
+ config.footerPaddingBottom = value
+ }
var footerPaddingLeft: Int
- get() = if (shareLayout) shareConfig.footerPaddingLeft else durConfig.footerPaddingLeft
- set(value) =
- if (shareLayout) shareConfig.footerPaddingLeft = value
- else durConfig.footerPaddingLeft = value
+ get() = config.footerPaddingLeft
+ set(value) {
+ config.footerPaddingLeft = value
+ }
var footerPaddingRight: Int
- get() = if (shareLayout) shareConfig.footerPaddingRight else durConfig.footerPaddingRight
- set(value) =
- if (shareLayout) shareConfig.footerPaddingRight = value
- else durConfig.footerPaddingRight = value
+ get() = config.footerPaddingRight
+ set(value) {
+ config.footerPaddingRight = value
+ }
var footerPaddingTop: Int
- get() = if (shareLayout) shareConfig.footerPaddingTop else durConfig.footerPaddingTop
- set(value) =
- if (shareLayout) shareConfig.footerPaddingTop = value
- else durConfig.footerPaddingTop = value
+ get() = config.footerPaddingTop
+ set(value) {
+ config.footerPaddingTop = value
+ }
var showHeaderLine: Boolean
- get() = if (shareLayout) shareConfig.showHeaderLine else durConfig.showHeaderLine
- set(value) =
- if (shareLayout) shareConfig.showHeaderLine = value
- else durConfig.showHeaderLine = value
+ get() = config.showHeaderLine
+ set(value) {
+ config.showHeaderLine = value
+ }
var showFooterLine: Boolean
- get() = if (shareLayout) shareConfig.showFooterLine else durConfig.showFooterLine
- set(value) =
- if (shareLayout) shareConfig.showFooterLine = value
- else durConfig.showFooterLine = value
+ get() = config.showFooterLine
+ set(value) {
+ config.showFooterLine = value
+ }
@Keep
class Config(
diff --git a/app/src/main/java/io/legado/app/help/ReadTipConfig.kt b/app/src/main/java/io/legado/app/help/ReadTipConfig.kt
new file mode 100644
index 000000000..9d6452b38
--- /dev/null
+++ b/app/src/main/java/io/legado/app/help/ReadTipConfig.kt
@@ -0,0 +1,74 @@
+package io.legado.app.help
+
+import io.legado.app.App
+import io.legado.app.R
+import io.legado.app.utils.getPrefBoolean
+import io.legado.app.utils.getPrefInt
+import io.legado.app.utils.putPrefBoolean
+import io.legado.app.utils.putPrefInt
+
+object ReadTipConfig {
+ val tipArray: Array = App.INSTANCE.resources.getStringArray(R.array.read_tip)
+ const val none = 0
+ const val chapterTitle = 1
+ const val time = 2
+ const val battery = 3
+ const val page = 4
+ const val totalProgress = 5
+ const val pageAndTotal = 6
+
+ val tipHeaderLeftStr: String get() = tipArray.getOrElse(tipHeaderLeft) { tipArray[none] }
+ val tipHeaderMiddleStr: String get() = tipArray.getOrElse(tipHeaderMiddle) { tipArray[none] }
+ val tipHeaderRightStr: String get() = tipArray.getOrElse(tipHeaderRight) { tipArray[none] }
+ val tipFooterLeftStr: String get() = tipArray.getOrElse(tipFooterLeft) { tipArray[none] }
+ val tipFooterMiddleStr: String get() = tipArray.getOrElse(tipFooterMiddle) { tipArray[none] }
+ val tipFooterRightStr: String get() = tipArray.getOrElse(tipFooterRight) { tipArray[none] }
+
+ var tipHeaderLeft: Int
+ get() = App.INSTANCE.getPrefInt("tipHeaderLeft", time)
+ set(value) {
+ App.INSTANCE.putPrefInt("tipHeaderLeft", value)
+ }
+
+ var tipHeaderMiddle: Int
+ get() = App.INSTANCE.getPrefInt("tipHeaderMiddle", none)
+ set(value) {
+ App.INSTANCE.putPrefInt("tipHeaderMiddle", value)
+ }
+
+ var tipHeaderRight: Int
+ get() = App.INSTANCE.getPrefInt("tipHeaderRight", battery)
+ set(value) {
+ App.INSTANCE.putPrefInt("tipHeaderRight", value)
+ }
+
+ var tipFooterLeft: Int
+ get() = App.INSTANCE.getPrefInt("tipFooterLeft", chapterTitle)
+ set(value) {
+ App.INSTANCE.putPrefInt("tipFooterLeft", value)
+ }
+
+ var tipFooterMiddle: Int
+ get() = App.INSTANCE.getPrefInt("tipFooterMiddle", none)
+ set(value) {
+ App.INSTANCE.putPrefInt("tipFooterMiddle", value)
+ }
+
+ var tipFooterRight: Int
+ get() = App.INSTANCE.getPrefInt("tipFooterRight", pageAndTotal)
+ set(value) {
+ App.INSTANCE.putPrefInt("tipFooterRight", value)
+ }
+
+ var hideHeader: Boolean
+ get() = App.INSTANCE.getPrefBoolean("hideHeader", true)
+ set(value) {
+ App.INSTANCE.putPrefBoolean("hideHeader", value)
+ }
+
+ var hideFooter: Boolean
+ get() = App.INSTANCE.getPrefBoolean("hideFooter", false)
+ set(value) {
+ App.INSTANCE.putPrefBoolean("hideFooter", value)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/help/http/AjaxWebView.kt b/app/src/main/java/io/legado/app/help/http/AjaxWebView.kt
index f501fcb71..4f5cbda46 100644
--- a/app/src/main/java/io/legado/app/help/http/AjaxWebView.kt
+++ b/app/src/main/java/io/legado/app/help/http/AjaxWebView.kt
@@ -180,6 +180,7 @@ class AjaxWebView {
mWebView.get()?.evaluateJavascript(mJavaScript) {
if (it.isNotEmpty() && it != "null") {
val content = StringEscapeUtils.unescapeJson(it)
+ .replace("^\"|\"$".toRegex(), "")
handler.obtainMessage(MSG_SUCCESS, Res(url, content))
.sendToTarget()
handler.removeCallbacks(this)
diff --git a/app/src/main/java/io/legado/app/help/storage/Backup.kt b/app/src/main/java/io/legado/app/help/storage/Backup.kt
index c47951385..5b1e88186 100644
--- a/app/src/main/java/io/legado/app/help/storage/Backup.kt
+++ b/app/src/main/java/io/legado/app/help/storage/Backup.kt
@@ -32,9 +32,7 @@ object Backup {
val lastBackup = context.getPrefLong(PreferKey.lastBackup)
if (lastBackup + TimeUnit.DAYS.toMillis(1) < System.currentTimeMillis()) {
Coroutine.async {
- context.getPrefString(PreferKey.backupPath)?.let {
- backup(context, it, true)
- }
+ backup(context, context.getPrefString(PreferKey.backupPath) ?: "", true)
}
}
}
@@ -71,7 +69,11 @@ object Backup {
if (path.isContentPath()) {
copyBackup(context, Uri.parse(path), isAuto)
} else {
- copyBackup(File(path), isAuto)
+ if (path.isEmpty()) {
+ copyBackup(context.getExternalFilesDir(null)!!, false)
+ } else {
+ copyBackup(File(path), isAuto)
+ }
}
}
}
diff --git a/app/src/main/java/io/legado/app/help/storage/OldRule.kt b/app/src/main/java/io/legado/app/help/storage/OldRule.kt
index 7696bb383..d605b02fe 100644
--- a/app/src/main/java/io/legado/app/help/storage/OldRule.kt
+++ b/app/src/main/java/io/legado/app/help/storage/OldRule.kt
@@ -19,7 +19,7 @@ object OldRule {
source = GSON.fromJsonObject(json.trim())
}
runCatching {
- if (source == null || source?.searchUrl.isNullOrBlank()) {
+ if (source == null || source?.ruleToc.isNullOrBlank()) {
source = BookSource().apply {
val jsonItem = jsonPath.parse(json.trim())
bookSourceUrl = jsonItem.readString("bookSourceUrl") ?: ""
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 51ae12afd..58944e05b 100644
--- a/app/src/main/java/io/legado/app/model/Debug.kt
+++ b/app/src/main/java/io/legado/app/model/Debug.kt
@@ -54,7 +54,8 @@ object Debug {
cancelDebug()
debugSource = rssSource.sourceUrl
log(debugSource, "︾开始解析")
- Rss.getArticles(rssSource, null)
+ val sort = rssSource.sortUrls().entries.first()
+ Rss.getArticles(sort.key, sort.value, rssSource, null)
.onSuccess {
if (it.articles.isEmpty()) {
log(debugSource, "⇒列表页解析成功,为空")
diff --git a/app/src/main/java/io/legado/app/model/Rss.kt b/app/src/main/java/io/legado/app/model/Rss.kt
index 24dadade0..8b29913d9 100644
--- a/app/src/main/java/io/legado/app/model/Rss.kt
+++ b/app/src/main/java/io/legado/app/model/Rss.kt
@@ -15,6 +15,8 @@ import kotlin.coroutines.CoroutineContext
object Rss {
fun getArticles(
+ sortName: String,
+ sortUrl: String,
rssSource: RssSource,
pageUrl: String? = null,
scope: CoroutineScope = Coroutine.DEFAULT,
@@ -22,11 +24,11 @@ object Rss {
): Coroutine {
return Coroutine.async(scope, context) {
val analyzeUrl = AnalyzeUrl(
- pageUrl ?: rssSource.sourceUrl,
+ pageUrl ?: sortUrl,
headerMapF = rssSource.getHeaderMap()
)
val body = analyzeUrl.getResponseAwait(rssSource.sourceUrl).body
- RssParserByRule.parseXML(body, rssSource)
+ RssParserByRule.parseXML(sortName, sortUrl, body, rssSource)
}
}
diff --git a/app/src/main/java/io/legado/app/model/localBook/AnalyzeTxtFile.kt b/app/src/main/java/io/legado/app/model/localBook/AnalyzeTxtFile.kt
index 96de16e8c..494437d92 100644
--- a/app/src/main/java/io/legado/app/model/localBook/AnalyzeTxtFile.kt
+++ b/app/src/main/java/io/legado/app/model/localBook/AnalyzeTxtFile.kt
@@ -18,6 +18,7 @@ class AnalyzeTxtFile {
private val tocRules = arrayListOf()
private lateinit var charset: Charset
+ @Throws(Exception::class)
fun analyze(context: Context, book: Book): ArrayList {
val bookFile = getBookFile(context, book)
book.charset = EncodingDetect.getEncode(bookFile)
@@ -33,6 +34,7 @@ class AnalyzeTxtFile {
return analyze(bookStream, book, rulePattern)
}
+ @Throws(Exception::class)
private fun analyze(
bookStream: RandomAccessFile,
book: Book,
@@ -58,18 +60,19 @@ class AnalyzeTxtFile {
var allLength = 0
//获取文件中的数据到buffer,直到没有数据为止
- while (bookStream.read(buffer, 0, buffer.size).also { length = it } > 0) {
+ while (bookStream.read(buffer).also { length = it } > 0) {
blockPos++
- var blockContent = String(buffer, charset)
- val lastN = blockContent.lastIndexOf("\n")
- if (lastN > 0) {
- blockContent = blockContent.substring(0, lastN)
- length = blockContent.toByteArray(charset).size
- allLength += length
- bookStream.seek(allLength.toLong())
- }
//如果存在Chapter
- if (rulePattern != null) { //将数据转换成String
+ if (rulePattern != null) {
+ //将数据转换成String, 不能超过length
+ var blockContent = String(buffer, 0, length, charset)
+ val lastN = blockContent.lastIndexOf("\n")
+ if (lastN > 0) {
+ blockContent = blockContent.substring(0, lastN)
+ length = blockContent.toByteArray(charset).size
+ allLength += length
+ bookStream.seek(allLength.toLong())
+ }
//当前Block下使过的String的指针
var seekPos = 0
//进行正则匹配
@@ -79,35 +82,59 @@ class AnalyzeTxtFile {
val chapterStart = matcher.start()
//获取章节内容
val chapterContent = blockContent.substring(seekPos, chapterStart)
- if (chapterContent.length > 30000 && pattern == null) {
+ val chapterLength = chapterContent.toByteArray(charset).size
+ if (chapterLength > 30000 && pattern == null) {
//移除不匹配的规则
tocRules.remove(tocRule)
return analyze(bookStream, book, null)
}
//如果 seekPos == 0 && nextChapterPos != 0 表示当前block处前面有一段内容
- //第一种情况一定是序章 第二种情况可能是上一个章节的内容
- if (seekPos == 0 && chapterStart != 0 && toc.isEmpty()) { //获取当前章节的内容
- val chapter = BookChapter()
- chapter.title = "前言"
- chapter.start = 0
- chapter.end = chapterContent.toByteArray(charset).size.toLong()
- toc.add(chapter)
- //创建当前章节
- val curChapter = BookChapter()
- curChapter.title = matcher.group()
- curChapter.start = chapter.end
- toc.add(curChapter)
+ //第一种情况一定是序章 第二种情况是上一个章节的内容
+ if (seekPos == 0 && chapterStart != 0) { //获取当前章节的内容
+ if (toc.isEmpty()) { //如果当前没有章节,那么就是序章
+ //加入简介
+ if (StringUtils.trim(chapterContent).isNotEmpty()) {
+ val qyChapter = BookChapter()
+ qyChapter.title = "前言"
+ qyChapter.start = 0
+ qyChapter.end = chapterLength.toLong()
+ toc.add(qyChapter)
+ }
+ //创建当前章节
+ val curChapter = BookChapter()
+ curChapter.title = matcher.group()
+ curChapter.start = chapterLength.toLong()
+ toc.add(curChapter)
+ } else { //否则就block分割之后,上一个章节的剩余内容
+ //获取上一章节
+ val lastChapter = toc.last()
+ //将当前段落添加上一章去
+ lastChapter.end =
+ lastChapter.end!! + chapterLength.toLong()
+ //创建当前章节
+ val curChapter = BookChapter()
+ curChapter.title = matcher.group()
+ curChapter.start = lastChapter.end
+ toc.add(curChapter)
+ }
} else {
- val lastChapter = toc.lastOrNull()
- lastChapter?.let {
- //上一章节结束等于这一章节开始
- it.end = it.start!! + chapterContent.toByteArray(charset).size
+ if (toc.isNotEmpty()) { //获取章节内容
+ //获取上一章节
+ val lastChapter = toc.last()
+ lastChapter.end =
+ lastChapter.start!! + chapterContent.toByteArray(charset).size.toLong()
+ //创建当前章节
+ val curChapter = BookChapter()
+ curChapter.title = matcher.group()
+ curChapter.start = lastChapter.end
+ toc.add(curChapter)
+ } else { //如果章节不存在则创建章节
+ val curChapter = BookChapter()
+ curChapter.title = matcher.group()
+ curChapter.start = 0
+ curChapter.end = 0
+ toc.add(curChapter)
}
- //创建当前章节
- val curChapter = BookChapter()
- curChapter.title = matcher.group()
- curChapter.start = lastChapter?.end ?: 0
- toc.add(curChapter)
}
//设置指针偏移
seekPos += chapterContent.length
@@ -154,7 +181,8 @@ class AnalyzeTxtFile {
//block的偏移点
curOffset += length.toLong()
- if (rulePattern != null) { //设置上一章的结尾
+ if (rulePattern != null) {
+ //设置上一章的结尾
val lastChapter = toc.last()
lastChapter.end = curOffset
}
@@ -173,6 +201,7 @@ class AnalyzeTxtFile {
bean.url = (MD5Utils.md5Encode16(book.originName + i + bean.title) ?: "")
}
book.latestChapterTitle = toc.last().title
+ book.totalChapterNum = toc.size
System.gc()
System.runFinalization()
@@ -220,10 +249,9 @@ class AnalyzeTxtFile {
val bookFile = getBookFile(App.INSTANCE, book)
//获取文件流
val bookStream = RandomAccessFile(bookFile, "r")
- bookStream.seek(bookChapter.start ?: 0)
- val extent = (bookChapter.end!! - bookChapter.start!!).toInt()
- val content = ByteArray(extent)
- bookStream.read(content, 0, extent)
+ val content = ByteArray((bookChapter.end!! - bookChapter.start!!).toInt())
+ bookStream.seek(bookChapter.start!!)
+ bookStream.read(content)
return String(content, book.fileCharset())
}
diff --git a/app/src/main/java/io/legado/app/model/rss/RssParser.kt b/app/src/main/java/io/legado/app/model/rss/RssParser.kt
index 7bda16e6d..09cd756bb 100644
--- a/app/src/main/java/io/legado/app/model/rss/RssParser.kt
+++ b/app/src/main/java/io/legado/app/model/rss/RssParser.kt
@@ -11,7 +11,7 @@ import java.io.StringReader
object RssParser {
@Throws(XmlPullParserException::class, IOException::class)
- fun parseXML(xml: String, sourceUrl: String): Result {
+ fun parseXML(sortName: String, xml: String, sourceUrl: String): Result {
val articleList = mutableListOf()
var currentArticle = RssArticle()
@@ -87,6 +87,7 @@ object RssParser {
// The item is correctly parsed
insideItem = false
currentArticle.origin = sourceUrl
+ currentArticle.sort = sortName
articleList.add(currentArticle)
currentArticle = RssArticle()
}
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 b06950031..cd90b6b1d 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
@@ -13,7 +13,7 @@ import io.legado.app.utils.NetworkUtils
object RssParserByRule {
@Throws(Exception::class)
- fun parseXML(body: String?, rssSource: RssSource): Result {
+ fun parseXML(sortName: String, sortUrl: String, body: String?, rssSource: RssSource): Result {
val sourceUrl = rssSource.sourceUrl
var nextUrl: String? = null
if (body.isNullOrBlank()) {
@@ -28,11 +28,11 @@ object RssParserByRule {
var ruleArticles = rssSource.ruleArticles
if (ruleArticles.isNullOrBlank()) {
Debug.log(sourceUrl, "⇒列表规则为空, 使用默认规则解析")
- return RssParser.parseXML(body, sourceUrl)
+ return RssParser.parseXML(sortName, body, sourceUrl)
} else {
val articleList = mutableListOf()
val analyzeRule = AnalyzeRule()
- analyzeRule.setContent(body, rssSource.sourceUrl)
+ analyzeRule.setContent(body, sortUrl)
var reverse = false
if (ruleArticles.startsWith("-")) {
reverse = true
@@ -45,7 +45,7 @@ object RssParserByRule {
Debug.log(sourceUrl, "┌获取下一页链接")
nextUrl = analyzeRule.getString(rssSource.ruleNextPage)
if (nextUrl.isNotEmpty()) {
- nextUrl = NetworkUtils.getAbsoluteURL(sourceUrl, nextUrl)
+ nextUrl = NetworkUtils.getAbsoluteURL(sortUrl, nextUrl)
}
Debug.log(sourceUrl, "└$nextUrl")
}
@@ -59,7 +59,8 @@ object RssParserByRule {
sourceUrl, item, analyzeRule, index == 0,
ruleTitle, rulePubDate, ruleDescription, ruleImage, ruleLink
)?.let {
- it.origin = rssSource.sourceUrl
+ it.sort = sortName
+ it.origin = sourceUrl
articleList.add(it)
}
}
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 8559351f4..78a139345 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
@@ -193,6 +193,7 @@ object BookChapterList {
list.getOrNull(book.durChapterIndex)?.title ?: book.latestChapterTitle
if (book.totalChapterNum < list.size) {
book.lastCheckCount = list.size - book.totalChapterNum
+ book.latestChapterTime = System.currentTimeMillis()
}
book.totalChapterNum = list.size
return list
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 873b6b3a9..d83ffb832 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
@@ -101,6 +101,7 @@ object BookContent {
}
}
+ content.deleteCharAt(content.length - 1)
Debug.log(bookSource.bookSourceUrl, "┌获取章节名称")
Debug.log(bookSource.bookSourceUrl, "└${bookChapter.title}")
Debug.log(bookSource.bookSourceUrl, "┌获取正文内容")
diff --git a/app/src/main/java/io/legado/app/receiver/MediaButtonReceiver.kt b/app/src/main/java/io/legado/app/receiver/MediaButtonReceiver.kt
index 00c9d0522..fb1f5df59 100644
--- a/app/src/main/java/io/legado/app/receiver/MediaButtonReceiver.kt
+++ b/app/src/main/java/io/legado/app/receiver/MediaButtonReceiver.kt
@@ -8,9 +8,14 @@ import io.legado.app.App
import io.legado.app.constant.EventBus
import io.legado.app.data.entities.Book
import io.legado.app.help.ActivityHelp
+import io.legado.app.service.AudioPlayService
+import io.legado.app.service.BaseReadAloudService
+import io.legado.app.service.help.AudioPlay
+import io.legado.app.service.help.ReadAloud
import io.legado.app.ui.audio.AudioPlayActivity
import io.legado.app.ui.book.read.ReadBookActivity
import io.legado.app.ui.main.MainActivity
+import io.legado.app.utils.getPrefBoolean
import io.legado.app.utils.postEvent
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
@@ -50,11 +55,23 @@ class MediaButtonReceiver : BroadcastReceiver() {
private fun readAloud(context: Context) {
when {
+ BaseReadAloudService.isRun -> if (BaseReadAloudService.isPlay()) {
+ ReadAloud.pause(context)
+ AudioPlay.pause(context)
+ } else {
+ ReadAloud.resume(context)
+ AudioPlay.resume(context)
+ }
+ AudioPlayService.isRun -> if (AudioPlayService.pause) {
+ AudioPlay.resume(context)
+ } else {
+ AudioPlay.pause(context)
+ }
ActivityHelp.isExist(AudioPlayActivity::class.java) ->
postEvent(EventBus.MEDIA_BUTTON, true)
ActivityHelp.isExist(ReadBookActivity::class.java) ->
postEvent(EventBus.MEDIA_BUTTON, true)
- else -> {
+ else -> if (context.getPrefBoolean("mediaButtonOnExit", true)) {
GlobalScope.launch(Main) {
val lastBook: Book? = withContext(IO) {
App.db.bookDao().lastReadBook
diff --git a/app/src/main/java/io/legado/app/service/CheckSourceService.kt b/app/src/main/java/io/legado/app/service/CheckSourceService.kt
index 336dfb18d..8cbd80afd 100644
--- a/app/src/main/java/io/legado/app/service/CheckSourceService.kt
+++ b/app/src/main/java/io/legado/app/service/CheckSourceService.kt
@@ -7,20 +7,22 @@ import io.legado.app.R
import io.legado.app.base.BaseService
import io.legado.app.constant.AppConst
import io.legado.app.constant.IntentAction
+import io.legado.app.data.entities.BookSource
import io.legado.app.help.AppConfig
import io.legado.app.help.IntentHelp
-import io.legado.app.help.coroutine.Coroutine
+import io.legado.app.help.coroutine.CompositeCoroutine
import io.legado.app.model.WebBook
import io.legado.app.ui.book.source.manage.BookSourceActivity
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.asCoroutineDispatcher
import org.jetbrains.anko.toast
import java.util.concurrent.Executors
+import kotlin.math.min
class CheckSourceService : BaseService() {
private val threadCount = AppConfig.threadCount
private var searchPool = Executors.newFixedThreadPool(threadCount).asCoroutineDispatcher()
- private var task: Coroutine<*>? = null
+ private var tasks = CompositeCoroutine()
private val allIds = ArrayList()
private val checkedIds = ArrayList()
private var processIndex = 0
@@ -42,23 +44,23 @@ class CheckSourceService : BaseService() {
override fun onDestroy() {
super.onDestroy()
- task?.cancel()
+ tasks.clear()
searchPool.close()
}
private fun check(ids: List) {
- task?.cancel()
+ if (allIds.isNotEmpty()) {
+ toast("已有书源在校验,等完成后再试")
+ return
+ }
+ tasks.clear()
allIds.clear()
checkedIds.clear()
allIds.addAll(ids)
processIndex = 0
updateNotification(0, getString(R.string.progress_show, 0, allIds.size))
- task = execute {
- for (i in 0 until threadCount) {
- check()
- }
- }.onError {
- toast("校验书源出错:${it.localizedMessage}")
+ for (i in 0 until min(threadCount, allIds.size)) {
+ check()
}
}
@@ -67,27 +69,41 @@ class CheckSourceService : BaseService() {
synchronized(this) {
processIndex++
}
- if (processIndex < allIds.size) {
- val sourceUrl = allIds[processIndex]
- App.db.bookSourceDao().getBookSource(sourceUrl)?.let { source ->
- val webBook = WebBook(source)
- webBook.searchBook("我的", scope = this, context = searchPool)
- .onError(IO) {
- source.addGroup("失效")
- App.db.bookSourceDao().update(source)
- }.onFinally(IO) {
- check()
- checkedIds.add(sourceUrl)
- updateNotification(
- checkedIds.size,
- getString(R.string.progress_show, checkedIds.size, allIds.size)
- )
- synchronized(this) {
- if (processIndex >= allIds.size + threadCount - 1) {
- stopSelf()
- }
- }
+ execute {
+ if (processIndex < allIds.size) {
+ val sourceUrl = allIds[processIndex]
+ App.db.bookSourceDao().getBookSource(sourceUrl)?.let { source ->
+ if (source.searchUrl.isNullOrEmpty()) {
+ onNext(sourceUrl)
+ } else {
+ check(source)
}
+ } ?: onNext(sourceUrl)
+ }
+ }
+ }
+
+ private fun check(source: BookSource) {
+ val webBook = WebBook(source)
+ tasks.add(webBook.searchBook("我的", scope = this, context = searchPool)
+ .onError(IO) {
+ source.addGroup("失效")
+ App.db.bookSourceDao().update(source)
+ }.onFinally(IO) {
+ onNext(source.bookSourceUrl)
+ })
+ }
+
+ private fun onNext(sourceUrl: String) {
+ synchronized(this) {
+ check()
+ checkedIds.add(sourceUrl)
+ updateNotification(
+ checkedIds.size,
+ getString(R.string.progress_show, checkedIds.size, allIds.size)
+ )
+ if (processIndex >= allIds.size + min(threadCount, allIds.size) - 1) {
+ stopSelf()
}
}
}
diff --git a/app/src/main/java/io/legado/app/service/DownloadService.kt b/app/src/main/java/io/legado/app/service/DownloadService.kt
index dd48933e8..1cbfe44f4 100644
--- a/app/src/main/java/io/legado/app/service/DownloadService.kt
+++ b/app/src/main/java/io/legado/app/service/DownloadService.kt
@@ -13,6 +13,7 @@ import io.legado.app.data.entities.BookChapter
import io.legado.app.help.AppConfig
import io.legado.app.help.BookHelp
import io.legado.app.help.IntentHelp
+import io.legado.app.help.coroutine.CompositeCoroutine
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.model.WebBook
import io.legado.app.utils.postEvent
@@ -25,7 +26,7 @@ import java.util.concurrent.Executors
class DownloadService : BaseService() {
private var searchPool =
Executors.newFixedThreadPool(AppConfig.threadCount).asCoroutineDispatcher()
- private var tasks: ArrayList> = arrayListOf()
+ private var tasks = CompositeCoroutine()
private val handler = Handler()
private var runnable: Runnable = Runnable { upDownload() }
private val downloadMap = hashMapOf>()
@@ -125,11 +126,7 @@ class DownloadService : BaseService() {
chapter,
scope = this,
context = searchPool
- )
- //.onStart {
- // notificationContent = "启动:" + chapter.title
- //}
- .onSuccess(IO) { content ->
+ ).onSuccess(IO) { content ->
downloadCount[entry.key]?.increaseSuccess()
BookHelp.saveContent(book, chapter, content)
}
@@ -165,7 +162,7 @@ class DownloadService : BaseService() {
tasks.add(task)
task.invokeOnCompletion {
tasks.remove(task)
- if (tasks.isEmpty()) {
+ if (tasks.isEmpty) {
stopSelf()
}
}
@@ -192,17 +189,21 @@ class DownloadService : BaseService() {
val notification = builder.build()
startForeground(AppConst.notificationIdDownload, notification)
}
-}
-class DownloadCount{
- @Volatile public var downloadFinishedCount = 0 // 下载完成的条目数量
- @Volatile public var successCount = 0 //下载成功的条目数量
- fun increaseSuccess(){
- ++successCount;
- }
+ class DownloadCount {
+ @Volatile
+ var downloadFinishedCount = 0 // 下载完成的条目数量
+
+ @Volatile
+ var successCount = 0 //下载成功的条目数量
- fun increaseFinished(){
- ++downloadFinishedCount;
+ fun increaseSuccess() {
+ ++successCount;
+ }
+
+ fun increaseFinished() {
+ ++downloadFinishedCount;
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/service/help/ReadBook.kt b/app/src/main/java/io/legado/app/service/help/ReadBook.kt
index f48f13d11..89f730ae5 100644
--- a/app/src/main/java/io/legado/app/service/help/ReadBook.kt
+++ b/app/src/main/java/io/legado/app/service/help/ReadBook.kt
@@ -331,7 +331,7 @@ object ReadBook {
book.durChapterTime = System.currentTimeMillis()
book.durChapterIndex = durChapterIndex
book.durChapterPos = durPageIndex
- curTextChapter?.let {
+ App.db.bookChapterDao().getChapter(book.bookUrl, durChapterIndex)?.let {
book.durChapterTitle = it.title
}
App.db.bookDao().update(book)
diff --git a/app/src/main/java/io/legado/app/ui/about/AboutFragment.kt b/app/src/main/java/io/legado/app/ui/about/AboutFragment.kt
index 365381fbd..3b56737cf 100644
--- a/app/src/main/java/io/legado/app/ui/about/AboutFragment.kt
+++ b/app/src/main/java/io/legado/app/ui/about/AboutFragment.kt
@@ -22,6 +22,7 @@ class AboutFragment : PreferenceFragmentCompat() {
private val qqGroups = linkedMapOf(
Pair("(QQ群VIP1)701903217", "-iolizL4cbJSutKRpeImHlXlpLDZnzeF"),
Pair("(QQ群VIP2)263949160", "xwfh7_csb2Gf3Aw2qexEcEtviLfLfd4L"),
+ Pair("(QQ群VIP3)680280282", "_N0i7yZObjKSeZQvzoe2ej7j02kLnOOK"),
Pair("(QQ群1)805192012", "6GlFKjLeIk5RhQnR3PNVDaKB6j10royo"),
Pair("(QQ群2)773736122", "5Bm5w6OgLupXnICbYvbgzpPUgf0UlsJF"),
Pair("(QQ群3)981838750", "g_Sgmp2nQPKqcZQ5qPcKLHziwX_mpps9"),
diff --git a/app/src/main/java/io/legado/app/ui/audio/AudioPlayViewModel.kt b/app/src/main/java/io/legado/app/ui/audio/AudioPlayViewModel.kt
index 8f0cd9fa4..124fd710f 100644
--- a/app/src/main/java/io/legado/app/ui/audio/AudioPlayViewModel.kt
+++ b/app/src/main/java/io/legado/app/ui/audio/AudioPlayViewModel.kt
@@ -11,7 +11,6 @@ import io.legado.app.help.BookHelp
import io.legado.app.model.WebBook
import io.legado.app.service.help.AudioPlay
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
class AudioPlayViewModel(application: Application) : BaseViewModel(application) {
@@ -93,9 +92,6 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application)
AudioPlay.book?.let {
book1.order = it.order
App.db.bookDao().delete(it)
- }
- withContext(Dispatchers.Main) {
-
}
App.db.bookDao().insert(book1)
AudioPlay.book = book1
diff --git a/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt
index e7d78a6f4..491922cb1 100644
--- a/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt
+++ b/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt
@@ -11,6 +11,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
+import io.legado.app.constant.AppConst
import io.legado.app.constant.PreferKey
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookGroup
@@ -105,10 +106,10 @@ class ArrangeBookActivity : VMBaseActivity(R.layout.activi
booksLiveData?.removeObservers(this)
booksLiveData =
when (groupId) {
- -1 -> App.db.bookDao().observeAll()
- -2 -> App.db.bookDao().observeLocal()
- -3 -> App.db.bookDao().observeAudio()
- -11 -> App.db.bookDao().observeNoGroup()
+ AppConst.bookGroupAll.groupId -> App.db.bookDao().observeAll()
+ AppConst.bookGroupLocal.groupId -> App.db.bookDao().observeLocal()
+ AppConst.bookGroupAudio.groupId -> App.db.bookDao().observeAudio()
+ AppConst.bookGroupNone.groupId -> App.db.bookDao().observeNoGroup()
else -> App.db.bookDao().observeByGroup(groupId)
}
booksLiveData?.observe(this, Observer { list ->
@@ -129,22 +130,22 @@ class ArrangeBookActivity : VMBaseActivity(R.layout.activi
.show(supportFragmentManager, "groupManage")
R.id.menu_no_group -> {
title_bar.subtitle = getString(R.string.no_group)
- groupId = -11
+ groupId = AppConst.bookGroupNone.groupId
initBookData()
}
R.id.menu_all -> {
title_bar.subtitle = item.title
- groupId = -1
+ groupId = AppConst.bookGroupAll.groupId
initBookData()
}
R.id.menu_local -> {
title_bar.subtitle = item.title
- groupId = -2
+ groupId = AppConst.bookGroupLocal.groupId
initBookData()
}
R.id.menu_audio -> {
title_bar.subtitle = item.title
- groupId = -3
+ groupId = AppConst.bookGroupAudio.groupId
initBookData()
}
else -> if (item.groupId == R.id.menu_group) {
diff --git a/app/src/main/java/io/legado/app/ui/book/chapterlist/ChapterListFragment.kt b/app/src/main/java/io/legado/app/ui/book/chapterlist/ChapterListFragment.kt
index d717cb25f..104f78e23 100644
--- a/app/src/main/java/io/legado/app/ui/book/chapterlist/ChapterListFragment.kt
+++ b/app/src/main/java/io/legado/app/ui/book/chapterlist/ChapterListFragment.kt
@@ -1,5 +1,6 @@
package io.legado.app.ui.book.chapterlist
+import android.annotation.SuppressLint
import android.app.Activity.RESULT_OK
import android.content.Intent
import android.os.Bundle
@@ -13,7 +14,7 @@ import io.legado.app.constant.EventBus
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter
import io.legado.app.help.BookHelp
-import io.legado.app.lib.theme.backgroundColor
+import io.legado.app.lib.theme.bottomBackground
import io.legado.app.ui.widget.recycler.UpLinearLayoutManager
import io.legado.app.ui.widget.recycler.VerticalDivider
import io.legado.app.utils.getViewModelOfActivity
@@ -54,7 +55,7 @@ class ChapterListFragment : VMBaseFragment(R.layout.fragme
}
private fun initView() {
- ll_chapter_base_info.setBackgroundColor(backgroundColor)
+ ll_chapter_base_info.setBackgroundColor(bottomBackground)
iv_chapter_top.onClick { mLayoutManager.scrollToPositionWithOffset(0, 0) }
iv_chapter_bottom.onClick {
if (adapter.itemCount > 0) {
@@ -66,6 +67,7 @@ class ChapterListFragment : VMBaseFragment(R.layout.fragme
}
}
+ @SuppressLint("SetTextI18n")
private fun initBook() {
launch {
withContext(IO) {
@@ -74,7 +76,8 @@ class ChapterListFragment : VMBaseFragment(R.layout.fragme
initDoc()
book?.let {
durChapterIndex = it.durChapterIndex
- tv_current_chapter_info.text = it.durChapterTitle
+ tv_current_chapter_info.text =
+ "${it.durChapterTitle}(${it.durChapterIndex + 1}/${it.totalChapterNum})"
initCacheFileNames(it)
}
}
diff --git a/app/src/main/java/io/legado/app/ui/book/group/GroupManageDialog.kt b/app/src/main/java/io/legado/app/ui/book/group/GroupManageDialog.kt
index 60010f46d..a5d719b57 100644
--- a/app/src/main/java/io/legado/app/ui/book/group/GroupManageDialog.kt
+++ b/app/src/main/java/io/legado/app/ui/book/group/GroupManageDialog.kt
@@ -99,6 +99,8 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener {
.isChecked = AppConfig.bookGroupLocalShow
it.findItem(R.id.menu_group_audio)
.isChecked = AppConfig.bookGroupAudioShow
+ it.findItem(R.id.menu_group_none)
+ .isChecked = AppConfig.bookGroupNoneShow
}
}
@@ -120,6 +122,10 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener {
AppConfig.bookGroupAudioShow = item.isChecked
callBack?.upGroup()
}
+ R.id.menu_group_none -> {
+ item.isChecked = !item.isChecked
+ AppConfig.bookGroupNoneShow = item.isChecked
+ }
}
return true
}
diff --git a/app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt b/app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt
index 29df624e7..9440a7c46 100644
--- a/app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt
+++ b/app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt
@@ -94,8 +94,7 @@ class GroupSelectDialog : DialogFragment(), Toolbar.OnMenuItemClickListener {
tool_bar.inflateMenu(R.menu.book_group_manage)
tool_bar.menu.applyTint(requireContext(), Theme.getTheme())
tool_bar.setOnMenuItemClickListener(this)
- tool_bar.menu.findItem(R.id.menu_group_local).isVisible = false
- tool_bar.menu.findItem(R.id.menu_group_audio).isVisible = false
+ tool_bar.menu.setGroupVisible(R.id.menu_groups, false)
adapter = GroupAdapter(requireContext())
recycler_view.layoutManager = LinearLayoutManager(requireContext())
recycler_view.addItemDecoration(VerticalDivider(requireContext()))
diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt
index ba83c10ef..47dc6c33f 100644
--- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt
+++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt
@@ -112,6 +112,8 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
toast(R.string.error_no_source)
}
}
+ }.onError {
+ toast("LoadTocError:${it.localizedMessage}")
}
}
@@ -156,8 +158,10 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
chapters
)
book.durChapterTitle = chapters[book.durChapterIndex].title
- App.db.bookDao().insert(book)
- App.db.bookChapterDao().insert(*chapters.toTypedArray())
+ if (inBookshelf) {
+ App.db.bookDao().insert(book)
+ App.db.bookChapterDao().insert(*chapters.toTypedArray())
+ }
bookData.postValue(book)
chapterListData.postValue(chapters)
}
@@ -169,6 +173,10 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
if (book.order == 0) {
book.order = App.db.bookDao().maxOrder + 1
}
+ App.db.bookDao().getBook(book.name, book.author)?.let {
+ book.durChapterPos = it.durChapterPos
+ book.durChapterTitle = it.durChapterTitle
+ }
App.db.bookDao().insert(book)
}
}.onSuccess {
@@ -192,6 +200,10 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
if (book.order == 0) {
book.order = App.db.bookDao().maxOrder + 1
}
+ App.db.bookDao().getBook(book.name, book.author)?.let {
+ book.durChapterPos = it.durChapterPos
+ book.durChapterTitle = it.durChapterTitle
+ }
App.db.bookDao().insert(book)
}
chapterListData.value?.let {
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 043c419eb..43d03c332 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
@@ -134,6 +134,10 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo
timeBatteryReceiver = null
}
upSystemUiVisibility()
+ if (!BuildConfig.DEBUG) {
+ SyncBookProgress.uploadBookProgress()
+ Backup.autoBack(this)
+ }
}
/**
@@ -225,6 +229,7 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo
R.id.menu_copy_text ->
TextDialog.show(supportFragmentManager, ReadBook.curTextChapter?.getContent())
R.id.menu_update_toc -> ReadBook.book?.let {
+ ReadBook.upMsg(getString(R.string.toc_updateing))
viewModel.loadChapterList(it)
}
R.id.menu_enable_replace -> ReadBook.book?.let {
@@ -705,6 +710,7 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo
observeEvent(EventBus.UP_CONFIG) {
upSystemUiVisibility()
page_view.upBg()
+ page_view.upTipStyle()
page_view.upStyle()
if (it) {
ReadBook.loadContent(resetPageOffset = false)
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 977a65a10..cc129056a 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
@@ -107,6 +107,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
App.db.bookChapterDao().insert(*it.toTypedArray())
App.db.bookDao().update(book)
ReadBook.chapterSize = it.size
+ ReadBook.upMsg(null)
ReadBook.loadContent(resetPageOffset = true)
}
} else {
@@ -129,6 +130,8 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
ReadBook.upMsg(context.getString(R.string.error_load_toc))
}
}
+ }.onError {
+ ReadBook.upMsg("LoadTocError:${it.localizedMessage}")
}
}
@@ -175,7 +178,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
}
}
}.onStart {
- ReadBook.upMsg("正在自动换源")
+ ReadBook.upMsg(context.getString(R.string.source_auto_changing))
}.onFinally {
ReadBook.upMsg(null)
}
diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/MoreConfigDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/MoreConfigDialog.kt
index a23725143..8672d04bb 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/config/MoreConfigDialog.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/config/MoreConfigDialog.kt
@@ -94,6 +94,7 @@ class MoreConfigDialog : DialogFragment() {
key: String?
) {
when (key) {
+ PreferKey.readBodyToLh -> activity?.recreate()
PreferKey.hideStatusBar -> {
ReadBookConfig.hideStatusBar = getPrefBoolean(PreferKey.hideStatusBar)
postEvent(EventBus.UP_CONFIG, true)
diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/PaddingConfigDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/PaddingConfigDialog.kt
index ed1c296de..4534898e4 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/config/PaddingConfigDialog.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/config/PaddingConfigDialog.kt
@@ -11,10 +11,7 @@ import io.legado.app.R
import io.legado.app.constant.EventBus
import io.legado.app.help.ReadBookConfig
import io.legado.app.ui.book.read.Help
-import io.legado.app.utils.dp
-import io.legado.app.utils.gone
import io.legado.app.utils.postEvent
-import io.legado.app.utils.visible
import kotlinx.android.synthetic.main.dialog_read_padding.*
class PaddingConfigDialog : DialogFragment() {
@@ -54,13 +51,6 @@ class PaddingConfigDialog : DialogFragment() {
}
private fun initData() = ReadBookConfig.apply {
- if (hideStatusBar) {
- ll_header_padding.visible()
- tv_body_padding.setPadding(0, 10.dp, 0, 10.dp)
- } else {
- ll_header_padding.gone()
- tv_body_padding.setPadding(0, 0.dp, 0, 10.dp)
- }
//正文
dsb_padding_top.progress = paddingTop
dsb_padding_bottom.progress = paddingBottom
diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt
index f29c4ddba..19cad6738 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt
@@ -104,10 +104,8 @@ class ReadStyleDialog : DialogFragment(), FontSelectDialog.CallBack {
showTitleConfig()
}
tv_text_bold.onClick {
- ReadBookConfig.apply {
- textBold = !textBold
- tv_text_bold.isSelected = textBold
- }
+ ReadBookConfig.textBold = !ReadBookConfig.textBold
+ tv_text_bold.isSelected = ReadBookConfig.textBold
postEvent(EventBus.UP_CONFIG, true)
}
tv_text_font.onClick {
@@ -126,6 +124,9 @@ class ReadStyleDialog : DialogFragment(), FontSelectDialog.CallBack {
dismiss()
callBack?.showPaddingConfig()
}
+ tv_tip.onClick {
+ TipConfigDialog().show(childFragmentManager, "tipConfigDialog")
+ }
rg_page_anim.onCheckedChange { _, checkedId ->
ReadBookConfig.pageAnim = rg_page_anim.getIndexById(checkedId)
callBack?.page_view?.upPageAnim()
diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/TipConfigDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/TipConfigDialog.kt
new file mode 100644
index 000000000..cb9cfa594
--- /dev/null
+++ b/app/src/main/java/io/legado/app/ui/book/read/config/TipConfigDialog.kt
@@ -0,0 +1,117 @@
+package io.legado.app.ui.book.read.config
+
+import android.os.Bundle
+import android.util.DisplayMetrics
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import io.legado.app.R
+import io.legado.app.base.BaseDialogFragment
+import io.legado.app.constant.EventBus
+import io.legado.app.help.ReadTipConfig
+import io.legado.app.lib.dialogs.selector
+import io.legado.app.ui.book.read.Help
+import io.legado.app.utils.postEvent
+import kotlinx.android.synthetic.main.dialog_tip_config.*
+import org.jetbrains.anko.sdk27.listeners.onCheckedChange
+import org.jetbrains.anko.sdk27.listeners.onClick
+
+class TipConfigDialog : BaseDialogFragment() {
+
+ override fun onStart() {
+ super.onStart()
+ val dm = DisplayMetrics()
+ activity?.let {
+ Help.upSystemUiVisibility(it)
+ it.windowManager?.defaultDisplay?.getMetrics(dm)
+ }
+ dialog?.window?.let {
+ val attr = it.attributes
+ attr.dimAmount = 0.0f
+ it.attributes = attr
+ it.setLayout((dm.widthPixels * 0.9).toInt(), ViewGroup.LayoutParams.WRAP_CONTENT)
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ return inflater.inflate(R.layout.dialog_tip_config, container)
+ }
+
+ override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
+ initView()
+ initEvent()
+ }
+
+ private fun initView() {
+ tv_header_left.text = ReadTipConfig.tipHeaderLeftStr
+ tv_header_middle.text = ReadTipConfig.tipHeaderMiddleStr
+ tv_header_right.text = ReadTipConfig.tipHeaderRightStr
+ tv_footer_left.text = ReadTipConfig.tipFooterLeftStr
+ tv_footer_middle.text = ReadTipConfig.tipFooterMiddleStr
+ tv_footer_right.text = ReadTipConfig.tipFooterRightStr
+ sw_hide_header.isChecked = ReadTipConfig.hideHeader
+ sw_hide_footer.isChecked = ReadTipConfig.hideFooter
+ }
+
+ private fun initEvent() {
+ tv_header_left.onClick {
+ selector(items = ReadTipConfig.tipArray.toList()) { _, i ->
+ ReadTipConfig.tipHeaderLeft = i
+ tv_header_left.text = ReadTipConfig.tipArray[i]
+ postEvent(EventBus.UP_CONFIG, true)
+ }
+ }
+ tv_header_middle.onClick {
+ selector(items = ReadTipConfig.tipArray.toList()) { _, i ->
+ ReadTipConfig.tipHeaderMiddle = i
+ tv_header_middle.text = ReadTipConfig.tipArray[i]
+ postEvent(EventBus.UP_CONFIG, true)
+ }
+ }
+ tv_header_right.onClick {
+ selector(items = ReadTipConfig.tipArray.toList()) { _, i ->
+ ReadTipConfig.tipHeaderRight = i
+ tv_header_right.text = ReadTipConfig.tipArray[i]
+ postEvent(EventBus.UP_CONFIG, true)
+ }
+ }
+ tv_footer_left.onClick {
+ selector(items = ReadTipConfig.tipArray.toList()) { _, i ->
+ ReadTipConfig.tipFooterLeft = i
+ tv_footer_left.text = ReadTipConfig.tipArray[i]
+ postEvent(EventBus.UP_CONFIG, true)
+ }
+ }
+ tv_footer_middle.onClick {
+ selector(items = ReadTipConfig.tipArray.toList()) { _, i ->
+ ReadTipConfig.tipFooterMiddle = i
+ tv_footer_middle.text = ReadTipConfig.tipArray[i]
+ postEvent(EventBus.UP_CONFIG, true)
+ }
+ }
+ tv_footer_right.onClick {
+ selector(items = ReadTipConfig.tipArray.toList()) { _, i ->
+ ReadTipConfig.tipFooterRight = i
+ tv_footer_right.text = ReadTipConfig.tipArray[i]
+ postEvent(EventBus.UP_CONFIG, true)
+ }
+ }
+ sw_hide_header.onCheckedChange { buttonView, isChecked ->
+ if (buttonView?.isPressed == true) {
+ ReadTipConfig.hideHeader = isChecked
+ postEvent(EventBus.UP_CONFIG, true)
+ }
+ }
+ sw_hide_footer.onCheckedChange { buttonView, isChecked ->
+ if (buttonView?.isPressed == true) {
+ ReadTipConfig.hideFooter = isChecked
+ postEvent(EventBus.UP_CONFIG, true)
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/ChapterProvider.kt b/app/src/main/java/io/legado/app/ui/book/read/page/ChapterProvider.kt
index 0d6a0009e..ea0a1bd37 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/page/ChapterProvider.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/page/ChapterProvider.kt
@@ -1,6 +1,7 @@
package io.legado.app.ui.book.read.page
import android.graphics.Typeface
+import android.os.Build
import android.text.Layout
import android.text.StaticLayout
import android.text.TextPaint
@@ -31,8 +32,8 @@ object ChapterProvider {
private var titleTopSpacing = 0
private var titleBottomSpacing = 0
var typeface: Typeface = Typeface.SANS_SERIF
- var titlePaint = TextPaint()
- var contentPaint = TextPaint()
+ lateinit var titlePaint: TextPaint
+ lateinit var contentPaint: TextPaint
init {
upStyle()
@@ -262,30 +263,36 @@ object ChapterProvider {
Typeface.SANS_SERIF
}
//标题
- titlePaint.isAntiAlias = true
+ titlePaint = TextPaint()
titlePaint.color = ReadBookConfig.durConfig.textColor()
titlePaint.letterSpacing = ReadBookConfig.letterSpacing
- titlePaint.typeface = Typeface.create(typeface, Typeface.BOLD)
+ titlePaint.typeface = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ Typeface.create(typeface, if (ReadBookConfig.textBold) 900 else 700, false)
+ } else {
+ Typeface.create(typeface, Typeface.BOLD)
+ }
titlePaint.textSize = with(ReadBookConfig) { textSize + titleSize }.sp.toFloat()
+ titlePaint.isAntiAlias = true
//正文
- contentPaint.isAntiAlias = true
+ contentPaint = TextPaint()
contentPaint.color = ReadBookConfig.durConfig.textColor()
contentPaint.letterSpacing = ReadBookConfig.letterSpacing
val style = if (ReadBookConfig.textBold) Typeface.BOLD else Typeface.NORMAL
contentPaint.typeface = Typeface.create(typeface, style)
contentPaint.textSize = ReadBookConfig.textSize.sp.toFloat()
+ contentPaint.isAntiAlias = true
//间距
lineSpacingExtra = ReadBookConfig.lineSpacingExtra
paragraphSpacing = ReadBookConfig.paragraphSpacing
titleTopSpacing = ReadBookConfig.titleTopSpacing.dp
titleBottomSpacing = ReadBookConfig.titleBottomSpacing.dp
- upSize()
+ upViewSize()
}
/**
* 更新View尺寸
*/
- fun upSize() {
+ fun upViewSize() {
paddingLeft = ReadBookConfig.paddingLeft.dp
paddingTop = ReadBookConfig.paddingTop.dp
visibleWidth = viewWidth - paddingLeft - ReadBookConfig.paddingRight.dp
diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt
index 53f03462f..62f240303 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt
@@ -61,7 +61,7 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
super.onSizeChanged(w, h, oldw, oldh)
ChapterProvider.viewWidth = w
ChapterProvider.viewHeight = h
- ChapterProvider.upSize()
+ ChapterProvider.upViewSize()
upVisibleRect()
textPage.format()
}
diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt
index d87311f09..67e40bf0e 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt
@@ -5,13 +5,20 @@ import android.content.Context
import android.graphics.drawable.Drawable
import android.view.MotionEvent
import android.widget.FrameLayout
-import com.github.houbb.opencc4j.core.impl.ZhConvertBootstrap
+import androidx.core.view.isGone
+import androidx.core.view.isInvisible
+import com.hankcs.hanlp.HanLP
import io.legado.app.R
import io.legado.app.constant.AppConst.timeFormat
import io.legado.app.help.AppConfig
import io.legado.app.help.ReadBookConfig
+import io.legado.app.help.ReadTipConfig
import io.legado.app.ui.book.read.page.entities.TextPage
-import io.legado.app.utils.*
+import io.legado.app.ui.widget.BatteryView
+import io.legado.app.utils.dp
+import io.legado.app.utils.getCompatColor
+import io.legado.app.utils.statusBarHeight
+import io.legado.app.utils.visible
import kotlinx.android.synthetic.main.view_book_page.view.*
import java.util.*
@@ -19,14 +26,22 @@ import java.util.*
class ContentView(context: Context) : FrameLayout(context) {
private var battery = 100
+ private var tvTitle: BatteryView? = null
+ private var tvTime: BatteryView? = null
+ private var tvBattery: BatteryView? = null
+ private var tvPage: BatteryView? = null
+ private var tvTotalProgress: BatteryView? = null
+ private var tvPageAndTotal: BatteryView? = null
+
+ val headerHeight: Int
+ get() = if (ReadBookConfig.hideStatusBar) ll_header.height else context.statusBarHeight
init {
//设置背景防止切换背景时文字重叠
setBackgroundColor(context.getCompatColor(R.color.background))
inflate(context, R.layout.view_book_page, this)
-
+ upTipStyle()
upStyle()
- upTime()
content_text_view.upView = {
setProgress(it)
}
@@ -34,25 +49,27 @@ class ContentView(context: Context) : FrameLayout(context) {
fun upStyle() {
ReadBookConfig.apply {
- tv_top_left.typeface = ChapterProvider.typeface
- tv_top_right.typeface = ChapterProvider.typeface
- tv_bottom_left.typeface = ChapterProvider.typeface
- tv_bottom_right.typeface = ChapterProvider.typeface
- battery_view.typeface = ChapterProvider.typeface
+ tv_header_left.typeface = ChapterProvider.typeface
+ tv_header_middle.typeface = ChapterProvider.typeface
+ tv_header_right.typeface = ChapterProvider.typeface
+ tv_footer_left.typeface = ChapterProvider.typeface
+ tv_footer_middle.typeface = ChapterProvider.typeface
+ tv_footer_right.typeface = ChapterProvider.typeface
+ tv_header_left.setColor(durConfig.textColor())
+ tv_header_middle.setColor(durConfig.textColor())
+ tv_header_right.setColor(durConfig.textColor())
+ tv_footer_left.setColor(durConfig.textColor())
+ tv_footer_middle.setColor(durConfig.textColor())
+ tv_footer_right.setColor(durConfig.textColor())
//显示状态栏时隐藏header
- if (hideStatusBar) {
- ll_header.setPadding(
- headerPaddingLeft.dp,
- headerPaddingTop.dp,
- headerPaddingRight.dp,
- headerPaddingBottom.dp
- )
- ll_header.visible()
- page_panel.setPadding(0, 0, 0, 0)
- } else {
- ll_header.gone()
- page_panel.setPadding(0, context.statusBarHeight, 0, 0)
- }
+ vw_status_bar.setPadding(0, context.statusBarHeight, 0, 0)
+ vw_status_bar.isGone = hideStatusBar
+ ll_header.setPadding(
+ headerPaddingLeft.dp,
+ headerPaddingTop.dp,
+ headerPaddingRight.dp,
+ headerPaddingBottom.dp
+ )
ll_footer.setPadding(
footerPaddingLeft.dp,
footerPaddingTop.dp,
@@ -62,47 +79,119 @@ class ContentView(context: Context) : FrameLayout(context) {
vw_top_divider.visible(showHeaderLine)
vw_bottom_divider.visible(showFooterLine)
content_text_view.upVisibleRect()
- durConfig.textColor().let {
- tv_top_left.setTextColor(it)
- tv_top_right.setTextColor(it)
- tv_bottom_left.setTextColor(it)
- tv_bottom_right.setTextColor(it)
- battery_view.setColor(it)
- }
- if (hideStatusBar) {
- tv_bottom_left.text = timeFormat.format(Date(System.currentTimeMillis()))
- battery_view.visible()
- battery_view.setBattery(battery)
- } else {
- battery_view.gone()
- }
}
+ upTime()
+ upBattery(battery)
}
- val headerHeight: Int
- get() {
- return if (ReadBookConfig.hideStatusBar) {
- ll_header.height
- } else {
- context.statusBarHeight
- }
+ fun upTipStyle() {
+ ReadTipConfig.apply {
+ val tipHeaderLeftNone = tipHeaderLeft == none
+ val tipHeaderRightNone = tipHeaderRight == none
+ val tipHeaderMiddleNone = tipHeaderMiddle == none
+ val tipFooterLeftNone = tipFooterLeft == none
+ val tipFooterRightNone = tipFooterRight == none
+ val tipFooterMiddleNone = tipFooterMiddle == none
+ tv_header_left.isInvisible = tipHeaderLeftNone
+ tv_header_right.isGone = tipHeaderRightNone
+ tv_header_middle.isGone = tipHeaderMiddleNone
+ tv_footer_left.isInvisible = tipFooterLeftNone
+ tv_footer_right.isGone = tipFooterRightNone
+ tv_footer_middle.isGone = tipFooterMiddleNone
+ ll_header.isGone = hideHeader
+ ll_footer.isGone = hideFooter
+ }
+ tvTitle = when (ReadTipConfig.chapterTitle) {
+ ReadTipConfig.tipHeaderLeft -> tv_header_left
+ ReadTipConfig.tipHeaderMiddle -> tv_header_middle
+ ReadTipConfig.tipHeaderRight -> tv_header_right
+ ReadTipConfig.tipFooterLeft -> tv_footer_left
+ ReadTipConfig.tipFooterMiddle -> tv_footer_middle
+ ReadTipConfig.tipFooterRight -> tv_footer_right
+ else -> null
+ }
+ tvTitle?.apply {
+ isBattery = false
+ textSize = 12f
+ }
+ tvTime = when (ReadTipConfig.time) {
+ ReadTipConfig.tipHeaderLeft -> tv_header_left
+ ReadTipConfig.tipHeaderMiddle -> tv_header_middle
+ ReadTipConfig.tipHeaderRight -> tv_header_right
+ ReadTipConfig.tipFooterLeft -> tv_footer_left
+ ReadTipConfig.tipFooterMiddle -> tv_footer_middle
+ ReadTipConfig.tipFooterRight -> tv_footer_right
+ else -> null
+ }
+ tvTime?.apply {
+ isBattery = false
+ textSize = 12f
+ }
+ tvBattery = when (ReadTipConfig.battery) {
+ ReadTipConfig.tipHeaderLeft -> tv_header_left
+ ReadTipConfig.tipHeaderMiddle -> tv_header_middle
+ ReadTipConfig.tipHeaderRight -> tv_header_right
+ ReadTipConfig.tipFooterLeft -> tv_footer_left
+ ReadTipConfig.tipFooterMiddle -> tv_footer_middle
+ ReadTipConfig.tipFooterRight -> tv_footer_right
+ else -> null
}
+ tvBattery?.apply {
+ isBattery = true
+ textSize = 10f
+ }
+ tvPage = when (ReadTipConfig.page) {
+ ReadTipConfig.tipHeaderLeft -> tv_header_left
+ ReadTipConfig.tipHeaderMiddle -> tv_header_middle
+ ReadTipConfig.tipHeaderRight -> tv_header_right
+ ReadTipConfig.tipFooterLeft -> tv_footer_left
+ ReadTipConfig.tipFooterMiddle -> tv_footer_middle
+ ReadTipConfig.tipFooterRight -> tv_footer_right
+ else -> null
+ }
+ tvPage?.apply {
+ isBattery = false
+ textSize = 12f
+ }
+ tvTotalProgress = when (ReadTipConfig.totalProgress) {
+ ReadTipConfig.tipHeaderLeft -> tv_header_left
+ ReadTipConfig.tipHeaderMiddle -> tv_header_middle
+ ReadTipConfig.tipHeaderRight -> tv_header_right
+ ReadTipConfig.tipFooterLeft -> tv_footer_left
+ ReadTipConfig.tipFooterMiddle -> tv_footer_middle
+ ReadTipConfig.tipFooterRight -> tv_footer_right
+ else -> null
+ }
+ tvTotalProgress?.apply {
+ isBattery = false
+ textSize = 12f
+ }
+ tvPageAndTotal = when (ReadTipConfig.pageAndTotal) {
+ ReadTipConfig.tipHeaderLeft -> tv_header_left
+ ReadTipConfig.tipHeaderMiddle -> tv_header_middle
+ ReadTipConfig.tipHeaderRight -> tv_header_right
+ ReadTipConfig.tipFooterLeft -> tv_footer_left
+ ReadTipConfig.tipFooterMiddle -> tv_footer_middle
+ ReadTipConfig.tipFooterRight -> tv_footer_right
+ else -> null
+ }
+ tvPageAndTotal?.apply {
+ isBattery = false
+ textSize = 12f
+ }
+ }
fun setBg(bg: Drawable?) {
page_panel.background = bg
}
fun upTime() {
- if (ReadBookConfig.hideStatusBar) {
- tv_bottom_right.text = timeFormat.format(Date(System.currentTimeMillis()))
- }
+ tvTime?.text = timeFormat.format(Date(System.currentTimeMillis()))
}
fun upBattery(battery: Int) {
this.battery = battery
- if (ReadBookConfig.hideStatusBar) {
- battery_view.setBattery(battery)
- }
+ tvBattery?.setBattery(battery)
}
fun setContent(textPage: TextPage, resetPageOffset: Boolean = true) {
@@ -119,18 +208,14 @@ class ContentView(context: Context) : FrameLayout(context) {
@SuppressLint("SetTextI18n")
fun setProgress(textPage: TextPage) = textPage.apply {
val title = when (AppConfig.chineseConverterType) {
- 1 -> ZhConvertBootstrap.newInstance().toSimple(textPage.title)
- 2 -> ZhConvertBootstrap.newInstance().toTraditional(textPage.title)
+ 1 -> HanLP.convertToSimplifiedChinese(textPage.title)
+ 2 -> HanLP.convertToTraditionalChinese(textPage.title)
else -> textPage.title
}
- if (ReadBookConfig.hideStatusBar) {
- tv_top_left.text = title
- tv_top_right.text = readProgress
- tv_bottom_left.text = "${index.plus(1)}/$pageSize"
- } else {
- tv_bottom_left.text = title
- tv_bottom_right.text = "${index.plus(1)}/$pageSize $readProgress"
- }
+ tvTitle?.text = title
+ tvPage?.text = "${index.plus(1)}/$pageSize"
+ tvTotalProgress?.text = readProgress
+ tvPageAndTotal?.text = "${index.plus(1)}/$pageSize $readProgress"
}
fun onScroll(offset: Float) {
diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt
index dd19fdc0e..3a996bfe9 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt
@@ -110,6 +110,12 @@ class PageView(context: Context, attrs: AttributeSet) :
callBack.screenOffTimerStart()
}
+ fun upTipStyle() {
+ curPage.upTipStyle()
+ prevPage.upTipStyle()
+ nextPage.upTipStyle()
+ }
+
fun upStyle() {
ChapterProvider.upStyle()
curPage.upStyle()
diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt b/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt
index 2fcf2f7e2..e81af6986 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt
@@ -44,12 +44,11 @@ data class TextPage(
if (y < 0) y = 0f
for (lineIndex in 0 until layout.lineCount) {
val textLine = TextLine()
- textLine.lineTop = (ChapterProvider.paddingTop + y -
- (layout.getLineBottom(lineIndex) - layout.getLineTop(lineIndex)))
- textLine.lineBase = (ChapterProvider.paddingTop + y -
- (layout.getLineBottom(lineIndex) - layout.getLineBaseline(lineIndex)))
+ textLine.lineTop = ChapterProvider.paddingTop + y + layout.getLineTop(lineIndex)
+ textLine.lineBase =
+ ChapterProvider.paddingTop + y + layout.getLineBaseline(lineIndex)
textLine.lineBottom =
- textLine.lineBase + ChapterProvider.contentPaint.fontMetrics.descent
+ ChapterProvider.paddingTop + y + layout.getLineBottom(lineIndex)
var x = ChapterProvider.paddingLeft +
(ChapterProvider.visibleWidth - layout.getLineMax(lineIndex)) / 2
textLine.text =
diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceViewModel.kt
index 8f0f46d94..5857fe8ef 100644
--- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceViewModel.kt
+++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceViewModel.kt
@@ -16,7 +16,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.jetbrains.anko.toast
import java.io.File
-import java.net.URLEncoder
class BookSourceViewModel(application: Application) : BaseViewModel(application) {
@@ -228,7 +227,7 @@ class BookSourceViewModel(application: Application) : BaseViewModel(application)
}
private fun importSourceUrl(url: String): Int {
- HttpHelper.simpleGet(url)?.let { body ->
+ HttpHelper.simpleGet(url, "UTF-8")?.let { body ->
val bookSources = mutableListOf()
val items: List