Merge pull request #8 from gedoor/master

merge
pull/441/head
口口吕 4 years ago committed by GitHub
commit eae5ae2244
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      app/proguard-rules.pro
  2. 0
      app/src/main/assets/defaultData/httpTTS.json
  3. 0
      app/src/main/assets/defaultData/readConfig.json
  4. 0
      app/src/main/assets/defaultData/themeConfig.json
  5. 0
      app/src/main/assets/defaultData/txtTocRule.json
  6. 0
      app/src/main/assets/font/number.ttf
  7. 0
      app/src/main/assets/help/help.md
  8. 15
      app/src/main/assets/help/httpTts.md
  9. 4
      app/src/main/assets/updateLog.md
  10. 1
      app/src/main/java/io/legado/app/base/BaseFragment.kt
  11. 4
      app/src/main/java/io/legado/app/base/BaseService.kt
  12. 1
      app/src/main/java/io/legado/app/base/BaseViewModel.kt
  13. 1
      app/src/main/java/io/legado/app/base/adapter/CommonRecyclerAdapter.kt
  14. 1
      app/src/main/java/io/legado/app/base/adapter/InfiniteScrollListener.kt
  15. 1
      app/src/main/java/io/legado/app/base/adapter/ItemAnimation.kt
  16. 2
      app/src/main/java/io/legado/app/data/AppDatabase.kt
  17. 2
      app/src/main/java/io/legado/app/data/entities/rule/ContentRule.kt
  18. 1
      app/src/main/java/io/legado/app/help/ActivityHelp.kt
  19. 2
      app/src/main/java/io/legado/app/help/BlurTransformation.kt
  20. 27
      app/src/main/java/io/legado/app/help/BookHelp.kt
  21. 47
      app/src/main/java/io/legado/app/help/DefaultData.kt
  22. 19
      app/src/main/java/io/legado/app/help/DefaultValueHelp.kt
  23. 3
      app/src/main/java/io/legado/app/help/EventMessage.kt
  24. 1
      app/src/main/java/io/legado/app/help/IntentHelp.kt
  25. 1
      app/src/main/java/io/legado/app/help/LayoutManager.kt
  26. 8
      app/src/main/java/io/legado/app/help/ReadBookConfig.kt
  27. 7
      app/src/main/java/io/legado/app/help/ThemeConfig.kt
  28. 1
      app/src/main/java/io/legado/app/help/coroutine/CompositeCoroutine.kt
  29. 1
      app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt
  30. 2
      app/src/main/java/io/legado/app/help/http/CookieStore.kt
  31. 6
      app/src/main/java/io/legado/app/help/http/HttpHelper.kt
  32. 1
      app/src/main/java/io/legado/app/help/http/SSLHelper.kt
  33. 1
      app/src/main/java/io/legado/app/help/permission/Permissions.kt
  34. 9
      app/src/main/java/io/legado/app/help/permission/PermissionsCompat.kt
  35. 9
      app/src/main/java/io/legado/app/help/storage/Backup.kt
  36. 2
      app/src/main/java/io/legado/app/help/storage/ImportOldData.kt
  37. 1
      app/src/main/java/io/legado/app/help/storage/OldRule.kt
  38. 23
      app/src/main/java/io/legado/app/help/storage/Restore.kt
  39. 1
      app/src/main/java/io/legado/app/lib/theme/ATH.kt
  40. 1
      app/src/main/java/io/legado/app/lib/theme/DrawableUtils.kt
  41. 2
      app/src/main/java/io/legado/app/lib/theme/MaterialValueHelper.kt
  42. 1
      app/src/main/java/io/legado/app/lib/theme/NavigationViewUtils.kt
  43. 6
      app/src/main/java/io/legado/app/lib/theme/Selector.kt
  44. 1
      app/src/main/java/io/legado/app/lib/theme/ThemeStore.kt
  45. 92
      app/src/main/java/io/legado/app/lib/theme/TintHelper.kt
  46. 1
      app/src/main/java/io/legado/app/lib/theme/ViewUtils.kt
  47. 5
      app/src/main/java/io/legado/app/lib/webdav/WebDav.kt
  48. 1
      app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSonPath.kt
  49. 20
      app/src/main/java/io/legado/app/model/localBook/AnalyzeTxtFile.kt
  50. 1
      app/src/main/java/io/legado/app/model/rss/RssParserDefault.kt
  51. 16
      app/src/main/java/io/legado/app/receiver/TimeBatteryReceiver.kt
  52. 25
      app/src/main/java/io/legado/app/service/help/CacheBook.kt
  53. 8
      app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineDialog.kt
  54. 12
      app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineViewModel.kt
  55. 6
      app/src/main/java/io/legado/app/ui/book/read/config/TocRegexViewModel.kt
  56. 1
      app/src/main/java/io/legado/app/ui/book/read/page/entities/TextLine.kt
  57. 4
      app/src/main/java/io/legado/app/ui/book/search/SearchViewModel.kt
  58. 2
      app/src/main/java/io/legado/app/ui/book/toc/ChapterListActivity.kt
  59. 8
      app/src/main/java/io/legado/app/ui/filechooser/adapter/FileAdapter.kt
  60. 2
      app/src/main/java/io/legado/app/ui/filechooser/adapter/PathAdapter.kt
  61. 10
      app/src/main/java/io/legado/app/ui/filechooser/utils/FilePickerIcon.java
  62. 6
      app/src/main/java/io/legado/app/ui/main/MainViewModel.kt
  63. 2
      app/src/main/java/io/legado/app/ui/main/my/MyFragment.kt
  64. 2
      app/src/main/java/io/legado/app/ui/welcome/WelcomeActivity.kt
  65. 3
      app/src/main/java/io/legado/app/ui/widget/BatteryView.kt
  66. 2
      app/src/main/java/io/legado/app/utils/StringExtensions.kt

@ -54,6 +54,8 @@
# Android开发中一些需要保留的公共部分
#
#############################################
# 屏蔽错误Unresolved class name
#noinspection ShrinkerUnresolvedReference
# 保留我们使用的四大组件,自定义的Application等等这些类不被混淆
# 因为这些子类都有可能被外部调用
@ -66,7 +68,6 @@
-keep public class * extends android.preference.Preference
-keep public class * extends android.view.View
# 保留androidx下的所有类及其内部类
-keep class androidx.** {*;}

@ -0,0 +1,15 @@
# 在线朗读规则说明
* 在线朗读规则为url规则,同书源url
* js参数
~~~
speakText //朗读文本
speakSpeed //朗读速度,0-45
~~~
* 例:
~~~
http://tts.baidu.com/text2audio,{
"method": "POST",
"body": "tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=5003&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio"
}
~~~

@ -3,6 +3,10 @@
* 关注合作公众号 **[小说拾遗]()** 获取好看的小说。
* 旧版数据导入教程:先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】。
**2020/10/19**
* 优化分组管理
* 修复预下载没有保存的bug
**2020/10/18**
* 优化分组管理,默认分组可以重命名了
* 修复书架空白的bug,是constraintlayout库新版本的bug

@ -15,6 +15,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlin.coroutines.CoroutineContext
@Suppress("MemberVisibilityCanBePrivate")
abstract class BaseFragment(layoutID: Int) : Fragment(layoutID),
CoroutineScope {
lateinit var job: Job

@ -18,7 +18,9 @@ abstract class BaseService : Service(), CoroutineScope by MainScope() {
block: suspend CoroutineScope.() -> T
) = Coroutine.async(scope, context) { block() }
override fun onBind(intent: Intent?) = null
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onDestroy() {
super.onDestroy()

@ -11,6 +11,7 @@ import org.jetbrains.anko.AnkoLogger
import org.jetbrains.anko.toast
import kotlin.coroutines.CoroutineContext
@Suppress("unused")
open class BaseViewModel(application: Application) : AndroidViewModel(application),
CoroutineScope by MainScope(),
AnkoLogger {

@ -15,6 +15,7 @@ import java.util.*
*
* 通用的adapter 可添加headerfooter以及不同类型item
*/
@Suppress("unused", "MemberVisibilityCanBePrivate")
abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context) :
RecyclerView.Adapter<ItemViewHolder>() {

@ -8,6 +8,7 @@ import androidx.recyclerview.widget.RecyclerView
*
* 上拉加载更多
*/
@Suppress("unused")
abstract class InfiniteScrollListener() : RecyclerView.OnScrollListener() {
private val loadMoreRunnable = Runnable { onLoadMore() }

@ -7,6 +7,7 @@ import io.legado.app.base.adapter.animations.*
/**
* Created by Invincible on 2017/12/15.
*/
@Suppress("unused")
class ItemAnimation private constructor() {
var itemAnimEnabled = false

@ -49,12 +49,10 @@ abstract class AppDatabase: RoomDatabase() {
private val dbCallback = object : Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
db.setLocale(Locale.CHINESE)
}
override fun onOpen(db: SupportSQLiteDatabase) {
db.setLocale(Locale.CHINESE)
db.execSQL(
"""
insert into book_groups(groupId, groupName, 'order', show) select ${AppConst.bookGroupAllId}, '全部', -10, 1

@ -10,5 +10,5 @@ data class ContentRule(
var webJs: String? = null,
var sourceRegex: String? = null,
var replaceRegex: String? = null,
var imageStyle: String? = null //默认大小居中,1最大宽度
var imageStyle: String? = null //默认大小居中,FULL最大宽度
) : Parcelable

@ -10,6 +10,7 @@ import java.util.*
/**
* Activity管理器,管理项目中Activity的状态
*/
@Suppress("unused")
object ActivityHelp : Application.ActivityLifecycleCallbacks {
private val activities: MutableList<WeakReference<Activity>> = arrayListOf()

@ -28,7 +28,7 @@ class BlurTransformation(context: Context, private val radius: Int) : CenterCrop
//图片缩小1/2
val width = (min(outWidth, transform.width) / 2f).roundToInt()
val height = (min(outHeight, transform.height) / 2f).roundToInt()
val blurredBitmap = Bitmap.createScaledBitmap(transform, width, height, false);
val blurredBitmap = Bitmap.createScaledBitmap(transform, width, height, false)
// Allocate memory for Renderscript to work with
//分配用于渲染脚本的内存
val input = Allocation.createFromBitmap(

@ -267,8 +267,9 @@ object BookHelp {
}
}
private val chapterNamePattern =
private val chapterNamePattern by lazy {
Pattern.compile("^(.*?第([\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟0-9\\s]+)[章节篇回集])[、,。 ::.\\s]*")
}
private fun getChapterNum(chapterName: String?): Int {
if (chapterName != null) {
@ -280,15 +281,25 @@ object BookHelp {
return -1
}
private fun getPureChapterName(chapterName: String?): String {
@Suppress("SpellCheckingInspection")
private val regexOther by lazy {
// 所有非字母数字中日韩文字 CJK区+扩展A-F区
return@lazy "[^\\w\\u4E00-\\u9FEF〇\\u3400-\\u4DBF\\u20000-\\u2A6DF\\u2A700-\\u2EBEF]".toRegex()
}
private val regexA by lazy {
return@lazy "\\s".toRegex()
}
private val regexB by lazy {
return@lazy "^第.*?章|[(\\[][^()\\[\\]]{2,}[)\\]]$".toRegex()
}
private fun getPureChapterName(chapterName: String?): String {
return if (chapterName == null) "" else StringUtils.fullToHalf(chapterName)
.replace("\\s".toRegex(), "")
.replace("^第.*?章|[(\\[][^()\\[\\]]{2,}[)\\]]$".toRegex(), "")
.replace(
"[^\\w\\u4E00-\\u9FEF〇\\u3400-\\u4DBF\\u20000-\\u2A6DF\\u2A700-\\u2EBEF]".toRegex(),
""
)
.replace(regexA, "")
.replace(regexB, "")
.replace(regexOther, "")
}
private var bookName: String? = null

@ -0,0 +1,47 @@
package io.legado.app.help
import io.legado.app.App
import io.legado.app.data.entities.HttpTTS
import io.legado.app.data.entities.TxtTocRule
import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonArray
import java.io.File
object DefaultData {
const val httpTtsFileName = "httpTTS.json"
const val txtTocRuleFileName = "txtTocRule.json"
val defaultHttpTTS by lazy {
val json =
String(
App.INSTANCE.assets.open("defaultData${File.separator}$httpTtsFileName")
.readBytes()
)
GSON.fromJsonArray<HttpTTS>(json)!!
}
val defaultReadConfigs by lazy {
val json = String(
App.INSTANCE.assets.open("defaultData${File.separator}${ReadBookConfig.configFileName}")
.readBytes()
)
GSON.fromJsonArray<ReadBookConfig.Config>(json)!!
}
val defaultTxtTocRules by lazy {
val json = String(
App.INSTANCE.assets.open("defaultData${File.separator}$txtTocRuleFileName")
.readBytes()
)
GSON.fromJsonArray<TxtTocRule>(json)!!
}
val defaultThemeConfigs by lazy {
val json = String(
App.INSTANCE.assets.open("defaultData${File.separator}${ThemeConfig.configFileName}")
.readBytes()
)
GSON.fromJsonArray<ThemeConfig.Config>(json)!!
}
}

@ -1,19 +0,0 @@
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())
}
}
}

@ -2,8 +2,7 @@ package io.legado.app.help
import android.text.TextUtils
import java.util.Arrays
@Suppress("unused")
class EventMessage {
var what: Int?=null

@ -7,6 +7,7 @@ import android.os.Bundle
import io.legado.app.R
import org.jetbrains.anko.toast
@Suppress("unused")
object IntentHelp {

@ -6,6 +6,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
@Suppress("unused")
object LayoutManager {
interface LayoutManagerFactory {

@ -26,10 +26,6 @@ object ReadBookConfig {
val shareConfigFilePath = FileUtils.getPath(App.INSTANCE.filesDir, shareConfigFileName)
val configList: ArrayList<Config> = arrayListOf()
lateinit var shareConfig: Config
private val defaultConfigs by lazy {
val json = String(App.INSTANCE.assets.open(configFileName).readBytes())
GSON.fromJsonArray<Config>(json)!!
}
var durConfig
get() = getConfig(styleSelect)
set(value) {
@ -68,7 +64,7 @@ object ReadBookConfig {
e.printStackTrace()
}
}
(configs ?: defaultConfigs).let {
(configs ?: DefaultData.defaultReadConfigs).let {
configList.clear()
configList.addAll(it)
}
@ -131,7 +127,7 @@ object ReadBookConfig {
}
private fun resetAll() {
defaultConfigs.let {
DefaultData.defaultReadConfigs.let {
configList.clear()
configList.addAll(it)
save()

@ -13,10 +13,7 @@ import java.io.File
object ThemeConfig {
const val configFileName = "themeConfig.json"
val configFilePath = FileUtils.getPath(App.INSTANCE.filesDir, configFileName)
private val defaultConfigs by lazy {
val json = String(App.INSTANCE.assets.open(configFileName).readBytes())
GSON.fromJsonArray<Config>(json)!!
}
val configList = arrayListOf<Config>()
init {
@ -24,7 +21,7 @@ object ThemeConfig {
}
fun upConfig() {
(getConfigs() ?: defaultConfigs).let {
(getConfigs() ?: DefaultData.defaultThemeConfigs).let {
configList.clear()
configList.addAll(it)
}

@ -1,5 +1,6 @@
package io.legado.app.help.coroutine
@Suppress("unused")
class CompositeCoroutine : CoroutineContainer {
private var resources: HashSet<Coroutine<*>>? = null

@ -5,6 +5,7 @@ import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext
@Suppress("unused")
class Coroutine<T>(
val scope: CoroutineScope,
context: CoroutineContext = Dispatchers.IO,

@ -1,3 +1,5 @@
@file:Suppress("unused")
package io.legado.app.help.http
import android.text.TextUtils

@ -112,7 +112,7 @@ object HttpHelper {
proxy: String? = null
): Retrofit {
val r = Regex("(http|socks4|socks5)://(.*):(\\d{2,5})(@.*@.*)?")
val ms = proxy?.let { r.findAll(it) };
val ms = proxy?.let { r.findAll(it) }
val group = ms?.first()
var type = "direct" //直接连接
var host = "127.0.0.1" //代理服务器hostname
@ -135,9 +135,9 @@ object HttpHelper {
val builder = client.newBuilder()
if (type != "direct" && host != "") {
if (type == "http") {
builder.proxy(Proxy(Proxy.Type.HTTP, InetSocketAddress(host, port)));
builder.proxy(Proxy(Proxy.Type.HTTP, InetSocketAddress(host, port)))
} else {
builder.proxy(Proxy(Proxy.Type.SOCKS, InetSocketAddress(host, port)));
builder.proxy(Proxy(Proxy.Type.SOCKS, InetSocketAddress(host, port)))
}
if (username != "" && password != "") {
builder.proxyAuthenticator { _, response -> //设置代理服务器账号密码

@ -12,6 +12,7 @@ import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
import javax.net.ssl.*
@Suppress("unused")
object SSLHelper {
/**

@ -1,5 +1,6 @@
package io.legado.app.help.permission
@Suppress("unused")
object Permissions {
const val READ_CALENDAR = "android.permission.READ_CALENDAR"

@ -5,6 +5,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import java.util.*
@Suppress("unused")
class PermissionsCompat private constructor() {
private var request: Request? = null
@ -16,11 +17,11 @@ class PermissionsCompat private constructor() {
companion object {
// 检查权限, 如果已经拥有返回 true
fun check(activity: AppCompatActivity, vararg permissions: String): Boolean {
var request = Request(activity)
var pers = ArrayList<String>()
val request = Request(activity)
val pers = ArrayList<String>()
pers.addAll(listOf(*permissions))
var data = request.getDeniedPermissions(pers.toTypedArray())
return data == null;
val data = request.getDeniedPermissions(pers.toTypedArray())
return data == null
}
}

@ -5,6 +5,7 @@ import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import io.legado.app.App
import io.legado.app.constant.PreferKey
import io.legado.app.help.DefaultData
import io.legado.app.help.ReadBookConfig
import io.legado.app.help.ThemeConfig
import io.legado.app.help.coroutine.Coroutine
@ -31,9 +32,9 @@ object Backup {
"rssSource.json",
"rssStar.json",
"replaceRule.json",
"txtTocRule.json",
"readRecord.json",
"httpTTS.json",
DefaultData.txtTocRuleFileName,
DefaultData.httpTtsFileName,
ReadBookConfig.configFileName,
ReadBookConfig.shareConfigFileName,
ThemeConfig.configFileName,
@ -62,9 +63,9 @@ object Backup {
writeListToJson(App.db.rssSourceDao().all, "rssSource.json", backupPath)
writeListToJson(App.db.rssStarDao().all, "rssStar.json", backupPath)
writeListToJson(App.db.replaceRuleDao().all, "replaceRule.json", backupPath)
writeListToJson(App.db.txtTocRule().all, "txtTocRule.json", backupPath)
writeListToJson(App.db.readRecordDao().all, "readRecord.json", backupPath)
writeListToJson(App.db.httpTTSDao().all, "httpTTS.json", backupPath)
writeListToJson(App.db.txtTocRule().all, DefaultData.txtTocRuleFileName, backupPath)
writeListToJson(App.db.httpTTSDao().all, DefaultData.httpTtsFileName, backupPath)
GSON.toJson(ReadBookConfig.configList).let {
FileUtils.createFileIfNotExist(backupPath + File.separator + ReadBookConfig.configFileName)
.writeText(it)

@ -100,7 +100,7 @@ object ImportOldData {
return bookSources.size
}
fun importOldReplaceRule(json: String): Int {
private fun importOldReplaceRule(json: String): Int {
val rules = OldReplace.jsonToReplaceRules(json)
App.db.replaceRuleDao().insert(*rules.toTypedArray())
return rules.size

@ -9,6 +9,7 @@ import io.legado.app.help.storage.Restore.jsonPath
import io.legado.app.utils.*
import java.util.regex.Pattern
@Suppress("RegExpRedundantEscape")
object OldRule {
private val headerPattern = Pattern.compile("@Header:\\{.+?\\}", Pattern.CASE_INSENSITIVE)
private val jsPattern = Pattern.compile("\\{\\{.+?\\}\\}", Pattern.CASE_INSENSITIVE)

@ -13,10 +13,7 @@ import io.legado.app.R
import io.legado.app.constant.EventBus
import io.legado.app.constant.PreferKey
import io.legado.app.data.entities.*
import io.legado.app.help.AppConfig
import io.legado.app.help.LauncherIconHelp
import io.legado.app.help.ReadBookConfig
import io.legado.app.help.ThemeConfig
import io.legado.app.help.*
import io.legado.app.service.help.ReadBook
import io.legado.app.ui.book.read.page.provider.ChapterProvider
import io.legado.app.utils.*
@ -81,7 +78,7 @@ object Restore {
for (fileName in Backup.backupFileNames) {
if (doc.name == fileName) {
DocumentUtils.readText(context, doc.uri)?.let {
FileUtils.createFileIfNotExist(Backup.backupPath + File.separator + fileName)
FileUtils.createFileIfNotExist("${Backup.backupPath}${File.separator}$fileName")
.writeText(it)
}
}
@ -94,7 +91,7 @@ object Restore {
FileUtils.getFile(file, fileName).let {
if (it.exists()) {
it.copyTo(
FileUtils.createFileIfNotExist(Backup.backupPath + File.separator + fileName),
FileUtils.createFileIfNotExist("${Backup.backupPath}${File.separator}$fileName"),
true
)
}
@ -132,9 +129,12 @@ object Restore {
fileToListT<ReplaceRule>(path, "replaceRule.json")?.let {
App.db.replaceRuleDao().insert(*it.toTypedArray())
}
fileToListT<TxtTocRule>(path, "txtTocRule.json")?.let {
fileToListT<TxtTocRule>(path, DefaultData.txtTocRuleFileName)?.let {
App.db.txtTocRule().insert(*it.toTypedArray())
}
fileToListT<HttpTTS>(path, DefaultData.httpTtsFileName)?.let {
App.db.httpTTSDao().insert(*it.toTypedArray())
}
fileToListT<ReadRecord>(path, "readRecord.json")?.let {
it.forEach { readRecord ->
//判断是不是本机记录
@ -149,9 +149,6 @@ object Restore {
}
}
}
fileToListT<HttpTTS>(path, "httpTTS.json")?.let {
App.db.httpTTSDao().insert(*it.toTypedArray())
}
}
}
@ -159,7 +156,7 @@ object Restore {
withContext(IO) {
try {
val file =
FileUtils.createFileIfNotExist(path + File.separator + ThemeConfig.configFileName)
FileUtils.createFileIfNotExist("$path${File.separator}${ThemeConfig.configFileName}")
if (file.exists()) {
FileUtils.deleteFile(ThemeConfig.configFilePath)
file.copyTo(File(ThemeConfig.configFilePath))
@ -171,7 +168,7 @@ object Restore {
if (!ignoreReadConfig) {
try {
val file =
FileUtils.createFileIfNotExist(path + File.separator + ReadBookConfig.configFileName)
FileUtils.createFileIfNotExist("$path${File.separator}${ReadBookConfig.configFileName}")
if (file.exists()) {
FileUtils.deleteFile(ReadBookConfig.configFilePath)
file.copyTo(File(ReadBookConfig.configFilePath))
@ -182,7 +179,7 @@ object Restore {
}
try {
val file =
FileUtils.createFileIfNotExist(path + File.separator + ReadBookConfig.shareConfigFileName)
FileUtils.createFileIfNotExist("$path${File.separator}${ReadBookConfig.shareConfigFileName}")
if (file.exists()) {
FileUtils.deleteFile(ReadBookConfig.shareConfigFilePath)
file.copyTo(File(ReadBookConfig.shareConfigFilePath))

@ -30,6 +30,7 @@ import org.jetbrains.anko.backgroundColor
/**
* @author Karim Abou Zeid (kabouzeid)
*/
@Suppress("unused", "MemberVisibilityCanBePrivate")
object ATH {
@SuppressLint("CommitPrefEdits")

@ -11,6 +11,7 @@ import androidx.core.graphics.drawable.DrawableCompat
/**
* @author Karim Abou Zeid (kabouzeid)
*/
@Suppress("unused")
object DrawableUtils {
fun createTransitionDrawable(@ColorInt startColor: Int, @ColorInt endColor: Int): TransitionDrawable {

@ -1,3 +1,5 @@
@file:Suppress("unused")
package io.legado.app.lib.theme
import android.annotation.SuppressLint

@ -8,6 +8,7 @@ import com.google.android.material.navigation.NavigationView
/**
* @author Karim Abou Zeid (kabouzeid)
*/
@Suppress("unused")
object NavigationViewUtils {
fun setItemIconColors(navigationView: NavigationView, @ColorInt normalColor: Int, @ColorInt selectedColor: Int) {

@ -13,6 +13,7 @@ import androidx.annotation.DrawableRes
import androidx.annotation.IntDef
import androidx.core.content.ContextCompat
@Suppress("unused")
object Selector {
fun shapeBuild(): ShapeSelector {
return ShapeSelector()
@ -260,7 +261,8 @@ object Selector {
* @author hjy
* created at 2017/12/11 22:34
*/
class DrawableSelector constructor() {
@Suppress("MemberVisibilityCanBePrivate")
class DrawableSelector {
private var mDefaultDrawable: Drawable? = null
private var mDisabledDrawable: Drawable? = null
@ -355,7 +357,7 @@ object Selector {
* @author hjy
* created at 2017/12/11 22:26
*/
class ColorSelector constructor() {
class ColorSelector {
private var mDefaultColor: Int = 0
private var mDisabledColor: Int = 0

@ -16,6 +16,7 @@ import io.legado.app.utils.ColorUtils
/**
* @author Aidan Follestad (afollestad), Karim Abou Zeid (kabouzeid)
*/
@Suppress("unused")
class ThemeStore @SuppressLint("CommitPrefEdits")
private constructor(private val mContext: Context) : ThemeStoreInterface {
private val mEditor: SharedPreferences.Editor

@ -23,6 +23,7 @@ import io.legado.app.utils.ColorUtils
/**
* @author afollestad, plusCubed
*/
@Suppress("MemberVisibilityCanBePrivate")
object TintHelper {
@SuppressLint("PrivateResource")
@ -37,7 +38,10 @@ object TintHelper {
)
}
private fun getDisabledColorStateList(@ColorInt normal: Int, @ColorInt disabled: Int): ColorStateList {
private fun getDisabledColorStateList(
@ColorInt normal: Int,
@ColorInt disabled: Int
): ColorStateList {
return ColorStateList(
arrayOf(
intArrayOf(-android.R.attr.state_enabled),
@ -61,48 +65,52 @@ object TintHelper {
)
val sl: ColorStateList
if (view is Button) {
sl = getDisabledColorStateList(color, disabled)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && view.getBackground() is RippleDrawable) {
val rd = view.getBackground() as RippleDrawable
rd.setColor(ColorStateList.valueOf(rippleColor))
}
when (view) {
is Button -> {
sl = getDisabledColorStateList(color, disabled)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && view.getBackground() is RippleDrawable) {
val rd = view.getBackground() as RippleDrawable
rd.setColor(ColorStateList.valueOf(rippleColor))
}
// Disabled text color state for buttons, may get overridden later by ATE tags
view.setTextColor(
getDisabledColorStateList(
textColor,
ContextCompat.getColor(
view.getContext(),
if (useDarkTheme) R.color.ate_button_text_disabled_dark else R.color.ate_button_text_disabled_light
// Disabled text color state for buttons, may get overridden later by ATE tags
view.setTextColor(
getDisabledColorStateList(
textColor,
ContextCompat.getColor(
view.getContext(),
if (useDarkTheme) R.color.ate_button_text_disabled_dark else R.color.ate_button_text_disabled_light
)
)
)
)
} else if (view is FloatingActionButton) {
// FloatingActionButton doesn't support disabled state?
sl = ColorStateList(
arrayOf(
intArrayOf(-android.R.attr.state_pressed),
intArrayOf(android.R.attr.state_pressed)
), intArrayOf(color, pressed)
)
}
is FloatingActionButton -> {
// FloatingActionButton doesn't support disabled state?
sl = ColorStateList(
arrayOf(
intArrayOf(-android.R.attr.state_pressed),
intArrayOf(android.R.attr.state_pressed)
), intArrayOf(color, pressed)
)
view.rippleColor = rippleColor
view.backgroundTintList = sl
if (view.drawable != null)
view.setImageDrawable(createTintedDrawable(view.drawable, textColor))
return
} else {
sl = ColorStateList(
arrayOf(
intArrayOf(-android.R.attr.state_enabled),
intArrayOf(android.R.attr.state_enabled),
intArrayOf(android.R.attr.state_enabled, android.R.attr.state_pressed),
intArrayOf(android.R.attr.state_enabled, android.R.attr.state_activated),
intArrayOf(android.R.attr.state_enabled, android.R.attr.state_checked)
),
intArrayOf(disabled, color, pressed, activated, activated)
)
view.rippleColor = rippleColor
view.backgroundTintList = sl
if (view.drawable != null)
view.setImageDrawable(createTintedDrawable(view.drawable, textColor))
return
}
else -> {
sl = ColorStateList(
arrayOf(
intArrayOf(-android.R.attr.state_enabled),
intArrayOf(android.R.attr.state_enabled),
intArrayOf(android.R.attr.state_enabled, android.R.attr.state_pressed),
intArrayOf(android.R.attr.state_enabled, android.R.attr.state_activated),
intArrayOf(android.R.attr.state_enabled, android.R.attr.state_checked)
),
intArrayOf(disabled, color, pressed, activated, activated)
)
}
}
var drawable: Drawable? = view.background
@ -386,7 +394,11 @@ object TintHelper {
return createTintedDrawable(from, sl)
}
fun setTint(switchView: Switch, @ColorInt color: Int, useDarker: Boolean) {
fun setTint(
@SuppressLint("UseSwitchCompatOrMaterialCode") switchView: Switch,
@ColorInt color: Int,
useDarker: Boolean
) {
if (switchView.trackDrawable != null) {
switchView.trackDrawable = modifySwitchDrawable(
switchView.context,

@ -10,6 +10,7 @@ import androidx.annotation.ColorInt
/**
* @author Karim Abou Zeid (kabouzeid)
*/
@Suppress("unused")
object ViewUtils {
fun removeOnGlobalLayoutListener(v: View, listener: ViewTreeObserver.OnGlobalLayoutListener) {

@ -14,6 +14,7 @@ import java.net.URL
import java.net.URLEncoder
import java.util.*
@Suppress("unused")
class WebDav(urlStr: String) {
companion object {
// 指定返回哪些属性
@ -60,9 +61,9 @@ class WebDav(urlStr: String) {
return field
}
fun getPath() = url.toString()
val path get() = url.toString()
fun getHost() = url.host
val host: String? get() = url.host
/**
* 填充文件信息实例化WebDAVFile对象时并没有将远程文件的信息填充到实例中需要手动填充

@ -8,6 +8,7 @@ import io.legado.app.utils.splitNotBlank
import java.util.*
import java.util.regex.Pattern
@Suppress("RegExpRedundantEscape")
@Keep
class AnalyzeByJSonPath {
private lateinit var ctx: ReadContext

@ -5,6 +5,7 @@ import io.legado.app.App
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter
import io.legado.app.data.entities.TxtTocRule
import io.legado.app.help.DefaultData
import io.legado.app.utils.*
import java.io.File
import java.io.RandomAccessFile
@ -281,24 +282,17 @@ class AnalyzeTxtFile {
}
private fun getTocRules(): List<TxtTocRule> {
val rules = App.db.txtTocRule().enabled
var rules = App.db.txtTocRule().enabled
if (rules.isEmpty()) {
return getDefaultEnabledRules()
rules = DefaultData.defaultTxtTocRules.apply {
App.db.txtTocRule().insert(*this.toTypedArray())
}.filter {
it.enable
}
}
return rules
}
fun getDefaultEnabledRules(): List<TxtTocRule> {
App.INSTANCE.assets.open("txtTocRule.json").readBytes().let { byteArray ->
GSON.fromJsonArray<TxtTocRule>(String(byteArray))?.let { txtTocRules ->
App.db.txtTocRule().insert(*txtTocRules.toTypedArray())
return txtTocRules.filter {
it.enable
}
}
}
return emptyList()
}
}
}

@ -8,6 +8,7 @@ import org.xmlpull.v1.XmlPullParserFactory
import java.io.IOException
import java.io.StringReader
@Suppress("unused")
object RssParserDefault {
@Throws(XmlPullParserException::class, IOException::class)

@ -25,15 +25,13 @@ class TimeBatteryReceiver : BroadcastReceiver() {
}
override fun onReceive(context: Context?, intent: Intent?) {
intent?.action?.let {
when (it) {
Intent.ACTION_TIME_TICK -> {
postEvent(EventBus.TIME_CHANGED, "")
}
Intent.ACTION_BATTERY_CHANGED -> {
val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
postEvent(EventBus.BATTERY_CHANGED, level)
}
when (intent?.action) {
Intent.ACTION_TIME_TICK -> {
postEvent(EventBus.TIME_CHANGED, "")
}
Intent.ACTION_BATTERY_CHANGED -> {
val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
postEvent(EventBus.BATTERY_CHANGED, level)
}
}
}

@ -77,23 +77,16 @@ object CacheBook {
downloadMap[book.bookUrl]?.add(chapter.index)
webBook.getContent(book, chapter)
.onSuccess(IO) { content ->
if (content.isNotBlank()) {
BookHelp.saveContent(book, chapter, content)
}
if (ReadBook.book?.bookUrl == book.bookUrl) {
if (content.isEmpty()) {
ReadBook.contentLoadFinish(
book,
chapter,
App.INSTANCE.getString(R.string.content_empty),
resetPageOffset = resetPageOffset
)
} else {
BookHelp.saveContent(book, chapter, content)
ReadBook.contentLoadFinish(
book,
chapter,
content,
resetPageOffset = resetPageOffset
)
}
ReadBook.contentLoadFinish(
book,
chapter,
content.ifBlank { App.INSTANCE.getString(R.string.content_empty) },
resetPageOffset = resetPageOffset
)
}
}.onError {
if (ReadBook.book?.bookUrl == book.bookUrl) {

@ -24,11 +24,13 @@ import io.legado.app.lib.dialogs.customView
import io.legado.app.lib.dialogs.okButton
import io.legado.app.lib.theme.primaryColor
import io.legado.app.service.help.ReadAloud
import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.utils.*
import kotlinx.android.synthetic.main.dialog_http_tts_edit.view.*
import kotlinx.android.synthetic.main.dialog_recycler_view.*
import kotlinx.android.synthetic.main.item_http_tts.view.*
import org.jetbrains.anko.sdk27.listeners.onClick
import java.io.File
class SpeakEngineDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener {
@ -126,6 +128,12 @@ class SpeakEngineDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener
ReadAloud.upReadAloudClass()
}
}
neutralButton(R.string.help) {
val helpStr = String(
requireContext().assets.open("help${File.separator}httpTts.md").readBytes()
)
TextDialog.show(childFragmentManager, helpStr, TextDialog.MD)
}
}.show().applyTint()
}

@ -3,8 +3,8 @@ 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.data.entities.HttpTTS
import io.legado.app.help.DefaultData
import io.legado.app.help.http.HttpHelper
import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonArray
@ -13,15 +13,17 @@ class SpeakEngineViewModel(application: Application) : BaseViewModel(application
fun importDefault() {
execute {
DefaultValueHelp.initHttpTTS()
DefaultData.defaultHttpTTS.let {
App.db.httpTTSDao().insert(*it.toTypedArray())
}
}
}
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())
GSON.fromJsonArray<HttpTTS>(json)?.let {
App.db.httpTTSDao().insert(*it.toTypedArray())
}
}
}.onSuccess {

@ -4,8 +4,8 @@ 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.DefaultData
import io.legado.app.help.http.HttpHelper
import io.legado.app.model.localBook.AnalyzeTxtFile
import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonArray
@ -23,7 +23,9 @@ class TocRegexViewModel(application: Application) : BaseViewModel(application) {
fun importDefault() {
execute {
App.db.txtTocRule().deleteDefault()
AnalyzeTxtFile.getDefaultEnabledRules()
DefaultData.defaultTxtTocRules.let {
App.db.txtTocRule().insert(*it.toTypedArray())
}
}
}

@ -4,6 +4,7 @@ import android.text.TextPaint
import io.legado.app.ui.book.read.page.provider.ChapterProvider
import io.legado.app.ui.book.read.page.provider.ChapterProvider.textHeight
@Suppress("unused")
data class TextLine(
var text: String = "",
val textChars: ArrayList<TextChar> = arrayListOf(),

@ -144,7 +144,7 @@ class SearchViewModel(application: Application) : BaseViewModel(application),
}
}
if (!scope.isActive) return
searchBooks.sortWith(Comparator { o1, o2 ->
searchBooks.sortWith { o1, o2 ->
if (o1.name == searchKey && o2.name != searchKey) {
1
} else if (o1.name != searchKey && o2.name == searchKey) {
@ -168,7 +168,7 @@ class SearchViewModel(application: Application) : BaseViewModel(application),
} else {
0
}
})
}
if (!scope.isActive) return
searchBooks = copyDataS
upAdapter()

@ -65,7 +65,7 @@ class ChapterListActivity : VMBaseActivity<ChapterListViewModel>(R.layout.activi
return super.onCompatCreateOptionsMenu(menu)
}
private inner class TabFragmentPageAdapter internal constructor(fm: FragmentManager) :
private inner class TabFragmentPageAdapter(fm: FragmentManager) :
FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getItem(position: Int): Fragment {
return when (position) {

@ -23,10 +23,10 @@ class FileAdapter(context: Context, val callBack: CallBack) :
private var rootPath: String? = null
var currentPath: String? = null
private set
private val homeIcon = ConvertUtils.toDrawable(FilePickerIcon.getHOME())
private val upIcon = ConvertUtils.toDrawable(FilePickerIcon.getUPDIR())
private val folderIcon = ConvertUtils.toDrawable(FilePickerIcon.getFOLDER())
private val fileIcon = ConvertUtils.toDrawable(FilePickerIcon.getFILE())
private val homeIcon = ConvertUtils.toDrawable(FilePickerIcon.getHome())
private val upIcon = ConvertUtils.toDrawable(FilePickerIcon.getUpDir())
private val folderIcon = ConvertUtils.toDrawable(FilePickerIcon.getFolder())
private val fileIcon = ConvertUtils.toDrawable(FilePickerIcon.getFile())
private val primaryTextColor = context.getPrimaryTextColor(!AppConfig.isNightTheme)
private val disabledTextColor = context.getPrimaryDisabledTextColor(!AppConfig.isNightTheme)

@ -17,7 +17,7 @@ class PathAdapter(context: Context, val callBack: CallBack) :
private val paths = LinkedList<String>()
@Suppress("DEPRECATION")
private val sdCardDirectory = Environment.getExternalStorageDirectory().absolutePath
private val arrowIcon = ConvertUtils.toDrawable(FilePickerIcon.getARROW())
private val arrowIcon = ConvertUtils.toDrawable(FilePickerIcon.getArrow())
fun getPath(position: Int): String {
val tmp = StringBuilder("$sdCardDirectory/")

@ -8,23 +8,23 @@ package io.legado.app.ui.filechooser.utils;
*/
public class FilePickerIcon {
public static byte[] getFILE() {
public static byte[] getFile() {
return FILE;
}
public static byte[] getFOLDER() {
public static byte[] getFolder() {
return FOLDER;
}
public static byte[] getHOME() {
public static byte[] getHome() {
return HOME;
}
public static byte[] getUPDIR() {
public static byte[] getUpDir() {
return UPDIR;
}
public static byte[] getARROW() {
public static byte[] getArrow() {
return ARROW;
}

@ -9,7 +9,7 @@ import io.legado.app.data.entities.Book
import io.legado.app.data.entities.RssSource
import io.legado.app.help.AppConfig
import io.legado.app.help.BookHelp
import io.legado.app.help.DefaultValueHelp
import io.legado.app.help.DefaultData
import io.legado.app.help.http.HttpHelper
import io.legado.app.help.storage.Restore
import io.legado.app.model.webBook.WebBook
@ -162,7 +162,9 @@ class MainViewModel(application: Application) : BaseViewModel(application) {
execute {
FileUtils.deleteFile(FileUtils.getPath(context.cacheDir, "Fonts"))
if (App.db.httpTTSDao().count == 0) {
DefaultValueHelp.initHttpTTS()
DefaultData.defaultHttpTTS.let {
App.db.httpTTSDao().insert(*it.toTypedArray())
}
}
}
}

@ -54,7 +54,7 @@ class MyFragment : BaseFragment(R.layout.fragment_my_config), FileChooserDialog.
override fun onCompatOptionsItemSelected(item: MenuItem) {
when (item.itemId) {
R.id.menu_help -> {
val text = String(requireContext().assets.open("help.md").readBytes())
val text = String(requireContext().assets.open("help/help.md").readBytes())
TextDialog.show(childFragmentManager, text, TextDialog.MD)
}
}

@ -32,7 +32,7 @@ open class WelcomeActivity : BaseActivity(R.layout.activity_welcome) {
private fun init() {
Coroutine.async {
//清过期数据
//清过期数据
App.db.searchBookDao()
.clearExpired(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1))
//初始化简繁转换引擎

@ -10,6 +10,7 @@ import android.util.AttributeSet
import androidx.annotation.ColorInt
import androidx.appcompat.widget.AppCompatTextView
import io.legado.app.utils.dp
import java.io.File
class BatteryView(context: Context, attrs: AttributeSet?) : AppCompatTextView(context, attrs) {
private val batteryPaint = Paint()
@ -22,7 +23,7 @@ class BatteryView(context: Context, attrs: AttributeSet?) : AppCompatTextView(co
batteryPaint.strokeWidth = 1.dp.toFloat()
batteryPaint.isAntiAlias = true
batteryPaint.color = paint.color
typeface = Typeface.createFromAsset(context.assets, "number.ttf")
typeface = Typeface.createFromAsset(context.assets, "font${File.separator}number.ttf")
}
fun setColor(@ColorInt color: Int) {

@ -1,3 +1,5 @@
@file:Suppress("unused")
package io.legado.app.utils
import android.net.Uri

Loading…
Cancel
Save