Merge pull request #5 from gedoor/master

merge
pull/441/head
口口吕 4 years ago committed by GitHub
commit ca7a000e4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      app/build.gradle
  2. 10
      app/src/main/AndroidManifest.xml
  3. 2
      app/src/main/assets/help.md
  4. 2
      app/src/main/assets/txtTocRule.json
  5. 649
      app/src/main/assets/updateLog.md
  6. 2
      app/src/main/java/io/legado/app/README.md
  7. 66
      app/src/main/java/io/legado/app/api/ReaderProvider.kt
  8. 2
      app/src/main/java/io/legado/app/base/README.md
  9. 1
      app/src/main/java/io/legado/app/constant/EventBus.kt
  10. 2
      app/src/main/java/io/legado/app/data/README.md
  11. 5
      app/src/main/java/io/legado/app/help/BookHelp.kt
  12. 2
      app/src/main/java/io/legado/app/help/README.md
  13. 2
      app/src/main/java/io/legado/app/lib/README.md
  14. 2
      app/src/main/java/io/legado/app/model/README.md
  15. 8
      app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSonPath.kt
  16. 2
      app/src/main/java/io/legado/app/model/localBook/AnalyzeTxtFile.kt
  17. 2
      app/src/main/java/io/legado/app/service/README.md
  18. 2
      app/src/main/java/io/legado/app/ui/README.md
  19. 2
      app/src/main/java/io/legado/app/ui/about/ReadRecordActivity.kt
  20. 2
      app/src/main/java/io/legado/app/ui/audio/AudioPlayActivity.kt
  21. 7
      app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt
  22. 28
      app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookAdapter.kt
  23. 2
      app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt
  24. 16
      app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt
  25. 7
      app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt
  26. 1
      app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt
  27. 2
      app/src/main/java/io/legado/app/ui/book/toc/BookmarkAdapter.kt
  28. 2
      app/src/main/java/io/legado/app/ui/book/toc/BookmarkFragment.kt
  29. 2
      app/src/main/java/io/legado/app/ui/book/toc/ChapterListActivity.kt
  30. 2
      app/src/main/java/io/legado/app/ui/book/toc/ChapterListAdapter.kt
  31. 2
      app/src/main/java/io/legado/app/ui/book/toc/ChapterListFragment.kt
  32. 2
      app/src/main/java/io/legado/app/ui/book/toc/ChapterListViewModel.kt
  33. 12
      app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksFragment.kt
  34. 7
      app/src/main/java/io/legado/app/ui/main/explore/ExploreFragment.kt
  35. 2
      app/src/main/java/io/legado/app/ui/main/my/MyFragment.kt
  36. 8
      app/src/main/java/io/legado/app/ui/main/rss/RssFragment.kt
  37. 2
      app/src/main/java/io/legado/app/ui/replace/DiffCallBack.kt
  38. 2
      app/src/main/java/io/legado/app/ui/replace/GroupManageDialog.kt
  39. 15
      app/src/main/java/io/legado/app/ui/replace/ReplaceRuleActivity.kt
  40. 2
      app/src/main/java/io/legado/app/ui/replace/ReplaceRuleAdapter.kt
  41. 2
      app/src/main/java/io/legado/app/ui/replace/ReplaceRuleViewModel.kt
  42. 166
      app/src/main/java/io/legado/app/ui/replace/edit/ReplaceEditActivity.kt
  43. 14
      app/src/main/java/io/legado/app/ui/replace/edit/ReplaceEditViewModel.kt
  44. 156
      app/src/main/java/io/legado/app/ui/replacerule/edit/ReplaceEditDialog.kt
  45. 27
      app/src/main/java/io/legado/app/ui/widget/TitleBar.kt
  46. 23
      app/src/main/res/layout/activity_chapter_list.xml
  47. 18
      app/src/main/res/layout/activity_replace_edit.xml
  48. 5
      app/src/main/res/layout/activity_replace_rule.xml
  49. 2
      app/src/main/res/layout/activity_source_debug.xml
  50. 33
      app/src/main/res/layout/fragment_books.xml
  51. 23
      app/src/main/res/layout/fragment_find_book.xml
  52. 30
      app/src/main/res/layout/fragment_rss.xml
  53. 53
      app/src/main/res/layout/item_bookshelf_grid.xml
  54. 8
      app/src/main/res/layout/item_bookshelf_list_add.xml
  55. 3
      app/src/main/res/layout/item_find_book.xml
  56. 2
      app/src/main/res/layout/item_rss.xml
  57. 4
      app/src/main/res/values-zh-rHK/strings.xml
  58. 4
      app/src/main/res/values-zh-rTW/strings.xml
  59. 4
      app/src/main/res/values-zh/strings.xml
  60. 4
      app/src/main/res/values/strings.xml
  61. 7
      app/src/main/res/values/styles.xml
  62. 5
      build.gradle
  63. 4
      gradle/wrapper/gradle-wrapper.properties

@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'de.timfreiheit.resourceplaceholders'
apply plugin: 'io.fabric'
apply plugin: 'com.google.firebase.crashlytics'
androidExtensions {
experimental = true
@ -128,7 +128,7 @@ dependencies {
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.media:media:1.2.0'
implementation 'androidx.preference:preference:1.1.1'
implementation 'androidx.preference:preference-ktx:1.1.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.viewpager2:viewpager2:1.0.0'

@ -181,6 +181,12 @@
android:configChanges="locale|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize|stateHidden" />
<!-- 书源编辑 -->
<activity
android:name=".ui.replace.edit.ReplaceEditActivity"
android:configChanges="locale|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize|stateHidden" />
<!-- 配置界面 -->
<activity
android:name=".ui.config.ConfigActivity"
@ -207,7 +213,7 @@
android:launchMode="singleTop" />
<!-- 替换规则界面 -->
<activity
android:name=".ui.replacerule.ReplaceRuleActivity"
android:name=".ui.replace.ReplaceRuleActivity"
android:launchMode="singleTop">
</activity>
<!-- 书籍管理 -->
@ -220,7 +226,7 @@
android:launchMode="singleTop" />
<!-- 目录 -->
<activity
android:name=".ui.book.chapterlist.ChapterListActivity"
android:name=".ui.book.toc.ChapterListActivity"
android:launchMode="singleTop"
android:screenOrientation="behind" />
<activity

@ -1,4 +1,4 @@
## 常见问题
# 常见问题
1.为什么第一次安装好之后什么东西都没有?
* 因为阅读只是一个转码工具,不提供内容,第一次安装app,需要自己手动导入书源,可以从公众号[开源阅读]()、QQ群、酷安评论里获取由书友制作分享的书源。

@ -31,7 +31,7 @@
"id": -5,
"enable": false,
"name": "数字(纯数字标题)",
"rule": "(?<=[ \\s])\\d+[  \\t]{0,4}$",
"rule": "(?<=[ \\s])\\d+\\.?[  \\t]{0,4}$",
"serialNumber": 4
},
{

@ -1,7 +1,16 @@
# 更新日志
* 关注公众号 **[开源阅读]()** 菜单•软件下载 提前享受新版本。
* 关注合作公众号 **[小说拾遗]()** 获取好看的小说。
- 旧版数据导入教程:先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】。
* 旧版数据导入教程:先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】。
**2020/10/14**
* 优化替换规则编辑界面
* 修复网格书架间距变大bug
* 其它一些优化,bug修复
**2020/10/13**
* 更新android studio 到 4.1
* 书架整理增加滑动选择
**2020/10/12**
* 优化预下载,防止同时下载太多卡顿
@ -107,16 +116,7 @@ getTxtInFolder(unzipPath: String): String
**2020/09/02**
* 搜索url支持put,get,js里使用java.put,java.get
* 对于搜索重定向的源,可以使用此方法获得重定向后的url
```
<js>
var url='https://www.yooread.net/e/search/index.php,'+JSON.stringify({
"method":"POST",
"body":"show=title&tempid=1&keyboard="+key
});
String(java.connect(url).raw().request().url())
</js>
```
* 正文合并后替换规则支持所有规则写法,包括js
**2020/09/01**
@ -126,11 +126,15 @@ String(java.connect(url).raw().request().url())
* 字体跟随背景,每个背景对应一个字体
* 优化图片下载
**2020/08/29**
* 修复一个null引起的崩溃bug
* 修复我的界面滚动时图标消失的bug
* 修复从详情页目录打开章节内容不对的bug
* 书源选择增加滑动选择, 选择框区域滑动时进行选择 by [Mupceet](https://github.com/Mupceet)
**功能介绍**
* 书源调试
- 调试搜索>>输入关键字,如:`系统`
- 调试发现>>输入发现URL,如:`月票榜::https://www.qidian.com/rank/yuepiao?page={{page}}`
- 调试详情页>>输入详情页URL,如:`https://m.qidian.com/book/1015609210`
- 调试目录页>>输入目录页URL,如:`++https://www.zhaishuyuan.com/read/30394`
- 调试正文页>>输入正文页URL,如:`--https://www.zhaishuyuan.com/chapter/30394/20940996`
* 修改订阅中自动添加style的情景
订阅源的内容规则中存在`<style>``style=`
* 请求头,支持http代理,socks4 socks5代理设置 by [10bits](https://github.com/10bits)
```
socks5代理
@ -147,606 +151,13 @@ http代理
}
注意:这些请求头是无意义的,会被忽略掉
```
**2020/08/28**
* 修复一些bug
* 换源不再改变书名和作者,防止换到一些错误的书源后不能再换源
**2020/08/27**
* 修复主题bug
* 修复封面bug
* 优化书籍更新,搜索,换源
* e-ink模式不再固定背景
**2020/08/26**
* js添加java.encodeURI(speakText),用于解决js编码时有~的语句朗读不出来
* 修复书名太长删除阅读记录按钮不显示的bug
* 完成本地书籍编码选择
**2020/08/25**
* 阅读记录可以删除了
* 修复翻页模式选择颜色问题
* 修复toolbar在一些情况下文字颜色不对的bug
* 多设备阅读记录叠加
* 封面链接支持修改headers
**2020/08/24**
* 应用被杀死时停止朗读
* 默认封面添加删除操作
* 备份阅读记录
* 书源添加移除分组支持多选,多个分组以逗号(中英均可)隔开
* 可以自定义在线朗读了
**2020/08/22**
* 添加阅读时间记录
**2020/08/21**
* 图片(漫画源)支持离线下载了
**2020/08/20**
* 正文图片(漫画源)链接支持修改headers
**2020/08/19**
* 选择文本替换时带入书名和书源
**2020/08/16**
* 添加亮度调节控件显示开关
* 添加应用内语言切换
* 底栏颜色限制去除,自动适配
**2020/08/12**
* 增加了Content Provider 接口支持 by [w568w](https://github.com/w568w)
* 修复阅读界面加入书架后,书籍详情页还是显示加入书架按钮的bug
* 修复低版本手机自动阅读速度拉动最左边崩溃的bug
* 给亮度调节加个半透明背景,很多人找不到
* 修复替换分组选择无效的bug
* 备份添加书签
* 修复web端进度更新后手机端进入阅读界面进度不变的bug
* 增加了txt目录规则备份
* 优化了导入功能,导入之前对比已有书源,可选择性导入
* 其它一些bug修复
**2020/08/08**
* 继续适配主题,现在应该所有地方都按照主题变色了
* 朗读定时增加到3个小时,朗读暂停恢复后继续定时
* 优化了主题颜色选择,会影响体验的颜色禁止选,会有提示
* 订阅规则下一页支持页数,下一页规则填page
**2020/08/07**
* 修复其它一些主题色没有适配到的地方
* 添加默认启用替换配置
**2020/08/06**
* 菜单背景根随主题色
* 修复其它一些主题色没有适配到的地方
* 取消图片颜色为FULL时的自动滚动
* 其它一些优化,升级库文件之类
* 显示订阅加入恢复忽略列表
**2020/08/03**
* 修复一些主题色没有适配到的地方
* 尝试修复书架最新章节更新不及时的bug
**2020/08/02**
* 阅读菜单底部几个按钮的背景动态设置为底部操作栏颜色
* 优化书签功能,解决一些bug
**2020/07/29**
* 正文图片样式为FULL的自动为滚动模式
**2020/07/28**
* 长图正文规则添加图片样式FULL,可以滚动浏览了
**2020/07/26**
* 优化翻页,加快翻页速度
**2020/07/25**
* 正文规则添加多页合并后的替换规则,格式同样是##regex##replaceTo
* 正文图片添加长按缩放
* 正文规则添加图片样式规则,可以设置为FULL
* 其它一些bug修复
**2020/07/21**
* 优化文字选择,不再缓存
* 添加忽略恢复列表,方便不同手机配置不同
* 其它一些bug修复
**2020/07/19**
* 添加自定义默认封面
* 修复封面选择本地图片时书架不显示的bug
**2020/07/14**
* 添加英文语言 by [52fisher](https://github.com/52fisher)
**2020/07/13**
* 在线阅读图片支持测试成功,最好把替换净化关了,防止图片url不对
* 书源保留img标签就行,@html自动保留标签
**2020/07/12**
* epub显示图片,未完善
* 在线阅读也支持图片,还未测试
**2020/07/11**
* epub可以正确识别书名和作者了
* epub封面正确显示
**2020/07/10**
* 修复一些窗口再墨水屏上背景透明的问题
* 添加epub支持
* web阅读时记住进度
* 导入书源时系统文件选择器可以选择json文件
**2020/07/06**
* 优化下载
**2020/07/05**
* 修复夜间模式底栏颜色调整无效的bug
* 【web看书】加了翻页、排序等 by [Celeter](https://github.com/Celeter)
* 两部xx' is recognized as a title by [52fisher](https://github.com/52fisher)
* 添加下载错误日志,从下载菜单浏览
* 修复vip标识引发的bug
**2020/07/04**
* 修复滚动bug
* 其它一些优化
**2020/07/03**
* 修复关闭两端对齐是朗读高亮不准确的bug
* 添加文字底部对齐开关
**2020/06/25**
* E-Ink模式合并到主题模式里, E-Ink模式不能修改阅读界面背景和文字颜色
* 添加判断,防止背景透明引起重影,花屏问题
**2020/06/22**
* 修复xpath获取正文多了许多逗号的bug
* 修复检验有效书源移除失效分组失败的bug
**2020/06/21**
* 双击书架图标返回顶部
**2020/06/20**
* 适配NavigationBar
**2020/06/19**
* 修复eInk bug
* 修复分组下载bug
* 导入本地添加滚动条
**2020/06/18**
* fadeapp.widgets:scrollless-recyclerView导致有些手机重影,暂时去除
* 下载界面添加分组
* 修复eInk bug
**2020/06/17**
* 修复更新书架时更新禁止更新的问题
* 修复导入旧版本数据问题
**2020/06/16**
* 刷新时只刷新当前书架
* 修复恢复备份需要退出重进的问题
* 保存打开 E-Ink 模式前的主题、翻页动画,关闭后恢复之前的配置, 现在可以切着玩了
* 修复因繁体语言导致的崩溃bug
**2020/06/15**
* 添加 E-Ink 模式 by [Modificator](https://github.com/Modificator)
* 修复发现打开书时可能的错误
**2020/06/14**
* 修复txt文件目录识别
* 书源分组添加已启用已禁用
**2020/06/13**
* 优化搜索
**2020/06/12**
* 修复分组变化的bug
**2020/06/10**
* 正文字体的粗细选择增加可以选择细体(Android O生效) by [hingbong](https://github.com/hingbong)
* 修复bug
**2020/06/09**
* 修复从发现界面打开已在书架的书时,显示不对的问题
**2020/06/07**
* 优化书源检测,自定义搜索关键词
* 失效书源如果校验为有效会去掉失效标志
**2020/06/06**
* 修复一些bug,包括从阅读界面退出后还是显示红色更新的bug
**2020/06/03**
* zh-TW translation by david082321
* 修复音频播放时播放速度调节会再下一章失效的bug
**2020/05/31**
* 更新到android studio 4.0
* 书源排序添加按url
* 去除朗读通知的进度条
* 修复恢复问题,暂时去除混淆
**2020/05/24**
* 添加自动翻页速度调节
**2020/05/23**
* 添加文字两端对齐配置
**2020/05/20**
* Rss列表增加一种显示样式
**2020/05/18**
* 修复http://alanskycn.gitee.io/书源导入失败问题,被屏蔽UA了
* Rss列表添加样式切换
**2020/05/17**
* 自动翻页功能完成
* 替换规则输入时弹出辅助输入条
**2020/05/10**
* 添加识别rss分组中的频道信息,在菜单中可以切换频道 from [yangyxd](https://github.com/yangyxd)
* 源管理添加置底,批量置顶,批量置地
* 封面选择本地图片完成
**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](https://github.com/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](https://github.com/wqfantexi)
**2020/03/22**
* 添加文件关联 by [wqfantexi](https://github.com/wqfantexi)
* 手动排序可以了,在书架整理里面拖动排序
* 删除分组时同时删除书籍里的分组信息,下次添加新分组时不会自动出现在分组内
* 修复换源丢失分组信息的bug
* 修复部分朗读引擎不自动朗读下一章的bug
**2020/03/21**
* 详情页点击书名搜索
**2020/03/20**
* 自动备份文件和手动备份文件分开
* 修复一些rss收藏取消不了的bug
* 修复rss请求头无效bug
**2020/03/19**
* 美化界面我的 by [yangyxd](https://github.com/yangyxd)
* 优化搜索
**2020/03/18**
* 尝试修复搜索时崩溃
* 解决看过书籍的移到顶部需要向上滚动才能看到的bug
* 只有再书源被删除找不到书源时才会自动换源
* 美化界面 by [yangyxd](https://github.com/yangyxd)
* 订阅后台播放
**2020/03/16**
* 修复滚动模式切换章节位置不归0的bug
* 修复文字选择更多菜单在部分手机上报错的bug
* 修复文字选择菜单问题
**2020/03/15**
* 加载正文无书源时自动换源
**2020/03/14**
* 修改导航栏图标
**2020/03/13**
* 更改书架控件,ViewPager2替换回2.0使用的ViewPager,解决下拉不流畅问题
* 修复点击作者搜索后,打开的详情页还是原来的书籍的bug
* 修改朗读菜单
* 优化rss朗读
**2020/03/12**
* 导入本地添加需要权限模式
**2020/03/11**
* 修复调节上边距时下边距一起动的bug
* 适配沚水的web阅读 by [六月](https://github.com/Celeter)
* 分组管理页面调整 by [yangyxd](https://github.com/yangyxd)
**2020/03/10**
* 优化文字选择菜单弹出位置
* 添加屏幕方向控制
* 添加点击作者搜索
**2020/03/09**
* 底部文字对齐
* 主题添加阴影调节 by [yangyxd](https://github.com/yangyxd)
**2020/03/08**
* 订阅长按保存图片
* 订阅全屏播放
* 书架全部分组可以隐藏了
* 内置web书架基本能用了 by [六月](https://github.com/Celeter)
* 书架整理加入未分组
* 显示总进度
* 隐藏状态栏时,标题显示在上方
**2020/03/07**
* 添加标题上下间距调整
* 添加标题大小调整
* 书籍整理添加批量启用禁用更新
* 换源禁用书源不显示
* 修复搜索界面简介最下面显示半行文字
* 搜索历史改为多行
**2020/03/06**
* 添加隐藏标题
* 行距段距改成倍距,根据字体大小变化
* 修复翻页时右下角页数闪烁
* 修复朗读错行
* 添加底部分隔线,开关在边距设置里
**2020/03/05**
* 修复翻页动画
* 修复主题模式跟随
* 修复滚动翻页切换章节时跳动
* 适配阅读3.0的web做源
* 本地目录规则网络导入
**2020/03/04**
* 修复仿真翻页动画
* 添加阅读记录同步,正常退出进入软件时同步阅读记录
**2020/03/03**
* 修复bug
* 优化排版,确保段距为0时每行在相同的位置
* 修复底部遮挡
**2020/03/02**
* 添加书源登录
* 替换规则实时生效
* 页面最后一行计算是否能放下时不计算行距
* 优化翻页动画
* 优化书源校验
* 按键翻页有动画了
**2020/03/01**
* 修复书源解析的一个bug
* 添加底部操作栏颜色配置
* 修复滚动点击翻页,修复滚动最后一页显示加载中
* 去除备份恢复默认路径
* 尝试修复部分手机一键导入书源报错
* 翻页还有些bug不用反馈了,我已经知道,会修复的
**2020/02/29**
* 添加书源一键导入
* 修复主题模式跟随系统
* 修复书源校验
* 添加书架排序
* 添加点击翻页开关
* 修复共用布局没有记住配置的bug
**2020/02/28**
* 解决阅读界面部分字体超出范围的问题
* 修复背景切换有时空白的bug
* 修复滚动翻页问题
**2020/02/27**
* 修复bug,边距调节,换源等一些bug,记不清了
* 修复默认字体问题
* 改了下包名,好上架应用市场
**2020/02/26**
* 修复仿真翻页
* 功能添加: 选择默认字体时, 可选择字体默认字体(非衬线), 系统衬线字体, 系统等宽字体by [hingbong](https://github.com/hingbong)
**2020/02/25**
* 优化文本选择和滚动,感觉很完美了
**2020/02/24**
* 滚动暂时可以滚了,先这样吧,头大
* 紧急修复朗读报错的bug
**2020/02/23**
* 修复BUG
* 本地目录正则自定义完成
* 选择文本修复框选不全的问题,增加操作按钮
**2020/02/22**
* 长按选择完成
**2020/02/21**
* 重写了阅读界面,实现了段距调整,两端对齐,页眉页脚调整
* 选择文本暂不可用,滚动暂不可用,仿真翻页还有问题
**2020/02/19**
* 导出功能完成
* 其它一些优化,仿真翻页有点问题,还没找到问题所在
**2020/02/15**
* 修复bug
* 添加一个图标
* 阅读界面文本选择开关
* 书源管理发现开启关闭标志
**2020/02/14**
* 书籍分组支持一本书籍在多个分组,既可以在追更,又可以在玄幻
* 搜索界面限制刷新频率,每秒刷新一次
* 添加一种图标,2.0的老图标
**2020/02/13**
* 修复BUG
* 优化已下载检测,解决目录卡顿
* 添加切换图标
**2020/02/12**
* 修复bug
* 优化,网页编码优先使用书源配置的编码
* 其它一些优化
* 添加简繁转换
**2020/02/10**
* 多页目录并行获取解析
* 优化详情页
* 优化换源页面,添加换源是否加载目录配置
* 换源顺序按书源顺序排列
**2020/02/09**
* 优化书源管理,备份恢复
* 主题色修改,底部操作栏更明显
**2020/02/08**
* 书架分组调整顺序后,书架及时变动
**2020/02/07**
* 优化
* 书源校验
* 书架整理
**2020/02/05**
* 修复bug
* Rss收藏功能完成
* Rss已读标记不会再丢失
**2020/02/04**
* 主界面切换时自动隐藏键盘
* 添加本地书籍完成,解析txt文件完成,本地txt可以看了
* 封面换源,书籍信息界面点击封面弹出封面换源界面
* 默认封面绘制书名和作者
* 修复在线朗读遇到单独标点,停止朗读的问题
**2020/02/02**
* merged commit e584606, rss修复BaseURL模式下部分图片无法加载, 修复可能出现的乱码
* 菜单添加网址功能完成
**2020/01/31**
* 修复搜索闪退,因为默认线程为0了
**2020/01/30**
* 优化缓存文件夹选择,不再需要存储权限
* 修复替换净化导入报错的bug
**2020/01/27**
* 添加根据系统主题切换夜间模式
* 合并Modificator提交的代码
**2020/01/26**
* 修复bug
* 未加入书架可查看目录
**2020/01/24**
* 添加线程数配置
* 记住退出时的书架
* 添加屏幕超时配置
**2020/01/11**
* RSS阅读界面添加朗读功能
* 其它一些优化
* 合并KKL369提交的代码,重写LinearLayoutManager,修复书籍目录模糊搜索后scrollToPosition在可见范围不置顶
**2020/01/10**
* 合并KKL369提交的代码
**2020/01/08**
* 导入本地源不再需要存储权限
**2020/01/07**
* 修复备份问题
* 设置背景不再需要存储权限
**2020/01/06**
* 适配Android 10 权限
* 备份恢复不再需要存储权限
**2020/01/03**
* 适配Android 10 权限
* 导入旧版本配置不在需要存储权限
* 选择字体不在需要存储权限
* 修改书源调试
- 调试搜索>>输入关键字,如:`系统`
- 调试发现>>输入发现URL,如:`月票榜::https://www.qidian.com/rank/yuepiao?page={{page}}`
- 调试详情页>>输入详情页URL,如:`https://m.qidian.com/book/1015609210`
- 调试目录页>>输入目录页URL,如:`++https://www.zhaishuyuan.com/read/30394`
- 调试正文页>>输入正文页URL,如:`--https://www.zhaishuyuan.com/chapter/30394/20940996`
* 修改订阅中自动添加style的情景
订阅源的内容规则中存在`<style>``style=`
* 对于搜索重定向的源,可以使用此方法获得重定向后的url
```
<js>
var url='https://www.yooread.net/e/search/index.php,'+JSON.stringify({
"method":"POST",
"body":"show=title&tempid=1&keyboard="+key
});
String(java.connect(url).raw().request().url())
</js>
```

@ -1,4 +1,4 @@
## 文件结构介绍
# 文件结构介绍
* base 基类
* constant 常量

@ -4,12 +4,11 @@
package io.legado.app.api
import android.content.ContentProvider
import android.content.ContentResolver
import android.content.ContentValues
import android.content.UriMatcher
import android.database.*
import android.database.Cursor
import android.database.MatrixCursor
import android.net.Uri
import android.os.Bundle
import com.google.gson.Gson
import io.legado.app.api.controller.BookshelfController
import io.legado.app.api.controller.SourceController
@ -121,66 +120,5 @@ class ReaderProvider : ContentProvider() {
addRow(arrayOf(mData))
}
override fun getCount() = 1
override fun getColumnIndex(s: String) = 0
@Throws(IllegalArgumentException::class)
override fun getColumnIndexOrThrow(s: String): Int {
throw UnsupportedOperationException("Not yet implemented")
}
override fun getColumnName(i: Int) = null as String?
override fun getColumnNames() = arrayOf<String>()
override fun getColumnCount() = 0
override fun getBlob(i: Int) = ByteArray(0)
override fun getString(i: Int) = mData
override fun copyStringToBuffer(
i: Int,
charArrayBuffer: CharArrayBuffer
) {
}
override fun getShort(i: Int) = 0.toShort()
override fun getInt(i: Int) = 0
override fun getLong(i: Int) = 0L
override fun getFloat(i: Int) = 0F
override fun getDouble(i: Int) = 0.toDouble()
override fun getType(i: Int) = 0
override fun isNull(i: Int) = false
override fun deactivate() {}
override fun requery() = false
override fun close() {}
override fun isClosed() = false
override fun registerContentObserver(contentObserver: ContentObserver) {}
override fun unregisterContentObserver(contentObserver: ContentObserver) {}
override fun registerDataSetObserver(dataSetObserver: DataSetObserver) {}
override fun unregisterDataSetObserver(dataSetObserver: DataSetObserver) {}
override fun setNotificationUri(contentResolver: ContentResolver, uri: Uri) {}
override fun getNotificationUri() = null as Uri?
override fun getWantsAllOnMoveCalls() = false
override fun setExtras(bundle: Bundle) {}
override fun getExtras() = null as Bundle?
override fun respond(bundle: Bundle) = null as Bundle?
}
}

@ -22,4 +22,5 @@ object EventBus {
const val SAVE_CONTENT = "saveContent"
const val CHECK_SOURCE = "checkSource"
const val CHECK_SOURCE_DONE = "checkSourceDone"
const val REPLACE_RULE_SAVE = "replaceRuleSave"
}

@ -1,4 +1,4 @@
## 存储数据用
# 存储数据用
* dao 数据操作
* entities 数据模型
* \Book 书籍信息

@ -322,11 +322,10 @@ object BookHelp {
}
val contents = arrayListOf<String>()
c.split("\n").forEach {
val str = it.replace("^\\s+".toRegex(), "")
.replace("\r", "")
val str = it.replace("^[\\n\\s\\r]+".toRegex(), "")
if (contents.isEmpty()) {
contents.add(title)
if (str != title && it.isNotEmpty()) {
if (str != title && str.isNotEmpty()) {
contents.add("${ReadBookConfig.paragraphIndent}$str")
}
} else if (str.isNotEmpty()) {

@ -1 +1 @@
## 放置一些帮助类
# 放置一些帮助类

@ -1,4 +1,4 @@
## 放置一些copy过来的库
# 放置一些copy过来的库
* dialogs 弹出框
* theme 主题
* webDav 网络存储

@ -1,4 +1,4 @@
## 放置一些模块类
# 放置一些模块类
* analyzeRule 书源规则解析
* localBook 本地书籍解析
* rss 订阅规则解析

@ -36,9 +36,9 @@ class AnalyzeByJSonPath {
if (rules.size == 1) {
if (!rule.contains("{$.")) {
ctx?.let {
try {
result = try {
val ob = it.read<Any>(rule)
result = if (ob is List<*>) {
if (ob is List<*>) {
val builder = StringBuilder()
for (o in ob) {
builder.append(o).append("\n")
@ -48,8 +48,8 @@ class AnalyzeByJSonPath {
ob.toString()
}
} catch (ignored: Exception) {
rule
}
}
return result
} else {
@ -108,8 +108,8 @@ class AnalyzeByJSonPath {
result.add(obj.toString())
}
} catch (ignored: Exception) {
result.add(rule)
}
return result
} else {
val matcher = jsonRulePattern.matcher(rule)

@ -261,6 +261,8 @@ class AnalyzeTxtFile {
bookStream.seek(bookChapter.start!!)
bookStream.read(content)
return String(content, book.fileCharset())
.substringAfter(bookChapter.title)
.replace("^[\\n\\s]+".toRegex(), "  ")
}
private fun getBookFile(book: Book): File {

@ -1,4 +1,4 @@
## android服务
# android服务
* AudioPlayService 音频播放服务
* CheckSourceService 书源检测服务
* DownloadService 缓存服务

@ -1,4 +1,4 @@
## 放置与界面有关的类
# 放置与界面有关的类
* about 关于界面
* association 导入书源界面

@ -2,7 +2,6 @@ package io.legado.app.ui.about
import android.content.Context
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.BaseActivity
@ -33,7 +32,6 @@ class ReadRecordActivity : BaseActivity(R.layout.activity_read_record) {
private fun initView() {
tv_book_name.setText(R.string.all_read_time)
recycler_view.layoutManager = LinearLayoutManager(this)
adapter = RecordAdapter(this)
recycler_view.adapter = adapter
iv_remove.onClick {

@ -25,7 +25,7 @@ import io.legado.app.lib.dialogs.okButton
import io.legado.app.service.AudioPlayService
import io.legado.app.service.help.AudioPlay
import io.legado.app.ui.book.changesource.ChangeSourceDialog
import io.legado.app.ui.book.chapterlist.ChapterListActivity
import io.legado.app.ui.book.toc.ChapterListActivity
import io.legado.app.ui.widget.image.CoverImageView
import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_audio_play.*

@ -21,6 +21,7 @@ import io.legado.app.lib.theme.ATH
import io.legado.app.ui.book.group.GroupManageDialog
import io.legado.app.ui.book.group.GroupSelectDialog
import io.legado.app.ui.widget.SelectActionBar
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
import io.legado.app.ui.widget.recycler.ItemTouchCallback
import io.legado.app.ui.widget.recycler.VerticalDivider
import io.legado.app.utils.applyTint
@ -71,6 +72,12 @@ class ArrangeBookActivity : VMBaseActivity<ArrangeBookViewModel>(R.layout.activi
val itemTouchCallback = ItemTouchCallback()
itemTouchCallback.onItemTouchCallbackListener = adapter
itemTouchCallback.isCanDrag = getPrefInt(PreferKey.bookshelfSort) == 3
val dragSelectTouchHelper: DragSelectTouchHelper =
DragSelectTouchHelper(adapter.initDragSelectTouchHelperCallback()).setSlideArea(16, 50)
dragSelectTouchHelper.attachToRecyclerView(recycler_view)
// When this page is opened, it is in selection mode
dragSelectTouchHelper.activeSlideSelect()
// Note: need judge selection first, so add ItemTouchHelper after it.
ItemTouchHelper(itemTouchCallback).attachToRecyclerView(recycler_view)
select_action_bar.setMainActionText(R.string.move_to_group)
select_action_bar.inflateMenu(R.menu.arrange_book_sel)

@ -2,6 +2,7 @@ package io.legado.app.ui.book.arrange
import android.content.Context
import android.view.View
import androidx.core.os.bundleOf
import androidx.recyclerview.widget.RecyclerView
import io.legado.app.R
import io.legado.app.base.adapter.ItemViewHolder
@ -9,6 +10,7 @@ import io.legado.app.base.adapter.SimpleRecyclerAdapter
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookGroup
import io.legado.app.lib.theme.backgroundColor
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
import io.legado.app.ui.widget.recycler.ItemTouchCallback
import kotlinx.android.synthetic.main.item_arrange_book.view.*
import org.jetbrains.anko.backgroundColor
@ -154,6 +156,32 @@ class ArrangeBookAdapter(context: Context, val callBack: CallBack) :
isMoved = false
}
fun initDragSelectTouchHelperCallback(): DragSelectTouchHelper.Callback {
return object : DragSelectTouchHelper.AdvanceCallback<Book>(Mode.ToggleAndReverse) {
override fun currentSelectedId(): MutableSet<Book> {
return selectedBooks
}
override fun getItemId(position: Int): Book {
return getItem(position)!!
}
override fun updateSelectState(position: Int, isSelected: Boolean): Boolean {
getItem(position)?.let {
if (isSelected) {
selectedBooks.add(it)
} else {
selectedBooks.remove(it)
}
notifyItemChanged(position, bundleOf(Pair("selected", null)))
callBack.upSelectCount()
return true
}
return false
}
}
}
interface CallBack {
val groupList: List<BookGroup>
fun upSelectCount()

@ -28,12 +28,12 @@ import io.legado.app.lib.theme.getPrimaryTextColor
import io.legado.app.ui.audio.AudioPlayActivity
import io.legado.app.ui.book.changecover.ChangeCoverDialog
import io.legado.app.ui.book.changesource.ChangeSourceDialog
import io.legado.app.ui.book.chapterlist.ChapterListActivity
import io.legado.app.ui.book.group.GroupSelectDialog
import io.legado.app.ui.book.info.edit.BookInfoEditActivity
import io.legado.app.ui.book.read.ReadBookActivity
import io.legado.app.ui.book.search.SearchActivity
import io.legado.app.ui.book.source.edit.BookSourceEditActivity
import io.legado.app.ui.book.toc.ChapterListActivity
import io.legado.app.ui.widget.image.CoverImageView
import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_book_info.*

@ -38,7 +38,6 @@ import io.legado.app.service.BaseReadAloudService
import io.legado.app.service.help.ReadAloud
import io.legado.app.service.help.ReadBook
import io.legado.app.ui.book.changesource.ChangeSourceDialog
import io.legado.app.ui.book.chapterlist.ChapterListActivity
import io.legado.app.ui.book.info.BookInfoActivity
import io.legado.app.ui.book.read.config.*
import io.legado.app.ui.book.read.config.BgTextConfigDialog.Companion.BG_COLOR
@ -49,9 +48,10 @@ import io.legado.app.ui.book.read.page.TextPageFactory
import io.legado.app.ui.book.read.page.delegate.PageDelegate
import io.legado.app.ui.book.searchContent.SearchContentActivity
import io.legado.app.ui.book.source.edit.BookSourceEditActivity
import io.legado.app.ui.book.toc.ChapterListActivity
import io.legado.app.ui.login.SourceLogin
import io.legado.app.ui.replacerule.ReplaceRuleActivity
import io.legado.app.ui.replacerule.edit.ReplaceEditDialog
import io.legado.app.ui.replace.ReplaceRuleActivity
import io.legado.app.ui.replace.edit.ReplaceEditActivity
import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_book_read.*
@ -78,7 +78,6 @@ class ReadBookActivity : VMBaseActivity<ReadBookViewModel>(R.layout.activity_boo
ReadBook.CallBack,
AutoReadDialog.CallBack,
TocRegexDialog.CallBack,
ReplaceEditDialog.CallBack,
ColorPickerDialogListener {
private val requestCodeChapterList = 568
private val requestCodeEditSource = 111
@ -487,8 +486,8 @@ class ReadBookActivity : VMBaseActivity<ReadBookViewModel>(R.layout.activity_boo
ReadBook.bookSource?.bookSourceUrl?.let {
scopes.add(it)
}
ReplaceEditDialog.show(
supportFragmentManager,
ReplaceEditActivity.show(
this,
pattern = selectedText,
scope = scopes.joinToString(";")
)
@ -696,7 +695,7 @@ class ReadBookActivity : VMBaseActivity<ReadBookViewModel>(R.layout.activity_boo
/**
* 替换规则变化
*/
override fun onReplaceRuleSave() {
private fun onReplaceRuleSave() {
Coroutine.async {
BookHelp.upReplaceRules()
ReadBook.loadContent(resetPageOffset = false)
@ -918,6 +917,9 @@ class ReadBookActivity : VMBaseActivity<ReadBookViewModel>(R.layout.activity_boo
observeEvent<String>(PreferKey.showBrightnessView) {
read_menu.upBrightnessState()
}
observeEvent<String>(EventBus.REPLACE_RULE_SAVE) {
onReplaceRuleSave()
}
}
private fun upScreenTimeOut() {

@ -177,7 +177,7 @@ class BgTextConfigDialog : BaseDialogFragment(), FileChooserDialog.CallBack {
postEvent(EventBus.UP_CONFIG, true)
dismiss()
} else {
toast("数量是最少,不能删除.")
toast("数量是最少,不能删除.")
}
}
}
@ -333,7 +333,10 @@ class BgTextConfigDialog : BaseDialogFragment(), FileChooserDialog.CallBack {
val bgName = FileUtils.getName(config.bgStr())
val bgPath = FileUtils.getPath(requireContext().externalFilesDir, "bg", bgName)
if (!FileUtils.exist(bgPath)) {
FileUtils.getFile(configDir, bgName).copyTo(File(bgPath))
val bgFile = FileUtils.getFile(configDir, bgName)
if (bgFile.exists()) {
bgFile.copyTo(File(bgPath))
}
}
}
ReadBookConfig.durConfig = config

@ -174,7 +174,6 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
dragSelectTouchHelper.attachToRecyclerView(recycler_view)
// When this page is opened, it is in selection mode
dragSelectTouchHelper.activeSlideSelect()
// Note: need judge selection first, so add ItemTouchHelper after it.
ItemTouchHelper(itemTouchCallback).attachToRecyclerView(recycler_view)
}

@ -1,4 +1,4 @@
package io.legado.app.ui.book.chapterlist
package io.legado.app.ui.book.toc
import android.view.LayoutInflater
import android.view.View

@ -1,4 +1,4 @@
package io.legado.app.ui.book.chapterlist
package io.legado.app.ui.book.toc
import android.annotation.SuppressLint
import android.app.Activity

@ -1,4 +1,4 @@
package io.legado.app.ui.book.chapterlist
package io.legado.app.ui.book.toc
import android.os.Bundle
import android.view.Menu

@ -1,4 +1,4 @@
package io.legado.app.ui.book.chapterlist
package io.legado.app.ui.book.toc
import android.content.Context
import android.view.View

@ -1,4 +1,4 @@
package io.legado.app.ui.book.chapterlist
package io.legado.app.ui.book.toc
import android.annotation.SuppressLint
import android.app.Activity.RESULT_OK

@ -1,4 +1,4 @@
package io.legado.app.ui.book.chapterlist
package io.legado.app.ui.book.toc
import android.app.Application

@ -2,6 +2,7 @@ package io.legado.app.ui.main.bookshelf.books
import android.os.Bundle
import android.view.View
import androidx.core.view.isGone
import androidx.lifecycle.LiveData
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.GridLayoutManager
@ -23,12 +24,17 @@ import io.legado.app.ui.audio.AudioPlayActivity
import io.legado.app.ui.book.info.BookInfoActivity
import io.legado.app.ui.book.read.ReadBookActivity
import io.legado.app.ui.main.MainViewModel
import io.legado.app.utils.*
import io.legado.app.utils.getPrefInt
import io.legado.app.utils.getViewModelOfActivity
import io.legado.app.utils.observeEvent
import io.legado.app.utils.startActivity
import kotlinx.android.synthetic.main.fragment_books.*
import org.jetbrains.anko.startActivity
import kotlin.math.max
/**
* 书架界面
*/
class BooksFragment : BaseFragment(R.layout.fragment_books),
BaseBooksAdapter.CallBack {
@ -55,6 +61,7 @@ class BooksFragment : BaseFragment(R.layout.fragment_books),
position = it.getInt("position", 0)
groupId = it.getLong("groupId", -1)
}
tv_empty_msg.setText(R.string.bookshelf_empty)
initRecyclerView()
upRecyclerData()
}
@ -104,6 +111,7 @@ class BooksFragment : BaseFragment(R.layout.fragment_books),
else -> App.db.bookDao().observeByGroup(groupId)
}
bookshelfLiveData?.observe(this, { list ->
tv_empty_msg.isGone = list.isNotEmpty()
val books = when (getPrefInt(PreferKey.bookshelfSort)) {
1 -> list.sortedByDescending { it.latestChapterTime }
2 -> list.sortedBy { it.name }

@ -6,6 +6,7 @@ import android.view.MenuItem
import android.view.SubMenu
import android.view.View
import androidx.appcompat.widget.SearchView
import androidx.core.view.isGone
import androidx.lifecycle.LiveData
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
@ -28,7 +29,9 @@ import kotlinx.android.synthetic.main.view_search.*
import kotlinx.android.synthetic.main.view_title_bar.*
import java.text.Collator
/**
* 发现界面
*/
class ExploreFragment : VMBaseFragment<ExploreViewModel>(R.layout.fragment_find_book),
ExploreAdapter.CallBack {
override val viewModel: ExploreViewModel
@ -43,6 +46,7 @@ class ExploreFragment : VMBaseFragment<ExploreViewModel>(R.layout.fragment_find_
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
setSupportToolbar(toolbar)
tv_empty_msg.setText(R.string.explore_empty)
initSearchView()
initRecyclerView()
initGroupData()
@ -111,6 +115,7 @@ class ExploreFragment : VMBaseFragment<ExploreViewModel>(R.layout.fragment_find_
App.db.bookSourceDao().liveExplore("%$key%")
}
liveExplore?.observe(viewLifecycleOwner, {
tv_empty_msg.isGone = it.isNotEmpty()
val diffResult = DiffUtil
.calculateDiff(ExploreDiffCallBack(ArrayList(adapter.getItems()), it))
adapter.setItems(it)

@ -24,7 +24,7 @@ import io.legado.app.ui.config.BackupRestoreUi
import io.legado.app.ui.config.ConfigActivity
import io.legado.app.ui.config.ConfigViewModel
import io.legado.app.ui.filechooser.FileChooserDialog
import io.legado.app.ui.replacerule.ReplaceRuleActivity
import io.legado.app.ui.replace.ReplaceRuleActivity
import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.ui.widget.prefs.NameListPreference
import io.legado.app.ui.widget.prefs.PreferenceCategory

@ -4,7 +4,7 @@ import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import androidx.recyclerview.widget.GridLayoutManager
import androidx.core.view.isGone
import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.VMBaseFragment
@ -22,6 +22,9 @@ import io.legado.app.utils.startActivity
import kotlinx.android.synthetic.main.fragment_rss.*
import kotlinx.android.synthetic.main.view_title_bar.*
/**
* 订阅界面
*/
class RssFragment : VMBaseFragment<RssSourceViewModel>(R.layout.fragment_rss),
RssAdapter.CallBack {
@ -31,6 +34,7 @@ class RssFragment : VMBaseFragment<RssSourceViewModel>(R.layout.fragment_rss),
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
setSupportToolbar(toolbar)
tv_empty_msg.setText(R.string.rss_source_empty)
initRecyclerView()
initData()
}
@ -50,12 +54,12 @@ class RssFragment : VMBaseFragment<RssSourceViewModel>(R.layout.fragment_rss),
private fun initRecyclerView() {
ATH.applyEdgeEffectColor(recycler_view)
adapter = RssAdapter(requireContext(), this)
recycler_view.layoutManager = GridLayoutManager(requireContext(), 4)
recycler_view.adapter = adapter
}
private fun initData() {
App.db.rssSourceDao().liveEnabled().observe(viewLifecycleOwner, {
tv_empty_msg.isGone = it.isNotEmpty()
if (it.isEmpty()) {
getViewModelOfActivity(MainViewModel::class.java).initRss()
}

@ -1,4 +1,4 @@
package io.legado.app.ui.replacerule
package io.legado.app.ui.replace
import android.os.Bundle
import androidx.recyclerview.widget.DiffUtil

@ -1,4 +1,4 @@
package io.legado.app.ui.replacerule
package io.legado.app.ui.replace
import android.annotation.SuppressLint
import android.content.Context

@ -1,4 +1,4 @@
package io.legado.app.ui.replacerule
package io.legado.app.ui.replace
import android.annotation.SuppressLint
import android.app.Activity
@ -28,7 +28,7 @@ import io.legado.app.lib.theme.primaryTextColor
import io.legado.app.ui.association.ImportReplaceRuleActivity
import io.legado.app.ui.filechooser.FileChooserDialog
import io.legado.app.ui.filechooser.FilePicker
import io.legado.app.ui.replacerule.edit.ReplaceEditDialog
import io.legado.app.ui.replace.edit.ReplaceEditActivity
import io.legado.app.ui.widget.SelectActionBar
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
import io.legado.app.ui.widget.recycler.ItemTouchCallback
@ -42,8 +42,11 @@ import org.jetbrains.anko.startActivity
import org.jetbrains.anko.toast
import java.io.File
class ReplaceRuleActivity : VMBaseActivity<ReplaceRuleViewModel>(R.layout.activity_replace_rule),
/**
* 替换规则管理
*/
class ReplaceRuleActivity :
VMBaseActivity<ReplaceRuleViewModel>(R.layout.activity_replace_rule),
SearchView.OnQueryTextListener,
PopupMenu.OnMenuItemClickListener,
FileChooserDialog.CallBack,
@ -166,7 +169,7 @@ class ReplaceRuleActivity : VMBaseActivity<ReplaceRuleViewModel>(R.layout.activi
override fun onCompatOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.menu_add_replace_rule ->
ReplaceEditDialog().show(supportFragmentManager, "replaceNew")
ReplaceEditActivity.show(this)
R.id.menu_group_manage ->
GroupManageDialog().show(supportFragmentManager, "groupManage")
@ -303,7 +306,7 @@ class ReplaceRuleActivity : VMBaseActivity<ReplaceRuleViewModel>(R.layout.activi
override fun edit(rule: ReplaceRule) {
setResult(Activity.RESULT_OK)
ReplaceEditDialog.show(supportFragmentManager, rule.id)
ReplaceEditActivity.show(this, rule.id)
}
override fun toTop(rule: ReplaceRule) {

@ -1,4 +1,4 @@
package io.legado.app.ui.replacerule
package io.legado.app.ui.replace
import android.content.Context
import android.os.Bundle

@ -1,4 +1,4 @@
package io.legado.app.ui.replacerule
package io.legado.app.ui.replace
import android.app.Application
import android.text.TextUtils

@ -0,0 +1,166 @@
package io.legado.app.ui.replace.edit
import android.content.Context
import android.content.Intent
import android.graphics.Rect
import android.os.Bundle
import android.view.Gravity
import android.view.Menu
import android.view.MenuItem
import android.view.ViewTreeObserver
import android.widget.EditText
import android.widget.PopupWindow
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.AppConst
import io.legado.app.constant.EventBus
import io.legado.app.data.entities.ReplaceRule
import io.legado.app.ui.widget.KeyboardToolPop
import io.legado.app.utils.getViewModel
import io.legado.app.utils.postEvent
import kotlinx.android.synthetic.main.activity_replace_edit.*
import org.jetbrains.anko.displayMetrics
import org.jetbrains.anko.toast
import kotlin.math.abs
/**
* 编辑替换规则
*/
class ReplaceEditActivity :
VMBaseActivity<ReplaceEditViewModel>(R.layout.activity_replace_edit, false),
ViewTreeObserver.OnGlobalLayoutListener,
KeyboardToolPop.CallBack {
companion object {
fun show(
context: Context,
id: Long = -1,
pattern: String? = null,
isRegex: Boolean = false,
scope: String? = null
) {
val intent = Intent(context, ReplaceEditActivity::class.java)
intent.putExtra("id", id)
intent.putExtra("pattern", pattern)
intent.putExtra("isRegex", isRegex)
intent.putExtra("scope", scope)
context.startActivity(intent)
}
}
override val viewModel: ReplaceEditViewModel
get() = getViewModel(ReplaceEditViewModel::class.java)
private var mSoftKeyboardTool: PopupWindow? = null
private var mIsSoftKeyBoardShowing = false
override fun onActivityCreated(savedInstanceState: Bundle?) {
mSoftKeyboardTool = KeyboardToolPop(this, AppConst.keyboardToolChars, this)
window.decorView.viewTreeObserver.addOnGlobalLayoutListener(this)
viewModel.replaceRuleData.observe(this, {
upReplaceView(it)
})
viewModel.initData(intent)
}
override fun onCompatCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.replace_edit, menu)
return super.onCompatCreateOptionsMenu(menu)
}
override fun onCompatOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.menu_save -> {
val rule = getReplaceRule()
if (!rule.isValid()) {
toast(R.string.replace_rule_invalid)
} else {
viewModel.save(rule) {
postEvent(EventBus.REPLACE_RULE_SAVE, "")
finish()
}
}
}
}
return true
}
private fun upReplaceView(replaceRule: ReplaceRule) {
et_name.setText(replaceRule.name)
et_group.setText(replaceRule.group)
et_replace_rule.setText(replaceRule.pattern)
cb_use_regex.isChecked = replaceRule.isRegex
et_replace_to.setText(replaceRule.replacement)
et_scope.setText(replaceRule.scope)
}
private fun getReplaceRule(): ReplaceRule {
val replaceRule: ReplaceRule = viewModel.replaceRuleData.value ?: ReplaceRule()
replaceRule.name = et_name.text.toString()
replaceRule.group = et_group.text.toString()
replaceRule.pattern = et_replace_rule.text.toString()
replaceRule.isRegex = cb_use_regex.isChecked
replaceRule.replacement = et_replace_to.text.toString()
replaceRule.scope = et_scope.text.toString()
return replaceRule
}
private fun insertText(text: String) {
if (text.isBlank()) return
val view = window?.decorView?.findFocus()
if (view is EditText) {
val start = view.selectionStart
val end = view.selectionEnd
val edit = view.editableText//获取EditText的文字
if (start < 0 || start >= edit.length) {
edit.append(text)
} else {
edit.replace(start, end, text)//光标所在位置插入文字
}
}
}
override fun sendText(text: String) {
if (text == AppConst.keyboardToolChars[0]) {
val view = window?.decorView?.findFocus()
view?.clearFocus()
} else {
insertText(text)
}
}
private fun showKeyboardTopPopupWindow() {
mSoftKeyboardTool?.let {
if (it.isShowing) return
if (!isFinishing) {
it.showAtLocation(ll_content, Gravity.BOTTOM, 0, 0)
}
}
}
private fun closePopupWindow() {
mSoftKeyboardTool?.dismiss()
}
override fun onGlobalLayout() {
val rect = Rect()
// 获取当前页面窗口的显示范围
window.decorView.getWindowVisibleDisplayFrame(rect)
val screenHeight = this.displayMetrics.heightPixels
val keyboardHeight = screenHeight - rect.bottom // 输入法的高度
val preShowing = mIsSoftKeyBoardShowing
if (abs(keyboardHeight) > screenHeight / 5) {
mIsSoftKeyBoardShowing = true // 超过屏幕五分之一则表示弹出了输入法
root_view.setPadding(0, 0, 0, 100)
showKeyboardTopPopupWindow()
} else {
mIsSoftKeyBoardShowing = false
root_view.setPadding(0, 0, 0, 0)
if (preShowing) {
closePopupWindow()
}
}
}
}

@ -1,7 +1,7 @@
package io.legado.app.ui.replacerule.edit
package io.legado.app.ui.replace.edit
import android.app.Application
import android.os.Bundle
import android.content.Intent
import androidx.lifecycle.MutableLiveData
import io.legado.app.App
import io.legado.app.base.BaseViewModel
@ -11,18 +11,18 @@ class ReplaceEditViewModel(application: Application) : BaseViewModel(application
val replaceRuleData = MutableLiveData<ReplaceRule>()
fun initData(bundle: Bundle) {
fun initData(intent: Intent) {
execute {
replaceRuleData.value ?: let {
val id = bundle.getLong("id")
val id = intent.getLongExtra("id", -1)
if (id > 0) {
App.db.replaceRuleDao().findById(id)?.let {
replaceRuleData.postValue(it)
}
} else {
val pattern = bundle.getString("pattern") ?: ""
val isRegex = bundle.getBoolean("isRegex")
val scope = bundle.getString("scope")
val pattern = intent.getStringExtra("pattern") ?: ""
val isRegex = intent.getBooleanExtra("isRegex", false)
val scope = intent.getStringExtra("scope")
val rule = ReplaceRule(
name = pattern,
pattern = pattern,

@ -1,156 +0,0 @@
package io.legado.app.ui.replacerule.edit
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.EditText
import android.widget.PopupWindow
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.FragmentManager
import io.legado.app.R
import io.legado.app.base.BaseDialogFragment
import io.legado.app.constant.AppConst
import io.legado.app.data.entities.ReplaceRule
import io.legado.app.lib.theme.primaryColor
import io.legado.app.ui.widget.KeyboardToolPop
import io.legado.app.utils.applyTint
import io.legado.app.utils.getViewModel
import io.legado.app.utils.toast
import kotlinx.android.synthetic.main.dialog_replace_edit.*
import org.jetbrains.anko.sdk27.listeners.onFocusChange
class ReplaceEditDialog : BaseDialogFragment(),
Toolbar.OnMenuItemClickListener,
KeyboardToolPop.CallBack {
companion object {
fun show(
fragmentManager: FragmentManager,
id: Long = -1,
pattern: String? = null,
isRegex: Boolean = false,
scope: String? = null
) {
val dialog = ReplaceEditDialog()
val bundle = Bundle()
bundle.putLong("id", id)
bundle.putString("pattern", pattern)
bundle.putBoolean("isRegex", isRegex)
bundle.putString("scope", scope)
dialog.arguments = bundle
dialog.show(fragmentManager, this::class.simpleName)
}
}
private lateinit var viewModel: ReplaceEditViewModel
private lateinit var mSoftKeyboardTool: PopupWindow
override fun onStart() {
super.onStart()
dialog?.window?.setLayout(MATCH_PARENT, WRAP_CONTENT)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
viewModel = getViewModel(ReplaceEditViewModel::class.java)
return inflater.inflate(R.layout.dialog_replace_edit, container)
}
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
tool_bar.setBackgroundColor(primaryColor)
mSoftKeyboardTool = KeyboardToolPop(requireContext(), AppConst.keyboardToolChars, this)
tool_bar.inflateMenu(R.menu.replace_edit)
tool_bar.menu.applyTint(requireContext())
tool_bar.setOnMenuItemClickListener(this)
viewModel.replaceRuleData.observe(viewLifecycleOwner, {
upReplaceView(it)
})
arguments?.let {
viewModel.initData(it)
}
et_replace_rule.onFocusChange { v, hasFocus ->
if (hasFocus) {
mSoftKeyboardTool.width = v.width
mSoftKeyboardTool.showAsDropDown(v)
} else {
mSoftKeyboardTool.dismiss()
}
}
}
override fun onMenuItemClick(item: MenuItem?): Boolean {
when (item?.itemId) {
R.id.menu_save -> {
val rule = getReplaceRule()
if (!rule.isValid()){
toast(R.string.replace_rule_invalid)
}
else{
viewModel.save(rule) {
callBack?.onReplaceRuleSave()
dismiss()
}
}
}
}
return true
}
private fun upReplaceView(replaceRule: ReplaceRule) {
et_name.setText(replaceRule.name)
et_group.setText(replaceRule.group)
et_replace_rule.setText(replaceRule.pattern)
cb_use_regex.isChecked = replaceRule.isRegex
et_replace_to.setText(replaceRule.replacement)
et_scope.setText(replaceRule.scope)
}
private fun getReplaceRule(): ReplaceRule {
val replaceRule: ReplaceRule = viewModel.replaceRuleData.value ?: ReplaceRule()
replaceRule.name = et_name.text.toString()
replaceRule.group = et_group.text.toString()
replaceRule.pattern = et_replace_rule.text.toString()
replaceRule.isRegex = cb_use_regex.isChecked
replaceRule.replacement = et_replace_to.text.toString()
replaceRule.scope = et_scope.text.toString()
return replaceRule
}
val callBack get() = activity as? CallBack
private fun insertText(text: String) {
if (text.isBlank()) return
val view = dialog?.window?.decorView?.findFocus()
if (view is EditText) {
val start = view.selectionStart
val end = view.selectionEnd
val edit = view.editableText//获取EditText的文字
if (start < 0 || start >= edit.length) {
edit.append(text)
} else {
edit.replace(start, end, text)//光标所在位置插入文字
}
}
}
override fun sendText(text: String) {
if (text == AppConst.keyboardToolChars[0]) {
val view = dialog?.window?.decorView?.findFocus()
view?.clearFocus()
} else {
insertText(text)
}
}
interface CallBack {
fun onReplaceRuleSave()
}
}

@ -138,23 +138,24 @@ class TitleBar(context: Context, attrs: AttributeSet?) : AppBarLayout(context, a
}
}
if (a.getBoolean(R.styleable.TitleBar_fitStatusBar, true)) {
topPadding = context.statusBarHeight
}
if (!isInEditMode) {
if (a.getBoolean(R.styleable.TitleBar_fitStatusBar, true)) {
topPadding = context.statusBarHeight
}
if (a.getBoolean(R.styleable.TitleBar_fitNavigationBar, false)) {
bottomPadding = context.navigationBarHeight
}
if (a.getBoolean(R.styleable.TitleBar_fitNavigationBar, false)) {
bottomPadding = context.navigationBarHeight
}
backgroundColor = context.primaryColor
backgroundColor = context.primaryColor
stateListAnimator = null
elevation = if (AppConfig.elevation < 0) {
context.elevation
} else {
AppConfig.elevation.toFloat()
stateListAnimator = null
elevation = if (AppConfig.elevation < 0) {
context.elevation
} else {
AppConfig.elevation.toFloat()
}
}
a.recycle()
}

@ -1,19 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<io.legado.app.ui.widget.TitleBar
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentLayout="@layout/view_tab_layout"/>
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentInsetStartWithNavigation="0dp"
app:contentLayout="@layout/view_tab_layout" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

@ -1,23 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:id="@+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/tool_bar"
android:background="@color/background_menu"
<io.legado.app.ui.widget.TitleBar
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="?attr/actionBarStyle"
app:titleTextAppearance="@style/ToolbarTitle"
app:popupTheme="@style/AppTheme.PopupOverlay"
app:contentInsetStartWithNavigation="0dp"
app:displayHomeAsUp="true"
app:fitStatusBar="false"
app:title="@string/replace_rule_edit" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/ll_content"

@ -1,16 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.replacerule.ReplaceRuleActivity">
tools:context=".ui.replace.ReplaceRuleActivity">
<io.legado.app.ui.widget.TitleBar
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentInsetStartWithNavigation="0dp"
app:contentLayout="@layout/view_search"
app:title="@string/replace_purify" />

@ -10,6 +10,7 @@
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentInsetStartWithNavigation="0dp"
app:contentLayout="@layout/view_search"
app:layout_constraintTop_toTopOf="parent"
app:title="@string/debug_source" />
@ -18,6 +19,7 @@
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toBottomOf="@+id/title_bar"
app:layout_constraintBottom_toBottomOf="parent" />

@ -1,12 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/refresh_layout"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_bookshelf"
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_bookshelf"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/item_bookshelf_list" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<TextView
android:id="@+id/tv_empty_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:gravity="center"
android:layout_gravity="center"
android:visibility="gone"
tools:text="TextView" />
</FrameLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
@ -17,6 +18,22 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_find"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@+id/title_bar"
app:layout_constraintBottom_toBottomOf="parent"
tools:listitem="@layout/item_find_book" />
</LinearLayout>
<TextView
android:id="@+id/tv_empty_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:gravity="center"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@+id/title_bar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:text="TextView" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -1,20 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:orientation="vertical">
<io.legado.app.ui.widget.TitleBar
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:attachToActivity="false"
app:layout_constraintTop_toTopOf="parent"
app:title="@string/rss" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/title_bar"
app:layout_constraintBottom_toBottomOf="parent"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="4"
tools:listitem="@layout/item_rss" />
</LinearLayout>
<TextView
android:id="@+id/tv_empty_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:gravity="center"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@+id/title_bar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:text="TextView" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -4,45 +4,30 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="2dp"
android:paddingRight="10dp"
android:paddingLeft="10dp">
android:paddingTop="8dp"
android:paddingRight="8dp"
android:paddingLeft="8dp"
android:paddingBottom="4dp">
<io.legado.app.ui.widget.ShadowLayout
android:id="@+id/bg_cover"
<io.legado.app.ui.widget.image.CoverImageView
android:id="@+id/iv_cover"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
tools:ignore="UnusedAttribute"
android:layout_margin="8dp"
android:scaleType="centerCrop"
android:src="@drawable/image_cover_default"
android:transitionName="img_cover"
app:layout_constraintTop_toTopOf="parent"
app:shadowColor="#16000000"
app:shadowShape="rectangle"
app:shadowDx="1dp"
app:shadowDy="3dp"
app:shadowRadius="4dp"
app:shadowSide="all">
<io.legado.app.ui.widget.image.CoverImageView
android:id="@+id/iv_cover"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:src="@drawable/image_cover_default"
android:transitionName="img_cover"
tools:ignore="UnusedAttribute" />
</io.legado.app.ui.widget.ShadowLayout>
tools:ignore="UnusedAttribute" />
<io.legado.app.ui.widget.text.BadgeView
android:id="@+id/bv_unread"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_margin="5dp"
android:includeFontPadding="false"
app:layout_constraintTop_toTopOf="@+id/bg_cover"
app:layout_constraintRight_toRightOf="@+id/bg_cover"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:ignore="RtlHardcoded" />
<io.legado.app.ui.widget.anima.RotateLoading
@ -51,9 +36,10 @@
android:layout_height="22dp"
android:layout_gravity="right"
android:visibility="invisible"
app:layout_constraintTop_toTopOf="@+id/bg_cover"
app:layout_constraintRight_toRightOf="@+id/bg_cover"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:loading_width="2dp"
app:hide_mode="invisible"
tools:ignore="RtlHardcoded" />
<TextView
@ -62,7 +48,6 @@
android:layout_height="wrap_content"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:paddingBottom="4dp"
android:includeFontPadding="false"
android:gravity="top|center_horizontal"
android:lines="2"
@ -70,9 +55,9 @@
android:text="@string/book_name"
android:textColor="@color/primaryText"
android:textSize="12sp"
app:layout_constraintLeft_toLeftOf="@+id/bg_cover"
app:layout_constraintRight_toRightOf="@+id/bg_cover"
app:layout_constraintTop_toBottomOf="@+id/bg_cover"
app:layout_constraintLeft_toLeftOf="@+id/iv_cover"
app:layout_constraintRight_toRightOf="@+id/iv_cover"
app:layout_constraintTop_toBottomOf="@+id/iv_cover"
tools:ignore="RtlHardcoded,RtlSymmetry" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="?android:attr/selectableItemBackground"
android:gravity="center"
android:text="@string/add"
android:textSize="24sp" />

@ -24,7 +24,8 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@color/primaryText" />
android:textColor="@color/primaryText"
tools:text="起点中文" />
<io.legado.app.ui.widget.anima.RotateLoading
android:id="@+id/rotate_loading"

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:padding="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@ -24,6 +25,7 @@
android:gravity="top|center_horizontal"
android:lines="2"
android:ellipsize="end"
tools:text="RSS"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/iv_icon" />

@ -45,7 +45,7 @@
<string name="recent_reading">最近閲讀</string>
<string name="last_read">最後閲讀</string>
<string name="update_log">更新日誌</string>
<string name="bookshelf_empty">書架還空着,快去添加吧</string>
<string name="bookshelf_empty">書架還空著,先去搜索書籍或從發現裏添加吧!\n如果初次使用請先關註公眾號[開源閱讀]獲取書源</string>
<string name="action_search">搜尋</string>
<string name="action_download">下載</string>
<string name="layout_list">列表</string>
@ -767,5 +767,7 @@
<string name="share_selected_source">分享選中書源</string>
<string name="sort_by_lastUppdateTime">時間排序</string>
<string name="search_content">全文搜索</string>
<string name="rss_source_empty">关注公众号[开源阅读]获取订阅源!</string>
<string name="explore_empty">当前没有发现源,关注公众号[开源阅读]添加带发现的书源!</string>
</resources>

@ -45,7 +45,7 @@
<string name="recent_reading">最近閱讀</string>
<string name="last_read">最後閱讀</string>
<string name="update_log">更新日誌</string>
<string name="bookshelf_empty">書架還空著,先去添加吧!</string>
<string name="bookshelf_empty">書架還空著,先去搜索書籍或從發現裏添加吧!\n如果初次使用請先關註公眾號[開源閱讀]獲取書源</string>
<string name="action_search">搜尋</string>
<string name="action_download">下載</string>
<string name="layout_list">列表</string>
@ -767,5 +767,7 @@
<string name="share_selected_source">分享選中書源</string>
<string name="sort_by_lastUppdateTime">時間排序</string>
<string name="search_content">全文搜尋</string>
<string name="rss_source_empty">关注公众号[开源阅读]获取订阅源!</string>
<string name="explore_empty">当前没有发现源,关注公众号[开源阅读]添加带发现的书源!</string>
</resources>

@ -47,7 +47,7 @@
<string name="recent_reading">最近阅读</string>
<string name="last_read">最后阅读</string>
<string name="update_log">更新日志</string>
<string name="bookshelf_empty">书架还空着,先去添加吧!</string>
<string name="bookshelf_empty">书架还空着,先去搜索书籍或从发现里添加吧!\n如果初次使用请先关注公众号[开源阅读]获取书源</string>
<string name="action_search">搜索</string>
<string name="action_download">下载</string>
<string name="layout_list">列表</string>
@ -770,5 +770,7 @@
<string name="select_theme">切换默认主题</string>
<string name="sort_by_lastUppdateTime">时间排序</string>
<string name="search_content">全文搜索</string>
<string name="rss_source_empty">关注公众号[开源阅读]获取订阅源!</string>
<string name="explore_empty">当前没有发现源,关注公众号[开源阅读]添加带发现的书源!</string>
</resources>

@ -48,7 +48,7 @@
<string name="recent_reading">Recent reading</string>
<string name="last_read">Last reading</string>
<string name="update_log">What\'s new</string>
<string name="bookshelf_empty">Still empty,please add it first.</string>
<string name="bookshelf_empty">The bookshelf is still empty. Search for books or add them from discovery! \n if you use it for the first time, please pay attention to the public account [开源阅读] to get the book source!</string>
<string name="action_search">Search</string>
<string name="action_download">Download</string>
<string name="layout_list">List</string>
@ -773,5 +773,7 @@
<string name="share_selected_source">Share selected sources</string>
<string name="sort_by_lastUppdateTime">Sort by update time</string>
<string name="search_content">Search content</string>
<string name="rss_source_empty">关注公众号[开源阅读]获取订阅源!</string>
<string name="explore_empty">当前没有发现源,关注公众号[开源阅读]添加带发现的书源!</string>
</resources>

@ -52,8 +52,7 @@
<style name="Spinner" parent="android:Theme.Holo.Light" />
//**************************************************************System
Style******************************************************************************//
//**********System Style******************//
<style name="Style.NavigationView" parent="android:Widget">
<item name="android:listPreferredItemHeightSmall">44dp</item>
@ -85,8 +84,7 @@
<item name="android:textSize">20sp</item>
</style>
//**************************************************************Widget
Style******************************************************************************//
//*******************Widget Style**********************************//
<style name="Style.Shadow.Top" parent="android:Widget">
<item name="android:layout_width">match_parent</item>
@ -130,4 +128,5 @@
<style name="Style.Text.Second.Normal.Wrap">
<item name="android:layout_width">wrap_content</item>
</style>
</resources>

@ -8,15 +8,14 @@ buildscript {
maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
maven { url 'https://s3.amazonaws.com/fabric-artifacts/public' }
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
maven { url 'https://maven.fabric.io/public' }
maven { url 'https://plugins.gradle.org/m2/' }
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.2'
classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'de.timfreiheit.resourceplaceholders:placeholders:0.3'
classpath 'com.google.gms:google-services:4.3.4'
classpath 'io.fabric.tools:gradle:1.31.2'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.3.0'
}
}

@ -1,6 +1,6 @@
#Sat May 30 10:00:31 CST 2020
#Tue Oct 13 11:35:54 CST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip

Loading…
Cancel
Save