diff --git a/.gitignore b/.gitignore
index 2543443bb..700c700fe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,4 +9,7 @@
/release
/tmp
node_modules/
+/app/app
+/app/google
+/app/gradle.properties
package-lock.json
diff --git a/app/build.gradle b/app/build.gradle
index 7dadb803b..75fdfb620 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 {
@@ -108,27 +110,27 @@ kapt {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
- testImplementation 'junit:junit:4.12'
+ testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
//kotlin
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.4.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'
implementation 'com.google.android.material:material:1.1.0'
implementation 'com.google.android:flexbox:1.1.0'
- implementation 'com.google.code.gson:gson:2.8.5'
+ implementation 'com.google.code.gson:gson:2.8.6'
//lifecycle
def lifecycle_version = '2.2.0'
@@ -157,19 +159,19 @@ dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
//规则相关
- implementation 'org.jsoup:jsoup:1.12.1'
+ implementation 'org.jsoup:jsoup:1.13.1'
implementation 'cn.wanghaomiao:JsoupXpath:2.3.2'
implementation 'com.jayway.jsonpath:json-path:2.4.0'
//JS rhino
implementation 'com.github.gedoor:rhino-android:1.4'
- //Retrofit
- implementation 'com.squareup.okhttp3:logging-interceptor:4.1.0'
- implementation 'com.squareup.retrofit2:retrofit:2.6.1'
+ //网络
+ //noinspection GradleDependency
+ implementation 'com.squareup.retrofit2:retrofit:2.7.2'
//Glide
- implementation 'com.github.bumptech.glide:glide:4.9.0'
+ implementation 'com.github.bumptech.glide:glide:4.11.0'
//webServer
implementation 'org.nanohttpd:nanohttpd:2.3.1'
@@ -182,15 +184,21 @@ 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.0.2'
+ implementation 'ru.noties.markwon:core:3.1.0'
//转换繁体
- implementation 'com.github.houbb:opencc4j:1.4.0'
+ implementation 'com.hankcs:hanlp:portable-1.7.7'
}
-apply plugin: 'com.google.gms.google-services'
\ No newline at end of file
+apply plugin: 'com.google.gms.google-services'
+
+afterEvaluate {
+ for (Task task : project.tasks.matching { it.name.startsWith('crashlyticsUploadDeobs') }) {
+ task.enabled = false
+ }
+}
\ No newline at end of file
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index 9af1203b9..1e8ab731b 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -160,7 +160,6 @@
-dontwarn rx.**
-dontwarn okio.**
--dontwarn retrofit2.**
-dontwarn javax.annotation.**
-dontwarn org.apache.log4j.lf5.viewer.**
-dontnote org.apache.log4j.lf5.viewer.**
@@ -172,7 +171,6 @@
-dontwarn com.jeremyliao.liveeventbus.**
-keep class com.jeremyliao.liveeventbus.** { *; }
--keep class retrofit2.**{*;}
-keep class okhttp3.**{*;}
-keep class okio.**{*;}
-keep class com.hwangjr.rxbus.**{*;}
diff --git a/app/src/debug/res/values/strings.xml b/app/src/debug/res/values/strings.xml
index b91572ada..e4464c88d 100644
--- a/app/src/debug/res/values/strings.xml
+++ b/app/src/debug/res/values/strings.xml
@@ -1,4 +1,4 @@
- 阅读.debug
- 阅读.debug·搜索
+ 阅读·D
+ 阅读·D·搜索
\ No newline at end of file
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 cfb6793b8..b33892324 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -257,7 +257,7 @@
android:launchMode="singleTop" />
+
diff --git a/app/src/main/assets/txtTocRule.json b/app/src/main/assets/txtTocRule.json
index ececb6800..aa5408b4c 100644
--- a/app/src/main/assets/txtTocRule.json
+++ b/app/src/main/assets/txtTocRule.json
@@ -1,98 +1,121 @@
[
{
+ "id": -1,
"enable": true,
"name": "目录",
- "rule": "^[ \\t]{0,4}(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$",
- "serialNumber": 0
+ "rule": "^[ \\t]{0,4}(?:序章|楔子|正文(?!完|结)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$",
+ "serialNumber": -17
},
{
+ "id": -2,
"enable": false,
"name": "目录(去空白)",
- "rule": "(?<=[ \\s])(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$",
- "serialNumber": 1
+ "rule": "(?<=[ \\s])(?:序章|楔子|正文(?!完|结)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$",
+ "serialNumber": -16
},
{
+ "id": -3,
"enable": false,
- "name": "目录(去简介)",
- "rule": "(?<=[ \\s])(?:前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|回(?![合来事去])|场(?![和合比电是])|篇(?!张))).{0,30}$",
- "serialNumber": 2
+ "name": "目录(匹配简介)",
+ "rule": "(?<=[ \\s])(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|回(?![合来事去])|场(?![和合比电是])|篇(?!张))).{0,30}$",
+ "serialNumber": -15
},
{
+ "id": -4,
"enable": false,
"name": "目录(古典、轻小说备用)",
- "rule": "^[ \\t]{0,4}(?:前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|回(?![合来事去])|场(?![和合比电是])|篇(?!张))).{0,30}$",
- "serialNumber": 3
+ "rule": "^[ \\t]{0,4}(?:序章|楔子|正文(?!完|结)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|回(?![合来事去])|场(?![和合比电是])|篇(?!张))).{0,30}$",
+ "serialNumber": -14
},
{
+ "id": -5,
"enable": false,
"name": "数字(纯数字标题)",
"rule": "(?<=[ \\s])\\d+[ \\t]{0,4}$",
- "serialNumber": 4
+ "serialNumber": -13
},
{
+ "id": -6,
"enable": true,
"name": "数字 分隔符 标题名称",
- "rule": "^[ \\t]{0,4}\\d{1,5}[\\,\\., 、\\-].{1,30}$",
- "serialNumber": 5
+ "rule": "^[ \\t]{0,4}\\d{1,5}[,., 、_—\\-].{1,30}$",
+ "serialNumber": -12
},
{
+ "id": -7,
+ "enable": true,
+ "name": "大写数字 分隔符 标题名称",
+ "rule": "^[ \\t]{0,4}[零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}[ 、_—\\-].{1,30}$",
+ "serialNumber": -11
+ },
+ {
+ "id": -8,
"enable": true,
"name": "正文 标题/序号",
"rule": "^[ \\t]{0,4}正文[ ]{1,4}.{0,20}$",
- "serialNumber": 6
+ "serialNumber": -10
},
{
+ "id": -9,
"enable": true,
"name": "Chapter/Section/Part/Episode 序号 标题",
"rule": "^[ \\t]{0,4}(?:[Cc]hapter|[Ss]ection|[Pp]art|PART|[Ee]pisode|(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外)\\s{0,4}\\d{1,4}.{0,30}$",
- "serialNumber": 7
+ "serialNumber": -9
},
{
+ "id": -10,
"enable": false,
"name": "Chapter(去简介)",
"rule": "^[ \\t]{0,4}(?:[Cc]hapter|[Ss]ection|[Pp]art|PART|[Ee]pisode)\\s{0,4}\\d{1,4}.{0,30}$",
- "serialNumber": 8
+ "serialNumber": -8
},
{
+ "id": -11,
"enable": true,
"name": "特殊符号 序号 标题",
- "rule": "(?<=[\\s ]{0,4}).{1,3}(?:第|卷|[Cc]hapter)[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,10}[章节]?[\\.:: \f\t].{0,20}$",
- "serialNumber": 9
+ "rule": "(?<=[\\s ])[【〔〖「『〈[\\[](?:第|[Cc]hapter)[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,10}[章节].{0,20}$",
+ "serialNumber": -7
},
{
+ "id": -12,
"enable": false,
"name": "特殊符号 标题(成对)",
"rule": "(?<=[\\s ]{0,4})(?:[\\[〈「『〖〔《(【\\(].{1,30}[\\)】)》〕〗』」〉\\]]?|(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外)[ ]{0,4}$",
- "serialNumber": 10
+ "serialNumber": -6
},
{
+ "id": -13,
"enable":true,
"name": "特殊符号 标题(单个)",
"rule": "(?<=[\\s ]{0,4})(?:[☆★✦✧].{1,30}|(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外)[ ]{0,4}$",
- "serialNumber": 11
+ "serialNumber": -5
},
{
+ "id": -14,
"enable": true,
"name": "章/卷 序号 标题",
"rule": "^[ \\t ]{0,4}(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外|[卷章][\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8})[ ]{0,4}.{0,30}$",
- "serialNumber": 12
+ "serialNumber": -4
},
{
+ "id": -15,
"enable":false,
"name": "顶格标题",
"rule": "^\\S.{1,20}$",
- "serialNumber": 13
+ "serialNumber": -3
},
{
+ "id": -16,
"enable":false,
"name": "双标题(前向)",
"rule": "(?m)(?<=[ \\t ]{0,4})第[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}章.{0,30}$(?=[\\s ]{0,8}第[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}章)",
- "serialNumber": 14
+ "serialNumber": -2
},
{
+ "id": -17,
"enable":false,
"name": "双标题(后向)",
"rule": "(?m)(?<=[ \\t ]{0,4}第[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}章.{0,30}$[\\s ]{0,8})第[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}章.{0,30}$",
- "serialNumber": 15
+ "serialNumber": -1
}
]
diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md
index 394bc51f9..34f05518c 100644
--- a/app/src/main/assets/updateLog.md
+++ b/app/src/main/assets/updateLog.md
@@ -1,7 +1,101 @@
## 更新日志
* 旧版数据导入教程:先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】。
-* 请关注[开源阅读]()支持我,同时关注合作公众号[小说拾遗](),阅读公众号小编。
-* 弄了个企业公众号[开源阅读](),后面弄好后会把原来的[开源阅读软件]()迁移过来
+* 请关注公众号[开源阅读]()支持我,同时关注合作公众号[小说拾遗](),阅读公众号小编。
+* 新公众号[开源阅读]()已启用,[开源阅读软件]()备用
+
+**2020/05/04**
+* 优化txt文件目录解析
+
+**2020/05/03**
+* 优化一些界面显示问题
+* 订阅源添加style
+* 修复一些重复目录的bug
+
+**2020/05/02**
+* 修复不停换源的bug
+* 修复本地书籍自动换源
+* 修复书源校验的一些问题
+
+**2020/05/01**
+* 尝试修复朗读时可能错位的bug
+* 添加自动换源配置
+* 换源添加禁用菜单
+
+**2020/04/29**
+* 修复bug
+* 订阅界面添加长按菜单
+
+**2020/04/26**
+* 添加导入旧的书源转换
+* 修复不自动朗读下一章的bug
+
+**2020/04/25**
+* 修复翻页按键设置为空时崩溃的bug
+* 翻页按键优先自定义按键,可覆盖音量按键
+* 写书源时的辅助键盘添加※
+* 更改了书源格式,不再需要转义符
+
+**2020/04/24**
+* 坚果云最近调整了策略,必须使用应用密码才能备份,用户信息,安全,第三方应用
+* text目录规则添加id字段,负值为系统自带规则
+* 其它一些优化
+
+**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,暂时退回上版本
+* 去除下载路径的配置,减少错误
+* 添加隐藏状态栏是否扩展到刘海
+
+**2020/03/24**
+* txt文件第一章之前的文字不再放到简介里
+* 优化txt目录识别,章节超过3万字判断为目录识别错误重新识别
+* 修复文件关联 by wqfantexi
**2020/03/22**
* 添加文件关联 by wqfantexi
diff --git a/app/src/main/assets/web/book.html b/app/src/main/assets/web/book.html
deleted file mode 100644
index bc7ea6c90..000000000
--- a/app/src/main/assets/web/book.html
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
- 阅读3.0书架
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/assets/web/bookshelf.html b/app/src/main/assets/web/bookshelf.html
index 87ee3bf9b..86639426f 100644
--- a/app/src/main/assets/web/bookshelf.html
+++ b/app/src/main/assets/web/bookshelf.html
@@ -1,46 +1,39 @@
-
-
+
+
-
-
-
-
- yd-web-tool
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ 阅读3.0书架
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/assets/web/index.html b/app/src/main/assets/web/index.html
index a0a00ef1c..4339538d9 100644
--- a/app/src/main/assets/web/index.html
+++ b/app/src/main/assets/web/index.html
@@ -359,8 +359,8 @@
(?i) 前缀表示忽略大小写
代码在线运行工具
- 阅读书架(经典)
- 阅读书架(新潮)
+ 阅读书架(经典)
+ 阅读书架(新潮)
diff --git a/app/src/main/assets/web/index.js b/app/src/main/assets/web/index.js
index fb2298bbd..7b0ec52a3 100644
--- a/app/src/main/assets/web/index.js
+++ b/app/src/main/assets/web/index.js
@@ -36,23 +36,28 @@ const RuleJSON = (() => {
// 搜索规则
$$('.rules .ruleSearch').forEach(item => searchJson[item.title] = '');
- ruleJson.ruleSearch = JSON.stringify(searchJson);
+ //ruleJson.ruleSearch = JSON.stringify(searchJson);
+ ruleJson.ruleSearch = searchJson;
// 发现规则
$$('.rules .ruleExplore').forEach(item => exploreJson[item.title] = '');
- ruleJson.ruleExplore = JSON.stringify(exploreJson);
+ //ruleJson.ruleExplore = JSON.stringify(exploreJson);
+ ruleJson.ruleExplore = exploreJson;
// 详情页规则
$$('.rules .ruleBookInfo').forEach(item => bookInfoJson[item.title] = '');
- ruleJson.ruleBookInfo = JSON.stringify(bookInfoJson);
+ //ruleJson.ruleBookInfo = JSON.stringify(bookInfoJson);
+ ruleJson.ruleBookInfo = bookInfoJson;
// 目录规则
$$('.rules .ruleToc').forEach(item => tocJson[item.title] = '');
- ruleJson.ruleToc = JSON.stringify(tocJson);
+ //ruleJson.ruleToc = JSON.stringify(tocJson);
+ ruleJson.ruleToc = tocJson;
// 正文规则
$$('.rules .ruleContent').forEach(item => contentJson[item.title] = '');
- ruleJson.ruleContent = JSON.stringify(contentJson);
+ //ruleJson.ruleContent = JSON.stringify(contentJson);
+ ruleJson.ruleContent = contentJson;
return ruleJson;
})();
@@ -110,38 +115,48 @@ function rule2json() {
// 转换搜索规则
let searchJson = {};
- Object.keys(JSON.parse(RuleJSON.ruleSearch)).forEach(key => {
+ //Object.keys(JSON.parse(RuleJSON.ruleSearch)).forEach(key => {
+ Object.keys(RuleJSON.ruleSearch).forEach(key => {
searchJson[key] = $('#' + 'ruleSearch_' + key).value;
});
- RuleJSON.ruleSearch = JSON.stringify(searchJson);
+ //RuleJSON.ruleSearch = JSON.stringify(searchJson);
+ RuleJSON.ruleSearch = searchJson;
// 转换发现规则
let exploreJson = {};
- Object.keys(JSON.parse(RuleJSON.ruleExplore)).forEach(key => {
+ //Object.keys(JSON.parse(RuleJSON.ruleExplore)).forEach(key => {
+ Object.keys(RuleJSON.ruleExplore).forEach(key => {
exploreJson[key] = $('#' + 'ruleExplore_' + key).value;
});
- RuleJSON.ruleExplore = JSON.stringify(exploreJson);
+ //RuleJSON.ruleExplore = JSON.stringify(exploreJson);
+ RuleJSON.ruleExplore = exploreJson;
// 转换详情页规则
let bookInfoJson = {};
- Object.keys(JSON.parse(RuleJSON.ruleBookInfo)).forEach(key => {
+ //Object.keys(JSON.parse(RuleJSON.ruleBookInfo)).forEach(key => {
+ Object.keys(RuleJSON.ruleBookInfo).forEach(key => {
bookInfoJson[key] = $('#' + 'ruleBookInfo_' + key).value;
});
- RuleJSON.ruleBookInfo = JSON.stringify(bookInfoJson);
+ //RuleJSON.ruleBookInfo = JSON.stringify(bookInfoJson);
+ RuleJSON.ruleBookInfo = bookInfoJson;
// 转换目录规则
let tocJson = {};
- Object.keys(JSON.parse(RuleJSON.ruleToc)).forEach(key => {
+ //Object.keys(JSON.parse(RuleJSON.ruleToc)).forEach(key => {
+ Object.keys(RuleJSON.ruleToc).forEach(key => {
tocJson[key] = $('#' + 'ruleToc_' + key).value;
});
- RuleJSON.ruleToc = JSON.stringify(tocJson);
+ //RuleJSON.ruleToc = JSON.stringify(tocJson);
+ RuleJSON.ruleToc = tocJson;
// 转换正文规则
let contentJson = {};
- Object.keys(JSON.parse(RuleJSON.ruleContent)).forEach(key => {
+ //Object.keys(JSON.parse(RuleJSON.ruleContent)).forEach(key => {
+ Object.keys(RuleJSON.ruleContent).forEach(key => {
contentJson[key] = $('#' + 'ruleContent_' + key).value;
});
- RuleJSON.ruleContent = JSON.stringify(contentJson);
+ //RuleJSON.ruleContent = JSON.stringify(contentJson);
+ RuleJSON.ruleContent = contentJson;
RuleJSON.lastUpdateTime = RuleJSON.lastUpdateTime == '' ? 0 : parseInt(RuleJSON.lastUpdateTime);
RuleJSON.customOrder = RuleJSON.customOrder == '' ? 0 : parseInt(RuleJSON.customOrder);
@@ -171,40 +186,50 @@ function json2rule(RuleEditor) {
// 转换搜索规则
if (RuleEditor.ruleSearch) {
- let searchJson = JSON.parse(RuleEditor.ruleSearch);
- Object.keys(JSON.parse(RuleJSON.ruleSearch)).forEach(key => {
+ //let searchJson = JSON.parse(RuleEditor.ruleSearch);
+ let searchJson = RuleEditor.ruleSearch;
+ //Object.keys(JSON.parse(RuleJSON.ruleSearch)).forEach(key => {
+ Object.keys(RuleJSON.ruleSearch).forEach(key => {
$('#' + 'ruleSearch_' + key).value = searchJson[key] ? searchJson[key] : '';
});
}
// 转换发现规则
if (RuleEditor.ruleExplore) {
- let exploreJson = JSON.parse(RuleEditor.ruleExplore);
- Object.keys(JSON.parse(RuleJSON.ruleExplore)).forEach(key => {
+ //let exploreJson = JSON.parse(RuleEditor.ruleExplore);
+ //Object.keys(JSON.parse(RuleJSON.ruleExplore)).forEach(key => {
+ let exploreJson = RuleEditor.ruleExplore;
+ Object.keys(RuleJSON.ruleExplore).forEach(key => {
$('#' + 'ruleExplore_' + key).value = exploreJson[key] ? exploreJson[key] : '';
});
}
// 转换详情页规则
if (RuleEditor.ruleBookInfo) {
- let bookInfoJson = JSON.parse(RuleEditor.ruleBookInfo);
- Object.keys(JSON.parse(RuleJSON.ruleBookInfo)).forEach(key => {
+ //let bookInfoJson = JSON.parse(RuleEditor.ruleBookInfo);
+ //Object.keys(JSON.parse(RuleJSON.ruleBookInfo)).forEach(key => {
+ let bookInfoJson = RuleEditor.ruleBookInfo;
+ Object.keys(RuleJSON.ruleBookInfo).forEach(key => {
$('#' + 'ruleBookInfo_' + key).value = bookInfoJson[key] ? bookInfoJson[key] : '';
});
}
// 转换目录规则
if (RuleEditor.ruleToc) {
- let tocJson = JSON.parse(RuleEditor.ruleToc);
- Object.keys(JSON.parse(RuleJSON.ruleToc)).forEach(key => {
+ //let tocJson = JSON.parse(RuleEditor.ruleToc);
+ //Object.keys(JSON.parse(RuleJSON.ruleToc)).forEach(key => {
+ let tocJson = RuleEditor.ruleToc;
+ Object.keys(RuleJSON.ruleToc).forEach(key => {
$('#' + 'ruleToc_' + key).value = tocJson[key] ? tocJson[key] : '';
});
}
// 转换正文规则
if (RuleEditor.ruleContent) {
- let contentJson = JSON.parse(RuleEditor.ruleContent);
- Object.keys(JSON.parse(RuleJSON.ruleContent)).forEach(key => {
+ //let contentJson = JSON.parse(RuleEditor.ruleContent);
+ //Object.keys(JSON.parse(RuleJSON.ruleContent)).forEach(key => {
+ let contentJson = RuleEditor.ruleContent;
+ Object.keys(RuleJSON.ruleContent).forEach(key => {
$('#' + 'ruleContent_' + key).value = contentJson[key] ? contentJson[key] : '';
});
}
diff --git a/app/src/main/assets/web/book.css b/app/src/main/assets/web/new/bookshelf.css
similarity index 100%
rename from app/src/main/assets/web/book.css
rename to app/src/main/assets/web/new/bookshelf.css
diff --git a/app/src/main/assets/web/new/bookshelf.html b/app/src/main/assets/web/new/bookshelf.html
new file mode 100644
index 000000000..87ee3bf9b
--- /dev/null
+++ b/app/src/main/assets/web/new/bookshelf.html
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+ yd-web-tool
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/assets/web/book.js b/app/src/main/assets/web/new/bookshelf.js
similarity index 100%
rename from app/src/main/assets/web/book.js
rename to app/src/main/assets/web/new/bookshelf.js
diff --git a/app/src/main/assets/web/css/about.f23c15cb.css b/app/src/main/assets/web/new/css/about.f23c15cb.css
similarity index 100%
rename from app/src/main/assets/web/css/about.f23c15cb.css
rename to app/src/main/assets/web/new/css/about.f23c15cb.css
diff --git a/app/src/main/assets/web/css/app.e1c0d2e4.css b/app/src/main/assets/web/new/css/app.e1c0d2e4.css
similarity index 100%
rename from app/src/main/assets/web/css/app.e1c0d2e4.css
rename to app/src/main/assets/web/new/css/app.e1c0d2e4.css
diff --git a/app/src/main/assets/web/css/chunk-vendors.ad4ff18f.css b/app/src/main/assets/web/new/css/chunk-vendors.ad4ff18f.css
similarity index 100%
rename from app/src/main/assets/web/css/chunk-vendors.ad4ff18f.css
rename to app/src/main/assets/web/new/css/chunk-vendors.ad4ff18f.css
diff --git a/app/src/main/assets/web/css/detail.42c41bd6.css b/app/src/main/assets/web/new/css/detail.42c41bd6.css
similarity index 100%
rename from app/src/main/assets/web/css/detail.42c41bd6.css
rename to app/src/main/assets/web/new/css/detail.42c41bd6.css
diff --git a/app/src/main/assets/web/fonts/element-icons.535877f5.woff b/app/src/main/assets/web/new/fonts/element-icons.535877f5.woff
similarity index 100%
rename from app/src/main/assets/web/fonts/element-icons.535877f5.woff
rename to app/src/main/assets/web/new/fonts/element-icons.535877f5.woff
diff --git a/app/src/main/assets/web/fonts/element-icons.732389de.ttf b/app/src/main/assets/web/new/fonts/element-icons.732389de.ttf
similarity index 100%
rename from app/src/main/assets/web/fonts/element-icons.732389de.ttf
rename to app/src/main/assets/web/new/fonts/element-icons.732389de.ttf
diff --git a/app/src/main/assets/web/fonts/iconfont.f9a3fb0e.woff b/app/src/main/assets/web/new/fonts/iconfont.f9a3fb0e.woff
similarity index 100%
rename from app/src/main/assets/web/fonts/iconfont.f9a3fb0e.woff
rename to app/src/main/assets/web/new/fonts/iconfont.f9a3fb0e.woff
diff --git a/app/src/main/assets/web/fonts/popfont.f39ecc1a.ttf b/app/src/main/assets/web/new/fonts/popfont.f39ecc1a.ttf
similarity index 100%
rename from app/src/main/assets/web/fonts/popfont.f39ecc1a.ttf
rename to app/src/main/assets/web/new/fonts/popfont.f39ecc1a.ttf
diff --git a/app/src/main/assets/web/fonts/shelffont.6c094b6d.ttf b/app/src/main/assets/web/new/fonts/shelffont.6c094b6d.ttf
similarity index 100%
rename from app/src/main/assets/web/fonts/shelffont.6c094b6d.ttf
rename to app/src/main/assets/web/new/fonts/shelffont.6c094b6d.ttf
diff --git a/app/src/main/assets/web/img/icons/android-chrome-192x192.png b/app/src/main/assets/web/new/img/icons/android-chrome-192x192.png
similarity index 100%
rename from app/src/main/assets/web/img/icons/android-chrome-192x192.png
rename to app/src/main/assets/web/new/img/icons/android-chrome-192x192.png
diff --git a/app/src/main/assets/web/img/icons/android-chrome-512x512.png b/app/src/main/assets/web/new/img/icons/android-chrome-512x512.png
similarity index 100%
rename from app/src/main/assets/web/img/icons/android-chrome-512x512.png
rename to app/src/main/assets/web/new/img/icons/android-chrome-512x512.png
diff --git a/app/src/main/assets/web/img/icons/apple-touch-icon-120x120.png b/app/src/main/assets/web/new/img/icons/apple-touch-icon-120x120.png
similarity index 100%
rename from app/src/main/assets/web/img/icons/apple-touch-icon-120x120.png
rename to app/src/main/assets/web/new/img/icons/apple-touch-icon-120x120.png
diff --git a/app/src/main/assets/web/img/icons/apple-touch-icon-152x152.png b/app/src/main/assets/web/new/img/icons/apple-touch-icon-152x152.png
similarity index 100%
rename from app/src/main/assets/web/img/icons/apple-touch-icon-152x152.png
rename to app/src/main/assets/web/new/img/icons/apple-touch-icon-152x152.png
diff --git a/app/src/main/assets/web/img/icons/apple-touch-icon-180x180.png b/app/src/main/assets/web/new/img/icons/apple-touch-icon-180x180.png
similarity index 100%
rename from app/src/main/assets/web/img/icons/apple-touch-icon-180x180.png
rename to app/src/main/assets/web/new/img/icons/apple-touch-icon-180x180.png
diff --git a/app/src/main/assets/web/img/icons/apple-touch-icon-60x60.png b/app/src/main/assets/web/new/img/icons/apple-touch-icon-60x60.png
similarity index 100%
rename from app/src/main/assets/web/img/icons/apple-touch-icon-60x60.png
rename to app/src/main/assets/web/new/img/icons/apple-touch-icon-60x60.png
diff --git a/app/src/main/assets/web/img/icons/apple-touch-icon-76x76.png b/app/src/main/assets/web/new/img/icons/apple-touch-icon-76x76.png
similarity index 100%
rename from app/src/main/assets/web/img/icons/apple-touch-icon-76x76.png
rename to app/src/main/assets/web/new/img/icons/apple-touch-icon-76x76.png
diff --git a/app/src/main/assets/web/img/icons/apple-touch-icon.png b/app/src/main/assets/web/new/img/icons/apple-touch-icon.png
similarity index 100%
rename from app/src/main/assets/web/img/icons/apple-touch-icon.png
rename to app/src/main/assets/web/new/img/icons/apple-touch-icon.png
diff --git a/app/src/main/assets/web/img/icons/favicon-16x16.png b/app/src/main/assets/web/new/img/icons/favicon-16x16.png
similarity index 100%
rename from app/src/main/assets/web/img/icons/favicon-16x16.png
rename to app/src/main/assets/web/new/img/icons/favicon-16x16.png
diff --git a/app/src/main/assets/web/img/icons/favicon-32x32.png b/app/src/main/assets/web/new/img/icons/favicon-32x32.png
similarity index 100%
rename from app/src/main/assets/web/img/icons/favicon-32x32.png
rename to app/src/main/assets/web/new/img/icons/favicon-32x32.png
diff --git a/app/src/main/assets/web/img/icons/msapplication-icon-144x144.png b/app/src/main/assets/web/new/img/icons/msapplication-icon-144x144.png
similarity index 100%
rename from app/src/main/assets/web/img/icons/msapplication-icon-144x144.png
rename to app/src/main/assets/web/new/img/icons/msapplication-icon-144x144.png
diff --git a/app/src/main/assets/web/img/icons/mstile-150x150.png b/app/src/main/assets/web/new/img/icons/mstile-150x150.png
similarity index 100%
rename from app/src/main/assets/web/img/icons/mstile-150x150.png
rename to app/src/main/assets/web/new/img/icons/mstile-150x150.png
diff --git a/app/src/main/assets/web/img/icons/safari-pinned-tab.svg b/app/src/main/assets/web/new/img/icons/safari-pinned-tab.svg
similarity index 100%
rename from app/src/main/assets/web/img/icons/safari-pinned-tab.svg
rename to app/src/main/assets/web/new/img/icons/safari-pinned-tab.svg
diff --git a/app/src/main/assets/web/img/noCover.b5c48bc1.jpeg b/app/src/main/assets/web/new/img/noCover.b5c48bc1.jpeg
similarity index 100%
rename from app/src/main/assets/web/img/noCover.b5c48bc1.jpeg
rename to app/src/main/assets/web/new/img/noCover.b5c48bc1.jpeg
diff --git a/app/src/main/assets/web/js/about.2589b5fe.js b/app/src/main/assets/web/new/js/about.2589b5fe.js
similarity index 100%
rename from app/src/main/assets/web/js/about.2589b5fe.js
rename to app/src/main/assets/web/new/js/about.2589b5fe.js
diff --git a/app/src/main/assets/web/js/about~detail.08c372e6.js b/app/src/main/assets/web/new/js/about~detail.08c372e6.js
similarity index 100%
rename from app/src/main/assets/web/js/about~detail.08c372e6.js
rename to app/src/main/assets/web/new/js/about~detail.08c372e6.js
diff --git a/app/src/main/assets/web/js/app.b25f3cec.js b/app/src/main/assets/web/new/js/app.b25f3cec.js
similarity index 100%
rename from app/src/main/assets/web/js/app.b25f3cec.js
rename to app/src/main/assets/web/new/js/app.b25f3cec.js
diff --git a/app/src/main/assets/web/js/chunk-vendors.b3838a2d.js b/app/src/main/assets/web/new/js/chunk-vendors.b3838a2d.js
similarity index 100%
rename from app/src/main/assets/web/js/chunk-vendors.b3838a2d.js
rename to app/src/main/assets/web/new/js/chunk-vendors.b3838a2d.js
diff --git a/app/src/main/assets/web/js/detail.043d6e39.js b/app/src/main/assets/web/new/js/detail.043d6e39.js
similarity index 100%
rename from app/src/main/assets/web/js/detail.043d6e39.js
rename to app/src/main/assets/web/new/js/detail.043d6e39.js
diff --git a/app/src/main/assets/web/manifest.json b/app/src/main/assets/web/new/manifest.json
similarity index 100%
rename from app/src/main/assets/web/manifest.json
rename to app/src/main/assets/web/new/manifest.json
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..cf37e2b10 100644
--- a/app/src/main/java/io/legado/app/constant/AppConst.kt
+++ b/app/src/main/java/io/legado/app/constant/AppConst.kt
@@ -41,17 +41,30 @@ object AppConst {
val keyboardToolChars: List by lazy {
arrayListOf(
- "@", "&", "|", "%", "/", ":", "[", "]", "{", "}", "<", ">", "\\", "$", "#", "!", ".",
- "href", "src", "textNodes", "xpath", "json", "css", "id", "class", "tag"
+ "※", "@", "&", "|", "%", "/", ":", "[", "]", "{", "}", "<", ">", "\\",
+ "$", "#", "!", ".", "href", "src", "textNodes", "xpath", "json", "css",
+ "id", "class", "tag"
)
}
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
const val notificationIdWeb = 1144773
const val notificationIdDownload = 1144774
+
+ val urlOption: String by lazy {
+ """
+ ,{
+ "charset": "",
+ "method": "POST",
+ "body": "",
+ "headers": {"User-Agent": ""}
+ }
+ """.trimIndent()
+ }
}
\ No newline at end of file
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..d2256dd85 100644
--- a/app/src/main/java/io/legado/app/data/AppDatabase.kt
+++ b/app/src/main/java/io/legado/app/data/AppDatabase.kt
@@ -4,6 +4,7 @@ import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
+import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import io.legado.app.data.dao.*
import io.legado.app.data.entities.*
@@ -18,7 +19,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 = 12,
exportSchema = true
)
abstract class AppDatabase : RoomDatabase() {
@@ -30,6 +31,7 @@ abstract class AppDatabase : RoomDatabase() {
fun createDatabase(context: Context): AppDatabase {
return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
.fallbackToDestructiveMigration()
+ .addMigrations(migration_10_11, migration_11_12)
.addCallback(object : Callback() {
override fun onDestructiveMigration(db: SupportSQLiteDatabase) {
GlobalScope.launch { Restore.restoreDatabase(Backup.backupPath) }
@@ -37,6 +39,29 @@ abstract class AppDatabase : RoomDatabase() {
})
.build()
}
+
+ private val migration_10_11 = object : Migration(10, 11) {
+ override fun migrate(database: SupportSQLiteDatabase) {
+ database.execSQL("DROP TABLE txtTocRules")
+ database.execSQL(
+ """
+ CREATE TABLE txtTocRules(id INTEGER NOT NULL,
+ name TEXT NOT NULL, rule TEXT NOT NULL, serialNumber INTEGER NOT NULL,
+ enable INTEGER NOT NULL, PRIMARY KEY (id))
+ """
+ )
+ }
+ }
+
+ private val migration_11_12 = object : Migration(11, 12) {
+ override fun migrate(database: SupportSQLiteDatabase) {
+ database.execSQL(
+ """
+ ALTER TABLE rssSources ADD style TEXT
+ """
+ )
+ }
+ }
}
abstract fun bookDao(): BookDao
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/dao/TxtTocRuleDao.kt b/app/src/main/java/io/legado/app/data/dao/TxtTocRuleDao.kt
index 1bd502a09..d1b023896 100644
--- a/app/src/main/java/io/legado/app/data/dao/TxtTocRuleDao.kt
+++ b/app/src/main/java/io/legado/app/data/dao/TxtTocRuleDao.kt
@@ -28,4 +28,6 @@ interface TxtTocRuleDao {
@Delete
fun delete(vararg rule: TxtTocRule)
+ @Query("delete from txtTocRules where id < 0")
+ fun deleteDefault()
}
\ No newline at end of file
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..1cb9a0269 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
@@ -1,10 +1,7 @@
package io.legado.app.data.entities
import android.os.Parcelable
-import androidx.room.Entity
-import androidx.room.Ignore
-import androidx.room.Index
-import androidx.room.PrimaryKey
+import androidx.room.*
import io.legado.app.App
import io.legado.app.constant.AppConst
import io.legado.app.constant.AppConst.userAgent
@@ -15,12 +12,12 @@ import io.legado.app.utils.ACache
import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonObject
import io.legado.app.utils.getPrefString
-import kotlinx.android.parcel.IgnoredOnParcel
import kotlinx.android.parcel.Parcelize
import java.util.*
import javax.script.SimpleBindings
@Parcelize
+@TypeConverters(BookSource.Converters::class)
@Entity(
tableName = "book_sources",
indices = [(Index(value = ["bookSourceUrl"], unique = false))]
@@ -40,12 +37,12 @@ data class BookSource(
var lastUpdateTime: Long = 0, // 最后更新时间,用于排序
var weight: Int = 0, // 智能排序的权重
var exploreUrl: String? = null, // 发现url
- var ruleExplore: String? = null, // 发现规则
+ var ruleExplore: ExploreRule? = null, // 发现规则
var searchUrl: String? = null, // 搜索url
- var ruleSearch: String? = null, // 搜索规则
- var ruleBookInfo: String? = null, // 书籍信息页规则
- var ruleToc: String? = null, // 目录页规则
- var ruleContent: String? = null // 正文页规则
+ var ruleSearch: SearchRule? = null, // 搜索规则
+ var ruleBookInfo: BookInfoRule? = null, // 书籍信息页规则
+ var ruleToc: TocRule? = null, // 目录页规则
+ var ruleContent: ContentRule? = null // 正文页规则
) : Parcelable, JsExtensions {
override fun hashCode(): Int {
@@ -59,26 +56,6 @@ data class BookSource(
return false
}
- @Ignore
- @IgnoredOnParcel
- private var searchRuleV: SearchRule? = null
-
- @Ignore
- @IgnoredOnParcel
- private var exploreRuleV: ExploreRule? = null
-
- @Ignore
- @IgnoredOnParcel
- private var bookInfoRuleV: BookInfoRule? = null
-
- @Ignore
- @IgnoredOnParcel
- private var tocRuleV: TocRule? = null
-
- @Ignore
- @IgnoredOnParcel
- private var contentRuleV: ContentRule? = null
-
@Throws(Exception::class)
fun getHeaderMap(): Map {
val headerMap = HashMap()
@@ -99,43 +76,23 @@ data class BookSource(
}
fun getSearchRule(): SearchRule {
- searchRuleV ?: let {
- searchRuleV = GSON.fromJsonObject(ruleSearch)
- searchRuleV ?: let { searchRuleV = SearchRule() }
- }
- return searchRuleV!!
+ return ruleSearch ?: SearchRule()
}
fun getExploreRule(): ExploreRule {
- exploreRuleV ?: let {
- exploreRuleV = GSON.fromJsonObject(ruleExplore)
- exploreRuleV ?: let { exploreRuleV = ExploreRule() }
- }
- return exploreRuleV!!
+ return ruleExplore ?: ExploreRule()
}
fun getBookInfoRule(): BookInfoRule {
- bookInfoRuleV ?: let {
- bookInfoRuleV = GSON.fromJsonObject(ruleBookInfo)
- bookInfoRuleV ?: let { bookInfoRuleV = BookInfoRule() }
- }
- return bookInfoRuleV!!
+ return ruleBookInfo ?: BookInfoRule()
}
fun getTocRule(): TocRule {
- tocRuleV ?: let {
- tocRuleV = GSON.fromJsonObject(ruleToc)
- tocRuleV ?: let { tocRuleV = TocRule() }
- }
- return tocRuleV!!
+ return ruleToc ?: TocRule()
}
fun getContentRule(): ContentRule {
- contentRuleV ?: let {
- contentRuleV = GSON.fromJsonObject(ruleContent)
- contentRuleV ?: let { contentRuleV = ContentRule() }
- }
- return contentRuleV!!
+ return ruleContent ?: ContentRule()
}
fun addGroup(group: String) {
@@ -169,7 +126,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]))
@@ -219,4 +176,57 @@ data class BookSource(
var title: String,
var url: String? = null
)
+
+ class Converters {
+ @TypeConverter
+ fun exploreRuleToString(exploreRule: ExploreRule?): String {
+ return GSON.toJson(exploreRule)
+ }
+
+ @TypeConverter
+ fun stringToExploreRule(json: String?): ExploreRule? {
+ return GSON.fromJsonObject(json)
+ }
+
+ @TypeConverter
+ fun searchRuleToString(searchRule: SearchRule): String {
+ return GSON.toJson(searchRule)
+ }
+
+ @TypeConverter
+ fun stringToSearchRule(json: String?): SearchRule? {
+ return GSON.fromJsonObject(json)
+ }
+
+ @TypeConverter
+ fun bookInfoRuleToString(bookInfoRule: BookInfoRule): String {
+ return GSON.toJson(bookInfoRule)
+ }
+
+ @TypeConverter
+ fun stringToBookInfoRule(json: String?): BookInfoRule? {
+ return GSON.fromJsonObject(json)
+ }
+
+ @TypeConverter
+ fun tocRuleToString(tocRule: TocRule): String {
+ return GSON.toJson(tocRule)
+ }
+
+ @TypeConverter
+ fun stringToTocRule(json: String?): TocRule? {
+ return GSON.fromJsonObject(json)
+ }
+
+ @TypeConverter
+ fun contentRuleToString(contentRule: ContentRule): String {
+ return GSON.toJson(contentRule)
+ }
+
+ @TypeConverter
+ fun stringToContentRule(json: String?): ContentRule? {
+ return GSON.fromJsonObject(json)
+ }
+
+ }
}
\ No newline at end of file
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..d9ae5531b 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 = "",
@@ -20,7 +21,7 @@ data class RssArticle(
) {
override fun hashCode(): Int {
- return super.hashCode()
+ return link.hashCode()
}
override fun equals(other: Any?): Boolean {
@@ -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..a7948e6e7 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,
@@ -33,9 +34,11 @@ data class RssSource(
var ruleImage: String? = null,
var ruleLink: String? = null,
var ruleContent: String? = null,
+ var style: String? = null,
var header: String? = null,
var enableJs: Boolean = false,
var loadWithBaseUrl: Boolean = false,
+
var customOrder: Int = 0
) : Parcelable, JsExtensions {
@@ -99,4 +102,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/data/entities/TxtTocRule.kt b/app/src/main/java/io/legado/app/data/entities/TxtTocRule.kt
index cdfca7567..52669dab7 100644
--- a/app/src/main/java/io/legado/app/data/entities/TxtTocRule.kt
+++ b/app/src/main/java/io/legado/app/data/entities/TxtTocRule.kt
@@ -7,6 +7,7 @@ import androidx.room.PrimaryKey
@Entity(tableName = "txtTocRules")
data class TxtTocRule(
@PrimaryKey
+ var id: Long = System.currentTimeMillis(),
var name: String = "",
var rule: String = "",
var serialNumber: Int = -1,
diff --git a/app/src/main/java/io/legado/app/data/entities/rule/BookInfoRule.kt b/app/src/main/java/io/legado/app/data/entities/rule/BookInfoRule.kt
index a28f3c6e6..57fa3c495 100644
--- a/app/src/main/java/io/legado/app/data/entities/rule/BookInfoRule.kt
+++ b/app/src/main/java/io/legado/app/data/entities/rule/BookInfoRule.kt
@@ -1,5 +1,8 @@
package io.legado.app.data.entities.rule
+import android.os.Parcel
+import android.os.Parcelable
+
data class BookInfoRule(
var init: String? = null,
var name: String? = null,
@@ -11,4 +14,45 @@ data class BookInfoRule(
var coverUrl: String? = null,
var tocUrl: String? = null,
var wordCount: String? = null
-)
\ No newline at end of file
+) : Parcelable {
+
+ constructor(parcel: Parcel) : this(
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString()
+ )
+
+ override fun writeToParcel(dest: Parcel, flags: Int) {
+ dest.writeString(init)
+ dest.writeString(name)
+ dest.writeString(author)
+ dest.writeString(intro)
+ dest.writeString(kind)
+ dest.writeString(lastChapter)
+ dest.writeString(updateTime)
+ dest.writeString(coverUrl)
+ dest.writeString(tocUrl)
+ dest.writeString(wordCount)
+ }
+
+ override fun describeContents(): Int {
+ return 0
+ }
+
+ companion object CREATOR : Parcelable.Creator {
+ override fun createFromParcel(parcel: Parcel): BookInfoRule {
+ return BookInfoRule(parcel)
+ }
+
+ override fun newArray(size: Int): Array {
+ return arrayOfNulls(size)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/data/entities/rule/ContentRule.kt b/app/src/main/java/io/legado/app/data/entities/rule/ContentRule.kt
index b0fe78614..306e7e659 100644
--- a/app/src/main/java/io/legado/app/data/entities/rule/ContentRule.kt
+++ b/app/src/main/java/io/legado/app/data/entities/rule/ContentRule.kt
@@ -1,8 +1,39 @@
package io.legado.app.data.entities.rule
+import android.os.Parcel
+import android.os.Parcelable
+
data class ContentRule(
var content: String? = null,
var nextContentUrl: String? = null,
var webJs: String? = null,
var sourceRegex: String? = null
-)
\ No newline at end of file
+) : Parcelable {
+ constructor(parcel: Parcel) : this(
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString()
+ )
+
+ override fun writeToParcel(dest: Parcel, flags: Int) {
+ dest.writeString(content)
+ dest.writeString(nextContentUrl)
+ dest.writeString(webJs)
+ dest.writeString(sourceRegex)
+ }
+
+ override fun describeContents(): Int {
+ return 0
+ }
+
+ companion object CREATOR : Parcelable.Creator {
+ override fun createFromParcel(parcel: Parcel): ContentRule {
+ return ContentRule(parcel)
+ }
+
+ override fun newArray(size: Int): Array {
+ return arrayOfNulls(size)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/data/entities/rule/ExploreRule.kt b/app/src/main/java/io/legado/app/data/entities/rule/ExploreRule.kt
index 22b267ed3..8ccbe8aba 100644
--- a/app/src/main/java/io/legado/app/data/entities/rule/ExploreRule.kt
+++ b/app/src/main/java/io/legado/app/data/entities/rule/ExploreRule.kt
@@ -1,5 +1,8 @@
package io.legado.app.data.entities.rule
+import android.os.Parcel
+import android.os.Parcelable
+
data class ExploreRule(
override var bookList: String? = null,
override var name: String? = null,
@@ -11,4 +14,46 @@ data class ExploreRule(
override var bookUrl: String? = null,
override var coverUrl: String? = null,
override var wordCount: String? = null
-) : BookListRule
\ No newline at end of file
+) : BookListRule, Parcelable {
+
+ constructor(parcel: Parcel) : this(
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString()
+ )
+
+ override fun writeToParcel(dest: Parcel, flags: Int) {
+ dest.writeString(bookList)
+ dest.writeString(name)
+ dest.writeString(author)
+ dest.writeString(intro)
+ dest.writeString(kind)
+ dest.writeString(lastChapter)
+ dest.writeString(updateTime)
+ dest.writeString(bookUrl)
+ dest.writeString(coverUrl)
+ dest.writeString(wordCount)
+ }
+
+ override fun describeContents(): Int {
+ return 0
+ }
+
+ companion object CREATOR : Parcelable.Creator {
+ override fun createFromParcel(parcel: Parcel): ExploreRule {
+ return ExploreRule(parcel)
+ }
+
+ override fun newArray(size: Int): Array {
+ return arrayOfNulls(size)
+ }
+ }
+}
+
diff --git a/app/src/main/java/io/legado/app/data/entities/rule/SearchRule.kt b/app/src/main/java/io/legado/app/data/entities/rule/SearchRule.kt
index 83921e56d..3968226e2 100644
--- a/app/src/main/java/io/legado/app/data/entities/rule/SearchRule.kt
+++ b/app/src/main/java/io/legado/app/data/entities/rule/SearchRule.kt
@@ -1,5 +1,8 @@
package io.legado.app.data.entities.rule
+import android.os.Parcel
+import android.os.Parcelable
+
data class SearchRule(
override var bookList: String? = null,
override var name: String? = null,
@@ -11,4 +14,46 @@ data class SearchRule(
override var bookUrl: String? = null,
override var coverUrl: String? = null,
override var wordCount: String? = null
-) : BookListRule
\ No newline at end of file
+) : BookListRule, Parcelable {
+
+ constructor(parcel: Parcel) : this(
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString()
+ )
+
+ override fun writeToParcel(dest: Parcel, flags: Int) {
+ dest.writeString(bookList)
+ dest.writeString(name)
+ dest.writeString(author)
+ dest.writeString(intro)
+ dest.writeString(kind)
+ dest.writeString(lastChapter)
+ dest.writeString(updateTime)
+ dest.writeString(bookUrl)
+ dest.writeString(coverUrl)
+ dest.writeString(wordCount)
+ }
+
+ override fun describeContents(): Int {
+ return 0
+ }
+
+ companion object CREATOR : Parcelable.Creator {
+ override fun createFromParcel(parcel: Parcel): SearchRule {
+ return SearchRule(parcel)
+ }
+
+ override fun newArray(size: Int): Array {
+ return arrayOfNulls(size)
+ }
+ }
+}
+
diff --git a/app/src/main/java/io/legado/app/data/entities/rule/TocRule.kt b/app/src/main/java/io/legado/app/data/entities/rule/TocRule.kt
index c484e7226..d49a08e33 100644
--- a/app/src/main/java/io/legado/app/data/entities/rule/TocRule.kt
+++ b/app/src/main/java/io/legado/app/data/entities/rule/TocRule.kt
@@ -1,5 +1,8 @@
package io.legado.app.data.entities.rule
+import android.os.Parcel
+import android.os.Parcelable
+
data class TocRule(
var chapterList: String? = null,
var chapterName: String? = null,
@@ -7,4 +10,36 @@ data class TocRule(
var isVip: String? = null,
var updateTime: String? = null,
var nextTocUrl: String? = null
-)
\ No newline at end of file
+) : Parcelable {
+ constructor(parcel: Parcel) : this(
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString(),
+ parcel.readString()
+ )
+
+ override fun writeToParcel(dest: Parcel, flags: Int) {
+ dest.writeString(chapterList)
+ dest.writeString(chapterName)
+ dest.writeString(chapterUrl)
+ dest.writeString(isVip)
+ dest.writeString(updateTime)
+ dest.writeString(nextTocUrl)
+ }
+
+ override fun describeContents(): Int {
+ return 0
+ }
+
+ companion object CREATOR : Parcelable.Creator {
+ override fun createFromParcel(parcel: Parcel): TocRule {
+ return TocRule(parcel)
+ }
+
+ override fun newArray(size: Int): Array {
+ return arrayOfNulls(size)
+ }
+ }
+}
\ No newline at end of file
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 2e336fdad..547322cce 100644
--- a/app/src/main/java/io/legado/app/help/AppConfig.kt
+++ b/app/src/main/java/io/legado/app/help/AppConfig.kt
@@ -115,12 +115,23 @@ 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 autoChangeSource: Boolean get() = App.INSTANCE.getPrefBoolean("autoChangeSource", true)
+
+ val readBodyToLh: Boolean get() = App.INSTANCE.getPrefBoolean(PreferKey.readBodyToLh, true)
+
+ val isGooglePlay: Boolean get() = App.INSTANCE.channel == "google"
}
val Context.channel: String
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 b6e3ec000..3c0fa644e 100644
--- a/app/src/main/java/io/legado/app/help/BookHelp.kt
+++ b/app/src/main/java/io/legado/app/help/BookHelp.kt
@@ -1,16 +1,16 @@
package io.legado.app.help
-import android.net.Uri
-import androidx.documentfile.provider.DocumentFile
-import com.github.houbb.opencc4j.core.impl.ZhConvertBootstrap
+import com.hankcs.hanlp.HanLP
import io.legado.app.App
-import io.legado.app.R
import io.legado.app.constant.EventBus
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter
import io.legado.app.data.entities.ReplaceRule
import io.legado.app.model.localBook.AnalyzeTxtFile
-import io.legado.app.utils.*
+import io.legado.app.utils.FileUtils
+import io.legado.app.utils.MD5Utils
+import io.legado.app.utils.postEvent
+import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.withContext
import org.apache.commons.text.similarity.JaccardSimilarity
@@ -20,12 +20,9 @@ import kotlin.math.min
object BookHelp {
private const val cacheFolderName = "book_cache"
- val downloadPath: String
- get() = App.INSTANCE.getPrefString(R.string.pk_download_path)
- ?: App.INSTANCE.getExternalFilesDir(null)?.absolutePath
- ?: App.INSTANCE.cacheDir.absolutePath
-
- private val downloadUri get() = Uri.parse(downloadPath)
+ private val downloadDir: File =
+ App.INSTANCE.getExternalFilesDir(null)
+ ?: App.INSTANCE.cacheDir
private fun bookFolderName(book: Book): String {
return formatFolderName(book.name) + MD5Utils.md5Encode16(book.bookUrl)
@@ -40,137 +37,73 @@ object BookHelp {
}
fun clearCache() {
- if (downloadPath.isContentPath()) {
- DocumentFile.fromTreeUri(App.INSTANCE, downloadUri)
- ?.findFile(cacheFolderName)
- ?.delete()
- } else {
- FileUtils.deleteFile(
- FileUtils.getPath(
- File(downloadPath),
- subDirs = *arrayOf(cacheFolderName)
- )
+ FileUtils.deleteFile(
+ FileUtils.getPath(
+ downloadDir,
+ subDirs = *arrayOf(cacheFolderName)
)
- }
+ )
}
@Synchronized
fun saveContent(book: Book, bookChapter: BookChapter, content: String) {
if (content.isEmpty()) return
- if (downloadPath.isContentPath()) {
- DocumentFile.fromTreeUri(App.INSTANCE, downloadUri)?.let { root ->
- DocumentUtils.createFileIfNotExist(
- root,
- formatChapterName(bookChapter),
- subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
- )?.uri?.writeText(App.INSTANCE, content)
- }
- } else {
- FileUtils.createFileIfNotExist(
- File(downloadPath),
- formatChapterName(bookChapter),
- subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
- ).writeText(content)
- }
+ FileUtils.createFileIfNotExist(
+ downloadDir,
+ formatChapterName(bookChapter),
+ subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
+ ).writeText(content)
postEvent(EventBus.SAVE_CONTENT, bookChapter)
}
fun getChapterFiles(book: Book): List {
val fileNameList = arrayListOf()
- if (downloadPath.isContentPath()) {
- DocumentFile.fromTreeUri(App.INSTANCE, downloadUri)?.let { root ->
- DocumentUtils.createFolderIfNotExist(
- root,
- subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
- )?.let { bookDoc ->
- DocumentUtils.listFiles(App.INSTANCE, bookDoc.uri).forEach {
- fileNameList.add(it.name)
- }
- }
- }
- } else {
- FileUtils.createFolderIfNotExist(
- File(downloadPath),
- subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
- ).list()?.let {
- fileNameList.addAll(it)
- }
+ FileUtils.createFolderIfNotExist(
+ downloadDir,
+ subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
+ ).list()?.let {
+ fileNameList.addAll(it)
}
return fileNameList
}
fun hasContent(book: Book, bookChapter: BookChapter): Boolean {
- when {
- book.isLocalBook() -> {
- return true
- }
- downloadPath.isContentPath() -> {
- DocumentFile.fromTreeUri(App.INSTANCE, downloadUri)?.let { root ->
- return DocumentUtils.exists(
- root,
- formatChapterName(bookChapter),
- subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
- )
- }
- }
- else -> {
- return FileUtils.exists(
- File(downloadPath),
- formatChapterName(bookChapter),
- subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
- )
- }
+ return if (book.isLocalBook()) {
+ true
+ } else {
+ FileUtils.exists(
+ downloadDir,
+ formatChapterName(bookChapter),
+ subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
+ )
}
- return false
}
fun getContent(book: Book, bookChapter: BookChapter): String? {
- when {
- book.isLocalBook() -> {
- return AnalyzeTxtFile.getContent(book, bookChapter)
- }
- downloadPath.isContentPath() -> {
- DocumentFile.fromTreeUri(App.INSTANCE, downloadUri)?.let { root ->
- return DocumentUtils.getDirDocument(
- root,
- subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
- )?.findFile(formatChapterName(bookChapter))
- ?.uri?.readText(App.INSTANCE)
- }
- }
- else -> {
- val file = FileUtils.getFile(
- File(downloadPath),
- formatChapterName(bookChapter),
- subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
- )
- if (file.exists()) {
- return file.readText()
- }
+ if (book.isLocalBook()) {
+ return AnalyzeTxtFile.getContent(book, bookChapter)
+ } else {
+ val file = FileUtils.getFile(
+ downloadDir,
+ formatChapterName(bookChapter),
+ subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
+ )
+ if (file.exists()) {
+ return file.readText()
}
}
return null
}
fun delContent(book: Book, bookChapter: BookChapter) {
- when {
- book.isLocalBook() -> return
- downloadPath.isContentPath() -> {
- DocumentFile.fromTreeUri(App.INSTANCE, downloadUri)?.let { root ->
- DocumentUtils.getDirDocument(
- root,
- subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
- )?.findFile(formatChapterName(bookChapter))
- ?.delete()
- }
- }
- else -> {
- FileUtils.createFileIfNotExist(
- File(downloadPath),
- formatChapterName(bookChapter),
- subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
- ).delete()
- }
+ if (book.isLocalBook()) {
+ return
+ } else {
+ FileUtils.createFileIfNotExist(
+ downloadDir,
+ formatChapterName(bookChapter),
+ subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
+ ).delete()
}
}
@@ -242,24 +175,16 @@ object BookHelp {
private var replaceRules: List = arrayListOf()
@Synchronized
- fun upReplaceRules(name: String? = null, origin: String? = null) {
- if (name != null) {
- if (bookName != name || bookOrigin != origin) {
- replaceRules = if (origin.isNullOrEmpty()) {
- App.db.replaceRuleDao().findEnabledByScope(name)
- } else {
- App.db.replaceRuleDao().findEnabledByScope(name, origin)
- }
- bookName = name
- bookOrigin = origin
- }
- } else {
- val o = bookOrigin
- bookName?.let {
- replaceRules = if (o.isNullOrEmpty()) {
- App.db.replaceRuleDao().findEnabledByScope(it)
- } else {
- App.db.replaceRuleDao().findEnabledByScope(it, o)
+ suspend fun upReplaceRules() {
+ withContext(IO) {
+ synchronized(this) {
+ val o = bookOrigin
+ bookName?.let {
+ replaceRules = if (o.isNullOrEmpty()) {
+ App.db.replaceRuleDao().findEnabledByScope(it)
+ } else {
+ App.db.replaceRuleDao().findEnabledByScope(it, o)
+ }
}
}
}
@@ -271,10 +196,20 @@ object BookHelp {
origin: String?,
content: String,
enableReplace: Boolean
- ): String {
+ ): List {
var c = content
if (enableReplace) {
- upReplaceRules(name, origin)
+ synchronized(this) {
+ if (bookName != name || bookOrigin != origin) {
+ bookName = name
+ bookOrigin = origin
+ replaceRules = if (origin.isNullOrEmpty()) {
+ App.db.replaceRuleDao().findEnabledByScope(name)
+ } else {
+ App.db.replaceRuleDao().findEnabledByScope(name, origin)
+ }
+ }
+ }
replaceRules.forEach { item ->
item.pattern.let {
if (it.isNotEmpty()) {
@@ -293,15 +228,29 @@ object BookHelp {
}
}
}
- if (!c.substringBefore("\n").contains(title)) {
- c = "$title\n$c"
+ try {
+ when (AppConfig.chineseConverterType) {
+ 1 -> c = HanLP.convertToSimplifiedChinese(c)
+ 2 -> c = HanLP.convertToTraditionalChinese(c)
+ }
+ } catch (e: Exception) {
+ withContext(Main) {
+ App.INSTANCE.toast("简繁转换出错")
+ }
}
- when (AppConfig.chineseConverterType) {
- 1 -> c = ZhConvertBootstrap.newInstance().toSimple(c)
- 2 -> c = ZhConvertBootstrap.newInstance().toTraditional(c)
+ val contents = arrayListOf()
+ c.split("\n").forEach {
+ val str = it.replace("^\\s+".toRegex(), "")
+ .replace("\r", "")
+ if (contents.isEmpty()) {
+ contents.add(title)
+ if (str != title && it.isNotEmpty()) {
+ contents.add("${ReadBookConfig.bodyIndent}$str")
+ }
+ } else if (str.isNotEmpty()) {
+ contents.add("${ReadBookConfig.bodyIndent}$str")
+ }
}
- return c
- .replace("\\s*\\n+\\s*".toRegex(), "\n${ReadBookConfig.bodyIndent}")
- .replace("[\\n\\s]+$".toRegex(), "") //移除尾部空行
+ return contents
}
}
\ 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/http/HttpHelper.kt b/app/src/main/java/io/legado/app/help/http/HttpHelper.kt
index df417e2f9..31064e268 100644
--- a/app/src/main/java/io/legado/app/help/http/HttpHelper.kt
+++ b/app/src/main/java/io/legado/app/help/http/HttpHelper.kt
@@ -3,9 +3,11 @@ package io.legado.app.help.http
import io.legado.app.help.http.api.HttpGetApi
import io.legado.app.utils.NetworkUtils
import kotlinx.coroutines.suspendCancellableCoroutine
-import okhttp3.*
+import okhttp3.ConnectionSpec
+import okhttp3.Interceptor
+import okhttp3.OkHttpClient
+import okhttp3.Protocol
import retrofit2.Retrofit
-import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.coroutines.resume
@@ -13,14 +15,12 @@ import kotlin.coroutines.resume
object HttpHelper {
val client: OkHttpClient by lazy {
- val default = ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
- .tlsVersions(TlsVersion.TLS_1_2)
- .build()
- val specs = ArrayList()
- specs.add(default)
- specs.add(ConnectionSpec.COMPATIBLE_TLS)
- specs.add(ConnectionSpec.CLEARTEXT)
+ val specs = arrayListOf(
+ ConnectionSpec.MODERN_TLS,
+ ConnectionSpec.COMPATIBLE_TLS,
+ ConnectionSpec.CLEARTEXT
+ )
val builder = OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
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/ImportOldData.kt b/app/src/main/java/io/legado/app/help/storage/ImportOldData.kt
index 4af39cbb2..9882e4d4f 100644
--- a/app/src/main/java/io/legado/app/help/storage/ImportOldData.kt
+++ b/app/src/main/java/io/legado/app/help/storage/ImportOldData.kt
@@ -136,14 +136,12 @@ object ImportOldData {
return bookSources.size
}
-
-
fun importOldReplaceRule(json: String): Int {
val replaceRules = mutableListOf()
val items: List