Merge remote-tracking branch 'upstream/master' into h11128dev

pull/374/head
Jason Yao 4 years ago
commit 08e1650ca1
  1. 10
      .github/workflows/legado.yml
  2. 4
      README.md
  3. 9
      app/src/main/assets/updateLog.md
  4. 36
      app/src/main/assets/web/index.html
  5. 23
      app/src/main/assets/web/index.js
  6. 3
      app/src/main/assets/web/new/bookshelf.html
  7. 2
      app/src/main/assets/web/new/css/about.dbe575e1.css
  8. 0
      app/src/main/assets/web/new/css/app.e4c919b7.css
  9. 0
      app/src/main/assets/web/new/css/chunk-vendors.ad4ff18f.css
  10. 1
      app/src/main/assets/web/new/css/detail.9ba76c69.css
  11. 1
      app/src/main/assets/web/new/css/detail.fb767a87.css
  12. 0
      app/src/main/assets/web/new/favicon.ico
  13. 0
      app/src/main/assets/web/new/fonts/element-icons.535877f5.woff
  14. 0
      app/src/main/assets/web/new/fonts/element-icons.732389de.ttf
  15. 0
      app/src/main/assets/web/new/fonts/iconfont.f9a3fb0e.woff
  16. 0
      app/src/main/assets/web/new/fonts/popfont.f39ecc1a.ttf
  17. 0
      app/src/main/assets/web/new/fonts/shelffont.6c094b6d.ttf
  18. 0
      app/src/main/assets/web/new/img/icons/android-chrome-192x192.png
  19. 0
      app/src/main/assets/web/new/img/icons/android-chrome-512x512.png
  20. 0
      app/src/main/assets/web/new/img/icons/apple-touch-icon-120x120.png
  21. 0
      app/src/main/assets/web/new/img/icons/apple-touch-icon-152x152.png
  22. 0
      app/src/main/assets/web/new/img/icons/apple-touch-icon-180x180.png
  23. 0
      app/src/main/assets/web/new/img/icons/apple-touch-icon-60x60.png
  24. 0
      app/src/main/assets/web/new/img/icons/apple-touch-icon-76x76.png
  25. 0
      app/src/main/assets/web/new/img/icons/apple-touch-icon.png
  26. 0
      app/src/main/assets/web/new/img/icons/favicon-16x16.png
  27. 0
      app/src/main/assets/web/new/img/icons/favicon-32x32.png
  28. 0
      app/src/main/assets/web/new/img/icons/msapplication-icon-144x144.png
  29. 0
      app/src/main/assets/web/new/img/icons/mstile-150x150.png
  30. 0
      app/src/main/assets/web/new/img/icons/safari-pinned-tab.svg
  31. 0
      app/src/main/assets/web/new/img/noCover.b5c48bc1.jpeg
  32. 3
      app/src/main/assets/web/new/index.html
  33. 1
      app/src/main/assets/web/new/js/about.59a63964.js
  34. 1
      app/src/main/assets/web/new/js/about.a0534951.js
  35. 1
      app/src/main/assets/web/new/js/about~detail.1caf6ef5.js
  36. 1
      app/src/main/assets/web/new/js/about~detail.47586100.js
  37. 1
      app/src/main/assets/web/new/js/app.a7aae935.js
  38. 1
      app/src/main/assets/web/new/js/app.d7843716.js
  39. 33
      app/src/main/assets/web/new/js/chunk-vendors.8dd9045a.js
  40. 33
      app/src/main/assets/web/new/js/chunk-vendors.c98251cd.js
  41. 1
      app/src/main/assets/web/new/js/detail.11777eca.js
  42. 1
      app/src/main/assets/web/new/js/detail.ff471d08.js
  43. 0
      app/src/main/assets/web/new/manifest.json
  44. 38
      app/src/main/assets/web/new/precache-manifest.78eb8adcb8f052b2a72d462abe0dc498.js
  45. 2
      app/src/main/assets/web/new/robots.txt
  46. 2
      app/src/main/assets/web/new/service-worker.js
  47. 127
      app/src/main/java/io/legado/app/help/ReadBookConfig.kt
  48. 32
      app/src/main/java/io/legado/app/help/ThemeConfig.kt
  49. 4
      app/src/main/java/io/legado/app/help/storage/Backup.kt
  50. 13
      app/src/main/java/io/legado/app/help/storage/Restore.kt
  51. 23
      app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt
  52. 12
      app/src/main/java/io/legado/app/model/webBook/BookContent.kt
  53. 17
      app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt
  54. 130
      app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt
  55. 11
      app/src/main/java/io/legado/app/ui/config/ThemeListDialog.kt
  56. 13
      app/src/main/java/io/legado/app/ui/widget/image/CircleImageView.kt
  57. 35
      app/src/main/res/layout/dialog_read_bg_text.xml
  58. 84
      app/src/main/res/layout/dialog_read_book_style.xml
  59. 6
      app/src/main/res/layout/item_bg_image.xml
  60. 12
      app/src/main/res/layout/item_read_style.xml
  61. 2
      app/src/main/res/values/pref_key_value.xml
  62. 2
      build.gradle

@ -6,11 +6,11 @@ on:
push: push:
branches: branches:
- master - master
tags: # tags:
- '3.*' # - '3.*'
pull_request: # pull_request:
branches: # branches:
- master # - master
# watch: # watch:
# types: [started] # types: [started]
# schedule: # schedule:

@ -3,8 +3,8 @@
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
## 阅读3.0 ## 阅读3.0
* 书源规则 https://celeter.github.io * [书源规则](https://alanskycn.gitee.io/teachme/)
* 更新日志 [updateLog.md](/app/src/main/assets/updateLog.md) * [更新日志](/app/src/main/assets/updateLog.md)
![image](https://github.com/gedoor/gedoor.github.io/blob/master/images/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B1.jpg) ![image](https://github.com/gedoor/gedoor.github.io/blob/master/images/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B1.jpg)
![image](https://github.com/gedoor/gedoor.github.io/blob/master/images/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B2.jpg) ![image](https://github.com/gedoor/gedoor.github.io/blob/master/images/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B2.jpg)

@ -3,6 +3,15 @@
* 关注合作公众号 **[小说拾遗]()** 获取好看的小说。 * 关注合作公众号 **[小说拾遗]()** 获取好看的小说。
- 旧版数据导入教程:先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】。 - 旧版数据导入教程:先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】。
**2020/09/12**
* web看书同步最新章
* web写源增加图片样式等规则
* 正文规则可以使用@get{title}获取目录标题,js里使用title
**2020/09/11**
* 修复一些bug
* 背景配置自由添加
**2020/09/10** **2020/09/10**
* 修复自动换源的bug * 修复自动换源的bug
* 修复保存主题的bug * 修复保存主题的bug

@ -14,7 +14,7 @@
<div class="rules"> <div class="rules">
<div><b>基本</b></div> <div><b>基本</b></div>
<div> <div>
<div>URL :</div> <div>域名 :</div>
<textarea rows="1" id="bookSourceUrl" class="base" title="bookSourceUrl" <textarea rows="1" id="bookSourceUrl" class="base" title="bookSourceUrl"
placeholder="<必填>通常填写网站主页,例: https://www.qidian.com"></textarea> placeholder="<必填>通常填写网站主页,例: https://www.qidian.com"></textarea>
</div> </div>
@ -33,16 +33,16 @@
<textarea rows="1" id="bookSourceGroup" class="base" title="bookSourceGroup" <textarea rows="1" id="bookSourceGroup" class="base" title="bookSourceGroup"
placeholder="&lt;选填&gt;描述书源的特征信息"></textarea> placeholder="&lt;选填&gt;描述书源的特征信息"></textarea>
</div> </div>
<div>
<div>源注释 :</div>
<textarea rows="1" id="bookSourceComment" class="base" title="bookSourceComment"
placeholder="&lt;选填&gt;描述书源作者和状态"></textarea>
</div>
<div> <div>
<div>登录地址:</div> <div>登录地址:</div>
<textarea rows="1" id="loginUrl" class="base" title="loginUrl" <textarea rows="1" id="loginUrl" class="base" title="loginUrl"
placeholder="&lt;选填&gt;填写网站登录网址,仅在需要登录的书源有用"></textarea> placeholder="&lt;选填&gt;填写网站登录网址,仅在需要登录的书源有用"></textarea>
</div> </div>
<div>
<div>注释:</div>
<textarea rows="1" id="bookSourceComment" class="base" title="bookSourceComment"
placeholder="&lt;选填&gt;描述书源作者和状态"></textarea>
</div>
<div> <div>
<div>链接验证:</div> <div>链接验证:</div>
<textarea rows="1" id="bookUrlPattern" class="base" title="bookUrlPattern" <textarea rows="1" id="bookUrlPattern" class="base" title="bookUrlPattern"
@ -56,7 +56,7 @@
<div><b>搜索</b></div> <div><b>搜索</b></div>
<div> <div>
<div>搜索地址:</div> <div>搜索地址:</div>
<textarea rows="1" id="searchUrl" class="base" title="searchUrl" <textarea rows="3" id="searchUrl" class="base" title="searchUrl"
placeholder="[域名可省略]/search.php@kw={{key}}"></textarea> placeholder="[域名可省略]/search.php@kw={{key}}"></textarea>
</div> </div>
<div> <div>
@ -250,13 +250,23 @@
<div> <div>
<div>脚本注入:</div> <div>脚本注入:</div>
<textarea rows="3" id="ruleContent_webJs" class="ruleContent" title="webJs" <textarea rows="3" id="ruleContent_webJs" class="ruleContent" title="webJs"
placeholder="注入javascript,用于模拟鼠标点击等,无返回结果"></textarea> placeholder="注入javascript,用于模拟鼠标点击等,必须有返回值,一般为String类型"></textarea>
</div> </div>
<div> <div>
<div>资源正则:</div> <div>资源正则:</div>
<textarea rows="1" id="ruleContent_sourceRegex" class="ruleContent" title="sourceRegex" <textarea rows="1" id="ruleContent_sourceRegex" class="ruleContent" title="sourceRegex"
placeholder="匹配资源的url特征,用于嗅探"></textarea> placeholder="匹配资源的url特征,用于嗅探"></textarea>
</div> </div>
<div>
<div>替换规则:</div>
<textarea rows="1" id="ruleContent_replaceRegex" class="ruleContent" title="replaceRegex"
placeholder="多页内容合并后替换,用于正文净化"></textarea>
</div>
<div>
<div>图片样式:</div>
<textarea rows="1" id="ruleContent_imageStyle" class="ruleContent" title="imageStyle"
placeholder="FULL:铺满 不填:默认样式"></textarea>
</div>
<p></p> <p></p>
<div><b>其它规则</b></div> <div><b>其它规则</b></div>
<div> <div>
@ -353,19 +363,19 @@
</div> </div>
<div class="tab4"> <div class="tab4">
<div class="context link"> <div class="context link">
<a target="_blank" href="https://celeter.github.io">源制作教程</a> <a target="_blank" href="https://alanskycn.gitee.io/teachme">源制作教程</a>
<a target="_blank" href="https://zhuanlan.zhihu.com/p/29436838">Xpath基础教程</a> <a target="_blank" href="https://zhuanlan.zhihu.com/p/29436838">Xpath基础教程</a>
<a target="_blank" href="https://zhuanlan.zhihu.com/p/32187820">Xpath高级教程</a> <a target="_blank" href="https://zhuanlan.zhihu.com/p/32187820">Xpath高级教程</a>
<a target="_blank" href="https://www.w3cschool.cn/regex_rmjc/?">正则表达式教程</a> <a target="_blank" href="https://www.w3cschool.cn/regex_rmjc">正则表达式教程</a>
<a target="_blank" href="https://regexr.com/">正则表达式在线验证工具</a> <a target="_blank" href="https://regexr.com">正则表达式在线验证工具</a>
<div>^$()[]{}.?+*| 这些是Java正则特殊符号,匹配需转义 <div>^$()[]{}.?+*| 这些是Java正则特殊符号,匹配需转义
<br>(?s) 前缀表示跨行解析 <br>(?s) 前缀表示跨行解析
<br>(?m) 前缀表示逐行匹配 <br>(?m) 前缀表示逐行匹配
<br>(?i) 前缀表示忽略大小写 <br>(?i) 前缀表示忽略大小写
</div> </div>
<a target="_blank" href="https://www.beta.browxy.com/">代码在线运行工具</a> <a target="_blank" href="https://www.beta.browxy.com">代码在线运行工具</a>
<a target="_blank" href="bookshelf.html">阅读书架(经典)</a> <a target="_blank" href="bookshelf.html">阅读书架(经典)</a>
<a target="_blank" href="new/bookshelf.html">阅读书架(新潮)</a> <a target="_blank" href="new/index.html">阅读书架(新潮)</a>
</div> </div>
</div> </div>
</div> </div>

@ -18,7 +18,7 @@ function hashParam(key, val) {
} }
} }
// 创建书源规则容器对象 // 创建书源规则容器对象
const RuleJSON = (() => { function Container() {
let ruleJson = {}; let ruleJson = {};
let searchJson = {}; let searchJson = {};
let exploreJson = {}; let exploreJson = {};
@ -33,7 +33,6 @@ const RuleJSON = (() => {
ruleJson.weight = 0; ruleJson.weight = 0;
ruleJson.enabled = true; ruleJson.enabled = true;
ruleJson.enabledExplore = true; ruleJson.enabledExplore = true;
ruleJson.bookSourceComment = ""
// 搜索规则 // 搜索规则
$$('.rules .ruleSearch').forEach(item => searchJson[item.title] = ''); $$('.rules .ruleSearch').forEach(item => searchJson[item.title] = '');
@ -61,7 +60,7 @@ const RuleJSON = (() => {
ruleJson.ruleContent = contentJson; ruleJson.ruleContent = contentJson;
return ruleJson; return ruleJson;
})(); }
// 选项卡Tab切换事件处理 // 选项卡Tab切换事件处理
function showTab(tabName) { function showTab(tabName) {
$$('.tabtitle>*').forEach(node => { node.className = node.className.replace(' this', ''); }); $$('.tabtitle>*').forEach(node => { node.className = node.className.replace(' this', ''); });
@ -107,6 +106,7 @@ function HttpPost(url, data) {
} }
// 将书源表单转化为书源对象 // 将书源表单转化为书源对象
function rule2json() { function rule2json() {
let RuleJSON = Container();
// 转换base // 转换base
Object.keys(RuleJSON).forEach(key => { Object.keys(RuleJSON).forEach(key => {
if (!key.startsWith("rule")) { if (!key.startsWith("rule")) {
@ -118,7 +118,8 @@ function rule2json() {
let searchJson = {}; let searchJson = {};
//Object.keys(JSON.parse(RuleJSON.ruleSearch)).forEach(key => { //Object.keys(JSON.parse(RuleJSON.ruleSearch)).forEach(key => {
Object.keys(RuleJSON.ruleSearch).forEach(key => { Object.keys(RuleJSON.ruleSearch).forEach(key => {
searchJson[key] = $('#' + 'ruleSearch_' + key).value; if ($('#' + 'ruleSearch_' + key).value)
searchJson[key] = $('#' + 'ruleSearch_' + key).value;
}); });
//RuleJSON.ruleSearch = JSON.stringify(searchJson); //RuleJSON.ruleSearch = JSON.stringify(searchJson);
RuleJSON.ruleSearch = searchJson; RuleJSON.ruleSearch = searchJson;
@ -127,7 +128,8 @@ function rule2json() {
let exploreJson = {}; let exploreJson = {};
//Object.keys(JSON.parse(RuleJSON.ruleExplore)).forEach(key => { //Object.keys(JSON.parse(RuleJSON.ruleExplore)).forEach(key => {
Object.keys(RuleJSON.ruleExplore).forEach(key => { Object.keys(RuleJSON.ruleExplore).forEach(key => {
exploreJson[key] = $('#' + 'ruleExplore_' + key).value; if ($('#' + 'ruleExplore_' + key).value)
exploreJson[key] = $('#' + 'ruleExplore_' + key).value;
}); });
//RuleJSON.ruleExplore = JSON.stringify(exploreJson); //RuleJSON.ruleExplore = JSON.stringify(exploreJson);
RuleJSON.ruleExplore = exploreJson; RuleJSON.ruleExplore = exploreJson;
@ -136,7 +138,8 @@ function rule2json() {
let bookInfoJson = {}; let bookInfoJson = {};
//Object.keys(JSON.parse(RuleJSON.ruleBookInfo)).forEach(key => { //Object.keys(JSON.parse(RuleJSON.ruleBookInfo)).forEach(key => {
Object.keys(RuleJSON.ruleBookInfo).forEach(key => { Object.keys(RuleJSON.ruleBookInfo).forEach(key => {
bookInfoJson[key] = $('#' + 'ruleBookInfo_' + key).value; if ($('#' + 'ruleBookInfo_' + key).value)
bookInfoJson[key] = $('#' + 'ruleBookInfo_' + key).value;
}); });
//RuleJSON.ruleBookInfo = JSON.stringify(bookInfoJson); //RuleJSON.ruleBookInfo = JSON.stringify(bookInfoJson);
RuleJSON.ruleBookInfo = bookInfoJson; RuleJSON.ruleBookInfo = bookInfoJson;
@ -145,7 +148,8 @@ function rule2json() {
let tocJson = {}; let tocJson = {};
//Object.keys(JSON.parse(RuleJSON.ruleToc)).forEach(key => { //Object.keys(JSON.parse(RuleJSON.ruleToc)).forEach(key => {
Object.keys(RuleJSON.ruleToc).forEach(key => { Object.keys(RuleJSON.ruleToc).forEach(key => {
tocJson[key] = $('#' + 'ruleToc_' + key).value; if ($('#' + 'ruleToc_' + key).value)
tocJson[key] = $('#' + 'ruleToc_' + key).value;
}); });
//RuleJSON.ruleToc = JSON.stringify(tocJson); //RuleJSON.ruleToc = JSON.stringify(tocJson);
RuleJSON.ruleToc = tocJson; RuleJSON.ruleToc = tocJson;
@ -154,13 +158,13 @@ function rule2json() {
let contentJson = {}; let contentJson = {};
//Object.keys(JSON.parse(RuleJSON.ruleContent)).forEach(key => { //Object.keys(JSON.parse(RuleJSON.ruleContent)).forEach(key => {
Object.keys(RuleJSON.ruleContent).forEach(key => { Object.keys(RuleJSON.ruleContent).forEach(key => {
contentJson[key] = $('#' + 'ruleContent_' + key).value; if ($('#' + 'ruleContent_' + key).value)
contentJson[key] = $('#' + 'ruleContent_' + key).value;
}); });
//RuleJSON.ruleContent = JSON.stringify(contentJson); //RuleJSON.ruleContent = JSON.stringify(contentJson);
RuleJSON.ruleContent = contentJson; RuleJSON.ruleContent = contentJson;
RuleJSON.lastUpdateTime = RuleJSON.lastUpdateTime == '' ? 0 : parseInt(RuleJSON.lastUpdateTime); RuleJSON.lastUpdateTime = RuleJSON.lastUpdateTime == '' ? 0 : parseInt(RuleJSON.lastUpdateTime);
RuleJSON.bookSourceComment = RuleJSON.bookSourceComment == '' ? "" : String(RuleJSON.bookSourceComment);
RuleJSON.customOrder = RuleJSON.customOrder == '' ? 0 : parseInt(RuleJSON.customOrder); RuleJSON.customOrder = RuleJSON.customOrder == '' ? 0 : parseInt(RuleJSON.customOrder);
RuleJSON.weight = RuleJSON.weight == '' ? 0 : parseInt(RuleJSON.weight); RuleJSON.weight = RuleJSON.weight == '' ? 0 : parseInt(RuleJSON.weight);
RuleJSON.bookSourceType == RuleJSON.bookSourceType == '' ? 0 : parseInt(RuleJSON.weight); RuleJSON.bookSourceType == RuleJSON.bookSourceType == '' ? 0 : parseInt(RuleJSON.weight);
@ -170,6 +174,7 @@ function rule2json() {
} }
// 将书源对象填充到书源表单 // 将书源对象填充到书源表单
function json2rule(RuleEditor) { function json2rule(RuleEditor) {
let RuleJSON = Container();
// 转换base // 转换base
Object.keys(RuleJSON).forEach(key => { Object.keys(RuleJSON).forEach(key => {
if (!key.startsWith("rule")) { if (!key.startsWith("rule")) {

@ -1,3 +0,0 @@
<!DOCTYPE html><html lang=en style="padding: 0;height:100%"><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="favicon.ico" /><![endif]--><title>yd-web-tool</title><link href=css/about.8c965d87.css rel=prefetch><link href=css/detail.fb767a87.css rel=prefetch><link href=js/about.a0534951.js rel=prefetch><link href=js/about~detail.47586100.js rel=prefetch><link href=js/detail.ff471d08.js rel=prefetch><link href=css/app.e1c0d2e4.css rel=preload as=style><link href=css/chunk-vendors.ad4ff18f.css rel=preload as=style><link href=js/app.a7aae935.js rel=preload as=script><link href=js/chunk-vendors.c98251cd.js rel=preload as=script><link href=css/chunk-vendors.ad4ff18f.css rel=stylesheet><link href=css/app.e1c0d2e4.css rel=stylesheet><link rel=icon type=image/png sizes=32x32 href=img/icons/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=img/icons/favicon-16x16.png><link rel=manifest href=manifest.json><meta name=theme-color content=#4DBA87><meta name=apple-mobile-web-app-capable content=no><meta name=apple-mobile-web-app-status-bar-style content=default><meta name=apple-mobile-web-app-title content=yd-web-tool><link rel=apple-touch-icon href=img/icons/apple-touch-icon-152x152.png><link rel=mask-icon href=img/icons/safari-pinned-tab.svg color=#4DBA87><meta name=msapplication-TileImage content=img/icons/msapplication-icon-144x144.png><meta name=msapplication-TileColor content=#000000></head><style>body::-webkit-scrollbar {
display: none;
}</style><body style="margin: 0;height:100%"><noscript><strong>We're sorry but yd-web-tool doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=js/chunk-vendors.c98251cd.js></script><script src=js/app.a7aae935.js></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Before

Width:  |  Height:  |  Size: 799 B

After

Width:  |  Height:  |  Size: 799 B

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

@ -0,0 +1,3 @@
<!DOCTYPE html><html lang=en style="padding: 0;height:100%"><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="favicon.ico" /><![endif]--><title>Legado Bookshelf</title><link href=css/about.dbe575e1.css rel=prefetch><link href=css/detail.9ba76c69.css rel=prefetch><link href=js/about.59a63964.js rel=prefetch><link href=js/about~detail.1caf6ef5.js rel=prefetch><link href=js/detail.11777eca.js rel=prefetch><link href=css/app.e4c919b7.css rel=preload as=style><link href=css/chunk-vendors.ad4ff18f.css rel=preload as=style><link href=js/app.d7843716.js rel=preload as=script><link href=js/chunk-vendors.8dd9045a.js rel=preload as=script><link href=css/chunk-vendors.ad4ff18f.css rel=stylesheet><link href=css/app.e4c919b7.css rel=stylesheet><link rel=icon type=image/png sizes=32x32 href=img/icons/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=img/icons/favicon-16x16.png><link rel=manifest href=manifest.json><meta name=theme-color content=#4DBA87><meta name=apple-mobile-web-app-capable content=no><meta name=apple-mobile-web-app-status-bar-style content=default><meta name=apple-mobile-web-app-title content=yd-web-tool><link rel=apple-touch-icon href=img/icons/apple-touch-icon-152x152.png><link rel=mask-icon href=img/icons/safari-pinned-tab.svg color=#4DBA87><meta name=msapplication-TileImage content=img/icons/msapplication-icon-144x144.png><meta name=msapplication-TileColor content=#000000></head><style>body::-webkit-scrollbar {
display: none;
}</style><body style="margin: 0;height:100%"><noscript><strong>We're sorry but yd-web-tool doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=js/chunk-vendors.8dd9045a.js></script><script src=js/app.d7843716.js></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,19 +1,19 @@
self.__precacheManifest = (self.__precacheManifest || []).concat([ self.__precacheManifest = (self.__precacheManifest || []).concat([
{ {
"revision": "80a8de284bb3fa9a4a9f", "revision": "a77097c019b699bc81ee",
"url": "css/about.8c965d87.css" "url": "css/about.dbe575e1.css"
}, },
{ {
"revision": "9da3e990110565bfa57c", "revision": "4d729c4b428d537ebd8d",
"url": "css/app.e1c0d2e4.css" "url": "css/app.e4c919b7.css"
}, },
{ {
"revision": "c900d6091039998c94b9", "revision": "3e91096748e0f4d6bb89",
"url": "css/chunk-vendors.ad4ff18f.css" "url": "css/chunk-vendors.ad4ff18f.css"
}, },
{ {
"revision": "607ffe83acdcd9c9180e", "revision": "8f2124417070a994ebbd",
"url": "css/detail.fb767a87.css" "url": "css/detail.9ba76c69.css"
}, },
{ {
"revision": "535877f50039c0cb49a6196a5b7517cd", "revision": "535877f50039c0cb49a6196a5b7517cd",
@ -40,35 +40,35 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
"url": "img/noCover.b5c48bc1.jpeg" "url": "img/noCover.b5c48bc1.jpeg"
}, },
{ {
"revision": "1006935c8b91408961a7012a08445ffd", "revision": "ad9f43586bb9220e0df71ce8fad92d8b",
"url": "index.html" "url": "index.html"
}, },
{ {
"revision": "80a8de284bb3fa9a4a9f", "revision": "a77097c019b699bc81ee",
"url": "js/about.a0534951.js" "url": "js/about.59a63964.js"
}, },
{ {
"revision": "8e5e793e10c338503af6", "revision": "2c81bd893f3a92f018d8",
"url": "js/about~detail.47586100.js" "url": "js/about~detail.1caf6ef5.js"
}, },
{ {
"revision": "9da3e990110565bfa57c", "revision": "4d729c4b428d537ebd8d",
"url": "js/app.a7aae935.js" "url": "js/app.d7843716.js"
}, },
{ {
"revision": "c900d6091039998c94b9", "revision": "3e91096748e0f4d6bb89",
"url": "js/chunk-vendors.c98251cd.js" "url": "js/chunk-vendors.8dd9045a.js"
}, },
{ {
"revision": "607ffe83acdcd9c9180e", "revision": "8f2124417070a994ebbd",
"url": "js/detail.ff471d08.js" "url": "js/detail.11777eca.js"
}, },
{ {
"revision": "b46d04eb43bc31ca0f9f95121646440d", "revision": "b46d04eb43bc31ca0f9f95121646440d",
"url": "manifest.json" "url": "manifest.json"
}, },
{ {
"revision": "735ab4f94fbcd57074377afca324c813", "revision": "b6216d61c03e6ce0c9aea6ca7808f7ca",
"url": "robots.txt" "url": "robots.txt"
} }
]); ]);

@ -0,0 +1,2 @@
User-agent: *
Disallow:

@ -14,7 +14,7 @@
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js"); importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
importScripts( importScripts(
"precache-manifest.9ae0b839acd886dbe2adc2f9d92aeabf.js" "precache-manifest.78eb8adcb8f052b2a72d462abe0dc498.js"
); );
workbox.core.setCacheNameDetails({prefix: "yd-web-tool"}); workbox.core.setCacheNameDetails({prefix: "yd-web-tool"});

@ -21,8 +21,11 @@ import java.io.File
@Keep @Keep
object ReadBookConfig { object ReadBookConfig {
const val configFileName = "readConfig.json" const val configFileName = "readConfig.json"
const val shareConfigFileName = "shareReadConfig.json"
val configFilePath = FileUtils.getPath(App.INSTANCE.filesDir, configFileName) val configFilePath = FileUtils.getPath(App.INSTANCE.filesDir, configFileName)
val shareConfigFilePath = FileUtils.getPath(App.INSTANCE.filesDir, shareConfigFileName)
val configList: ArrayList<Config> = arrayListOf() val configList: ArrayList<Config> = arrayListOf()
lateinit var shareConfig: Config
private val defaultConfigs by lazy { private val defaultConfigs by lazy {
val json = String(App.INSTANCE.assets.open(configFileName).readBytes()) val json = String(App.INSTANCE.assets.open(configFileName).readBytes())
GSON.fromJsonArray<Config>(json)!! GSON.fromJsonArray<Config>(json)!!
@ -32,7 +35,7 @@ object ReadBookConfig {
set(value) { set(value) {
configList[styleSelect] = value configList[styleSelect] = value
if (shareLayout) { if (shareLayout) {
configList[5] = value shareConfig = value
} }
upBg() upBg()
} }
@ -42,7 +45,8 @@ object ReadBookConfig {
val textColor: Int get() = durConfig.textColor() val textColor: Int get() = durConfig.textColor()
init { init {
upConfig() initConfigs()
initShareConfig()
} }
@Synchronized @Synchronized
@ -50,30 +54,38 @@ object ReadBookConfig {
if (configList.size < 5) { if (configList.size < 5) {
resetAll() resetAll()
} }
if (configList.size < 6) { return configList.getOrNull(index) ?: configList[0]
configList.add(Config())
}
return configList[index]
} }
fun upConfig() { fun initConfigs() {
(getConfigs() ?: defaultConfigs).let { val configFile = File(configFilePath)
var configs: List<Config>? = null
if (configFile.exists()) {
try {
val json = configFile.readText()
configs = GSON.fromJsonArray(json)
} catch (e: Exception) {
e.printStackTrace()
}
}
(configs ?: defaultConfigs).let {
configList.clear() configList.clear()
configList.addAll(it) configList.addAll(it)
} }
} }
private fun getConfigs(): List<Config>? { fun initShareConfig() {
val configFile = File(configFilePath) val configFile = File(configFilePath)
var c: Config? = null
if (configFile.exists()) { if (configFile.exists()) {
try { try {
val json = configFile.readText() val json = configFile.readText()
return GSON.fromJsonArray(json) c = GSON.fromJsonObject(json)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }
} }
return null shareConfig = c ?: configList.getOrNull(5) ?: Config()
} }
fun upBg() { fun upBg() {
@ -94,20 +106,28 @@ object ReadBookConfig {
fun save() { fun save() {
Coroutine.async { Coroutine.async {
synchronized(this) { synchronized(this) {
val json = GSON.toJson(configList) GSON.toJson(configList).let {
FileUtils.deleteFile(configFilePath) FileUtils.deleteFile(configFilePath)
FileUtils.createFileIfNotExist(configFilePath).writeText(json) FileUtils.createFileIfNotExist(configFilePath).writeText(it)
}
GSON.toJson(shareConfig).let {
FileUtils.deleteFile(shareConfigFilePath)
FileUtils.createFileIfNotExist(shareConfigFilePath).writeText(it)
}
} }
} }
} }
fun resetDur() { fun deleteDur(): Boolean {
defaultConfigs[styleSelect].let { if (configList.size > 5) {
durConfig.setBg(it.bgType(), it.bgStr()) configList.removeAt(styleSelect)
durConfig.setTextColor(it.textColor()) if (styleSelect > 0) {
styleSelect -= 1
}
upBg() upBg()
save() return true
} }
return false
} }
private fun resetAll() { private fun resetAll() {
@ -160,7 +180,7 @@ object ReadBookConfig {
var hideStatusBar = App.INSTANCE.getPrefBoolean(PreferKey.hideStatusBar) var hideStatusBar = App.INSTANCE.getPrefBoolean(PreferKey.hideStatusBar)
var hideNavigationBar = App.INSTANCE.getPrefBoolean(PreferKey.hideNavigationBar) var hideNavigationBar = App.INSTANCE.getPrefBoolean(PreferKey.hideNavigationBar)
val config get() = if (shareLayout) getConfig(5) else durConfig val config get() = if (shareLayout) shareConfig else durConfig
var textFont: String var textFont: String
get() = config.textFont get() = config.textFont
@ -308,39 +328,38 @@ object ReadBookConfig {
fun getExportConfig(): Config { fun getExportConfig(): Config {
val exportConfig = GSON.fromJsonObject<Config>(GSON.toJson(durConfig))!! val exportConfig = GSON.fromJsonObject<Config>(GSON.toJson(durConfig))!!
if (shareLayout) { if (shareLayout) {
val shearConfig = getConfig(5) exportConfig.textFont = shareConfig.textFont
exportConfig.textFont = shearConfig.textFont exportConfig.textBold = shareConfig.textBold
exportConfig.textBold = shearConfig.textBold exportConfig.textSize = shareConfig.textSize
exportConfig.textSize = shearConfig.textSize exportConfig.letterSpacing = shareConfig.letterSpacing
exportConfig.letterSpacing = shearConfig.letterSpacing exportConfig.lineSpacingExtra = shareConfig.lineSpacingExtra
exportConfig.lineSpacingExtra = shearConfig.lineSpacingExtra exportConfig.paragraphSpacing = shareConfig.paragraphSpacing
exportConfig.paragraphSpacing = shearConfig.paragraphSpacing exportConfig.titleMode = shareConfig.titleMode
exportConfig.titleMode = shearConfig.titleMode exportConfig.titleSize = shareConfig.titleSize
exportConfig.titleSize = shearConfig.titleSize exportConfig.titleTopSpacing = shareConfig.titleTopSpacing
exportConfig.titleTopSpacing = shearConfig.titleTopSpacing exportConfig.titleBottomSpacing = shareConfig.titleBottomSpacing
exportConfig.titleBottomSpacing = shearConfig.titleBottomSpacing exportConfig.paddingBottom = shareConfig.paddingBottom
exportConfig.paddingBottom = shearConfig.paddingBottom exportConfig.paddingLeft = shareConfig.paddingLeft
exportConfig.paddingLeft = shearConfig.paddingLeft exportConfig.paddingRight = shareConfig.paddingRight
exportConfig.paddingRight = shearConfig.paddingRight exportConfig.paddingTop = shareConfig.paddingTop
exportConfig.paddingTop = shearConfig.paddingTop exportConfig.headerPaddingBottom = shareConfig.headerPaddingBottom
exportConfig.headerPaddingBottom = shearConfig.headerPaddingBottom exportConfig.headerPaddingLeft = shareConfig.headerPaddingLeft
exportConfig.headerPaddingLeft = shearConfig.headerPaddingLeft exportConfig.headerPaddingRight = shareConfig.headerPaddingRight
exportConfig.headerPaddingRight = shearConfig.headerPaddingRight exportConfig.headerPaddingTop = shareConfig.headerPaddingTop
exportConfig.headerPaddingTop = shearConfig.headerPaddingTop exportConfig.footerPaddingBottom = shareConfig.footerPaddingBottom
exportConfig.footerPaddingBottom = shearConfig.footerPaddingBottom exportConfig.footerPaddingLeft = shareConfig.footerPaddingLeft
exportConfig.footerPaddingLeft = shearConfig.footerPaddingLeft exportConfig.footerPaddingRight = shareConfig.footerPaddingRight
exportConfig.footerPaddingRight = shearConfig.footerPaddingRight exportConfig.footerPaddingTop = shareConfig.footerPaddingTop
exportConfig.footerPaddingTop = shearConfig.footerPaddingTop exportConfig.showHeaderLine = shareConfig.showHeaderLine
exportConfig.showHeaderLine = shearConfig.showHeaderLine exportConfig.showFooterLine = shareConfig.showFooterLine
exportConfig.showFooterLine = shearConfig.showFooterLine exportConfig.tipHeaderLeft = shareConfig.tipHeaderLeft
exportConfig.tipHeaderLeft = shearConfig.tipHeaderLeft exportConfig.tipHeaderMiddle = shareConfig.tipHeaderMiddle
exportConfig.tipHeaderMiddle = shearConfig.tipHeaderMiddle exportConfig.tipHeaderRight = shareConfig.tipHeaderRight
exportConfig.tipHeaderRight = shearConfig.tipHeaderRight exportConfig.tipFooterLeft = shareConfig.tipFooterLeft
exportConfig.tipFooterLeft = shearConfig.tipFooterLeft exportConfig.tipFooterMiddle = shareConfig.tipFooterMiddle
exportConfig.tipFooterMiddle = shearConfig.tipFooterMiddle exportConfig.tipFooterRight = shareConfig.tipFooterRight
exportConfig.tipFooterRight = shearConfig.tipFooterRight exportConfig.hideHeader = shareConfig.hideHeader
exportConfig.hideHeader = shearConfig.hideHeader exportConfig.hideFooter = shareConfig.hideFooter
exportConfig.hideFooter = shearConfig.hideFooter
} }
return exportConfig return exportConfig
} }
@ -365,7 +384,7 @@ object ReadBookConfig {
var textSize: Int = 20,//文字大小 var textSize: Int = 20,//文字大小
var letterSpacing: Float = 0.1f,//字间距 var letterSpacing: Float = 0.1f,//字间距
var lineSpacingExtra: Int = 12,//行间距 var lineSpacingExtra: Int = 12,//行间距
var paragraphSpacing: Int = 4,//段距 var paragraphSpacing: Int = 2,//段距
var titleMode: Int = 0,//标题居中 var titleMode: Int = 0,//标题居中
var titleSize: Int = 0, var titleSize: Int = 0,
var titleTopSpacing: Int = 0, var titleTopSpacing: Int = 0,

@ -7,7 +7,6 @@ import io.legado.app.App
import io.legado.app.R import io.legado.app.R
import io.legado.app.constant.EventBus import io.legado.app.constant.EventBus
import io.legado.app.constant.PreferKey import io.legado.app.constant.PreferKey
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.utils.* import io.legado.app.utils.*
import java.io.File import java.io.File
@ -32,19 +31,22 @@ object ThemeConfig {
} }
fun save() { fun save() {
Coroutine.async { val json = GSON.toJson(configList)
synchronized(this) { FileUtils.deleteFile(configFilePath)
val json = GSON.toJson(configList) FileUtils.createFileIfNotExist(configFilePath).writeText(json)
FileUtils.deleteFile(configFilePath) }
FileUtils.createFileIfNotExist(configFilePath).writeText(json)
} fun delConfig(index: Int) {
} configList.removeAt(index)
save()
} }
fun addConfig(json: String) { fun addConfig(json: String): Boolean {
GSON.fromJsonObject<Config>(json)?.let { GSON.fromJsonObject<Config>(json.trim { it < ' ' })?.let {
addConfig(it) addConfig(it)
return true
} }
return false
} }
private fun addConfig(newConfig: Config) { private fun addConfig(newConfig: Config) {
@ -114,9 +116,15 @@ object ThemeConfig {
fun saveNightTheme(context: Context, name: String) { fun saveNightTheme(context: Context, name: String) {
val primary = val primary =
context.getPrefInt(PreferKey.cNPrimary, context.getCompatColor(R.color.md_blue_grey_600)) context.getPrefInt(
PreferKey.cNPrimary,
context.getCompatColor(R.color.md_blue_grey_600)
)
val accent = val accent =
context.getPrefInt(PreferKey.cNAccent, context.getCompatColor(R.color.md_deep_orange_800)) context.getPrefInt(
PreferKey.cNAccent,
context.getCompatColor(R.color.md_deep_orange_800)
)
val background = val background =
context.getPrefInt(PreferKey.cNBackground, context.getCompatColor(R.color.md_grey_900)) context.getPrefInt(PreferKey.cNBackground, context.getCompatColor(R.color.md_grey_900))
val bBackground = val bBackground =

@ -35,6 +35,7 @@ object Backup {
"readRecord.json", "readRecord.json",
"httpTTS.json", "httpTTS.json",
ReadBookConfig.configFileName, ReadBookConfig.configFileName,
ReadBookConfig.shareConfigFileName,
ThemeConfig.configFileName, ThemeConfig.configFileName,
"config.xml" "config.xml"
) )
@ -67,6 +68,9 @@ object Backup {
FileUtils.createFileIfNotExist(backupPath + File.separator + ReadBookConfig.configFileName) FileUtils.createFileIfNotExist(backupPath + File.separator + ReadBookConfig.configFileName)
.writeText(it) .writeText(it)
} }
GSON.toJson(ReadBookConfig.shareConfig).let {
FileUtils.createFileIfNotExist(backupPath + File.separator + ReadBookConfig.shareConfigFileName)
}
GSON.toJson(ThemeConfig.configList).let { GSON.toJson(ThemeConfig.configList).let {
FileUtils.createFileIfNotExist(backupPath + File.separator + ThemeConfig.configFileName) FileUtils.createFileIfNotExist(backupPath + File.separator + ThemeConfig.configFileName)
.writeText(it) .writeText(it)

@ -177,7 +177,18 @@ object Restore {
if (file.exists()) { if (file.exists()) {
FileUtils.deleteFile(ReadBookConfig.configFilePath) FileUtils.deleteFile(ReadBookConfig.configFilePath)
file.copyTo(File(ReadBookConfig.configFilePath)) file.copyTo(File(ReadBookConfig.configFilePath))
ReadBookConfig.upConfig() ReadBookConfig.initConfigs()
}
} catch (e: Exception) {
e.printStackTrace()
}
try {
val file =
FileUtils.createFileIfNotExist(path + File.separator + ReadBookConfig.shareConfigFileName)
if (file.exists()) {
FileUtils.deleteFile(ReadBookConfig.shareConfigFilePath)
file.copyTo(File(ReadBookConfig.shareConfigFilePath))
ReadBookConfig.initShareConfig()
} }
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()

@ -580,6 +580,10 @@ class AnalyzeRule(var book: BaseBook? = null) : JsExtensions {
} }
fun get(key: String): String { fun get(key: String): String {
val chapter = chapter
if (chapter != null && key == "title") {
return chapter.title
}
return chapter?.variableMap?.get(key) return chapter?.variableMap?.get(key)
?: book?.variableMap?.get(key) ?: book?.variableMap?.get(key)
?: "" ?: ""
@ -589,17 +593,14 @@ class AnalyzeRule(var book: BaseBook? = null) : JsExtensions {
* 执行JS * 执行JS
*/ */
private fun evalJS(jsStr: String, result: Any?): Any? { private fun evalJS(jsStr: String, result: Any?): Any? {
try { val bindings = SimpleBindings()
val bindings = SimpleBindings() bindings["java"] = this
bindings["java"] = this bindings["book"] = book
bindings["book"] = book bindings["result"] = result
bindings["result"] = result bindings["baseUrl"] = baseUrl
bindings["baseUrl"] = baseUrl bindings["chapter"] = chapter
return SCRIPT_ENGINE.eval(jsStr, bindings) bindings["title"] = chapter?.title
} catch (e: Exception) { return SCRIPT_ENGINE.eval(jsStr, bindings)
e.printStackTrace()
throw e
}
} }
/** /**

@ -27,10 +27,7 @@ object BookContent {
nextChapterUrlF: String? = null nextChapterUrlF: String? = null
): String { ): String {
body ?: throw Exception( body ?: throw Exception(
App.INSTANCE.getString( App.INSTANCE.getString(R.string.error_get_web_content, baseUrl)
R.string.error_get_web_content,
baseUrl
)
) )
Debug.log(bookSource.bookSourceUrl, "≡获取成功:${baseUrl}") Debug.log(bookSource.bookSourceUrl, "≡获取成功:${baseUrl}")
val content = StringBuilder() val content = StringBuilder()
@ -97,9 +94,12 @@ object BookContent {
} }
content.deleteCharAt(content.length - 1) content.deleteCharAt(content.length - 1)
var contentStr = content.toString().htmlFormat() var contentStr = content.toString().htmlFormat()
val replaceRegex = bookSource.ruleContent?.replaceRegex?.trim() val replaceRegex = bookSource.ruleContent?.replaceRegex
if (!replaceRegex.isNullOrEmpty()) { if (!replaceRegex.isNullOrEmpty()) {
contentStr = AnalyzeRule(book).setContent(contentStr).getString(replaceRegex) val analyzeRule = AnalyzeRule(book)
analyzeRule.setContent(body, baseUrl)
analyzeRule.chapter = bookChapter
contentStr = analyzeRule.getString(replaceRegex)
} }
Debug.log(bookSource.bookSourceUrl, "┌获取章节名称") Debug.log(bookSource.bookSourceUrl, "┌获取章节名称")
Debug.log(bookSource.bookSourceUrl, "${bookChapter.title}") Debug.log(bookSource.bookSourceUrl, "${bookChapter.title}")

@ -11,8 +11,6 @@ import android.os.Bundle
import android.util.DisplayMetrics import android.util.DisplayMetrics
import android.view.* import android.view.*
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.jaredrummler.android.colorpicker.ColorPickerDialog import com.jaredrummler.android.colorpicker.ColorPickerDialog
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseDialogFragment import io.legado.app.base.BaseDialogFragment
@ -104,6 +102,7 @@ class BgTextConfigDialog : BaseDialogFragment(), FileChooserDialog.CallBack {
sw_dark_status_icon.setTextColor(primaryTextColor) sw_dark_status_icon.setTextColor(primaryTextColor)
iv_import.setColorFilter(primaryTextColor) iv_import.setColorFilter(primaryTextColor)
iv_export.setColorFilter(primaryTextColor) iv_export.setColorFilter(primaryTextColor)
iv_delete.setColorFilter(primaryTextColor)
tv_bg_image.setTextColor(primaryTextColor) tv_bg_image.setTextColor(primaryTextColor)
} }
@ -111,8 +110,6 @@ class BgTextConfigDialog : BaseDialogFragment(), FileChooserDialog.CallBack {
private fun initData() = with(ReadBookConfig.durConfig) { private fun initData() = with(ReadBookConfig.durConfig) {
sw_dark_status_icon.isChecked = statusIconDark() sw_dark_status_icon.isChecked = statusIconDark()
adapter = BgAdapter(requireContext()) adapter = BgAdapter(requireContext())
recycler_view.layoutManager =
LinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false)
recycler_view.adapter = adapter recycler_view.adapter = adapter
val headerView = LayoutInflater.from(requireContext()) val headerView = LayoutInflater.from(requireContext())
.inflate(R.layout.item_bg_image, recycler_view, false) .inflate(R.layout.item_bg_image, recycler_view, false)
@ -153,10 +150,6 @@ class BgTextConfigDialog : BaseDialogFragment(), FileChooserDialog.CallBack {
.setDialogId(BG_COLOR) .setDialogId(BG_COLOR)
.show(requireActivity()) .show(requireActivity())
} }
tv_default.onClick {
ReadBookConfig.resetDur()
postEvent(EventBus.UP_CONFIG, false)
}
iv_import.onClick { iv_import.onClick {
val importFormNet = "网络导入" val importFormNet = "网络导入"
val otherActions = arrayListOf(importFormNet) val otherActions = arrayListOf(importFormNet)
@ -179,6 +172,14 @@ class BgTextConfigDialog : BaseDialogFragment(), FileChooserDialog.CallBack {
title = getString(R.string.export_str) title = getString(R.string.export_str)
) )
} }
iv_delete.onClick {
if (ReadBookConfig.deleteDur()) {
postEvent(EventBus.UP_CONFIG, true)
dismiss()
} else {
toast("数量以是最少,不能删除.")
}
}
} }
private fun selectImage() { private fun selectImage() {

@ -8,6 +8,8 @@ import android.view.*
import androidx.core.view.get import androidx.core.view.get
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseDialogFragment import io.legado.app.base.BaseDialogFragment
import io.legado.app.base.adapter.ItemViewHolder
import io.legado.app.base.adapter.SimpleRecyclerAdapter
import io.legado.app.constant.EventBus import io.legado.app.constant.EventBus
import io.legado.app.help.ReadBookConfig import io.legado.app.help.ReadBookConfig
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
@ -21,6 +23,7 @@ import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_book_read.* import kotlinx.android.synthetic.main.activity_book_read.*
import kotlinx.android.synthetic.main.dialog_read_book_style.* import kotlinx.android.synthetic.main.dialog_read_book_style.*
import kotlinx.android.synthetic.main.dialog_title_config.view.* import kotlinx.android.synthetic.main.dialog_title_config.view.*
import kotlinx.android.synthetic.main.item_read_style.view.*
import org.jetbrains.anko.sdk27.listeners.onCheckedChange import org.jetbrains.anko.sdk27.listeners.onCheckedChange
import org.jetbrains.anko.sdk27.listeners.onClick import org.jetbrains.anko.sdk27.listeners.onClick
import org.jetbrains.anko.sdk27.listeners.onLongClick import org.jetbrains.anko.sdk27.listeners.onLongClick
@ -28,6 +31,7 @@ import org.jetbrains.anko.sdk27.listeners.onLongClick
class ReadStyleDialog : BaseDialogFragment(), FontSelectDialog.CallBack { class ReadStyleDialog : BaseDialogFragment(), FontSelectDialog.CallBack {
val callBack get() = activity as? ReadBookActivity val callBack get() = activity as? ReadBookActivity
private lateinit var styleAdapter: StyleAdapter
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
@ -82,6 +86,20 @@ class ReadStyleDialog : BaseDialogFragment(), FontSelectDialog.CallBack {
} }
dsb_line_size.valueFormat = { ((it - 10) / 10f).toString() } dsb_line_size.valueFormat = { ((it - 10) / 10f).toString() }
dsb_paragraph_spacing.valueFormat = { (it / 10f).toString() } dsb_paragraph_spacing.valueFormat = { (it / 10f).toString() }
styleAdapter = StyleAdapter()
rv_style.adapter = styleAdapter
val footerView = LayoutInflater.from(requireContext())
.inflate(R.layout.item_read_style, rv_style, false)
footerView.iv_style.setPadding(6.dp, 6.dp, 6.dp, 6.dp)
footerView.iv_style.setText(null)
footerView.iv_style.setColorFilter(textColor)
footerView.iv_style.borderColor = textColor
footerView.iv_style.setImageResource(R.drawable.ic_add)
styleAdapter.addFooterView(footerView)
footerView.onClick {
ReadBookConfig.configList.add(ReadBookConfig.Config())
showBgTextConfig(ReadBookConfig.configList.lastIndex)
}
} }
private fun initData() { private fun initData() {
@ -92,8 +110,7 @@ class ReadStyleDialog : BaseDialogFragment(), FontSelectDialog.CallBack {
} }
} }
upStyle() upStyle()
setBg() styleAdapter.setItems(ReadBookConfig.configList)
upBg()
} }
private fun initViewEvent() { private fun initViewEvent() {
@ -152,16 +169,6 @@ class ReadStyleDialog : BaseDialogFragment(), FontSelectDialog.CallBack {
ReadBookConfig.paragraphSpacing = it ReadBookConfig.paragraphSpacing = it
postEvent(EventBus.UP_CONFIG, true) postEvent(EventBus.UP_CONFIG, true)
} }
bg0.onClick { changeBg(0) }
bg0.onLongClick { showBgTextConfig(0) }
bg1.onClick { changeBg(1) }
bg1.onLongClick { showBgTextConfig(1) }
bg2.onClick { changeBg(2) }
bg2.onLongClick { showBgTextConfig(2) }
bg3.onClick { changeBg(3) }
bg3.onLongClick { showBgTextConfig(3) }
bg4.onClick { changeBg(4) }
bg4.onLongClick { showBgTextConfig(4) }
} }
@SuppressLint("InflateParams") @SuppressLint("InflateParams")
@ -195,11 +202,13 @@ class ReadStyleDialog : BaseDialogFragment(), FontSelectDialog.CallBack {
} }
private fun changeBg(index: Int) { private fun changeBg(index: Int) {
if (ReadBookConfig.styleSelect != index) { val oldIndex = ReadBookConfig.styleSelect
if (index != oldIndex) {
ReadBookConfig.styleSelect = index ReadBookConfig.styleSelect = index
ReadBookConfig.upBg() ReadBookConfig.upBg()
upStyle() upStyle()
upBg() styleAdapter.notifyItemChanged(oldIndex)
styleAdapter.notifyItemChanged(index)
postEvent(EventBus.UP_CONFIG, true) postEvent(EventBus.UP_CONFIG, true)
} }
} }
@ -220,59 +229,6 @@ class ReadStyleDialog : BaseDialogFragment(), FontSelectDialog.CallBack {
} }
} }
private fun setBg() = ReadBookConfig.apply {
bg0.setTextColor(getConfig(0).textColor())
bg1.setTextColor(getConfig(1).textColor())
bg2.setTextColor(getConfig(2).textColor())
bg3.setTextColor(getConfig(3).textColor())
bg4.setTextColor(getConfig(4).textColor())
for (i in 0..4) {
val iv = when (i) {
1 -> bg1
2 -> bg2
3 -> bg3
4 -> bg4
else -> bg0
}
iv.setImageDrawable(getConfig(i).bgDrawable(100, 150))
}
}
private fun upBg() = ReadBookConfig.apply {
bg0.borderColor = getConfig(0).textColor()
bg0.setTextBold(false)
bg1.borderColor = getConfig(1).textColor()
bg1.setTextBold(false)
bg2.borderColor = getConfig(2).textColor()
bg2.setTextBold(false)
bg3.borderColor = getConfig(3).textColor()
bg3.setTextBold(false)
bg4.borderColor = getConfig(4).textColor()
bg4.setTextBold(false)
when (styleSelect) {
1 -> {
bg1.borderColor = accentColor
bg1.setTextBold(true)
}
2 -> {
bg2.borderColor = accentColor
bg2.setTextBold(true)
}
3 -> {
bg3.borderColor = accentColor
bg3.setTextBold(true)
}
4 -> {
bg4.borderColor = accentColor
bg4.setTextBold(true)
}
else -> {
bg0.borderColor = accentColor
bg0.setTextBold(true)
}
}
}
override val curFontPath: String override val curFontPath: String
get() = ReadBookConfig.textFont get() = ReadBookConfig.textFont
@ -282,4 +238,44 @@ class ReadStyleDialog : BaseDialogFragment(), FontSelectDialog.CallBack {
postEvent(EventBus.UP_CONFIG, true) postEvent(EventBus.UP_CONFIG, true)
} }
} }
inner class StyleAdapter :
SimpleRecyclerAdapter<ReadBookConfig.Config>(requireContext(), R.layout.item_read_style) {
override fun convert(
holder: ItemViewHolder,
item: ReadBookConfig.Config,
payloads: MutableList<Any>
) {
holder.itemView.apply {
iv_style.setTextColor(item.textColor())
iv_style.setImageDrawable(item.bgDrawable(100, 150))
if (ReadBookConfig.styleSelect == holder.layoutPosition) {
iv_style.borderColor = accentColor
iv_style.setTextBold(true)
} else {
iv_style.borderColor = item.textColor()
iv_style.setTextBold(false)
}
}
}
override fun registerListener(holder: ItemViewHolder) {
holder.itemView.apply {
iv_style.onClick {
if (iv_style.isInView) {
changeBg(holder.layoutPosition)
}
}
iv_style.onLongClick {
if (iv_style.isInView) {
showBgTextConfig(holder.layoutPosition)
} else {
false
}
}
}
}
}
} }

@ -21,6 +21,7 @@ import io.legado.app.ui.widget.recycler.VerticalDivider
import io.legado.app.utils.GSON import io.legado.app.utils.GSON
import io.legado.app.utils.applyTint import io.legado.app.utils.applyTint
import io.legado.app.utils.getClipText import io.legado.app.utils.getClipText
import io.legado.app.utils.toast
import kotlinx.android.synthetic.main.dialog_recycler_view.* import kotlinx.android.synthetic.main.dialog_recycler_view.*
import kotlinx.android.synthetic.main.item_theme_config.view.* import kotlinx.android.synthetic.main.item_theme_config.view.*
import org.jetbrains.anko.sdk27.listeners.onClick import org.jetbrains.anko.sdk27.listeners.onClick
@ -74,8 +75,11 @@ class ThemeListDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener {
when (item?.itemId) { when (item?.itemId) {
R.id.menu_import -> { R.id.menu_import -> {
requireContext().getClipText()?.let { requireContext().getClipText()?.let {
ThemeConfig.addConfig(it) if (ThemeConfig.addConfig(it)) {
initData() initData()
} else {
toast("格式不对,添加失败")
}
} }
} }
} }
@ -85,8 +89,7 @@ class ThemeListDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener {
fun delete(index: Int) { fun delete(index: Int) {
alert(R.string.delete, R.string.sure_del) { alert(R.string.delete, R.string.sure_del) {
okButton { okButton {
ThemeConfig.configList.removeAt(index) ThemeConfig.delConfig(index)
ThemeConfig.save()
initData() initData()
} }
noButton() noButton()

@ -119,6 +119,7 @@ class CircleImageView(context: Context, attrs: AttributeSet) :
private var textColor = context.getCompatColor(R.color.primaryText) private var textColor = context.getCompatColor(R.color.primaryText)
private var textBold = false private var textBold = false
var isInView = false
init { init {
super.setScaleType(SCALE_TYPE) super.setScaleType(SCALE_TYPE)
@ -223,6 +224,11 @@ class CircleImageView(context: Context, attrs: AttributeSet) :
} }
} }
fun setText(text: String?) {
this.text = text
invalidate()
}
fun setTextColor(@ColorInt textColor: Int) { fun setTextColor(@ColorInt textColor: Int) {
this.textColor = textColor this.textColor = textColor
invalidate() invalidate()
@ -422,7 +428,12 @@ class CircleImageView(context: Context, attrs: AttributeSet) :
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(event: MotionEvent): Boolean { override fun onTouchEvent(event: MotionEvent): Boolean {
return inTouchableArea(event.x, event.y) && super.onTouchEvent(event) when (event.action) {
MotionEvent.ACTION_DOWN -> {
isInView = (inTouchableArea(event.x, event.y))
}
}
return super.onTouchEvent(event)
} }
private fun inTouchableArea(x: Float, y: Float): Boolean { private fun inTouchableArea(x: Float, y: Float): Boolean {

@ -57,23 +57,6 @@
app:isBottomBackground="true" app:isBottomBackground="true"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<io.legado.app.ui.widget.text.StrokeTextView
android:id="@+id/tv_default"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_weight="3"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:padding="6dp"
android:singleLine="true"
android:text="@string/btn_default_s"
android:textSize="14sp"
app:isBottomBackground="true"
tools:ignore="HardcodedText" />
<ImageView <ImageView
android:id="@+id/iv_import" android:id="@+id/iv_import"
android:layout_width="36dp" android:layout_width="36dp"
@ -98,6 +81,18 @@
android:tooltipText="@string/export_str" android:tooltipText="@string/export_str"
tools:ignore="UnusedAttribute" /> tools:ignore="UnusedAttribute" />
<ImageView
android:id="@+id/iv_delete"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:background="?attr/selectableItemBackground"
android:contentDescription="@string/delete"
android:src="@drawable/ic_clear_all"
android:tooltipText="@string/delete"
tools:ignore="UnusedAttribute" />
</LinearLayout> </LinearLayout>
<TextView <TextView
@ -112,7 +107,9 @@
android:id="@+id/recycler_view" android:id="@+id/recycler_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="100dp" android:layout_height="100dp"
android:padding="6dp" /> android:orientation="horizontal"
android:padding="6dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_bg_image" />
</LinearLayout> </LinearLayout>

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tool="http://schemas.android.com/tools"
android:id="@+id/root_view" android:id="@+id/root_view"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -323,87 +324,12 @@
</LinearLayout> </LinearLayout>
<LinearLayout <androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_style"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:gravity="center_vertical"> app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tool:listitem="@layout/item_read_style" />
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5" />
<io.legado.app.ui.widget.image.CircleImageView
android:id="@+id/bg0"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/image_cover_default"
app:civ_border_color="@color/primaryText"
app:civ_border_width="1dp"
app:text="@string/text" />
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<io.legado.app.ui.widget.image.CircleImageView
android:id="@+id/bg1"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/image_cover_default"
app:civ_border_color="@color/primaryText"
app:civ_border_width="1dp"
app:text="@string/text" />
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<io.legado.app.ui.widget.image.CircleImageView
android:id="@+id/bg2"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/image_cover_default"
app:civ_border_color="@color/primaryText"
app:civ_border_width="1dp"
app:text="@string/text" />
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<io.legado.app.ui.widget.image.CircleImageView
android:id="@+id/bg3"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/image_cover_default"
app:civ_border_color="@color/primaryText"
app:civ_border_width="1dp"
app:text="@string/text" />
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<io.legado.app.ui.widget.image.CircleImageView
android:id="@+id/bg4"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/image_cover_default"
app:civ_border_color="@color/primaryText"
app:civ_border_width="1dp"
app:text="@string/text" />
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5" />
</LinearLayout>
</LinearLayout> </LinearLayout>

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="66dp" android:layout_width="66dp"
android:layout_height="match_parent" android:layout_height="88dp"
xmlns:tool="http://schemas.android.com/tools"
android:padding="2dp" android:padding="2dp"
android:orientation="vertical"> android:orientation="vertical">
@ -11,7 +12,8 @@
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1" android:layout_weight="1"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:contentDescription="@string/bg_image" /> android:contentDescription="@string/bg_image"
tool:src="@drawable/ic_image" />
<TextView <TextView
android:id="@+id/tv_name" android:id="@+id/tv_name"

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<io.legado.app.ui.widget.image.CircleImageView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/iv_style"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:src="@drawable/image_cover_default"
app:civ_border_color="@color/primaryText"
app:civ_border_width="1dp"
app:text="@string/text" />

@ -13,7 +13,7 @@
<string name="pk_check_update" translatable="false">checkUpdate</string> <string name="pk_check_update" translatable="false">checkUpdate</string>
<string name="legado_gzh" translatable="false">开源阅读</string> <string name="legado_gzh" translatable="false">开源阅读</string>
<string name="source_rule_url" translatable="false">https://celeter.github.io/</string> <string name="source_rule_url" translatable="false">https://alanskycn.gitee.io/teachme/</string>
<string name="this_github_url" translatable="false">https://github.com/gedoor/legado</string> <string name="this_github_url" translatable="false">https://github.com/gedoor/legado</string>
<string name="contributors_url" translatable="false">https://github.com/gedoor/legado/graphs/contributors</string> <string name="contributors_url" translatable="false">https://github.com/gedoor/legado/graphs/contributors</string>
<string name="disclaimer_url" translatable="false">https://gedoor.github.io/MyBookshelf/disclaimer.html</string> <string name="disclaimer_url" translatable="false">https://gedoor.github.io/MyBookshelf/disclaimer.html</string>

@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '1.4.0' ext.kotlin_version = '1.4.10'
repositories { repositories {
google() google()
jcenter() jcenter()

Loading…
Cancel
Save