新增书籍分享

pull/5/head
fengyuecanzhu 5 years ago
parent ecfed14906
commit b7a7dbf5c4
  1. 4
      .idea/assetWizardSettings.xml
  2. BIN
      .idea/caches/build_file_checksums.ser
  3. 4
      .idea/modules.xml
  4. 1
      .idea/sqldialects.xml
  5. 2
      LICENSE
  6. 17
      README.md
  7. 18
      app/build.gradle
  8. 5
      app/src/main/AndroidManifest.xml
  9. BIN
      app/src/main/assets/bg/p01.jpg
  10. BIN
      app/src/main/assets/bg/p02.jpg
  11. BIN
      app/src/main/assets/bg/p03.jpg
  12. BIN
      app/src/main/assets/bg/p04.jpg
  13. BIN
      app/src/main/assets/bg/p05.jpg
  14. BIN
      app/src/main/assets/bg/p06.jpeg
  15. BIN
      app/src/main/assets/bg/p07.jpeg
  16. BIN
      app/src/main/assets/bg/p08.jpeg
  17. BIN
      app/src/main/assets/bg/p09.jpeg
  18. BIN
      app/src/main/assets/bg/p10.jpeg
  19. BIN
      app/src/main/assets/bg/p11.png
  20. BIN
      app/src/main/assets/bg/p12.png
  21. BIN
      app/src/main/assets/bg/p13.jpg
  22. BIN
      app/src/main/assets/bg/p21.png
  23. BIN
      app/src/main/assets/bg/p22.png
  24. BIN
      app/src/main/assets/bg/p23.png
  25. BIN
      app/src/main/assets/bg/p24.png
  26. BIN
      app/src/main/assets/bg/p25.png
  27. BIN
      app/src/main/assets/bg/p26.png
  28. BIN
      app/src/main/assets/bg/p27.png
  29. BIN
      app/src/main/assets/font_img/仓耳与墨W02.png
  30. BIN
      app/src/main/assets/font_img/仓耳舒圆体W02.png
  31. BIN
      app/src/main/assets/font_img/仓耳非白W02.png
  32. BIN
      app/src/main/assets/font_img/包图小白体.png
  33. BIN
      app/src/main/assets/font_img/千图小兔体.png
  34. BIN
      app/src/main/assets/font_img/品如手写体.png
  35. BIN
      app/src/main/assets/font_img/手书体.png
  36. BIN
      app/src/main/assets/font_img/方正书宋简体.png
  37. BIN
      app/src/main/assets/font_img/方正仿宋简体.png
  38. BIN
      app/src/main/assets/font_img/方正楷体.png
  39. BIN
      app/src/main/assets/font_img/方正硬笔行书.png
  40. BIN
      app/src/main/assets/font_img/方正行楷.png
  41. BIN
      app/src/main/assets/font_img/方正黄草.png
  42. BIN
      app/src/main/assets/font_img/方正黑体简体.png
  43. BIN
      app/src/main/assets/font_img/杨任东竹石体.png
  44. BIN
      app/src/main/assets/font_img/演示夏行楷.png
  45. BIN
      app/src/main/assets/font_img/演示悠然小楷.png
  46. BIN
      app/src/main/assets/font_img/演示春风楷.png
  47. BIN
      app/src/main/assets/font_img/演示秋鸿楷.png
  48. BIN
      app/src/main/assets/font_img/站酷仓耳渔阳体.png
  49. BIN
      app/src/main/assets/font_img/经典宋体.png
  50. BIN
      app/src/main/assets/font_img/迷你隶书.png
  51. BIN
      app/src/main/assets/share.png
  52. 53
      app/src/main/assets/updatelog.fy
  53. 9
      app/src/main/java/xyz/fycz/myreader/application/MyApplication.java
  54. 66
      app/src/main/java/xyz/fycz/myreader/application/SysManager.java
  55. 34
      app/src/main/java/xyz/fycz/myreader/common/APPCONST.java
  56. 813
      app/src/main/java/xyz/fycz/myreader/entity/ReadBookControl.java
  57. 318
      app/src/main/java/xyz/fycz/myreader/entity/ReadStyle.java
  58. 566
      app/src/main/java/xyz/fycz/myreader/entity/Setting.java
  59. 102
      app/src/main/java/xyz/fycz/myreader/entity/SharedBook.java
  60. 9
      app/src/main/java/xyz/fycz/myreader/entity/bookstore/BookType.java
  61. 49
      app/src/main/java/xyz/fycz/myreader/enums/BookSource.java
  62. 5
      app/src/main/java/xyz/fycz/myreader/enums/FindType.java
  63. 44
      app/src/main/java/xyz/fycz/myreader/enums/Font.java
  64. 9
      app/src/main/java/xyz/fycz/myreader/enums/Language.java
  65. 7
      app/src/main/java/xyz/fycz/myreader/enums/ReadStyle.java
  66. 9
      app/src/main/java/xyz/fycz/myreader/greendao/GreenDaoManager.java
  67. 117
      app/src/main/java/xyz/fycz/myreader/greendao/entity/Book.java
  68. 169
      app/src/main/java/xyz/fycz/myreader/greendao/entity/ReplaceRuleBean.java
  69. 114
      app/src/main/java/xyz/fycz/myreader/model/ReplaceRuleManager.java
  70. 7
      app/src/main/java/xyz/fycz/myreader/model/SearchEngine.java
  71. 333
      app/src/main/java/xyz/fycz/myreader/model/backup/UserService.java
  72. 20
      app/src/main/java/xyz/fycz/myreader/model/storage/Backup.kt
  73. 7
      app/src/main/java/xyz/fycz/myreader/model/storage/BackupRestoreUi.kt
  74. 14
      app/src/main/java/xyz/fycz/myreader/model/storage/Restore.kt
  75. 2
      app/src/main/java/xyz/fycz/myreader/model/storage/WebDavHelp.kt
  76. 23
      app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java
  77. 219
      app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java
  78. 40
      app/src/main/java/xyz/fycz/myreader/ui/activity/BookstoreActivity.java
  79. 10
      app/src/main/java/xyz/fycz/myreader/ui/activity/FontsActivity.java
  80. 231
      app/src/main/java/xyz/fycz/myreader/ui/activity/LoginActivity.java
  81. 72
      app/src/main/java/xyz/fycz/myreader/ui/activity/MainActivity.java
  82. 184
      app/src/main/java/xyz/fycz/myreader/ui/activity/MoreSettingActivity.java
  83. 261
      app/src/main/java/xyz/fycz/myreader/ui/activity/QRCodeScanActivity.java
  84. 719
      app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java
  85. 271
      app/src/main/java/xyz/fycz/myreader/ui/activity/RegisterActivity.java
  86. 59
      app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java
  87. 5
      app/src/main/java/xyz/fycz/myreader/ui/activity/SplashActivity.java
  88. 17
      app/src/main/java/xyz/fycz/myreader/ui/adapter/BookStoreBookAdapter.java
  89. 1
      app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDetailedAdapter.java
  90. 1
      app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java
  91. 112
      app/src/main/java/xyz/fycz/myreader/ui/adapter/FontsAdapter.java
  92. 34
      app/src/main/java/xyz/fycz/myreader/ui/adapter/SearchBookAdapter.java
  93. 6
      app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/BookStoreBookHolder.java
  94. 16
      app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/SearchBookHolder.java
  95. 1
      app/src/main/java/xyz/fycz/myreader/ui/dialog/AudioPlayerDialog.java
  96. 273
      app/src/main/java/xyz/fycz/myreader/ui/dialog/DialogCreator.java
  97. 2
      app/src/main/java/xyz/fycz/myreader/ui/dialog/MyAlertDialog.java
  98. 18
      app/src/main/java/xyz/fycz/myreader/ui/fragment/FindFragment.java
  99. 207
      app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java
  100. 86
      app/src/main/java/xyz/fycz/myreader/ui/popmenu/AutoPageMenu.java
  101. Some files were not shown because too many files have changed in this diff Show More

@ -19,8 +19,8 @@
<option name="values">
<map>
<entry key="assetSourceType" value="FILE" />
<entry key="outputName" value="ic_home" />
<entry key="sourceFile" value="F:\SVG图标\主页.svg" />
<entry key="outputName" value="ic_share" />
<entry key="sourceFile" value="F:\SVG图标\分享.svg" />
</map>
</option>
</PersistentState>

@ -2,8 +2,8 @@
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/modules/FYReader-master.iml" filepath="$PROJECT_DIR$/.idea/modules/FYReader-master.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/FYReader-master.app.iml" filepath="$PROJECT_DIR$/.idea/modules/app/FYReader-master.app.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/FYReader-master_-_内测.iml" filepath="$PROJECT_DIR$/.idea/modules/FYReader-master_-_内测.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/FYReader-master_-_内测.app.iml" filepath="$PROJECT_DIR$/.idea/modules/app/FYReader-master_-_内测.app.iml" />
</modules>
</component>
</project>

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="file://$PROJECT_DIR$/app/src/main/java/xyz/fycz/myreader/model/backup/UserService.java" dialect="GenericSQL" />
<file url="PROJECT" dialect="MySQL" />
</component>
</project>

@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Copyright 2020 fengyuecanzhu
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -200,3 +200,20 @@
![Image](./img/10.png)![Image](./img/5.png)
![Image](./img/6.png)![Image](./img/7.png)
![Image](./img/8.png)![Image](./img/9.png)
## LICENSE
```
Copyright 2020 fengyuecanzhu
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```

@ -136,7 +136,6 @@ dependencies {
implementation 'com.google.android.material:material:1.1.0'
implementation 'com.h6ah4i.android.widget.verticalseekbar:verticalseekbar:1.0.0'
//Scroller
implementation 'com.futuremind.recyclerfastscroll:fastscroll:0.2.5'
@ -154,10 +153,25 @@ dependencies {
//ImmersionBar
implementation 'com.gyf.immersionbar:immersionbar:3.0.0'
//
implementation 'com.luhuiguo:chinese-utils:1.0'
//
implementation 'com.jaredrummler:colorpicker:1.1.0'
//
implementation 'cn.bingoogolapple:bga-qrcode-zxing:1.3.7'
//Material Dialogs
/*def dialog_version = '3.3.0'
implementation "com.afollestad.material-dialogs:core:$dialog_version"
implementation "com.afollestad.material-dialogs:input:$dialog_version"
implementation "com.afollestad.material-dialogs:files:$dialog_version"
implementation "com.afollestad.material-dialogs:bottomsheets:$dialog_version"*/
}
greendao {
schemaVersion 16
schemaVersion 18
daoPackage 'xyz.fycz.myreader.greendao.gen'
// targetGenDir 'src/main/java'
}

@ -89,6 +89,10 @@
</activity>
<activity android:name=".ui.activity.FontsActivity"/>
<activity android:name=".ui.activity.LoginActivity"/>
<activity android:name=".ui.activity.RegisterActivity"/>
<activity android:name=".ui.activity.CatalogActivity"/>
<activity android:name=".ui.activity.AboutActivity"/>
@ -98,6 +102,7 @@
<activity android:name=".ui.activity.MoreSettingActivity"/>
<activity android:name=".ui.activity.BookstoreActivity"/>
<activity android:name=".ui.activity.WebDavSettingActivity"/>
<activity android:name=".ui.activity.QRCodeScanActivity"/>
<receiver android:name=".util.notification.NotificationClickReceiver"/>
<receiver android:name=".ui.presenter.BookcasePresenter$cancelDownloadReceiver"/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 647 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 741 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 707 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 718 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 501 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 505 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 579 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 KiB

@ -1,16 +1,63 @@
1、新增书架排序设置
2、新增书籍分享(以图片+二维码的形式分享)及扫一扫
2020.11.28
风月读书v1.20.112822
1、新增书源:妙趣阁、丹书铁券、小说旗、读一读网、飘天文学
2、新增书城:100本·实体(名著)、妙趣阁、小说旗
3、新增排行榜:小说旗
4、新增模糊搜索、精确搜索(建议选择模糊搜索)
5、修复书源:搜小说网
6、修复应用切换到后台后从桌面启动时重新进入欢迎页的bug
7、修复横屏模式下进入阅读界面闪退的bug
8、修复恢复备份后设置未立即生效的bug
9、阅读布局支持备份/恢复
2020.11.23
风月读书v1.20.112309
1、修复切换布局是预加载章节页面混乱的bug
2、修复自定义布局后自动覆盖已有布局的bug
2020.11.22
风月读书v1.20.112216
1、修复音量键翻页失效的bug
2、修复滚动模式下自动跳行的bug
3、修复上下翻页模式下使用音量键翻上页动画丢失的bug
4、修复不同布局下亮度和护眼混乱的bug
2020.11.22
风月读书v1.20.112212
1、新增布局设置:支持自定义阅读背景/背景颜色、字体颜色,并内置20张背景图片;支持保存布局(5套日间布局+1套夜间布局);支持导入导出布局
2、新增排版设置:支持自定义排版(行间距、段间距、字间距及四边距)
3、新增文字繁简转换
4、新增横屏阅读
5、新增上下翻页模式
6、新增护眼模式
7、新增朗读时音量键翻页、菜单显示章节标题/链接设置开关
8、优化自动翻页,修改自动翻页方式为滚屏
9、优化阅读设置菜单
10、优化阅读文字显示
2020.11.14
风月读书v1.20.1111420
1、修复语音朗读时部分章节朗读段落高亮错位的bug
2、新增阅读界面显示状态栏设置
3、新增阅读界面全屏点击翻下页设置
4、新增多种字体
5、优化翻页速度
2020.11.12
风月读书v1.20.1111217
1、修复语音朗读定时停止无效的bug
2、修复语音朗读时切换日夜间闪退的bug
3、修复语音朗读时切换章节闪退的bug
4、修复语音朗读时部分安卓版本卡死的bug
5、修复语音朗读时部分章节朗读段落高亮错位的bug
5、修复语音朗读时章节首页朗读段落高亮错位的bug
6、修复语音朗读时章节标题不高亮的bug
7、修复安卓5进入字体界面闪退的bug
2020.11.11
风月读书v1.20.1111121
1、新增语音朗读(听书)
1、新增语音朗读
2020.11.08
风月读书v1.20.1110811

@ -44,6 +44,8 @@ import javax.net.ssl.X509TrustManager;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.common.URLCONST;
import xyz.fycz.myreader.model.backup.UserService;
import xyz.fycz.myreader.model.storage.Backup;
import xyz.fycz.myreader.ui.dialog.APPDownloadTip;
import xyz.fycz.myreader.ui.dialog.DialogCreator;
import xyz.fycz.myreader.entity.Setting;
@ -51,7 +53,9 @@ import xyz.fycz.myreader.entity.UpdateInfo;
import xyz.fycz.myreader.ui.activity.MainActivity;
import xyz.fycz.myreader.ui.fragment.BookcaseFragment;
import xyz.fycz.myreader.util.*;
import xyz.fycz.myreader.util.llog.LLog;
import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.webapi.callback.ResultCallback;
public class MyApplication extends Application {
@ -73,6 +77,7 @@ public class MyApplication extends Application {
}
mFixedThreadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());//初始化线程池
initNightTheme();
// LLog.init(APPCONST.LOG_DIR);
}
public void initNightTheme() {
@ -87,7 +92,7 @@ public class MyApplication extends Application {
}
}
protected boolean isNightTheme() {
public boolean isNightTheme() {
return !SysManager.getSetting().isDayStyle();
}
@ -254,7 +259,7 @@ public class MyApplication extends Application {
MyApplication.getApplication().newThread(() -> {
Document doc = null;
try {
String url = "https://shimo.im/docs/JzVpMgbZUJARSaFs/read";
String url = "https://shimo.im/docs/cqkgjPRRydYYhQKt/read";
if (isApkInDebug(getmContext())) {
url = "https://shimo.im/docs/zfzpda7MUGskOC9v/read";
}

@ -1,41 +1,59 @@
package xyz.fycz.myreader.application;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.enums.BookSource;
import xyz.fycz.myreader.enums.BookcaseStyle;
import xyz.fycz.myreader.enums.Font;
import xyz.fycz.myreader.enums.Language;
import xyz.fycz.myreader.enums.ReadStyle;
import xyz.fycz.myreader.model.backup.UserService;
import xyz.fycz.myreader.model.storage.Backup;
import xyz.fycz.myreader.util.CacheHelper;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.entity.Setting;
import xyz.fycz.myreader.webapi.callback.ResultCallback;
import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil;
import xyz.fycz.myreader.widget.page.PageMode;
import static xyz.fycz.myreader.application.MyApplication.getVersionCode;
import static xyz.fycz.myreader.common.APPCONST.READ_STYLE_LEATHER;
import static xyz.fycz.myreader.common.APPCONST.s;
import static xyz.fycz.myreader.widget.page.PageLoader.DEFAULT_MARGIN_WIDTH;
public class SysManager {
public static void logout() {
}
private static Setting mSetting;
/**
* 获取设置
* @return
*/
public static Setting getSetting() {
if (mSetting != null){
return mSetting;
}
mSetting = (Setting) CacheHelper.readObject(APPCONST.FILE_NAME_SETTING);
if (mSetting == null){
mSetting = getDefaultSetting();
saveSetting(mSetting);
}
return mSetting;
}
public static Setting getNewSetting() {
Setting setting = (Setting) CacheHelper.readObject(APPCONST.FILE_NAME_SETTING);
if (setting == null){
if (setting == null) {
setting = getDefaultSetting();
saveSetting(setting);
}
return setting;
}
/**
* 保存设置
* @param setting
*/
/**
* 保存设置
* @param setting
*/
public static void saveSetting(Setting setting) {
CacheHelper.saveObject(setting, APPCONST.FILE_NAME_SETTING);
}
@ -48,19 +66,8 @@ public class SysManager {
private static Setting getDefaultSetting(){
Setting setting = new Setting();
setting.setDayStyle(true);
setting.setReadStyle(ReadStyle.leather);
setting.setReadWordSize(25);
setting.setBrightProgress(50);
setting.setBrightFollowSystem(true);
setting.setLanguage(Language.simplified);
setting.setFont(Font.默认字体);
setting.setAutoScrollSpeed(300);
setting.setPageMode(PageMode.COVER);
setting.setVolumeTurnPage(true);
setting.setResetScreen(3);
setting.setBookcaseStyle(BookcaseStyle.listMode);
setting.setNewestVersionCode(getVersionCode());
setting.setLocalFontName("");
setting.setAutoSyn(false);
setting.setMatchChapter(true);
setting.setMatchChapterSuitability(0.7f);
@ -68,9 +75,17 @@ public class SysManager {
setting.setRefreshWhenStart(true);
setting.setOpenBookStore(true);
setting.setSettingVersion(APPCONST.SETTING_VERSION);
setting.setSourceVersion(APPCONST.SOURCE_VERSION);
setting.setHorizontalScreen(false);
setting.initReadStyle();
setting.setCurReadStyleIndex(1);
return setting;
}
public static void regetmSetting(){
mSetting = (Setting) CacheHelper.readObject(APPCONST.FILE_NAME_SETTING);
}
/**
* 重置设置
@ -78,7 +93,18 @@ public class SysManager {
public static void resetSetting(){
Setting setting = getSetting();
Backup.INSTANCE.backup(MyApplication.getmContext(), APPCONST.BACKUP_FILE_DIR,null, false);
setting.initReadStyle();
setting.setCurReadStyleIndex(1);
setting.setSharedLayout(true);
setting.setSettingVersion(APPCONST.SETTING_VERSION);
saveSetting(setting);
}
public static void resetSource(){
Setting setting = getSetting();
ReadCrawlerUtil.addReadCrawler(BookSource.miaobi, BookSource.dstq, BookSource.xs7, BookSource.du1du,BookSource.paiotian);
ReadCrawlerUtil.removeReadCrawler("cangshu99");
setting.setSourceVersion(APPCONST.SOURCE_VERSION);
saveSetting(setting);
}
}

@ -18,6 +18,9 @@ public class APPCONST {
public static final String ALARM_SCHEDULE_MSG = "alarm_schedule_msg";
public static final String FILE_DIR = Environment.getExternalStorageDirectory() + "/FYReader/";
public static final String SHARE_FILE_DIR = Environment.getExternalStorageDirectory() + "/FYReader/share/";
public static final String LOG_DIR = Environment.getExternalStorageDirectory() + "/FYReader/log/";
public static final String BG_FILE_DIR = Environment.getExternalStorageDirectory() + "/FYReader/bg/";
public static final String TEM_FILE_DIR = Environment.getExternalStorageDirectory() + "/FYReader/tem/";
public static final String BACKUP_FILE_DIR = Environment.getExternalStorageDirectory() + "/FYReader/backup/";
public static final String TXT_BOOK_DIR = Environment.getExternalStorageDirectory() + "/FYReader/noveltxt/";
@ -29,6 +32,7 @@ public class APPCONST {
+ "book_cache"+ File.separator ;
public static String HTML_CACHE_PATH = FileUtils.getCachePath() + File.separator
+ "html_cache"+ File.separator ;
public static final String LOADING_ERROR = "\t\t \t\t\t\t\n\n  章节内容转码失败!\n\n\t\t \t\t\t\n\n";
public static long exitTime;
public static final int exitConfirmTime = 2000;
@ -41,28 +45,35 @@ public class APPCONST {
public static final String SEARCH_BOOK_BEAN = "SearchBookBean";
public static final String SOURCE_INDEX = "sourceIndex";
public static final String FONT = "font";
public static final String RESULT_RESET_SCREEN = "result_reset_screen";
public static final String RESULT_NEED_REFRESH = "result_need_refresh";
public static final String RESULT_IS_COLLECTED = "result_is_collected";
public static final String RESULT_LAST_READ_POSITION = "result_last_read_position";
public static final String RESULT_HISTORY_CHAPTER = "result_history_chapter";
public static final String RESULT_UP_MENU = "result_up_meu";
public static final int[] READ_STYLE_NIGHT = {R.color.sys_night_word, R.color.sys_night_bg};//黑夜
public static final int[] READ_STYLE_PROTECTED_EYE = {R.color.sys_protect_eye_word, R.color.sys_protect_eye_bg};//护眼
public static final int[] READ_STYLE_COMMON = {R.color.sys_common_word, R.color.sys_common_bg};//普通
public static final int[] READ_STYLE_BLUE_DEEP = {R.color.sys_blue_deep_word, R.color.sys_blue_deep_bg};//深蓝
public static final int[] READ_STYLE_LEATHER = {R.color.sys_leather_word, R.color.sys_leather_bg};//羊皮纸
public static final int[] READ_STYLE_BREEN_EYE = {R.color.sys_breen_word, R.color.sys_breen_bg};//棕绿色
public static final String[] READ_STYLE_NIGHT = {"#94928c", "#393431"};//黑夜
public static final String[] READ_STYLE_PROTECTED_EYE = {"#313031", "#E1F1DA"};//护眼
public static final String[] READ_STYLE_COMMON = {"#313031", "#f5f4f0"};//普通
public static final String[] READ_STYLE_BLUE_DEEP = {"#637079", "#001c29"};//深蓝
public static final String[] READ_STYLE_LEATHER = {"#313031", "#CEC29C"};//羊皮纸
public static final String[] READ_STYLE_BREEN = {"#313031", "#b5bd9a"};//棕绿色
public static final String FILE_NAME_SETTING = "setting";
public static final String FILE_NAME_UPDATE_INFO = "updateInfo";
public static final String FILE_NAME_SPLASH_IMAGE = "splashImage";
public static final int SELECT_TEXT_COLOR = 201;
public static final int SELECT_BG_COLOR = 301;
public static final int REQUEST_FONT = 1001;
public static final int REQUEST_CHAPTER_PAGE = 1002;
public static final int REQUEST_RESET_SCREEN_TIME = 1003;
public static final int REQUEST_LOGIN = 1004;
public static final int REQUEST_LOGIN = 1003;
public static final int REQUEST_REFRESH_READ_UI = 1004;
public static final int REQUEST_SELECT_BG = 1005;
public static final int REQUEST_IMPORT_LAYOUT = 1006;
public static final int REQUEST_QR_SCAN = 1007;
public static final int REQUEST_READ = 1;
@ -79,7 +90,9 @@ public class APPCONST {
public static final int PERMISSIONS_REQUEST_STORAGE = 10001;
//设置版本号
public static final int SETTING_VERSION = 6;
public static final int SETTING_VERSION = 11;
public static final int SOURCE_VERSION = 1;
public static final String FORMAT_FILE_DATE = "yyyy-MM-dd";
@ -87,7 +100,6 @@ public class APPCONST {
public final static String channelIdRead = "channel_read_aloud";
public static final String DEFAULT_WEB_DAV_URL = "https://dav.jianguoyun.com/dav/";
}

@ -0,0 +1,813 @@
//Copyright (c) 2017. 章钦豪. All rights reserved.
package xyz.fycz.myreader.entity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.provider.Settings;
import android.util.DisplayMetrics;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import xyz.fycz.myreader.application.MyApplication;
import xyz.fycz.myreader.util.SharedPreUtils;
import xyz.fycz.myreader.util.utils.BitmapUtil;
import xyz.fycz.myreader.util.utils.MeUtils;
import static xyz.fycz.myreader.widget.page2.PageLoader.DEFAULT_MARGIN_WIDTH;
public class ReadBookControl {
private static final int DEFAULT_BG = 1;
private int textDrawableIndex = DEFAULT_BG;
private List<Map<String, Integer>> textDrawable;
private Bitmap bgBitmap;
private int screenDirection;
private int speechRate;
private boolean speechRateFollowSys;
private int textSize;
private int textColor;
private boolean bgIsColor;
private int bgColor;
private float lineMultiplier;
private float paragraphSize;
private int pageMode;
private Boolean hideStatusBar;
private Boolean hideNavigationBar;
private String fontPath;
private int textConvert;
private int navBarColor;
private Boolean textBold;
private Boolean canClickTurn;
private Boolean canKeyTurn;
private Boolean readAloudCanKeyTurn;
private int CPM;
private Boolean clickAllNext;
private Boolean showTitle;
private Boolean showTimeBattery;
private Boolean showLine;
private Boolean darkStatusIcon;
private int indent;
private int screenTimeOut;
private int paddingLeft;
private int paddingTop;
private int paddingRight;
private int paddingBottom;
private int tipPaddingLeft;
private int tipPaddingTop;
private int tipPaddingRight;
private int tipPaddingBottom;
private float textLetterSpacing;
private boolean canSelectText;
public int minCPM = 200;
public int maxCPM = 2000;
private int defaultCPM = 500;
private SharedPreferences preferences;
private static ReadBookControl readBookControl;
public static ReadBookControl getInstance() {
if (readBookControl == null) {
synchronized (ReadBookControl.class) {
if (readBookControl == null) {
readBookControl = new ReadBookControl();
}
}
}
return readBookControl;
}
private ReadBookControl() {
preferences = SharedPreUtils.getInstance().getSharedReadable();
initTextDrawable();
updateReaderSettings();
}
public void updateReaderSettings() {
this.hideStatusBar = preferences.getBoolean("hide_status_bar", false);
this.hideNavigationBar = preferences.getBoolean("hide_navigation_bar", false);
this.indent = preferences.getInt("indent", 2);
this.textSize = preferences.getInt("textSize", 20);
this.canClickTurn = preferences.getBoolean("canClickTurn", true);
this.canKeyTurn = preferences.getBoolean("canKeyTurn", true);
this.readAloudCanKeyTurn = preferences.getBoolean("readAloudCanKeyTurn", false);
this.lineMultiplier = preferences.getFloat("lineMultiplier", 1);
this.paragraphSize = preferences.getFloat("paragraphSize", 1);
this.CPM = preferences.getInt("CPM", defaultCPM) > maxCPM
? minCPM : preferences.getInt("CPM", defaultCPM);
this.clickAllNext = preferences.getBoolean("clickAllNext", false);
this.fontPath = preferences.getString("fontPath", null);
this.textConvert = preferences.getInt("textConvertInt", 0);
this.textBold = preferences.getBoolean("textBold", false);
this.speechRate = preferences.getInt("speechRate", 10);
this.speechRateFollowSys = preferences.getBoolean("speechRateFollowSys", true);
this.showTitle = preferences.getBoolean("showTitle", true);
this.showTimeBattery = preferences.getBoolean("showTimeBattery", true);
this.showLine = preferences.getBoolean("showLine", true);
this.screenTimeOut = preferences.getInt("screenTimeOut", 0);
this.paddingLeft = preferences.getInt("paddingLeft", DEFAULT_MARGIN_WIDTH);
this.paddingTop = preferences.getInt("paddingTop", 0);
this.paddingRight = preferences.getInt("paddingRight", DEFAULT_MARGIN_WIDTH);
this.paddingBottom = preferences.getInt("paddingBottom", 0);
this.tipPaddingLeft = preferences.getInt("tipPaddingLeft", DEFAULT_MARGIN_WIDTH);
this.tipPaddingTop = preferences.getInt("tipPaddingTop", 0);
this.tipPaddingRight = preferences.getInt("tipPaddingRight", DEFAULT_MARGIN_WIDTH);
this.tipPaddingBottom = preferences.getInt("tipPaddingBottom", 0);
this.pageMode = preferences.getInt("pageMode", 0);
this.screenDirection = preferences.getInt("screenDirection", 0);
this.navBarColor = preferences.getInt("navBarColorInt", 0);
this.textLetterSpacing = preferences.getFloat("textLetterSpacing", 0);
this.canSelectText = preferences.getBoolean("canSelectText", false);
initTextDrawableIndex();
}
//阅读背景
private void initTextDrawable() {
if (null == textDrawable) {
textDrawable = new ArrayList<>();
Map<String, Integer> temp1 = new HashMap<>();
temp1.put("textColor", Color.parseColor("#3E3D3B"));
temp1.put("bgIsColor", 1);
temp1.put("textBackground", Color.parseColor("#F3F3F3"));
temp1.put("darkStatusIcon", 1);
textDrawable.add(temp1);
Map<String, Integer> temp2 = new HashMap<>();
temp2.put("textColor", Color.parseColor("#5E432E"));
temp2.put("bgIsColor", 1);
temp2.put("textBackground", Color.parseColor("#C6BAA1"));
temp2.put("darkStatusIcon", 1);
textDrawable.add(temp2);
Map<String, Integer> temp3 = new HashMap<>();
temp3.put("textColor", Color.parseColor("#22482C"));
temp3.put("bgIsColor", 1);
temp3.put("textBackground", Color.parseColor("#E1F1DA"));
temp3.put("darkStatusIcon", 1);
textDrawable.add(temp3);
Map<String, Integer> temp4 = new HashMap<>();
temp4.put("textColor", Color.parseColor("#FFFFFF"));
temp4.put("bgIsColor", 1);
temp4.put("textBackground", Color.parseColor("#015A86"));
temp4.put("darkStatusIcon", 0);
textDrawable.add(temp4);
Map<String, Integer> temp5 = new HashMap<>();
temp5.put("textColor", Color.parseColor("#808080"));
temp5.put("bgIsColor", 1);
temp5.put("textBackground", Color.parseColor("#000000"));
temp5.put("darkStatusIcon", 0);
textDrawable.add(temp5);
}
}
public void initTextDrawableIndex() {
if (getIsNightTheme()) {
textDrawableIndex = preferences.getInt("textDrawableIndexNight", 4);
} else {
textDrawableIndex = preferences.getInt("textDrawableIndex", DEFAULT_BG);
}
if (textDrawableIndex == -1) {
textDrawableIndex = DEFAULT_BG;
}
initPageStyle();
setTextDrawable();
}
@SuppressWarnings("ConstantConditions")
private void initPageStyle() {
int bgCustom = getBgCustom(textDrawableIndex);
if ((bgCustom == 2 || bgCustom == 3) && getBgPath(textDrawableIndex) != null) {
bgIsColor = false;
String bgPath = getBgPath(textDrawableIndex);
Resources resources = MyApplication.getApplication().getResources();
DisplayMetrics dm = resources.getDisplayMetrics();
int width = dm.widthPixels;
int height = dm.heightPixels;
if (bgCustom == 2) {
bgBitmap = BitmapUtil.getFitSampleBitmap(bgPath, width, height);
} else {
bgBitmap = MeUtils.getFitAssetsSampleBitmap(MyApplication.getApplication().getAssets(), bgPath, width, height);
}
if (bgBitmap != null) {
return;
}
} else if (getBgCustom(textDrawableIndex) == 1) {
bgIsColor = true;
bgColor = getBgColor(textDrawableIndex);
return;
}
bgIsColor = true;
bgColor = textDrawable.get(textDrawableIndex).get("textBackground");
}
private void setTextDrawable() {
darkStatusIcon = getDarkStatusIcon(textDrawableIndex);
textColor = getTextColor(textDrawableIndex);
}
public int getTextColor(int textDrawableIndex) {
if (preferences.getInt("textColor" + textDrawableIndex, 0) != 0) {
return preferences.getInt("textColor" + textDrawableIndex, 0);
} else {
return getDefaultTextColor(textDrawableIndex);
}
}
public void setTextColor(int textDrawableIndex, int textColor) {
preferences.edit()
.putInt("textColor" + textDrawableIndex, textColor)
.apply();
}
@SuppressWarnings("ConstantConditions")
public Drawable getBgDrawable(int textDrawableIndex, Context context, int width, int height) {
int color;
try {
Bitmap bitmap = null;
switch (getBgCustom(textDrawableIndex)) {
case 3:
bitmap = MeUtils.getFitAssetsSampleBitmap(context.getAssets(), getBgPath(textDrawableIndex), width, height);
if (bitmap != null) {
return new BitmapDrawable(context.getResources(), bitmap);
}
case 2:
bitmap = BitmapUtil.getFitSampleBitmap(getBgPath(textDrawableIndex), width, height);
if (bitmap != null) {
return new BitmapDrawable(context.getResources(), bitmap);
}
break;
case 1:
color = getBgColor(textDrawableIndex);
return new ColorDrawable(color);
}
if (textDrawable.get(textDrawableIndex).get("bgIsColor") != 0) {
color = textDrawable.get(textDrawableIndex).get("textBackground");
return new ColorDrawable(color);
} else {
return getDefaultBgDrawable(textDrawableIndex, context);
}
} catch (Exception e) {
if (textDrawable.get(textDrawableIndex).get("bgIsColor") != 0) {
color = textDrawable.get(textDrawableIndex).get("textBackground");
return new ColorDrawable(color);
} else {
return getDefaultBgDrawable(textDrawableIndex, context);
}
}
}
@SuppressWarnings("ConstantConditions")
public Drawable getDefaultBgDrawable(int textDrawableIndex, Context context) {
if (textDrawable.get(textDrawableIndex).get("bgIsColor") != 0) {
return new ColorDrawable(textDrawable.get(textDrawableIndex).get("textBackground"));
} else {
return context.getResources().getDrawable(getDefaultBg(textDrawableIndex));
}
}
public int getBgCustom(int textDrawableIndex) {
return preferences.getInt("bgCustom" + textDrawableIndex, 0);
}
public void setBgCustom(int textDrawableIndex, int bgCustom) {
preferences.edit()
.putInt("bgCustom" + textDrawableIndex, bgCustom)
.apply();
}
public String getBgPath(int textDrawableIndex) {
return preferences.getString("bgPath" + textDrawableIndex, null);
}
public void setBgPath(int textDrawableIndex, String bgUri) {
preferences.edit()
.putString("bgPath" + textDrawableIndex, bgUri)
.apply();
}
@SuppressWarnings("ConstantConditions")
public int getDefaultTextColor(int textDrawableIndex) {
return textDrawable.get(textDrawableIndex).get("textColor");
}
@SuppressWarnings("ConstantConditions")
private int getDefaultBg(int textDrawableIndex) {
return textDrawable.get(textDrawableIndex).get("textBackground");
}
public int getBgColor(int index) {
return preferences.getInt("bgColor" + index, Color.parseColor("#1e1e1e"));
}
public void setBgColor(int index, int bgColor) {
preferences.edit()
.putInt("bgColor" + index, bgColor)
.apply();
}
private boolean getIsNightTheme() {
return MyApplication.getApplication().isNightTheme();
}
public boolean getImmersionStatusBar() {
return preferences.getBoolean("immersionStatusBar", false);
}
public void setImmersionStatusBar(boolean immersionStatusBar) {
preferences.edit()
.putBoolean("immersionStatusBar", immersionStatusBar)
.apply();
}
public int getTextSize() {
return textSize;
}
public void setTextSize(int textSize) {
this.textSize = textSize;
preferences.edit()
.putInt("textSize", textSize)
.apply();
}
public int getTextColor() {
return textColor;
}
public boolean bgIsColor() {
return bgIsColor;
}
public Drawable getTextBackground(Context context) {
if (bgIsColor) {
return new ColorDrawable(bgColor);
}
return new BitmapDrawable(context.getResources(), bgBitmap);
}
public int getBgColor() {
return bgColor;
}
public boolean bgBitmapIsNull() {
return bgBitmap == null || bgBitmap.isRecycled();
}
public Bitmap getBgBitmap() {
return bgBitmap.copy(Bitmap.Config.ARGB_8888, true);
}
public int getTextDrawableIndex() {
return textDrawableIndex;
}
public void setTextDrawableIndex(int textDrawableIndex) {
this.textDrawableIndex = textDrawableIndex;
if (getIsNightTheme()) {
preferences.edit()
.putInt("textDrawableIndexNight", textDrawableIndex)
.apply();
} else {
preferences.edit()
.putInt("textDrawableIndex", textDrawableIndex)
.apply();
}
setTextDrawable();
}
public void setTextConvert(int textConvert) {
this.textConvert = textConvert;
preferences.edit()
.putInt("textConvertInt", textConvert)
.apply();
}
public void setNavBarColor(int navBarColor) {
this.navBarColor = navBarColor;
preferences.edit()
.putInt("navBarColorInt", navBarColor)
.apply();
}
public int getNavBarColor() {
return navBarColor;
}
public void setTextBold(boolean textBold) {
this.textBold = textBold;
preferences.edit()
.putBoolean("textBold", textBold)
.apply();
}
public void setReadBookFont(String fontPath) {
this.fontPath = fontPath;
preferences.edit()
.putString("fontPath", fontPath)
.apply();
}
public String getFontPath() {
return fontPath;
}
public int getTextConvert() {
return textConvert == -1 ? 2 : textConvert;
}
public Boolean getTextBold() {
return textBold;
}
public Boolean getCanKeyTurn(Boolean isPlay) {
if (!canKeyTurn) {
return false;
} else if (readAloudCanKeyTurn) {
return true;
} else {
return !isPlay;
}
}
public Boolean getCanKeyTurn() {
return canKeyTurn;
}
public void setCanKeyTurn(Boolean canKeyTurn) {
this.canKeyTurn = canKeyTurn;
preferences.edit()
.putBoolean("canKeyTurn", canKeyTurn)
.apply();
}
public Boolean getAloudCanKeyTurn() {
return readAloudCanKeyTurn;
}
public void setAloudCanKeyTurn(Boolean canAloudKeyTurn) {
this.readAloudCanKeyTurn = canAloudKeyTurn;
preferences.edit()
.putBoolean("readAloudCanKeyTurn", canAloudKeyTurn)
.apply();
}
public Boolean getCanClickTurn() {
return canClickTurn;
}
public void setCanClickTurn(Boolean canClickTurn) {
this.canClickTurn = canClickTurn;
preferences.edit()
.putBoolean("canClickTurn", canClickTurn)
.apply();
}
public float getTextLetterSpacing() {
return textLetterSpacing;
}
public void setTextLetterSpacing(float textLetterSpacing) {
this.textLetterSpacing = textLetterSpacing;
preferences.edit()
.putFloat("textLetterSpacing", textLetterSpacing)
.apply();
}
public float getLineMultiplier() {
return lineMultiplier;
}
public void setLineMultiplier(float lineMultiplier) {
this.lineMultiplier = lineMultiplier;
preferences.edit()
.putFloat("lineMultiplier", lineMultiplier)
.apply();
}
public float getParagraphSize() {
return paragraphSize;
}
public void setParagraphSize(float paragraphSize) {
this.paragraphSize = paragraphSize;
preferences.edit()
.putFloat("paragraphSize", paragraphSize)
.apply();
}
public int getCPM() {
return CPM;
}
public void setCPM(int cpm) {
if (cpm < minCPM || cpm > maxCPM) cpm = defaultCPM;
this.CPM = cpm;
preferences.edit()
.putInt("CPM", cpm)
.apply();
}
public Boolean getClickAllNext() {
return clickAllNext;
}
public void setClickAllNext(Boolean clickAllNext) {
this.clickAllNext = clickAllNext;
preferences.edit()
.putBoolean("clickAllNext", clickAllNext)
.apply();
}
public int getSpeechRate() {
return speechRate;
}
public void setSpeechRate(int speechRate) {
this.speechRate = speechRate;
preferences.edit()
.putInt("speechRate", speechRate)
.apply();
}
public boolean isSpeechRateFollowSys() {
return speechRateFollowSys;
}
public void setSpeechRateFollowSys(boolean speechRateFollowSys) {
this.speechRateFollowSys = speechRateFollowSys;
preferences.edit()
.putBoolean("speechRateFollowSys", speechRateFollowSys)
.apply();
}
public Boolean getShowTitle() {
return showTitle;
}
public void setShowTitle(Boolean showTitle) {
this.showTitle = showTitle;
preferences.edit()
.putBoolean("showTitle", showTitle)
.apply();
}
public Boolean getShowTimeBattery() {
return showTimeBattery;
}
public void setShowTimeBattery(Boolean showTimeBattery) {
this.showTimeBattery = showTimeBattery;
preferences.edit()
.putBoolean("showTimeBattery", showTimeBattery)
.apply();
}
public Boolean getHideStatusBar() {
return hideStatusBar;
}
public void setHideStatusBar(Boolean hideStatusBar) {
this.hideStatusBar = hideStatusBar;
preferences.edit()
.putBoolean("hide_status_bar", hideStatusBar)
.apply();
}
public Boolean getToLh() {
return preferences.getBoolean("toLh", false);
}
public void setToLh(Boolean toLh) {
preferences.edit()
.putBoolean("toLh", toLh)
.apply();
}
public Boolean getHideNavigationBar() {
return hideNavigationBar;
}
public void setHideNavigationBar(Boolean hideNavigationBar) {
this.hideNavigationBar = hideNavigationBar;
preferences.edit()
.putBoolean("hide_navigation_bar", hideNavigationBar)
.apply();
}
public Boolean getShowLine() {
return showLine;
}
public void setShowLine(Boolean showLine) {
this.showLine = showLine;
preferences.edit()
.putBoolean("showLine", showLine)
.apply();
}
public boolean getDarkStatusIcon() {
return darkStatusIcon;
}
@SuppressWarnings("ConstantConditions")
public boolean getDarkStatusIcon(int textDrawableIndex) {
return preferences.getBoolean("darkStatusIcon" + textDrawableIndex, textDrawable.get(textDrawableIndex).get("darkStatusIcon") != 0);
}
public void setDarkStatusIcon(int textDrawableIndex, Boolean darkStatusIcon) {
preferences.edit()
.putBoolean("darkStatusIcon" + textDrawableIndex, darkStatusIcon)
.apply();
}
public int getScreenTimeOut() {
return screenTimeOut;
}
public void setScreenTimeOut(int screenTimeOut) {
this.screenTimeOut = screenTimeOut;
preferences.edit()
.putInt("screenTimeOut", screenTimeOut)
.apply();
}
public int getPaddingLeft() {
return paddingLeft;
}
public void setPaddingLeft(int paddingLeft) {
this.paddingLeft = paddingLeft;
preferences.edit()
.putInt("paddingLeft", paddingLeft)
.apply();
}
public int getPaddingTop() {
return paddingTop;
}
public void setPaddingTop(int paddingTop) {
this.paddingTop = paddingTop;
preferences.edit()
.putInt("paddingTop", paddingTop)
.apply();
}
public int getPaddingRight() {
return paddingRight;
}
public void setPaddingRight(int paddingRight) {
this.paddingRight = paddingRight;
preferences.edit()
.putInt("paddingRight", paddingRight)
.apply();
}
public int getPaddingBottom() {
return paddingBottom;
}
public void setPaddingBottom(int paddingBottom) {
this.paddingBottom = paddingBottom;
preferences.edit()
.putInt("paddingBottom", paddingBottom)
.apply();
}
public int getTipPaddingLeft() {
return tipPaddingLeft;
}
public void setTipPaddingLeft(int tipPaddingLeft) {
this.tipPaddingLeft = tipPaddingLeft;
preferences.edit()
.putInt("tipPaddingLeft", tipPaddingLeft)
.apply();
}
public boolean isCanSelectText() {
return canSelectText;
}
public void setCanSelectText(boolean canSelectText) {
this.canSelectText = canSelectText;
preferences.edit()
.putBoolean("canSelectText", canSelectText)
.apply();
}
public int getTipPaddingTop() {
return tipPaddingTop;
}
public void setTipPaddingTop(int tipPaddingTop) {
this.tipPaddingTop = tipPaddingTop;
preferences.edit()
.putInt("tipPaddingTop", tipPaddingTop)
.apply();
}
public int getTipPaddingRight() {
return tipPaddingRight;
}
public void setTipPaddingRight(int tipPaddingRight) {
this.tipPaddingRight = tipPaddingRight;
preferences.edit()
.putInt("tipPaddingRight", tipPaddingRight)
.apply();
}
public int getTipPaddingBottom() {
return tipPaddingBottom;
}
public void setTipPaddingBottom(int tipPaddingBottom) {
this.tipPaddingBottom = tipPaddingBottom;
preferences.edit()
.putInt("tipPaddingBottom", tipPaddingBottom)
.apply();
}
public int getPageMode() {
return pageMode;
}
public void setPageMode(int pageMode) {
this.pageMode = pageMode;
preferences.edit()
.putInt("pageMode", pageMode)
.apply();
}
public int getScreenDirection() {
return screenDirection;
}
public void setScreenDirection(int screenDirection) {
this.screenDirection = screenDirection;
preferences.edit()
.putInt("screenDirection", screenDirection)
.apply();
}
public void setIndent(int indent) {
this.indent = indent;
preferences.edit()
.putInt("indent", indent)
.apply();
}
public int getIndent() {
return indent;
}
public int getLight() {
return preferences.getInt("light", getScreenBrightness());
}
public void setLight(int light) {
preferences.edit()
.putInt("light", light)
.apply();
}
public Boolean getLightFollowSys() {
return preferences.getBoolean("lightFollowSys", true);
}
public void setLightFollowSys(boolean isFollowSys) {
preferences.edit()
.putBoolean("lightFollowSys", isFollowSys)
.apply();
}
private int getScreenBrightness() {
int value = 0;
ContentResolver cr = MyApplication.getApplication().getContentResolver();
try {
value = Settings.System.getInt(cr, Settings.System.SCREEN_BRIGHTNESS);
} catch (Settings.SettingNotFoundException ignored) {
}
return value;
}
public boolean disableScrollClickTurn() {
return preferences.getBoolean("disableScrollClickTurn", false);
}
}

@ -0,0 +1,318 @@
package xyz.fycz.myreader.entity;
import com.google.gson.Gson;
import java.io.Serializable;
import xyz.fycz.myreader.enums.Font;
import xyz.fycz.myreader.enums.Language;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.widget.page.PageMode;
/**
* 阅读布局
*/
public class ReadStyle implements Serializable {
private static final long serialVersionUID = 2295691803219441757L;
private int readWordSize;//阅读字体大小
private int brightProgress;//亮度 1- 100
private boolean brightFollowSystem;//亮度跟随系统
private Language language;//简繁体
private Font font;//字体
private int autoScrollSpeed;//自动滑屏速度
private PageMode pageMode;//翻页模式
private boolean isVolumeTurnPage = true;//是否开启音量键翻页
private int resetScreen = 3;//息屏时间(单位:min,0是不息屏)
private String localFontName;//本地字体名字
private boolean isShowStatusBar;//是否显示状态栏
private boolean alwaysNext;//是否总是翻到下一页
private int intent;//缩进字符
private float lineMultiplier;//行间距
private float paragraphSize;//段间距
private float textLetterSpacing;//字间距
private int paddingLeft;//左边距
private int paddingTop;//上边距
private int paddingRight;//右边距
private int paddingBottom;//下边距
private int composition;//排版选择
private boolean tightCom;//是否紧凑排版
private boolean bgIsColor;//背景是否为颜色 不能共用
private boolean bgIsAssert;//背景是否为assert文件 不能共用
private int textColor;//文字颜色 不能共用
private int bgColor;//背景颜色 不能共用
private String bgPath;//背景图片地址 不能共用
private boolean protectEye;//开启护眼模式
private int blueFilterPercent;//蓝光过滤比率
@Override
public Object clone() {
try {
Gson gson = new Gson();
String json = gson.toJson(this);
return gson.fromJson(json, ReadStyle.class);
} catch (Exception e) {
e.printStackTrace();
}
return this;
}
public int getReadWordSize() {
return readWordSize;
}
public void setReadWordSize(int readWordSize) {
this.readWordSize = readWordSize;
}
public int getBrightProgress() {
return brightProgress;
}
public void setBrightProgress(int brightProgress) {
this.brightProgress = brightProgress;
}
public boolean isBrightFollowSystem() {
return brightFollowSystem;
}
public void setBrightFollowSystem(boolean brightFollowSystem) {
this.brightFollowSystem = brightFollowSystem;
}
public Language getLanguage() {
return language;
}
public void setLanguage(Language language) {
this.language = language;
}
public Font getFont() {
return font;
}
public void setFont(Font font) {
this.font = font;
}
public int getAutoScrollSpeed() {
return autoScrollSpeed;
}
public void setAutoScrollSpeed(int autoScrollSpeed) {
this.autoScrollSpeed = autoScrollSpeed;
}
public PageMode getPageMode() {
return pageMode;
}
public void setPageMode(PageMode pageMode) {
this.pageMode = pageMode;
}
public boolean isVolumeTurnPage() {
return isVolumeTurnPage;
}
public void setVolumeTurnPage(boolean volumeTurnPage) {
isVolumeTurnPage = volumeTurnPage;
}
public int getResetScreen() {
return resetScreen;
}
public void setResetScreen(int resetScreen) {
this.resetScreen = resetScreen;
}
public String getLocalFontName() {
return localFontName;
}
public void setLocalFontName(String localFontName) {
this.localFontName = localFontName;
}
public boolean isShowStatusBar() {
return isShowStatusBar;
}
public void setShowStatusBar(boolean showStatusBar) {
isShowStatusBar = showStatusBar;
}
public boolean isAlwaysNext() {
return alwaysNext;
}
public void setAlwaysNext(boolean alwaysNext) {
this.alwaysNext = alwaysNext;
}
public int getIntent() {
return intent;
}
public void setIntent(int intent) {
this.intent = intent;
}
public float getLineMultiplier() {
return lineMultiplier;
}
public void setLineMultiplier(float lineMultiplier) {
this.lineMultiplier = lineMultiplier;
}
public float getParagraphSize() {
return paragraphSize;
}
public void setParagraphSize(float paragraphSize) {
this.paragraphSize = paragraphSize;
}
public float getTextLetterSpacing() {
return textLetterSpacing;
}
public void setTextLetterSpacing(float textLetterSpacing) {
this.textLetterSpacing = textLetterSpacing;
}
public int getPaddingLeft() {
return paddingLeft;
}
public void setPaddingLeft(int paddingLeft) {
this.paddingLeft = paddingLeft;
}
public int getPaddingTop() {
return paddingTop;
}
public void setPaddingTop(int paddingTop) {
this.paddingTop = paddingTop;
}
public int getPaddingRight() {
return paddingRight;
}
public void setPaddingRight(int paddingRight) {
this.paddingRight = paddingRight;
}
public int getPaddingBottom() {
return paddingBottom;
}
public void setPaddingBottom(int paddingBottom) {
this.paddingBottom = paddingBottom;
}
public int getComposition() {
return composition;
}
public void setComposition(int composition) {
this.composition = composition;
}
public boolean isTightCom() {
return tightCom;
}
public void setTightCom(boolean tightCom) {
this.tightCom = tightCom;
}
public boolean bgIsColor() {
return bgIsColor;
}
public void setBgIsColor(boolean bgIsColor) {
this.bgIsColor = bgIsColor;
}
public boolean bgIsAssert() {
return bgIsAssert;
}
public void setBgIsAssert(boolean bgIsAssert) {
this.bgIsAssert = bgIsAssert;
}
public int getTextColor() {
return textColor;
}
public void setTextColor(int textColor) {
this.textColor = textColor;
}
public int getBgColor() {
return bgColor;
}
public void setBgColor(int bgColor) {
this.bgColor = bgColor;
}
public String getBgPath() {
return bgPath;
}
public void setBgPath(String bgPath) {
this.bgPath = bgPath;
}
public boolean isProtectEye() {
return protectEye;
}
public void setProtectEye(boolean protectEye) {
this.protectEye = protectEye;
}
public int getBlueFilterPercent() {
return blueFilterPercent;
}
public void setBlueFilterPercent(int blueFilterPercent) {
this.blueFilterPercent = blueFilterPercent;
}
}

@ -1,12 +1,41 @@
package xyz.fycz.myreader.entity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.Log;
import xyz.fycz.myreader.application.MyApplication;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.enums.BookcaseStyle;
import xyz.fycz.myreader.enums.Font;
import xyz.fycz.myreader.enums.Language;
import xyz.fycz.myreader.enums.ReadStyle;
import xyz.fycz.myreader.util.StringHelper;
import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.util.ZipUtils;
import xyz.fycz.myreader.util.utils.BitmapUtil;
import xyz.fycz.myreader.util.utils.FileUtils;
import xyz.fycz.myreader.util.utils.GsonExtensionsKt;
import xyz.fycz.myreader.util.utils.MeUtils;
import xyz.fycz.myreader.widget.page.PageMode;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import static xyz.fycz.myreader.common.APPCONST.READ_STYLE_BLUE_DEEP;
import static xyz.fycz.myreader.common.APPCONST.READ_STYLE_BREEN;
import static xyz.fycz.myreader.common.APPCONST.READ_STYLE_COMMON;
import static xyz.fycz.myreader.common.APPCONST.READ_STYLE_LEATHER;
import static xyz.fycz.myreader.common.APPCONST.READ_STYLE_NIGHT;
import static xyz.fycz.myreader.common.APPCONST.READ_STYLE_PROTECTED_EYE;
import static xyz.fycz.myreader.common.APPCONST.s;
import static xyz.fycz.myreader.widget.page.PageLoader.DEFAULT_MARGIN_WIDTH;
/**
* 用户设置
@ -17,30 +46,19 @@ public class Setting implements Serializable {
private static final long serialVersionUID = 2295691810299441757L;
private float readWordSize;//阅读字体大小
/**
* 共七套布局5套自带布局(0~4)一套自定义(5)一套夜间(6)
*/
private List<ReadStyle> readStyles;//阅读布局
private ReadStyle readStyle = ReadStyle.leather;//阅读模式
private int curReadStyleIndex;//当前阅读布局
private boolean dayStyle;//是否日间模式
private int brightProgress;//亮度 1- 100
private boolean brightFollowSystem;//亮度跟随系统
private Language language;//简繁体
private Font font;//字体
private int autoScrollSpeed = 3;//自动滑屏速度
private PageMode pageMode;//翻页模式
private boolean isVolumeTurnPage = true;//是否开启音量键翻页
private int resetScreen = 3;//息屏时间(单位:min,0是不息屏)
private BookcaseStyle bookcaseStyle;//书架布局
private int newestVersionCode;//最新版本号
private String localFontName;//本地字体名字
private boolean isAutoSyn;//是否自动同步书架
private boolean isMatchChapter = true;//是否开启智能匹配历史章节
@ -53,46 +71,257 @@ public class Setting implements Serializable {
private boolean openBookStore;//是否开启书城
private boolean sharedLayout;//是否共用布局
private boolean horizontalScreen;//是否横屏
private boolean noMenuChTitle;//关闭阅读上边菜单章节标题和链接显示
private boolean readAloudVolumeTurnPage;//朗读时音量键翻页
private int searchFilter;//搜索过滤:0-不过滤,1-模糊搜索,2-精确搜索
private int sortStyle;//排序方式:0-手动排序,1-按时间排序,2-按照书名排序
private int sourceVersion;//书源版本号
private int settingVersion;//设置版本号
public ReadStyle getCurReadStyle(){
//Log.d("curReadStyleIndex", String.valueOf(curReadStyleIndex));
ReadStyle readStyle = readStyles.get(curReadStyleIndex);
if (readStyle == null) {
initReadStyle();
}
if (!dayStyle){
return readStyles.get(6);
}
return readStyles.get(curReadStyleIndex);
}
public Drawable getBgDrawable(int readStyleIndex, Context context, int width, int height) {
ReadStyle readStyle = readStyles.get(readStyleIndex);
if (readStyle.bgIsColor()){
return new ColorDrawable(readStyle.getBgColor());
}else {
Bitmap bitmap = null;
try {
if (readStyle.bgIsAssert()) {
bitmap = MeUtils.getFitAssetsSampleBitmap(context.getAssets(), readStyle.getBgPath(), width, height);
} else {
bitmap = BitmapUtil.getFitSampleBitmap(readStyle.getBgPath(), width, height);
}
if (bitmap == null) {
bitmap = MeUtils.getFitAssetsSampleBitmap(context.getAssets(), "bg/p01.jpg", width, height);
}
}catch (Exception e){
bitmap = MeUtils.getFitAssetsSampleBitmap(context.getAssets(), "bg/p01.jpg", width, height);
}
return new BitmapDrawable(context.getResources(), bitmap);
}
}
public void initReadStyle(){
readStyles = new ArrayList<>();
for (int i = 0; i < 7; i++) {
ReadStyle readStyle = new ReadStyle();
String textColor;
String bgColor;
switch(i){
case 0:
textColor = READ_STYLE_COMMON[0];
bgColor = READ_STYLE_COMMON[1];
break;
case 1:
default:
textColor = READ_STYLE_LEATHER[0];
bgColor = READ_STYLE_LEATHER[1];
break;
case 2:
textColor = READ_STYLE_PROTECTED_EYE[0];
bgColor = READ_STYLE_PROTECTED_EYE[1];
break;
case 3:
textColor = READ_STYLE_BREEN[0];
bgColor = READ_STYLE_BREEN[1];
break;
case 4:
textColor = READ_STYLE_BLUE_DEEP[0];
bgColor = READ_STYLE_BLUE_DEEP[1];
break;
case 6:
textColor = READ_STYLE_NIGHT[0];
bgColor = READ_STYLE_NIGHT[1];
break;
}
readStyle.setTextColor(Color.parseColor(textColor));
readStyle.setBgColor(Color.parseColor(bgColor));
readStyle.setReadWordSize(20);
readStyle.setBrightProgress(50);
readStyle.setBrightFollowSystem(true);
readStyle.setLanguage(Language.normal);
readStyle.setFont(Font.默认字体);
readStyle.setLocalFontName("");
readStyle.setAutoScrollSpeed(60);
readStyle.setPageMode(PageMode.COVER);
readStyle.setVolumeTurnPage(true);
readStyle.setResetScreen(3);
readStyle.setShowStatusBar(false);
readStyle.setAlwaysNext(false);
readStyle.setIntent(2);
readStyle.setLineMultiplier(1);
readStyle.setParagraphSize(0.9f);
readStyle.setTextLetterSpacing(0);
readStyle.setPaddingLeft(DEFAULT_MARGIN_WIDTH);
readStyle.setPaddingRight(DEFAULT_MARGIN_WIDTH);
readStyle.setPaddingTop(0);
readStyle.setPaddingBottom(0);
readStyle.setTightCom(false);
readStyle.setBgIsColor(true);
readStyle.setBgIsAssert(true);
readStyle.setBgPath("");
readStyle.setBlueFilterPercent(30);
readStyle.setProtectEye(false);
readStyle.setComposition(1);
readStyles.add(readStyle);
}
}
public void resetLayout(){
for (int i = 0; i < 7; i++) {
ReadStyle readStyle = readStyles.get(i);
String textColor;
String bgColor;
switch(i){
case 0:
textColor = READ_STYLE_COMMON[0];
bgColor = READ_STYLE_COMMON[1];
break;
case 1:
default:
textColor = READ_STYLE_LEATHER[0];
bgColor = READ_STYLE_LEATHER[1];
break;
case 2:
textColor = READ_STYLE_PROTECTED_EYE[0];
bgColor = READ_STYLE_PROTECTED_EYE[1];
break;
case 3:
textColor = READ_STYLE_BREEN[0];
bgColor = READ_STYLE_BREEN[1];
break;
case 4:
textColor = READ_STYLE_BLUE_DEEP[0];
bgColor = READ_STYLE_BLUE_DEEP[1];
break;
case 6:
textColor = READ_STYLE_NIGHT[0];
bgColor = READ_STYLE_NIGHT[1];
break;
}
readStyle.setTextColor(Color.parseColor(textColor));
readStyle.setBgColor(Color.parseColor(bgColor));
readStyle.setBgIsColor(true);
readStyle.setBgIsAssert(true);
readStyle.setBgPath("");
}
}
public void sharedLayout(){
if (sharedLayout) {
for (int i = 0; i < 7; i++) {
if (curReadStyleIndex == i) continue;
ReadStyle newReadStyle = (ReadStyle) getCurReadStyle().clone();
ReadStyle oldReadStyle = readStyles.get(i);
newReadStyle.setTextColor(oldReadStyle.getTextColor());
newReadStyle.setBgColor(oldReadStyle.getBgColor());
newReadStyle.setBgIsAssert(oldReadStyle.bgIsAssert());
newReadStyle.setBgIsColor(oldReadStyle.bgIsColor());
newReadStyle.setBgPath(oldReadStyle.getBgPath());
readStyles.set(i, newReadStyle);
}
}
}
public void saveLayout(int index){
ReadStyle newReadStyle = (ReadStyle) getCurReadStyle().clone();
readStyles.set(index, newReadStyle);
}
public boolean exportLayout(int index){
ReadStyle readStyle = readStyles.get(index);
String json = GsonExtensionsKt.getGSON().toJson(readStyle);
List<String> filesPath = new ArrayList<>();
filesPath.add(APPCONST.TEM_FILE_DIR + "readConfig.fyl");
filesPath.add(APPCONST.TEM_FILE_DIR + "bg.fyl");
if (!FileUtils.writeFile(json.getBytes(),
FileUtils.getFile(filesPath.get(0)))){
return false;
}
if (!readStyle.bgIsColor() && !readStyle.bgIsAssert()){
if (!FileUtils.copy(readStyle.getBgPath(), filesPath.get(1))){
return false;
}
}
try {
ZipUtils.zipFiles(filesPath, APPCONST.FILE_DIR + "readConfig.zip", "风月读书布局导出配置");
FileUtils.deleteFile(filesPath.get(0));
FileUtils.deleteFile(filesPath.get(1));
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
public void importLayout(int index, ReadStyle readStyle){
readStyles.set(index, readStyle);
}
public int getAutoScrollSpeed() {
return autoScrollSpeed;
return getCurReadStyle().getAutoScrollSpeed();
}
public void setAutoScrollSpeed(int autoScrollSpeed) {
this.autoScrollSpeed = autoScrollSpeed;
getCurReadStyle().setAutoScrollSpeed(autoScrollSpeed);
sharedLayout();
}
public Font getFont() {
return font;
return getCurReadStyle().getFont();
}
public void setFont(Font font) {
this.font = font;
getCurReadStyle().setFont(font);
sharedLayout();
}
public Language getLanguage() {
return language;
return getCurReadStyle().getLanguage();
}
public void setLanguage(Language language) {
this.language = language;
getCurReadStyle().setLanguage(language);
sharedLayout();
}
public boolean isBrightFollowSystem() {
return brightFollowSystem;
return getCurReadStyle().isBrightFollowSystem();
}
public void setBrightFollowSystem(boolean brightFollowSystem) {
this.brightFollowSystem = brightFollowSystem;
getCurReadStyle().setBrightFollowSystem(brightFollowSystem);
sharedLayout();
}
public void setBrightProgress(int brightProgress) {
this.brightProgress = brightProgress;
getCurReadStyle().setBrightProgress(brightProgress);
sharedLayout();
}
public int getBrightProgress() {
return brightProgress;
return getCurReadStyle().getBrightProgress();
}
public boolean isDayStyle() {
@ -103,36 +332,31 @@ public class Setting implements Serializable {
this.dayStyle = dayStyle;
}
public float getReadWordSize() {
return readWordSize;
}
public void setReadWordSize(float readWordSize) {
this.readWordSize = readWordSize;
public int getReadWordSize() {
return getCurReadStyle().getReadWordSize();
}
public ReadStyle getReadStyle() {
return readStyle;
}
public void setReadStyle(ReadStyle readStyle) {
this.readStyle = readStyle;
public void setReadWordSize(int readWordSize) {
getCurReadStyle().setReadWordSize(readWordSize);
sharedLayout();
}
public PageMode getPageMode() {
return pageMode;
return getCurReadStyle().getPageMode();
}
public void setPageMode(PageMode pageMode) {
this.pageMode = pageMode;
getCurReadStyle().setPageMode(pageMode);
sharedLayout();
}
public boolean isVolumeTurnPage() {
return isVolumeTurnPage;
return getCurReadStyle().isVolumeTurnPage();
}
public void setVolumeTurnPage(boolean volumeTurnPage) {
isVolumeTurnPage = volumeTurnPage;
getCurReadStyle().setVolumeTurnPage(volumeTurnPage);
sharedLayout();
}
public BookcaseStyle getBookcaseStyle() {
@ -152,11 +376,12 @@ public class Setting implements Serializable {
}
public String getLocalFontName() {
return localFontName;
return getCurReadStyle().getLocalFontName();
}
public void setLocalFontName(String localFontName) {
this.localFontName = localFontName;
getCurReadStyle().setLocalFontName(localFontName);
sharedLayout();
}
public boolean isAutoSyn() {
@ -176,11 +401,12 @@ public class Setting implements Serializable {
}
public int getResetScreen() {
return resetScreen;
return getCurReadStyle().getResetScreen();
}
public void setResetScreen(int resetScreen) {
this.resetScreen = resetScreen;
getCurReadStyle().setResetScreen(resetScreen);
sharedLayout();
}
public boolean isMatchChapter() {
@ -215,6 +441,24 @@ public class Setting implements Serializable {
this.refreshWhenStart = refreshWhenStart;
}
public boolean isShowStatusBar() {
return getCurReadStyle().isShowStatusBar();
}
public void setShowStatusBar(boolean showStatusBar) {
getCurReadStyle().setShowStatusBar(showStatusBar);
sharedLayout();
}
public boolean isAlwaysNext() {
return getCurReadStyle().isAlwaysNext();
}
public void setAlwaysNext(boolean alwaysNext) {
getCurReadStyle().setAlwaysNext(alwaysNext);
sharedLayout();
}
public boolean isOpenBookStore() {
return openBookStore;
}
@ -222,4 +466,232 @@ public class Setting implements Serializable {
public void setOpenBookStore(boolean openBookStore) {
this.openBookStore = openBookStore;
}
public boolean isHorizontalScreen() {
return horizontalScreen;
}
public void setHorizontalScreen(boolean horizontalScreen) {
this.horizontalScreen = horizontalScreen;
}
public void setIntent(int intent) {
getCurReadStyle().setIntent(intent);
sharedLayout();
}
public void setLineMultiplier(float lineMultiplier) {
getCurReadStyle().setLineMultiplier(lineMultiplier);
sharedLayout();
}
public void setParagraphSize(float paragraphSize) {
getCurReadStyle().setParagraphSize(paragraphSize);
sharedLayout();
}
public int getIntent() {
return getCurReadStyle().getIntent();
}
public float getLineMultiplier() {
return getCurReadStyle().getLineMultiplier();
}
public float getParagraphSize() {
return getCurReadStyle().getParagraphSize();
}
public float getTextLetterSpacing() {
return getCurReadStyle().getTextLetterSpacing();
}
public void setTextLetterSpacing(float textLetterSpacing) {
getCurReadStyle().setTextLetterSpacing(textLetterSpacing);
sharedLayout();
}
public int getComposition() {
return getCurReadStyle().getComposition();
}
public void setComposition(int composition) {
getCurReadStyle().setComposition(composition);
sharedLayout();
}
public int getPaddingLeft() {
return getCurReadStyle().getPaddingLeft();
}
public void setPaddingLeft(int paddingLeft) {
getCurReadStyle().setPaddingLeft(paddingLeft);
sharedLayout();
}
public int getPaddingTop() {
return getCurReadStyle().getPaddingTop();
}
public void setPaddingTop(int paddingTop) {
getCurReadStyle().setPaddingTop(paddingTop);
sharedLayout();
}
public int getPaddingRight() {
return getCurReadStyle().getPaddingRight();
}
public void setPaddingRight(int paddingRight) {
getCurReadStyle().setPaddingRight(paddingRight);
sharedLayout();
}
public int getPaddingBottom() {
return getCurReadStyle().getPaddingBottom();
}
public void setPaddingBottom(int paddingBottom) {
getCurReadStyle().setPaddingBottom(paddingBottom);
sharedLayout();
}
public boolean isTightCom() {
return getCurReadStyle().isTightCom();
}
public void setTightCom(boolean tightCom) {
getCurReadStyle().setTightCom(tightCom);
sharedLayout();
}
public boolean bgIsColor() {
if (StringHelper.isEmpty(getCurReadStyle().getBgPath())) {
getCurReadStyle().setBgIsColor(true);
}
return getCurReadStyle().bgIsColor();
}
public void setBgIsColor(boolean bgIsColor) {
getCurReadStyle().setBgIsColor(bgIsColor);
}
public boolean bgIsAssert() {
return getCurReadStyle().bgIsAssert();
}
public void setBgIsAssert(boolean bgIsAssert) {
getCurReadStyle().setBgIsAssert(bgIsAssert);
}
public int getTextColor() {
if (getCurReadStyle().getTextColor() == 0) {
getCurReadStyle().setTextColor(Color.parseColor(READ_STYLE_LEATHER[0]));
}
return getCurReadStyle().getTextColor();
}
public void setTextColor(int textColor) {
getCurReadStyle().setTextColor(textColor);
}
public int getBgColor() {
if (getCurReadStyle().getBgColor() == 0) {
getCurReadStyle().setBgColor(Color.parseColor(READ_STYLE_LEATHER[1]));
}
return getCurReadStyle().getBgColor();
}
public void setBgColor(int bgColor) {
getCurReadStyle().setBgColor(bgColor);
}
public String getBgPath() {
return getCurReadStyle().getBgPath();
}
public void setBgPath(String bgPath) {
getCurReadStyle().setBgPath(bgPath);
}
public int getCurReadStyleIndex() {
return curReadStyleIndex;
}
public void setCurReadStyleIndex(int curReadStyleIndex) {
this.curReadStyleIndex = curReadStyleIndex;
}
public boolean isSharedLayout() {
return sharedLayout;
}
public void setSharedLayout(boolean sharedLayout) {
this.sharedLayout = sharedLayout;
}
public boolean isNoMenuChTitle() {
return noMenuChTitle;
}
public boolean isReadAloudVolumeTurnPage() {
return readAloudVolumeTurnPage;
}
public void setReadAloudVolumeTurnPage(boolean readAloudVolumeTurnPage) {
this.readAloudVolumeTurnPage = readAloudVolumeTurnPage;
}
public void setNoMenuChTitle(boolean noMenuChTitle) {
this.noMenuChTitle = noMenuChTitle;
}
public boolean isProtectEye() {
return getCurReadStyle().isProtectEye();
}
public void setProtectEye(boolean protectEye) {
getCurReadStyle().setProtectEye(protectEye);
}
public int getBlueFilterPercent() {
if (getCurReadStyle().getBlueFilterPercent() == 0) getCurReadStyle().setBlueFilterPercent(30);
return getCurReadStyle().getBlueFilterPercent();
}
public void setBlueFilterPercent(int blueFilterPercent) {
getCurReadStyle().setBlueFilterPercent(blueFilterPercent);
}
public int getSourceVersion() {
return sourceVersion;
}
public void setSourceVersion(int sourceVersion) {
this.sourceVersion = sourceVersion;
}
public List<ReadStyle> getReadStyles() {
return readStyles;
}
public void setReadStyles(List<ReadStyle> readStyles) {
this.readStyles = readStyles;
}
public int getSearchFilter() {
return searchFilter;
}
public void setSearchFilter(int searchFilter) {
this.searchFilter = searchFilter;
}
public int getSortStyle() {
return sortStyle;
}
public void setSortStyle(int sortStyle) {
this.sortStyle = sortStyle;
}
}

@ -0,0 +1,102 @@
package xyz.fycz.myreader.entity;
import xyz.fycz.myreader.greendao.entity.Book;
/**
* @author fengyue
* @date 2020/11/29 19:01
*/
public class SharedBook {
private String name;
private String author;
private String type;
private String desc;
private String imgUrl;
private String chapterUrl;
private String source;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getImgUrl() {
return imgUrl;
}
public void setImgUrl(String imgUrl) {
this.imgUrl = imgUrl;
}
public String getChapterUrl() {
return chapterUrl;
}
public void setChapterUrl(String chapterUrl) {
this.chapterUrl = chapterUrl;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public static SharedBook bookToSharedBook(Book book){
int maxDesc = 208;
String desc = book.getDesc();
if (desc.length() > maxDesc){
desc = desc.substring(0, maxDesc - 1) + "…";
}
SharedBook sharedBook = new SharedBook();
sharedBook.setName(book.getName());
sharedBook.setAuthor(book.getAuthor());
sharedBook.setType(book.getType());
sharedBook.setDesc(desc);
sharedBook.setImgUrl(book.getImgUrl());
sharedBook.setChapterUrl(book.getChapterUrl());
sharedBook.setSource(book.getSource());
return sharedBook;
}
public static Book sharedBookToBook(SharedBook sharedBook){
Book book = new Book();
book.setName(sharedBook.name);
book.setAuthor(sharedBook.author);
book.setType(sharedBook.type);
book.setDesc(sharedBook.desc);
book.setImgUrl(sharedBook.imgUrl);
book.setChapterUrl(sharedBook.chapterUrl);
book.setSource(sharedBook.source);
return book;
}
}

@ -9,6 +9,7 @@ public class BookType {
private String typeName;//分类名称
private String url;//分类链接
private int pageSize;//页数
public String getTypeName() {
return typeName;
@ -25,4 +26,12 @@ public class BookType {
public void setUrl(String url) {
this.url = url;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
}

@ -1,5 +1,9 @@
package xyz.fycz.myreader.enums;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.MyApplication;
import xyz.fycz.myreader.util.ToastUtils;
/**
* 小说源
*/
@ -7,21 +11,27 @@ package xyz.fycz.myreader.enums;
public enum BookSource {
fynovel("风月小说"),
tianlai("天籁小说"),
biquge44("笔趣阁44"),
pinshu("品书网"),
biquge("笔趣阁"),
qb5("全本小说"),
miqu("米趣小说"),
jiutao("九桃小说"),
yunzhong("云中书库"),
sonovel("搜小说网"),
quannovel("全小说网"),
qiqi("奇奇小说"),
chaoxing("超星图书·实体"),
zuopin("作品集·实体"),
cangshu99("99藏书·实体"),
ben100("100本·实体"),
tianlai(MyApplication.getApplication().getString(R.string.read_tianlai)),
biquge44(MyApplication.getApplication().getString(R.string.read_biquge44)),
pinshu(MyApplication.getApplication().getString(R.string.read_pinshu)),
biquge(MyApplication.getApplication().getString(R.string.read_biquge)),
qb5(MyApplication.getApplication().getString(R.string.read_qb5)),
miqu(MyApplication.getApplication().getString(R.string.read_miqu)),
jiutao(MyApplication.getApplication().getString(R.string.read_jiutao)),
miaobi(MyApplication.getApplication().getString(R.string.read_miaobi)),
dstq(MyApplication.getApplication().getString(R.string.read_dstq)),
yunzhong(MyApplication.getApplication().getString(R.string.read_yunzhong)),
sonovel(MyApplication.getApplication().getString(R.string.read_sonovel)),
quannovel(MyApplication.getApplication().getString(R.string.read_quannovel)),
qiqi(MyApplication.getApplication().getString(R.string.read_qiqi)),
xs7(MyApplication.getApplication().getString(R.string.read_xs7)),
du1du(MyApplication.getApplication().getString(R.string.read_du1du)),
paiotian(MyApplication.getApplication().getString(R.string.read_paiotian)),
chaoxing(MyApplication.getApplication().getString(R.string.read_chaoxing)),
zuopin(MyApplication.getApplication().getString(R.string.read_zuopin)),
cangshu99(MyApplication.getApplication().getString(R.string.read_cangshu99)),
ben100(MyApplication.getApplication().getString(R.string.read_ben100)),
//liulangcat("流浪猫·实体"),
local("本地书籍");
public String text;
@ -35,7 +45,7 @@ public enum BookSource {
return bookSource.toString();
}
}
return null;
return "";
}
public static BookSource get(int var0) {
@ -43,7 +53,12 @@ public enum BookSource {
}
public static BookSource fromString(String string) {
return valueOf(string);
try {
return valueOf(string);
} catch (Exception e) {
ToastUtils.showError(e.getLocalizedMessage());
return fynovel;
}
}
}

@ -2,11 +2,6 @@ package xyz.fycz.myreader.enums;
import java.io.Serializable;
/**
* 小说源
* Created by zhao on 2020/04/13.
*/
public enum FindType implements Serializable {
qidian("排行榜[起点中文网]", "https://www.qidian.com/rank"),

@ -1,29 +1,35 @@
package xyz.fycz.myreader.enums;
import xyz.fycz.myreader.application.SysManager;
import xyz.fycz.myreader.common.APPCONST;
/**
* Created by zhao on 2016/11/3.
*/
public enum Font {
默认字体("默认字体", "默认字体"),
方正楷体("fangzhengkaiti.ttf", "https://fycz.lanzous.com/ilLFMe6kefe"),
方正行楷("fangzhengxingkai.ttf", "https://fycz.lanzous.com/imFvne6keji"),
经典宋体("songti.ttf", "https://fycz.lanzous.com/idhI5e6keqf"),
迷你隶书("mini_lishu.ttf", "https://fycz.lanzous.com/ihaXVe6kekj"),
方正黄草("fangzhenghuangcao.ttf", "https://fycz.lanzous.com/iQg67e6keed"),
方正硬笔行书("fangzheng_yingbi_xingshu.ttf", "https://fycz.lanzous.com/ilVh6ep9xja"),
本地字体("本地字体", "默认字体");
public String fileName;
默认字体( "默认字体"),
本地字体( "默认字体"),
方正楷体( "https://fycz.lanzous.com/ilLFMe6kefe"),
方正行楷( "https://fycz.lanzous.com/imFvne6keji"),
经典宋体("https://fycz.lanzous.com/idhI5e6keqf"),
方正硬笔行书("https://fycz.lanzous.com/ilVh6ep9xja"),
包图小白体("https://fycz.lanzoui.com/i5qgAicrirc"),
仓耳非白W02("https://fycz.lanzoui.com/iHwRnicriuf"),
仓耳舒圆体W02("https://fycz.lanzoui.com/i3GVPicrj3e"),
仓耳与墨W02("https://fycz.lanzoui.com/ivhv9icrj7i"),
方正仿宋简体("https://fycz.lanzoui.com/iEcCHicrjef"),
方正黑体简体("https://fycz.lanzoui.com/iw8kKicrjij"),
方正书宋简体("https://fycz.lanzoui.com/i5976icrjmd"),
品如手写体("https://fycz.lanzoui.com/iZccuicrjyf"),
千图小兔体("https://fycz.lanzoui.com/iOONMicrkda"),
手书体("https://fycz.lanzoui.com/iqbmdicrkvi"),
演示春风楷("https://fycz.lanzoui.com/ioRJSicrldg"),
演示秋鸿楷("https://fycz.lanzoui.com/i8qnzicrlsb"),
演示夏行楷("https://fycz.lanzoui.com/iyYUTicrm6f"),
演示悠然小楷("https://fycz.lanzoui.com/ikKq7icrmrg"),
杨任东竹石体("https://fycz.lanzoui.com/iiWdVicrnbg"),
站酷仓耳渔阳体("https://fycz.lanzoui.com/if5weicrnje"),
迷你隶书( "https://fycz.lanzous.com/ihaXVe6kekj"),
方正黄草("https://fycz.lanzous.com/iQg67e6keed");
public String downloadPath;
Font(String fileName, String downloadPath) {
this.fileName = fileName;
Font(String downloadPath) {
this.downloadPath = downloadPath;
}

@ -1,13 +1,10 @@
package xyz.fycz.myreader.enums;
/**
* Created by zhao on 2016/11/3.
*/
public enum Language {
simplified,//简体中文
traditional;//繁体中文
normal,
simplified,//繁转简
traditional;//简转繁
Language() {

@ -1,16 +1,13 @@
package xyz.fycz.myreader.enums;
/**
* Created by zhao on 2016/11/3.
*/
public enum ReadStyle {
protectedEye,//护眼
common,//普通
blueDeep,//深蓝
leather,//羊皮纸
breen;//
breen,//
custom;
ReadStyle() {
}

@ -11,6 +11,8 @@ import xyz.fycz.myreader.greendao.util.MySQLiteOpenHelper;
public class GreenDaoManager {
private static GreenDaoManager instance;
private static DaoMaster daoMaster;
private DaoSession mDaoSession;
private static MySQLiteOpenHelper mySQLiteOpenHelper;
public static GreenDaoManager getInstance() {
@ -23,12 +25,15 @@ public class GreenDaoManager {
public GreenDaoManager(){
mySQLiteOpenHelper = new MySQLiteOpenHelper(MyApplication.getmContext(), "read" , null);
daoMaster = new DaoMaster(mySQLiteOpenHelper.getWritableDatabase());
mDaoSession = daoMaster.newSession();
}
public static DaoSession getDaoSession() {
return getInstance().mDaoSession;
}
public DaoSession getSession(){
return daoMaster.newSession();
return mDaoSession;
}
}

@ -2,11 +2,15 @@ package xyz.fycz.myreader.greendao.entity;
import androidx.annotation.Nullable;
import com.google.gson.Gson;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Transient;
import xyz.fycz.myreader.greendao.service.BookService;
import xyz.fycz.myreader.util.SharedPreUtils;
import java.io.Serializable;
import java.util.Objects;
@ -32,7 +36,6 @@ public class Book implements Serializable {
private String author;//作者
@Nullable
private String type;//类型(本地书籍为:本地书籍)
private String updateDate;//更新时间
@Nullable
private String newestChapterId;//最新章节id
@ -65,15 +68,19 @@ public class Book implements Serializable {
private int groupSort;//分组排序
@Generated(hash = 170911086)
public Book(String id, String name, String chapterUrl, String infoUrl,
String imgUrl, String desc, String author, String type,
String updateDate, String newestChapterId, String newestChapterTitle,
String newestChapterUrl, String historyChapterId,
int histtoryChapterNum, int sortCode, int noReadNum,
int chapterTotalNum, int lastReadPosition, String source,
boolean isCloseUpdate, boolean isDownLoadAll, String groupId,
int groupSort) {
private String tag;
private Boolean replaceEnable = SharedPreUtils.getInstance().getBoolean("replaceEnableDefault", true);
private long lastReadTime;
@Generated(hash = 1269102537)
public Book(String id, String name, String chapterUrl, String infoUrl, String imgUrl, String desc,
String author, String type, String updateDate, String newestChapterId, String newestChapterTitle,
String newestChapterUrl, String historyChapterId, int histtoryChapterNum, int sortCode, int noReadNum,
int chapterTotalNum, int lastReadPosition, String source, boolean isCloseUpdate,
boolean isDownLoadAll, String groupId, int groupSort, String tag, Boolean replaceEnable,
long lastReadTime) {
this.id = id;
this.name = name;
this.chapterUrl = chapterUrl;
@ -97,37 +104,27 @@ public class Book implements Serializable {
this.isDownLoadAll = isDownLoadAll;
this.groupId = groupId;
this.groupSort = groupSort;
this.tag = tag;
this.replaceEnable = replaceEnable;
this.lastReadTime = lastReadTime;
}
public Book(Book book) {
this.id = book.id;
this.name = book.name;
this.chapterUrl = book.chapterUrl;
this.infoUrl = book.infoUrl;
this.imgUrl = book.imgUrl;
this.desc = book.desc;
this.author = book.author;
this.type = book.type;
this.updateDate = book.updateDate;
this.newestChapterId = book.newestChapterId;
this.newestChapterTitle = book.newestChapterTitle;
this.newestChapterUrl = book.newestChapterUrl;
this.historyChapterId = book.historyChapterId;
this.histtoryChapterNum = book.histtoryChapterNum;
this.sortCode = book.sortCode;
this.noReadNum = book.noReadNum;
this.chapterTotalNum = book.chapterTotalNum;
this.lastReadPosition = book.lastReadPosition;
this.source = book.source;
this.isCloseUpdate = book.isCloseUpdate;
this.isDownLoadAll = book.isDownLoadAll;
this.groupId = book.groupId;
this.groupSort = book.groupSort;
}
@Generated(hash = 1839243756)
public Book() {
}
@Override
public Object clone() {
try {
Gson gson = new Gson();
String json = gson.toJson(this);
return gson.fromJson(json, Book.class);
} catch (Exception ignored) {
}
return this;
}
public String getId() {
return this.id;
}
@ -264,33 +261,6 @@ public class Book implements Serializable {
}
@Override
public String toString() {
return "{\n" +
"id='" + id + '\'' +
",\nname='" + name + '\'' +
",\nchapterUrl='" + chapterUrl + '\'' +
",\nimgUrl='" + imgUrl + '\'' +
",\ndesc='" + desc + '\'' +
",\nauthor='" + author + '\'' +
",\ntype='" + type + '\'' +
",\nupdateDate='" + updateDate + '\'' +
",\nnewestChapterId='" + newestChapterId + '\'' +
",\nnewestChapterTitle='" + newestChapterTitle + '\'' +
",\nnewestChapterUrl='" + newestChapterUrl + '\'' +
",\nhistoryChapterId='" + historyChapterId + '\'' +
",\nhisttoryChapterNum='" + histtoryChapterNum + '\'' +
",\nsortCode='" + sortCode + '\'' +
",\nnoReadNum='" + noReadNum + '\'' +
",\nchapterTotalNum='" + chapterTotalNum + '\'' +
",\nlastReadPosition='" + lastReadPosition + '\'' +
",\nsource='" + source + '\'' +
",\nisCloseUpdate='" + isCloseUpdate + '\'' +
",\nisDownLoadAll='" + isDownLoadAll + '\'' +
",\ngroupId='" + groupId + '\'' +
"\n}";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@ -324,11 +294,34 @@ public class Book implements Serializable {
}
public String getTag() {
return this.tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public Boolean getReplaceEnable() {
return this.replaceEnable;
}
public void setReplaceEnable(Boolean replaceEnable) {
this.replaceEnable = replaceEnable;
}
public long getLastReadTime() {
return this.lastReadTime;
}
public void setLastReadTime(long lastReadTime) {
this.lastReadTime = lastReadTime;
}
}

@ -0,0 +1,169 @@
package xyz.fycz.myreader.greendao.entity;
import android.os.Parcel;
import android.os.Parcelable;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.OrderBy;
import org.greenrobot.greendao.annotation.Transient;
import java.util.regex.Pattern;
/**
* Created by GKF on 2018/2/7.
* 阅读内容替换规则
*/
@Entity
public class ReplaceRuleBean implements Parcelable {
@Id(autoincrement = true)
private Long id;
//描述
private String replaceSummary;
//替换规则
private String regex;
//替换为
private String replacement;
//作用于
private String useTo;
private Boolean enable;
private Boolean isRegex;
@OrderBy
private int serialNumber;
private ReplaceRuleBean(Parcel in) {
id = in.readLong();
regex = in.readString();
replacement = in.readString();
replaceSummary = in.readString();
useTo = in.readString();
enable = in.readByte() != 0;
serialNumber = in.readInt();
isRegex = in.readByte() != 0;
}
@Generated(hash = 1896663649)
public ReplaceRuleBean(Long id, String replaceSummary, String regex, String replacement,
String useTo, Boolean enable, Boolean isRegex, int serialNumber) {
this.id = id;
this.replaceSummary = replaceSummary;
this.regex = regex;
this.replacement = replacement;
this.useTo = useTo;
this.enable = enable;
this.isRegex = isRegex;
this.serialNumber = serialNumber;
}
@Generated(hash = 582692869)
public ReplaceRuleBean() {
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeLong(id);
parcel.writeString(regex);
parcel.writeString(replacement);
parcel.writeString(replaceSummary);
parcel.writeString(useTo);
parcel.writeByte((byte) (enable ? 1 : 0));
parcel.writeInt(serialNumber);
parcel.writeByte((byte) (isRegex ? 1 : 0));
}
@Transient
public static final Creator<ReplaceRuleBean> CREATOR = new Creator<ReplaceRuleBean>() {
@Override
public ReplaceRuleBean createFromParcel(Parcel in) {
return new ReplaceRuleBean(in);
}
@Override
public ReplaceRuleBean[] newArray(int size) {
return new ReplaceRuleBean[size];
}
};
@Override
public int describeContents() {
return 0;
}
public String getReplaceSummary() {
return this.replaceSummary;
}
public void setReplaceSummary(String replaceSummary) {
this.replaceSummary = replaceSummary;
}
public String getRegex() {
return this.regex;
}
public String getFixedRegex() {
if (getIsRegex())
return this.regex;
else
return Pattern.quote(regex);
}
public void setRegex(String regex) {
this.regex = regex;
}
public String getReplacement() {
return this.replacement;
}
public void setReplacement(String replacement) {
this.replacement = replacement;
}
public Boolean getEnable() {
if (enable == null) {
return false;
}
return this.enable;
}
public void setEnable(Boolean enable) {
this.enable = enable;
}
public int getSerialNumber() {
return this.serialNumber;
}
public void setSerialNumber(int serialNumber) {
this.serialNumber = serialNumber;
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getUseTo() {
return this.useTo;
}
public void setUseTo(String useTo) {
this.useTo = useTo;
}
public Boolean getIsRegex() {
return isRegex == null ? true : isRegex;
}
public void setIsRegex(Boolean isRegex) {
this.isRegex = isRegex;
}
}

@ -0,0 +1,114 @@
package xyz.fycz.myreader.model;
import android.text.TextUtils;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.Single;
import io.reactivex.SingleOnSubscribe;
import xyz.fycz.myreader.greendao.GreenDaoManager;
import xyz.fycz.myreader.greendao.entity.ReplaceRuleBean;
import xyz.fycz.myreader.greendao.gen.ReplaceRuleBeanDao;
import xyz.fycz.myreader.util.utils.GsonUtils;
import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.util.utils.RxUtils;
import xyz.fycz.myreader.util.utils.StringUtils;
/**
* Created by GKF on 2018/2/12.
* 替换规则管理
*/
public class ReplaceRuleManager {
private static List<ReplaceRuleBean> replaceRuleBeansEnabled;
public static List<ReplaceRuleBean> getEnabled() {
if (replaceRuleBeansEnabled == null) {
replaceRuleBeansEnabled = GreenDaoManager.getDaoSession()
.getReplaceRuleBeanDao().queryBuilder()
.where(ReplaceRuleBeanDao.Properties.Enable.eq(true))
.orderAsc(ReplaceRuleBeanDao.Properties.SerialNumber)
.list();
}
return replaceRuleBeansEnabled;
}
public static Single<List<ReplaceRuleBean>> getAll() {
return Single.create((SingleOnSubscribe<List<ReplaceRuleBean>>) emitter -> emitter.onSuccess(GreenDaoManager.getDaoSession()
.getReplaceRuleBeanDao().queryBuilder()
.orderAsc(ReplaceRuleBeanDao.Properties.SerialNumber)
.list())).compose(RxUtils::toSimpleSingle);
}
public static Single<Boolean> saveData(ReplaceRuleBean replaceRuleBean) {
return Single.create((SingleOnSubscribe<Boolean>) emitter -> {
if (replaceRuleBean.getSerialNumber() == 0) {
replaceRuleBean.setSerialNumber((int) (GreenDaoManager.getDaoSession().getReplaceRuleBeanDao().queryBuilder().count() + 1));
}
GreenDaoManager.getDaoSession().getReplaceRuleBeanDao().insertOrReplace(replaceRuleBean);
refreshDataS();
emitter.onSuccess(true);
}).compose(RxUtils::toSimpleSingle);
}
public static void delData(ReplaceRuleBean replaceRuleBean) {
GreenDaoManager.getDaoSession().getReplaceRuleBeanDao().delete(replaceRuleBean);
refreshDataS();
}
public static void addDataS(List<ReplaceRuleBean> replaceRuleBeans) {
if (replaceRuleBeans != null && replaceRuleBeans.size() > 0) {
GreenDaoManager.getDaoSession().getReplaceRuleBeanDao().insertOrReplaceInTx(replaceRuleBeans);
refreshDataS();
}
}
public static void delDataS(List<ReplaceRuleBean> replaceRuleBeans) {
for (ReplaceRuleBean replaceRuleBean : replaceRuleBeans) {
GreenDaoManager.getDaoSession().getReplaceRuleBeanDao().delete(replaceRuleBean);
}
refreshDataS();
}
private static void refreshDataS() {
replaceRuleBeansEnabled = GreenDaoManager.getDaoSession()
.getReplaceRuleBeanDao().queryBuilder()
.where(ReplaceRuleBeanDao.Properties.Enable.eq(true))
.orderAsc(ReplaceRuleBeanDao.Properties.SerialNumber)
.list();
}
public static Observable<Boolean> importReplaceRule(String text) {
if (TextUtils.isEmpty(text)) return null;
text = text.trim();
if (text.length() == 0) return null;
if (StringUtils.isJsonType(text)) {
return importReplaceRuleO(text)
.compose(RxUtils::toSimpleSingle);
}
/*if (NetworkUtils.isUrl(text)) {
return BaseModelImpl.getInstance().getRetrofitString(StringUtils.getBaseUrl(text), "utf-8")
.create(IHttpGetApi.class)
.get(text, AnalyzeHeaders.getMap(null))
.flatMap(rsp -> importReplaceRuleO(rsp.body()))
.compose(RxUtils::toSimpleSingle);
}*/
return Observable.error(new Exception("不是Json或Url格式"));
}
private static Observable<Boolean> importReplaceRuleO(String json) {
return Observable.create(e -> {
try {
List<ReplaceRuleBean> replaceRuleBeans = GsonUtils.parseJArray(json, ReplaceRuleBean.class);
addDataS(replaceRuleBeans);
e.onNext(true);
} catch (Exception e1) {
e1.printStackTrace();
e.onNext(false);
}
e.onComplete();
});
}
}

@ -95,7 +95,7 @@ public class SearchEngine {
}
/**
* 搜索关键字
* 搜索关键字(模糊搜索)
*
* @param keyword
*/
@ -108,11 +108,12 @@ public class SearchEngine {
searchSuccessNum = 0;
searchSiteIndex = -1;
searchFinishNum = 0;
for (int i = 0; i < threadsNum; i++) {
for (int i = 0; i < Math.min(mSourceList.size(), threadsNum); i++) {
searchOnEngine(keyword);
}
}
/**
* 根据书名和作者搜索书籍
*
@ -128,7 +129,7 @@ public class SearchEngine {
searchSuccessNum = 0;
searchSiteIndex = -1;
searchFinishNum = 0;
for (int i = 0; i < threadsNum; i++) {
for (int i = 0; i < Math.min(mSourceList.size(), threadsNum); i++) {
searchOnEngine(title, author);
}
}

@ -0,0 +1,333 @@
package xyz.fycz.myreader.model.backup;
import io.reactivex.annotations.NonNull;
import xyz.fycz.myreader.application.MyApplication;
import xyz.fycz.myreader.model.storage.Backup;
import xyz.fycz.myreader.model.storage.Restore;
import xyz.fycz.myreader.webapi.callback.ResultCallback;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.common.URLCONST;
import xyz.fycz.myreader.util.*;
import xyz.fycz.myreader.util.utils.FileUtils;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
/**
* @author fengyue
* @date 2020/4/26 11:03
*/
public class UserService {
/**
* 登录
* @param userLoginInfo 用户名输入的用户名和密码等登录信息
* @return 是否成功登录
*/
public static void login(final Map<String, String> userLoginInfo, final ResultCallback resultCallback) {
MyApplication.getApplication().newThread(() -> {
HttpURLConnection conn = null;
try {
URL url = new URL(URLCONST.APP_WEB_URL + "login");
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setConnectTimeout(60 * 1000);
conn.setReadTimeout(60 * 1000);
conn.setDoInput(true);
conn.setDoOutput(true);
String params = "username=" + userLoginInfo.get("loginName") +
"&password=" + userLoginInfo.get("loginPwd") + makeSignalParam();
// 获取URLConnection对象对应的输出流
PrintWriter out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(params);
// flush输出流的缓冲
out.flush();
InputStream in = conn.getInputStream();
BufferedReader bw = new BufferedReader(new InputStreamReader(in, "utf-8"));
StringBuilder sb = new StringBuilder();
String line = bw.readLine();
while (line != null) {
sb.append(line);
line = bw.readLine();
}
resultCallback.onFinish(sb.toString(), 1);
} catch (IOException e) {
e.printStackTrace();
resultCallback.onError(e);
}finally {
if (conn != null) {
conn.disconnect();
}
}
});
}
public static void register(final Map<String, String> userRegisterInfo, final ResultCallback resultCallback) {
MyApplication.getApplication().newThread(() -> {
HttpURLConnection conn = null;
try {
URL url = new URL(URLCONST.APP_WEB_URL + "reg");
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
String params = "username=" + userRegisterInfo.get("username") + "&password=" +
CyptoUtils.encode(APPCONST.KEY, userRegisterInfo.get("password")) + "&key=" +
CyptoUtils.encode(APPCONST.KEY, APPCONST.publicKey) + makeSignalParam();
// 获取URLConnection对象对应的输出流
PrintWriter out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(params);
// flush输出流的缓冲
out.flush();
BufferedReader bw = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
StringBuilder sb = new StringBuilder();
String line = bw.readLine();
while (line != null) {
sb.append(line);
line = bw.readLine();
}
resultCallback.onFinish(sb.toString(), 1);
} catch (IOException e) {
e.printStackTrace();
resultCallback.onError(e);
} finally {
if (conn != null) {
conn.disconnect();
}
}
});
}
/**
* 写配置
* @param userLoginInfo
* @return
*/
public static boolean writeConfig(Map<String,String> userLoginInfo){
FileOutputStream fos = null;
try {
fos = MyApplication.getApplication().openFileOutput("userConfig.fy", MyApplication.getApplication().MODE_PRIVATE);
String userInfo = "username='" + userLoginInfo.get("loginName") + "',\npassword='" + userLoginInfo.get("loginPwd") + "'";
byte[] bs = userInfo.getBytes();
fos.write(bs);
//写完后一定要刷新
fos.flush();
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
IOUtils.close(fos);
}
}
/**
* 读配置
* @return
*/
public static Map<String,String> readConfig(){
File file = MyApplication.getApplication().getFileStreamPath("userConfig.fy");
if (!file.exists()){
return null;
}
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(file));
String tem;
StringBuilder config = new StringBuilder();
while ((tem = br.readLine()) != null){
config.append(tem);
}
String[] user = config.toString().split(",");
String userName = user[0].substring(user[0].indexOf("'") + 1, user[0].lastIndexOf("'"));
String password = user[1].substring(user[1].indexOf("'") + 1, user[1].lastIndexOf("'"));
Map<String,String> userInfo = new HashMap<>();
userInfo.put("userName", userName);
userInfo.put("password", password);
return userInfo;
} catch (IOException e) {
e.printStackTrace();
}finally {
IOUtils.close(br);
}
return null;
}
public static void writeUsername(String username){
File file = FileUtils.getFile(APPCONST.QQ_DATA_DIR + "user");
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(file));
bw.write(username);
bw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
IOUtils.close(bw);
}
}
public static String readUsername(){
File file = new File(APPCONST.QQ_DATA_DIR + "user");
if (!file.exists()){
return "";
}
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(file));
return br.readLine();
} catch (IOException e) {
e.printStackTrace();
return "";
} finally {
IOUtils.close(br);
}
}
/**
* 网络备份
* @return
*/
public static void webBackup(ResultCallback rc){
Map<String,String> userInfo = readConfig();
if (userInfo == null){
rc.onFinish(false, 0);
}
Backup.INSTANCE.backup(MyApplication.getmContext(), APPCONST.FILE_DIR + "webBackup/", new Backup.CallBack() {
@Override
public void backupSuccess() {
MyApplication.getApplication().newThread(() ->{
File inputFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup");
if (!inputFile.exists()) {
rc.onFinish(false, 0);
}
File zipFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup.zip");
FileInputStream fis = null;
HttpURLConnection conn = null;
try {
//压缩文件
ZipUtils.zipFile(inputFile, zipFile);
fis = new FileInputStream(zipFile);
URL url = new URL(URLCONST.APP_WEB_URL + "bak?username=" + userInfo.get("userName") +
makeSignalParam());
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-type", "multipart/form-data");
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream out = conn.getOutputStream();
byte[] bytes = new byte[1024];
int len = -1;
while ((len = fis.read(bytes)) != -1){
out.write(bytes, 0, len);
}
out.flush();
zipFile.delete();
BufferedReader bw = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
StringBuilder sb = new StringBuilder();
String line = bw.readLine();
while (line != null) {
sb.append(line);
line = bw.readLine();
}
String[] info = sb.toString().split(":");
int code = Integer.parseInt(info[0].trim());
rc.onFinish(code == 104, 0);
} catch (Exception e) {
e.printStackTrace();
rc.onError(e);
} finally {
IOUtils.close(fis);
if (conn != null) {
conn.disconnect();
}
}
});
}
@Override
public void backupError(@NonNull String msg) {
ToastUtils.showError(msg);
rc.onFinish(false, 0);
}
}, false);
}
/**
* 网络恢复
* @return
*/
public static void webRestore(ResultCallback rc){
Map<String,String> userInfo = readConfig();
if (userInfo == null){
rc.onFinish(false, 0);
}
FileOutputStream fos = null;
File zipFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup.zip");
HttpURLConnection conn = null;
try {
URL url = new URL(URLCONST.APP_WEB_URL + "ret?username=" + userInfo.get("userName") +
makeSignalParam());
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoInput(true);
InputStream is = conn.getInputStream();
fos = new FileOutputStream(zipFile);
//一边读,一边写
byte[] bytes = new byte[512];
int readCount = 0;
while ((readCount = is.read(bytes)) != -1) {
fos.write(bytes,0, readCount);
}
//刷新,输出流一定要刷新
fos.flush();
if (zipFile.length() == 0){
zipFile.delete();
rc.onFinish(false, 0);
}
ZipUtils.unzipFile(zipFile.getAbsolutePath(), APPCONST.FILE_DIR);
Restore.INSTANCE.restore(APPCONST.FILE_DIR + "webBackup/", new Restore.CallBack() {
@Override
public void restoreSuccess() {
zipFile.delete();
rc.onFinish(true, 0);
}
@Override
public void restoreError(@NonNull String msg) {
ToastUtils.showError(msg);
rc.onFinish(false, 0);
}
});
} catch (Exception e) {
e.printStackTrace();
rc.onError(e);
}finally {
IOUtils.close(fos);
if (conn != null) {
conn.disconnect();
}
}
}
private static String makeSignalParam(){
return "&signal=" + AppInfoUtils.getSingInfo(MyApplication.getmContext(),
MyApplication.getApplication().getPackageName(), AppInfoUtils.SHA1);
}
/**
* 判断是否登录
* @return
*/
public static boolean isLogin(){
File file = MyApplication.getApplication().getFileStreamPath("userConfig.fy");
return file.exists();
}
}

@ -39,6 +39,7 @@ object Backup {
"myBookMark.json",
"myBookGroup.json",
"setting.json",
"readStyles.json",
"config.xml"
)
}
@ -86,9 +87,22 @@ object Backup {
.writeText(json)
}
}
val json = GSON.toJson(SysManager.getSetting())
FileUtils.getFile(backupPath + File.separator + "setting.json")
.writeText(json)
try {
val setting = SysManager.getNewSetting()
val readStyles = setting.readStyles
val readStylesJson = GSON.toJson(readStyles)
setting.readStyles = null
val settingJson = GSON.toJson(setting)
FileUtils.getFile(backupPath + File.separator + "setting.json")
.writeText(settingJson)
FileUtils.getFile(backupPath + File.separator + "readStyles.json")
.writeText(readStylesJson)
} catch (e: Exception) {
e.printStackTrace()
}
Preferences.getSharedPreferences(context, backupPath, "config")?.let { sp ->
val edit = sp.edit()
SharedPreUtils.getInstance().all.map {

@ -1,18 +1,14 @@
package xyz.fycz.myreader.model.storage
import android.app.Activity
import android.app.Activity.RESULT_OK
import android.content.Intent
import android.net.Uri
import android.text.TextUtils
import androidx.core.content.ContextCompat
import androidx.documentfile.provider.DocumentFile
import io.reactivex.Single
import io.reactivex.SingleEmitter
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import org.jetbrains.anko.alert
import org.jetbrains.anko.toast
import xyz.fycz.myreader.application.SysManager
import xyz.fycz.myreader.base.observer.MySingleObserver
import xyz.fycz.myreader.common.APPCONST
import xyz.fycz.myreader.model.storage.WebDavHelp.getWebDavFileNames
@ -47,6 +43,7 @@ object BackupRestoreUi : Backup.CallBack, Restore.CallBack {
}
override fun restoreSuccess() {
SysManager.regetmSetting()
ToastUtils.showSuccess("恢复成功")
}

@ -10,6 +10,7 @@ import io.reactivex.schedulers.Schedulers
import xyz.fycz.myreader.application.MyApplication
import xyz.fycz.myreader.application.SysManager
import xyz.fycz.myreader.base.observer.MySingleObserver
import xyz.fycz.myreader.entity.ReadStyle
import xyz.fycz.myreader.entity.Setting
import xyz.fycz.myreader.greendao.GreenDaoManager
import xyz.fycz.myreader.greendao.entity.Book
@ -94,9 +95,16 @@ object Restore {
e.printStackTrace()
}
try {
val file = FileUtils.getFile(path + File.separator + "setting.json")
val json = file.readText()
SysManager.saveSetting(GSON.fromJsonObject<Setting>(json))
val settingFile = FileUtils.getFile(path + File.separator + "setting.json")
val settingJson = settingFile.readText()
val readStyleFile = FileUtils.getFile(path + File.separator + "readStyles.json")
val readStylesJson = readStyleFile.readText()
val readStyles = GSON.fromJsonObject<List<ReadStyle>>(readStylesJson)
val setting = GSON.fromJsonObject<Setting>(settingJson)
if (setting != null) {
setting.readStyles = readStyles
}
SysManager.saveSetting(setting)
} catch (e: Exception) {
e.printStackTrace()
}

@ -69,7 +69,7 @@ object WebDavHelp {
fun showRestoreDialog(context: Context, names: ArrayList<String>, callBack: Restore.CallBack?): Boolean {
return if (names.isNotEmpty()) {
context.selector(title = "选择恢复文件", items = names) { _, index ->
if (index in 0 until names.size) {
if (index in 0 until 30.coerceAtLeast(names.size)) {
restoreWebDav(names[index], callBack)
}
}

@ -33,6 +33,8 @@ public class AboutActivity extends BaseActivity {
CardView vmUpdate;
@BindView(R.id.vw_update_log)
CardView vmUpdateLog;
@BindView(R.id.vw_qq)
CardView vmQQ;
@BindView(R.id.vw_git)
CardView vmGit;
@BindView(R.id.vw_disclaimer)
@ -60,10 +62,29 @@ public class AboutActivity extends BaseActivity {
@Override
protected void initClick() {
super.initClick();
ClipboardManager mClipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
vmAuthor.setOnClickListener(v -> {
//数据
ClipData mClipData = ClipData.newPlainText("Label", "fy@fycz.xyz");
//把数据设置到剪切板上
assert mClipboardManager != null;
mClipboardManager.setPrimaryClip(mClipData);
ToastUtils.showSuccess("邮箱复制成功!");
});
vmShare.setOnClickListener(v -> ShareUtils.share(this, getString(R.string.share_text) +
SharedPreUtils.getInstance().getString(getString(R.string.downloadLink, URLCONST.LAN_ZOUS_URL))));
SharedPreUtils.getInstance().getString(getString(R.string.downloadLink), URLCONST.LAN_ZOUS_URL)));
vmUpdate.setOnClickListener(v -> MyApplication.checkVersionByServer(this, true, null));
vmUpdateLog.setOnClickListener(v -> DialogCreator.createAssetTipDialog(this, "更新日志", "updatelog.fy"));
vmQQ.setOnClickListener(v -> {
if (!MyApplication.joinQQGroup(this,"8PIOnHFuH6A38hgxvD_Rp2Bu-Ke1ToBn")){
//数据
ClipData mClipData = ClipData.newPlainText("Label", "1085028304");
//把数据设置到剪切板上
assert mClipboardManager != null;
mClipboardManager.setPrimaryClip(mClipData);
ToastUtils.showError("未安装手Q或安装的版本不支持!\n已复制QQ群号,您可自行前往QQ添加!");
}
});
vmGit.setOnClickListener(v -> openIntent(Intent.ACTION_VIEW, getString(R.string.this_github_url)));
vmDisclaimer.setOnClickListener(v -> DialogCreator.createAssetTipDialog(this, "免责声明", "disclaimer.fy"));

@ -2,27 +2,61 @@ package xyz.fycz.myreader.ui.activity;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.*;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.FileProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.OnClick;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.request.RequestOptions;
import com.google.zxing.EncodeHintType;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import cn.bingoogolapple.qrcode.zxing.QRCodeEncoder;
import io.reactivex.Single;
import io.reactivex.SingleOnSubscribe;
import io.reactivex.annotations.NonNull;
import xyz.fycz.myreader.BuildConfig;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.MyApplication;
import xyz.fycz.myreader.application.SysManager;
import xyz.fycz.myreader.base.BaseActivity;
import xyz.fycz.myreader.base.observer.MySingleObserver;
import xyz.fycz.myreader.common.URLCONST;
import xyz.fycz.myreader.entity.SharedBook;
import xyz.fycz.myreader.util.IOUtils;
import xyz.fycz.myreader.util.SharedPreUtils;
import xyz.fycz.myreader.util.utils.BitmapUtil;
import xyz.fycz.myreader.util.utils.FileUtils;
import xyz.fycz.myreader.util.utils.GsonExtensionsKt;
import xyz.fycz.myreader.util.utils.RxUtils;
import xyz.fycz.myreader.util.utils.ScreenUtils;
import xyz.fycz.myreader.util.utils.StringUtils;
import xyz.fycz.myreader.webapi.callback.ResultCallback;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.ui.dialog.SourceExchangeDialog;
@ -43,7 +77,11 @@ import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.webapi.CommonApi;
import xyz.fycz.myreader.widget.CoverImageView;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* @author fengyue
@ -52,8 +90,8 @@ import java.util.ArrayList;
public class BookDetailedActivity extends BaseActivity {
@BindView(R.id.book_detail_iv_cover)
CoverImageView mIvCover;
/* @BindView(R.id.book_detail_iv_blur_cover)
ImageView mIvBlurCover;*/
/* @BindView(R.id.book_detail_iv_blur_cover)
ImageView mIvBlurCover;*/
@BindView(R.id.book_detail_tv_author)
TextView mTvAuthor;
@BindView(R.id.book_detail_tv_type)
@ -188,7 +226,7 @@ public class BookDetailedActivity extends BaseActivity {
break;
}
}
}else {
} else {
aBooks.get(sourceIndex).setNewestChapterId("true");
}
}
@ -227,7 +265,7 @@ public class BookDetailedActivity extends BaseActivity {
//换源对话框
mSourceDialog.setOnSourceChangeListener((bean, pos) -> {
Book bookTem = new Book(mBook);
Book bookTem = (Book) mBook.clone();
bookTem.setChapterUrl(bean.getChapterUrl());
if (!StringHelper.isEmpty(bean.getImgUrl())) {
bookTem.setImgUrl(bean.getImgUrl());
@ -235,7 +273,7 @@ public class BookDetailedActivity extends BaseActivity {
if (!StringHelper.isEmpty(bean.getType())) {
bookTem.setType(bean.getType());
}
if (!StringHelper.isEmpty(bean.getDesc())){
if (!StringHelper.isEmpty(bean.getDesc())) {
bookTem.setDesc(bean.getDesc());
}
bookTem.setSource(bean.getSource());
@ -522,6 +560,9 @@ public class BookDetailedActivity extends BaseActivity {
}*/
mSourceDialog.show();
break;
case R.id.action_share:
shareBook();
break;
case R.id.action_reload: //重新加载
mHandler.sendEmptyMessage(1);
break;
@ -607,4 +648,172 @@ public class BookDetailedActivity extends BaseActivity {
}
}
}
/**
* 分享书籍
*/
private void shareBook() {
ToastUtils.showInfo("正在生成分享图片");
Single.create((SingleOnSubscribe<File>) emitter -> {
// 使用url
String url = SharedPreUtils.getInstance().getString(getString(R.string.downloadLink), URLCONST.LAN_ZOUS_URL);
if (url == null)
url = "";
int maxLength = 1273 - 1 - url.length();
SharedBook sharedBook = SharedBook.bookToSharedBook(mBook);
url = url + "#" + GsonExtensionsKt.getGSON().toJson(sharedBook);
Log.d("QRcode", "Length=" + url.length() + "\n" + url);
Bitmap bitmap;
QRCodeEncoder.HINTS.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
bitmap = QRCodeEncoder.syncEncodeQRCode(url, 360);
QRCodeEncoder.HINTS.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
File share = makeShareFile(bitmap);
if (share == null) {
ToastUtils.showError("分享图片生成失败");
return;
}
emitter.onSuccess(share);
}).compose(RxUtils::toSimpleSingle)
.subscribe(new MySingleObserver<File>() {
@Override
public void onSuccess(@NonNull File File) {
share(File);
}
});
}
/**
* 生成分享图片
* @param QRCode
* @return
*/
private File makeShareFile(Bitmap QRCode) {
FileOutputStream fos = null;
try {
Bitmap back = BitmapFactory.decodeStream(getResources().getAssets().open("share.png")).copy(Bitmap.Config.ARGB_8888, true);
int backWidth = back.getWidth();
int backHeight = back.getHeight();
int margin = 60;
int marginTop = 24;
mIvCover.setDrawingCacheEnabled(true);
Bitmap img = Bitmap.createBitmap(mIvCover.getDrawingCache()).copy(Bitmap.Config.ARGB_8888, true);
mIvCover.setDrawingCacheEnabled(false);
img = BitmapUtil.getBitmap(img, 152, 209);
Canvas cv = new Canvas(back);
cv.drawBitmap(img, margin, margin + marginTop * 2, null);
TextPaint textPaint = new TextPaint();
textPaint.setAntiAlias(true);
textPaint.setFilterBitmap(true);
textPaint.setColor(Color.BLACK);
textPaint.setTextSize(40);
String name = TextUtils.ellipsize(mBook.getName(), textPaint, backWidth - margin + marginTop * 3 - img.getWidth(), TextUtils.TruncateAt.END).toString();
cv.drawText(name, margin + marginTop + img.getWidth(), margin + marginTop * 4, textPaint);
textPaint.setColor(getResources().getColor(R.color.origin));
textPaint.setTextSize(32);
cv.drawText(mBook.getAuthor(), margin + marginTop + img.getWidth(), margin + marginTop * 6, textPaint);
textPaint.setColor(Color.BLACK);
cv.drawText(mBook.getType() == null ? "" : mBook.getType(), margin + marginTop + img.getWidth(), margin + marginTop * 8, textPaint);
assert mBook.getSource() != null;
cv.drawText("书源:" + BookSource.fromString(mBook.getSource()).text, margin + marginTop + img.getWidth(), margin + marginTop * 10, textPaint);
int textSize = 35;
int textInterval = textSize / 2;
textPaint.setTextSize(textSize);
drawDesc(getDescLines(backWidth - margin * 2, textPaint), textPaint, cv, margin + marginTop * 4 + img.getHeight(), margin, textInterval);
cv.drawBitmap(QRCode, backWidth - QRCode.getWidth(), backHeight - QRCode.getHeight(), null);
cv.save();// 保存
cv.restore();// 存储
File share = FileUtils.getFile(APPCONST.SHARE_FILE_DIR + mBook.getName() + "_share.png");
fos = new FileOutputStream(share);
back.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
Log.i("tag", "saveBitmap success: " + share.getAbsolutePath());
return share;
} catch (Exception e) {
e.printStackTrace();
ToastUtils.showError(e.getLocalizedMessage());
return null;
} finally {
IOUtils.close(fos);
}
}
/**
* 分享生成的图片
* @param share
*/
private void share(File share) {
//noinspection ResultOfMethodCallIgnored
share.setReadable(true, false);
Uri contentUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileprovider", share);
final Intent intent = new Intent(Intent.ACTION_SEND);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_STREAM, contentUri);
intent.setType("image/png");
startActivity(Intent.createChooser(intent, "分享书籍"));
}
/**
* 绘制简介
* @param lines
* @param textPaint
* @param canvas
* @param top
* @param left
* @param textInterval
*/
private void drawDesc(List<String> lines, TextPaint textPaint, Canvas canvas, int top, int left, int textInterval) {
float interval = textInterval + textPaint.getTextSize();
for (String line : lines) {
canvas.drawText(line, left, top, textPaint);
top += interval;
}
}
/**
* 生成简介lines
* @param width
* @param textPaint
* @return
*/
private List<String> getDescLines(int width, TextPaint textPaint) {
List<String> lines = new ArrayList<>();
String desc = StringUtils.halfToFull(" ") + mBook.getDesc();
int i = 0;
int wordCount = 0;
String subStr = null;
while (desc.length() > 0) {
if (i == 9) {
lines.add(TextUtils.ellipsize(desc, textPaint, width / 1.8f, TextUtils.TruncateAt.END).toString());
break;
}
wordCount = textPaint.breakText(desc, true, width, null);
subStr = desc.substring(0, wordCount);
lines.add(subStr);
desc = desc.substring(wordCount);
i++;
}
return lines;
}
}

@ -37,7 +37,9 @@ import xyz.fycz.myreader.webapi.crawler.find.QiDianMobileRank;
import xyz.fycz.myreader.widget.RefreshLayout;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* @author fengyue
@ -160,7 +162,7 @@ public class BookstoreActivity extends BaseActivity {
super.initClick();
mBookStoreBookAdapter.setOnItemClickListener((view, pos) -> {
Book book = bookList.get(pos);
if (!findCrawler.hasImg()) {
if (!findCrawler.needSearch()) {
goToBookDetail(book);
} else {
if (BookService.getInstance().isBookCollected(book)) {
@ -202,7 +204,7 @@ public class BookstoreActivity extends BaseActivity {
protected void processLogic() {
super.processLogic();
getData();
if (findCrawler.hasImg()) {
if (findCrawler.needSearch()) {
SharedPreUtils spu = SharedPreUtils.getInstance();
boolean isReadTopTip = spu.getBoolean(getString(R.string.isReadTopTip), false);
if (!isReadTopTip) {
@ -224,11 +226,8 @@ public class BookstoreActivity extends BaseActivity {
@Override
public void onFinish(Object o, int code) {
spu.putString(getString(R.string.qdCookie), (String) o);
mBookTypes = ((QiDianMobileRank) findCrawler).getRankTypes();
curType = mBookTypes.get(0);
mHandler.sendMessage(mHandler.obtainMessage(1));
page = 1;
getBooksData();
mBookTypes = findCrawler.getBookTypes();
initBooks();
}
@Override
@ -238,21 +237,17 @@ public class BookstoreActivity extends BaseActivity {
}
});
} else {
mBookTypes = ((QiDianMobileRank) findCrawler).getRankTypes();
curType = mBookTypes.get(0);
mHandler.sendMessage(mHandler.obtainMessage(1));
page = 1;
getBooksData();
mBookTypes = findCrawler.getBookTypes();
initBooks();
}
} else if ((mBookTypes = findCrawler.getBookTypes()) != null){
initBooks();
} else {
BookStoreApi.getBookTypeList(findCrawler, new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
mBookTypes = (ArrayList<BookType>) o;
curType = mBookTypes.get(0);
mHandler.sendMessage(mHandler.obtainMessage(1));
page = 1;
getBooksData();
initBooks();
}
@Override
@ -262,7 +257,13 @@ public class BookstoreActivity extends BaseActivity {
}
});
}
}
private void initBooks(){
curType = mBookTypes.get(0);
mHandler.sendMessage(mHandler.obtainMessage(1));
page = 1;
getBooksData();
}
/**
@ -311,7 +312,7 @@ public class BookstoreActivity extends BaseActivity {
}
});
} else {
BookStoreApi.getBookRankList(curType.getUrl(), findCrawler, new ResultCallback() {
BookStoreApi.getBookRankList(curType, findCrawler, new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
mHandler.sendMessage(mHandler.obtainMessage(2, o));
@ -366,7 +367,8 @@ public class BookstoreActivity extends BaseActivity {
rvBookList.scrollToPosition(0);
} else {
this.bookList.addAll(bookList);
mBookStoreBookAdapter.addItems(bookList);
this.bookList = new ArrayList<>(new LinkedHashSet<>(this.bookList));//去重
mBookStoreBookAdapter.refreshItems(this.bookList);
}
//刷新动作完成
@ -402,7 +404,7 @@ public class BookstoreActivity extends BaseActivity {
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (findCrawler.hasImg()) {
if (findCrawler.needSearch()) {
menu.findItem(R.id.action_tip).setVisible(true);
}
return true;

@ -26,6 +26,7 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import static xyz.fycz.myreader.util.UriFileUtil.getPath;
@ -81,14 +82,7 @@ public class FontsActivity extends BaseActivity {
private void initFonts() {
mFonts = new ArrayList<>();
mFonts.add(Font.默认字体);
mFonts.add(Font.方正楷体);
mFonts.add(Font.经典宋体);
mFonts.add(Font.方正行楷);
mFonts.add(Font.迷你隶书);
mFonts.add(Font.方正黄草);
mFonts.add(Font.方正硬笔行书);
mFonts.add(Font.本地字体);
Collections.addAll(mFonts, Font.values());
}
public void saveLocalFont(String path){

@ -0,0 +1,231 @@
package xyz.fycz.myreader.ui.activity;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.widget.Toolbar;
import butterknife.BindView;
import com.google.android.material.textfield.TextInputLayout;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.model.backup.UserService;
import xyz.fycz.myreader.base.BaseActivity;
import xyz.fycz.myreader.webapi.callback.ResultCallback;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.ui.dialog.DialogCreator;
import xyz.fycz.myreader.util.CodeUtil;
import xyz.fycz.myreader.util.CyptoUtils;
import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.util.utils.StringUtils;
import java.util.HashMap;
import java.util.Map;
/**
* @author fengyue
* @date 2020/9/18 22:27
*/
public class LoginActivity extends BaseActivity implements TextWatcher {
@BindView(R.id.et_user)
TextInputLayout user;
@BindView(R.id.et_password)
TextInputLayout password;
@BindView(R.id.bt_login)
Button loginBtn;
@BindView(R.id.tv_register)
TextView tvRegister;
@BindView(R.id.et_captcha)
TextInputLayout etCaptcha;
@BindView(R.id.iv_captcha)
ImageView ivCaptcha;
private String code;
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
@SuppressLint("HandlerLeak")
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
loginBtn.setEnabled(true);
break;
case 2:
createCaptcha();
break;
}
}
};
@Override
protected int getContentId() {
return R.layout.activity_login;
}
@Override
protected void setUpToolbar(Toolbar toolbar) {
super.setUpToolbar(toolbar);
setStatusBarColor(R.color.colorPrimary, true);
getSupportActionBar().setTitle("登录");
}
@Override
protected void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
}
@Override
protected void initWidget() {
super.initWidget();
mHandler.sendMessage(mHandler.obtainMessage(2));
String username = UserService.readUsername();
user.getEditText().setText(username);
user.getEditText().requestFocus(username.length());
//监听内容改变 -> 控制按钮的点击状态
user.getEditText().addTextChangedListener(this);
password.getEditText().addTextChangedListener(this);
etCaptcha.getEditText().addTextChangedListener(this);
}
@Override
protected void initClick() {
super.initClick();
ivCaptcha.setOnClickListener(v -> mHandler.sendMessage(mHandler.obtainMessage(2)));
loginBtn.setOnClickListener(v -> {
mHandler.sendMessage(mHandler.obtainMessage(2));
if (!code.toLowerCase().equals(etCaptcha.getEditText().getText().toString().toLowerCase())){
DialogCreator.createTipDialog(this, "验证码错误!");
return;
}
if (!NetworkUtils.isNetWorkAvailable()) {
ToastUtils.showError("无网络连接!");
return;
}
ProgressDialog dialog = DialogCreator.createProgressDialog(this, null, "正在登陆...");
loginBtn.setEnabled(false);
final String loginName = user.getEditText().getText().toString().trim();
String loginPwd = password.getEditText().getText().toString();
final Map<String, String> userLoginInfo = new HashMap<>();
userLoginInfo.put("loginName", loginName);
userLoginInfo.put("loginPwd", CyptoUtils.encode(APPCONST.KEY, loginPwd));
//验证用户名和密码
UserService.login(userLoginInfo, new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
String result = (String) o;
String[] info = result.split(":");
int resultCode = Integer.parseInt(info[0].trim());
String resultName = info[1].trim();
//最后输出结果
if (resultCode == 102) {
UserService.writeConfig(userLoginInfo);
UserService.writeUsername(loginName);
Intent intent = new Intent();
intent.putExtra("isLogin", true);
setResult(Activity.RESULT_OK, intent);
finish();
ToastUtils.showSuccess(resultName);
} else {
mHandler.sendMessage(mHandler.obtainMessage(1));
dialog.dismiss();
ToastUtils.showWarring(resultName);
}
}
@Override
public void onError(Exception e) {
ToastUtils.showError("登录失败\n" + e.getLocalizedMessage());
mHandler.sendMessage(mHandler.obtainMessage(1));
dialog.dismiss();
}
});
});
tvRegister.setOnClickListener(v -> {
Intent intent = new Intent(LoginActivity.this, RegisterActivity.class);
startActivity(intent);
});
}
public void createCaptcha() {
code = CodeUtil.getInstance().createCode();
Bitmap codeBitmap = CodeUtil.getInstance().createBitmap(code);
ivCaptcha.setImageBitmap(codeBitmap);
}
/**
* 当有控件获得焦点focus 自动弹出键盘
* 1. 点击软键盘的enter键 自动收回键盘
* 2. 代码控制 InputMethodManager
* requestFocus
* showSoftInput:显示键盘 必须先让这个view成为焦点requestFocus
*
* hideSoftInputFromWindow 隐藏键盘
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
//隐藏键盘
//1.获取系统输入的管理器
InputMethodManager inputManager =
(InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
//2.隐藏键盘
inputManager.hideSoftInputFromWindow(user.getWindowToken(),0);
//3.取消焦点
View focusView = getCurrentFocus();
if (focusView != null) {
focusView.clearFocus(); //取消焦点
}
//getCurrentFocus().clearFocus();
//focusView.requestFocus();//请求焦点
}
return true;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
//禁止输入中文
StringUtils.isNotChinese(s);
//判断两个输入框是否有内容
if (user.getEditText().getText().toString().length() > 0 &&
password.getEditText().getText().toString().length() > 0 &&
etCaptcha.getEditText().getText().toString().length() > 0){
//按钮可以点击
loginBtn.setEnabled(true);
}else{
//按钮不能点击
loginBtn.setEnabled(false);
}
}
}

@ -6,8 +6,10 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.ActionBar;
@ -16,19 +18,26 @@ import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
import butterknife.BindView;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.MyApplication;
import xyz.fycz.myreader.application.SysManager;
import xyz.fycz.myreader.base.BaseActivity;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.entity.SharedBook;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.ui.dialog.DialogCreator;
import xyz.fycz.myreader.ui.fragment.BookcaseFragment;
import xyz.fycz.myreader.ui.fragment.FindFragment;
import xyz.fycz.myreader.ui.fragment.MineFragment;
import xyz.fycz.myreader.util.SharedPreUtils;
import xyz.fycz.myreader.util.StringHelper;
import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.util.utils.GsonExtensionsKt;
import java.io.File;
import java.util.ArrayList;
@ -41,6 +50,7 @@ import static androidx.fragment.app.FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CU
* @date 2020/9/13 13:03
*/
public class MainActivity extends BaseActivity {
public static final String TAG = MainActivity.class.getSimpleName();
@BindView(R.id.bottom_navigation_view)
BottomNavigationView bottomNavigation;
@BindView(R.id.view_pager_main)
@ -138,9 +148,9 @@ public class MainActivity extends BaseActivity {
//将滑动到的页面对应的 menu 设置为选中状态
bottomNavigation.getMenu().getItem(i).setChecked(true);
getSupportActionBar().setTitle(titles[i]);
if (i == 0) {
if (i == 0) {
getSupportActionBar().setSubtitle(groupName);
}else {
} else {
getSupportActionBar().setSubtitle("");
}
invalidateOptionsMenu();
@ -162,11 +172,23 @@ public class MainActivity extends BaseActivity {
super.processLogic();
try {
int settingVersion = SysManager.getSetting().getSettingVersion();
if (settingVersion < APPCONST.SETTING_VERSION){
if (settingVersion < APPCONST.SETTING_VERSION) {
SysManager.resetSetting();
Log.d(TAG, "resetSetting");
}
} catch (Exception e) {
ToastUtils.showError(e.getLocalizedMessage());
e.printStackTrace();
}
try {
int sourceVersion = SysManager.getSetting().getSourceVersion();
if (sourceVersion < APPCONST.SOURCE_VERSION) {
SysManager.resetSource();
Log.d(TAG, "resetSource");
}
}catch (Exception e){
SysManager.resetSetting();
} catch (Exception e) {
ToastUtils.showError(e.getLocalizedMessage());
e.printStackTrace();
}
}
@ -232,7 +254,8 @@ public class MainActivity extends BaseActivity {
mBookcaseFragment.getmBookcasePresenter().cancelEdit();
invalidateOptionsMenu();
return true;
case R.id.action_change_group: case R.id.action_group_man:
case R.id.action_change_group:
case R.id.action_group_man:
if (!mBookcaseFragment.getmBookcasePresenter().hasOnGroupChangeListener()) {
mBookcaseFragment.getmBookcasePresenter().addOnGroupChangeListener(() -> {
groupName = SharedPreUtils.getInstance().getString(getString(R.string.curBookGroupName), "所有书籍");
@ -243,6 +266,10 @@ public class MainActivity extends BaseActivity {
case R.id.action_edit:
invalidateOptionsMenu();
break;
case R.id.action_qr_scan:
Intent intent = new Intent(this, QRCodeScanActivity.class);
startActivityForResult(intent, APPCONST.REQUEST_QR_SCAN);
break;
}
return mBookcaseFragment.getmBookcasePresenter().onOptionsItemSelected(item);
}
@ -271,17 +298,46 @@ public class MainActivity extends BaseActivity {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if ((resultCode == RESULT_OK || resultCode == RESULT_CANCELED) && requestCode == APPCONST.APP_INSTALL_CODE) {
installProcess(appFile, isForceUpdate);//再次执行安装流程,包含权限判等
}
if (resultCode == RESULT_OK) {
switch (requestCode) {
case APPCONST.REQUEST_LOGIN:
if (mMineFragment.isRecreate()){
if (mMineFragment.isRecreate()) {
reLoadFragment();
}
mMineFragment.onActivityResult(requestCode, resultCode, data);
break;
case APPCONST.REQUEST_QR_SCAN:
if (data != null) {
String result = data.getStringExtra("result");
if (!StringHelper.isEmpty(result)) {
String[] string = result.split("#", 2);
if (string.length == 2) {
SharedBook sharedBook = GsonExtensionsKt.getGSON().fromJson(string[1], SharedBook.class);
if (sharedBook != null && !StringHelper.isEmpty(sharedBook.getChapterUrl())){
Book book = SharedBook.sharedBookToBook(sharedBook);
Intent intent = new Intent(this, BookDetailedActivity.class);
intent.putExtra(APPCONST.BOOK, book);
startActivity(intent);
}else {
ToastUtils.showError("书籍加载失败");
}
}else {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse(result);
intent.setData(uri);
startActivity(intent);
}catch (Exception e){
ToastUtils.showError(e.getLocalizedMessage());
}
}
}
}
break;
}
}
}
@ -368,7 +424,7 @@ public class MainActivity extends BaseActivity {
}
}
public interface OnGroupChangeListener{
public interface OnGroupChangeListener {
void onChange();
}
}

@ -36,65 +36,91 @@ import java.util.Iterator;
import static xyz.fycz.myreader.common.APPCONST.BOOK_CACHE_PATH;
/**
* Created by newbiechen on 17-6-6.
* Created by fengyue on 17-6-6.
* 阅读界面的更多设置
*/
public class MoreSettingActivity extends BaseActivity {
@BindView(R.id.more_setting_ll_webdav)
@BindView(R.id.ll_webdav)
LinearLayout mLlWebdav;
@BindView(R.id.more_setting_rl_volume)
@BindView(R.id.rl_volume)
RelativeLayout mRlVolume;
@BindView(R.id.more_setting_sc_volume)
@BindView(R.id.sc_volume)
SwitchCompat mScVolume;
@BindView(R.id.more_setting_rl_reset_screen)
@BindView(R.id.rl_always_next)
RelativeLayout mRlAlwaysNext;
@BindView(R.id.sc_always_next)
SwitchCompat mScAlwaysNext;
@BindView(R.id.rl_show_status)
RelativeLayout mRlShowStatus;
@BindView(R.id.sc_show_status)
SwitchCompat mScShowStatus;
@BindView(R.id.rl_read_aloud_volume_turn_page)
RelativeLayout mRlReadAloudVolumeTurnPage;
@BindView(R.id.sc_read_aloud_volume_turn_page)
SwitchCompat mScReadAloudVolumeTurnPage;
@BindView(R.id.rl_no_menu_title)
RelativeLayout mRlNoMenuTitle;
@BindView(R.id.sc_no_menu_title)
SwitchCompat mScNoMenuTitle;
@BindView(R.id.rl_reset_screen)
RelativeLayout mRlResetScreen;
@BindView(R.id.more_setting_sc_reset_screen)
@BindView(R.id.sc_reset_screen)
Spinner mScResetScreen;
@BindView(R.id.more_setting_rl_auto_refresh)
@BindView(R.id.rl_auto_refresh)
RelativeLayout mRlAutoRefresh;
@BindView(R.id.more_setting_sc_auto_refresh)
@BindView(R.id.sc_auto_refresh)
SwitchCompat mScAutoRefresh;
@BindView(R.id.more_setting_ll_close_refresh)
@BindView(R.id.ll_book_sort)
LinearLayout mLlBookSort;
@BindView(R.id.tv_book_sort)
TextView mTvBookSort;
@BindView(R.id.ll_close_refresh)
LinearLayout mLlCloseRefresh;
@BindView(R.id.more_setting_ll_disable_source)
@BindView(R.id.ll_disable_source)
LinearLayout mLlDisableSource;
@BindView(R.id.more_setting_ll_thread_num)
@BindView(R.id.ll_thread_num)
LinearLayout mLlThreadNum;
@BindView(R.id.more_setting_tv_thread_num)
@BindView(R.id.tv_thread_num)
TextView mTvThreadNum;
@BindView(R.id.more_setting_iv_match_chapter_tip)
@BindView(R.id.iv_match_chapter_tip)
ImageView mIvMatchChapterTip;
@BindView(R.id.more_setting_rl_match_chapter)
@BindView(R.id.rl_match_chapter)
RelativeLayout mRlMatchChapter;
@BindView(R.id.more_setting_sc_match_chapter)
@BindView(R.id.sc_match_chapter)
SwitchCompat mScMatchChapter;
@BindView(R.id.more_setting_rl_match_chapter_suitability)
@BindView(R.id.rl_match_chapter_suitability)
RelativeLayout mRlMatchChapterSuitability;
@BindView(R.id.more_setting_sc_match_chapter_suitability)
@BindView(R.id.sc_match_chapter_suitability)
Spinner mScMatchChapterSuitability;
@BindView(R.id.more_setting_rl_cathe_gap)
@BindView(R.id.rl_cathe_gap)
RelativeLayout mRlCatheGap;
@BindView(R.id.more_setting_sc_cathe_gap)
@BindView(R.id.sc_cathe_gap)
Spinner mScCatheGap;
@BindView(R.id.more_setting_rl_delete_cathe)
@BindView(R.id.rl_delete_cathe)
RelativeLayout mRlDeleteCathe;
@BindView(R.id.more_setting_ll_download_all)
@BindView(R.id.ll_download_all)
LinearLayout mLlDownloadAll;
/*@BindView(R.id.more_setting_rl_bookstore)
/*@BindView(R.id.rl_bookstore)
RelativeLayout mRlBookstore;
@BindView(R.id.more_setting_sc_bookstore)
@BindView(R.id.sc_bookstore)
SwitchCompat mScBookstore;*/
private boolean needRefresh;
private boolean upMenu;
private Setting mSetting;
private boolean isVolumeTurnPage;
private int resetScreenTime;
private int sortStyle;
private boolean autoRefresh;
private boolean isMatchChapter;
private boolean openBookStore;
private float matchChapterSuitability;
private int catheCap;
private boolean isShowStatusBar;
private boolean alwaysNext;
private boolean noMenuTitle;
private boolean readAloudVolumeTurnPage;
private ArrayList<Book> mBooks;
int booksCount;
@ -105,12 +131,8 @@ public class MoreSettingActivity extends BaseActivity {
private AlertDialog mCloseRefreshDia;
//选择禁用更新书源对话框
private AlertDialog mDisableSourceDia;
//线程选择
private AlertDialog mThreadSelectDia;
//选择一键缓存书籍对话框
private AlertDialog mDownloadAllDia;
//选择清除缓存对话框
private AlertDialog mDeleteCatheDia;
@Override
@ -121,14 +143,19 @@ public class MoreSettingActivity extends BaseActivity {
@Override
protected void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
needRefresh = false;
mSetting = SysManager.getSetting();
isVolumeTurnPage = mSetting.isVolumeTurnPage();
alwaysNext = mSetting.isAlwaysNext();
resetScreenTime = mSetting.getResetScreen();
isMatchChapter = mSetting.isMatchChapter();
matchChapterSuitability = mSetting.getMatchChapterSuitability();
catheCap = mSetting.getCatheGap();
sortStyle = mSetting.getSortStyle();
autoRefresh = mSetting.isRefreshWhenStart();
openBookStore = mSetting.isOpenBookStore();
isShowStatusBar = mSetting.isShowStatusBar();
noMenuTitle = mSetting.isNoMenuChTitle();
readAloudVolumeTurnPage = mSetting.isReadAloudVolumeTurnPage();
threadNum = SharedPreUtils.getInstance().getInt(getString(R.string.threadNum), 8);
}
@ -143,6 +170,11 @@ public class MoreSettingActivity extends BaseActivity {
protected void initWidget() {
super.initWidget();
initSwitchStatus();
if (sortStyle == 1){
mTvBookSort.setText(getString(R.string.time_sort));
}else if (sortStyle == 2){
mTvBookSort.setText(getString(R.string.book_name_sort));
}
if (isMatchChapter) {
mRlMatchChapterSuitability.setVisibility(View.VISIBLE);
} else {
@ -154,9 +186,12 @@ public class MoreSettingActivity extends BaseActivity {
private void initSwitchStatus() {
mScVolume.setChecked(isVolumeTurnPage);
mScAlwaysNext.setChecked(alwaysNext);
mScMatchChapter.setChecked(isMatchChapter);
mScAutoRefresh.setChecked(autoRefresh);
//mScBookstore.setChecked(openBookStore);
mScShowStatus.setChecked(isShowStatusBar);
mScNoMenuTitle.setChecked(noMenuTitle);
mScReadAloudVolumeTurnPage.setChecked(readAloudVolumeTurnPage);
}
@Override
@ -176,6 +211,79 @@ public class MoreSettingActivity extends BaseActivity {
SysManager.saveSetting(mSetting);
}
);
mRlAlwaysNext.setOnClickListener(
(v) -> {
if (alwaysNext) {
alwaysNext = false;
} else {
alwaysNext = true;
}
mScAlwaysNext.setChecked(alwaysNext);
mSetting.setAlwaysNext(alwaysNext);
SysManager.saveSetting(mSetting);
}
);
mRlShowStatus.setOnClickListener(
(v) -> {
needRefresh = true;
if (isShowStatusBar) {
isShowStatusBar = false;
} else {
isShowStatusBar = true;
}
mScShowStatus.setChecked(isShowStatusBar);
mSetting.setShowStatusBar(isShowStatusBar);
SysManager.saveSetting(mSetting);
}
);
mRlReadAloudVolumeTurnPage.setOnClickListener(
(v) -> {
if (readAloudVolumeTurnPage) {
readAloudVolumeTurnPage = false;
} else {
readAloudVolumeTurnPage = true;
}
mScReadAloudVolumeTurnPage.setChecked(readAloudVolumeTurnPage);
mSetting.setReadAloudVolumeTurnPage(readAloudVolumeTurnPage);
SysManager.saveSetting(mSetting);
}
);
mRlNoMenuTitle.setOnClickListener(
(v) -> {
upMenu = true;
if (noMenuTitle) {
noMenuTitle = false;
} else {
noMenuTitle = true;
}
mScNoMenuTitle.setChecked(noMenuTitle);
mSetting.setNoMenuChTitle(noMenuTitle);
SysManager.saveSetting(mSetting);
}
);
mLlBookSort.setOnClickListener(v -> {
MyAlertDialog.build(this)
.setTitle(getString(R.string.book_sort))
.setSingleChoiceItems(R.array.book_sort, sortStyle, (dialog, which) -> {
sortStyle = which;
mSetting.setSortStyle(sortStyle);
SysManager.saveSetting(mSetting);
if (sortStyle == 0){
mTvBookSort.setText(getString(R.string.manual_sort));
if (!SharedPreUtils.getInstance().getBoolean("manualSortTip")){
DialogCreator.createTipDialog(this, "可在书架编辑状态下长按移动书籍进行排序!");
SharedPreUtils.getInstance().putBoolean("manualSortTip", true);
}
}else if (sortStyle == 1){
mTvBookSort.setText(getString(R.string.time_sort));
}else if (sortStyle == 2){
mTvBookSort.setText(getString(R.string.book_name_sort));
}
dialog.dismiss();
}).setNegativeButton("取消", null).show();
});
mRlAutoRefresh.setOnClickListener(
(v) -> {
if (autoRefresh) {
@ -289,7 +397,7 @@ public class MoreSettingActivity extends BaseActivity {
threadPick.setOnScrollListener((view1, scrollState) -> {
});
mThreadSelectDia = MyAlertDialog.build(this)
MyAlertDialog.build(this)
.setTitle("搜索线程数")
.setView(view)
.setPositiveButton("确定", (dialog, which) -> {
@ -383,7 +491,7 @@ public class MoreSettingActivity extends BaseActivity {
}
CharSequence[] cathes = {"章节缓存:" + eCatheFileSize, "图片缓存:" + catheFileSize};
boolean[] catheCheck = {true, true};
mDeleteCatheDia = new MultiChoiceDialog().create(this, "清除缓存", cathes, catheCheck, 2,
new MultiChoiceDialog().create(this, "清除缓存", cathes, catheCheck, 2,
(dialog, which) -> {
String tip = "";
if (catheCheck[0]) {
@ -411,6 +519,15 @@ public class MoreSettingActivity extends BaseActivity {
initSpinner();
}
@Override
public void finish() {
Intent result = new Intent();
result.putExtra(APPCONST.RESULT_NEED_REFRESH, needRefresh);
result.putExtra(APPCONST.RESULT_UP_MENU, upMenu);
setResult(AppCompatActivity.RESULT_OK, result);
super.finish();
}
private void initSpinner() {
// initSwitchStatus() be called earlier than onCreate(), so setSelection() won't work
ArrayAdapter<CharSequence> resetScreenAdapter = ArrayAdapter.createFromResource(this,
@ -453,9 +570,6 @@ public class MoreSettingActivity extends BaseActivity {
}
mSetting.setResetScreen(resetScreenTime);
SysManager.saveSetting(mSetting);
Intent result = new Intent();
result.putExtra(APPCONST.RESULT_RESET_SCREEN, resetScreenTime);
setResult(AppCompatActivity.RESULT_OK, result);
}
@Override

@ -0,0 +1,261 @@
package xyz.fycz.myreader.ui.activity;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.Objects;
import butterknife.BindView;
import cn.bingoogolapple.qrcode.core.QRCodeView;
import cn.bingoogolapple.qrcode.zxing.ZXingView;
import io.reactivex.Single;
import io.reactivex.SingleOnSubscribe;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.base.BaseActivity;
import xyz.fycz.myreader.base.observer.MySingleObserver;
import xyz.fycz.myreader.util.PermissionsChecker;
import xyz.fycz.myreader.util.StringHelper;
import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.util.utils.RxUtils;
import static xyz.fycz.myreader.util.UriFileUtil.getPath;
/**
* @author fengyue
* @date 2020/11/30 8:31
*/
public class QRCodeScanActivity extends BaseActivity implements QRCodeView.Delegate {
@BindView(R.id.zxingview)
ZXingView zxingview;
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.ll_flashlight)
LinearLayout llFlashLight;
@BindView(R.id.fab_flashlight)
FloatingActionButton fabFlashlight;
@BindView(R.id.tv_flashlight)
TextView tvFlashlight;
private final int REQUEST_QR_IMAGE = 202;
private static final String CAMERA = "android.permission.CAMERA";
private static final int PERMISSIONS_REQUEST_CAMERA = 101;
private boolean flashlightIsOpen;
private boolean needScale = true;
private String picPath;
@Override
protected int getContentId() {
return R.layout.activity_qrcode_capture;
}
@Override
protected void setUpToolbar(Toolbar toolbar) {
super.setUpToolbar(toolbar);
setStatusBarColor(R.color.colorPrimary, true);
getSupportActionBar().setTitle("扫一扫");
}
/**
* 数据初始化
*/
@Override
protected void initData(Bundle savedInstanceState) {
zxingview.setDelegate(this);
fabFlashlight.setOnClickListener(view -> {
if (flashlightIsOpen) {
flashlightIsOpen = false;
zxingview.closeFlashlight();
tvFlashlight.setText(getString(R.string.light_contact));
} else {
flashlightIsOpen = true;
zxingview.openFlashlight();
tvFlashlight.setText(getString(R.string.close_contact));
}
});
}
@Override
protected void onStart() {
super.onStart();
startCamera();
}
private void startCamera() {
requestPermission();
}
@Override
protected void onStop() {
zxingview.stopCamera(); // 关闭摄像头预览,并且隐藏扫描框
super.onStop();
}
@Override
protected void onDestroy() {
zxingview.onDestroy(); // 销毁二维码扫描控件
super.onDestroy();
}
@Override
public void onScanQRCodeSuccess(String result) {
Log.d("onScanQRCodeSuccess", needScale + "");
if (result == null) {
if (!needScale){
needScale = true;
if (StringHelper.isEmpty(picPath)) {
return;
}
scanFromPath(picPath);
}else {
ToastUtils.showError("二维码扫描失败");
}
}else {
Intent intent = new Intent();
Log.d("result", result);
intent.putExtra("result", result);
setResult(RESULT_OK, intent);
finish();
}
}
@Override
public void onCameraAmbientBrightnessChanged(boolean isDark) {
if (isDark){
llFlashLight.setVisibility(View.VISIBLE);
}else {
if (!flashlightIsOpen) {
llFlashLight.setVisibility(View.GONE);
}
}
}
@Override
public void onScanQRCodeOpenCameraError() {
}
private void startScan() {
zxingview.setVisibility(View.VISIBLE);
zxingview.startSpotAndShowRect(); // 显示扫描框,并开始识别
}
private void requestPermission() {
//获取读取和写入SD卡的权限
if (new PermissionsChecker(this).lacksPermissions(CAMERA)) {
ActivityCompat.requestPermissions(this, new String[]{CAMERA}, PERMISSIONS_REQUEST_CAMERA);
} else {
startScan();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case PERMISSIONS_REQUEST_CAMERA: {
// 如果取消权限,则返回的值为0
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//申请权限成功
startScan();
} else {
//申请权限失败
finish();
ToastUtils.showWarring("请给予相机权限,否则无法进行扫码!");
}
return;
}
}
}
// 添加菜单
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_qr_code_scan, menu);
return super.onCreateOptionsMenu(menu);
}
//菜单
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.action_choose_from_gallery:
chooseFromGallery();
break;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
zxingview.startSpotAndShowRect(); // 显示扫描框,并开始识别
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_QR_IMAGE) {
picPath = getPath(this, data.getData());
if (StringHelper.isEmpty(picPath)) {
return;
}
scanFromPath(picPath);
}
}
private void scanFromPath(String path){
// 本来就用到 QRCodeView 时可直接调 QRCodeView 的方法,走通用的回调
Single.create((SingleOnSubscribe<Bitmap>) emitter -> {
Bitmap bitmap = BitmapFactory.decodeFile(path);
if (bitmap == null)
return;
if (needScale) {
int size = 360;
bitmap = Bitmap.createBitmap(bitmap, bitmap.getWidth() - size, bitmap.getHeight() - size, size, size);
}
emitter.onSuccess(bitmap);
}).compose(RxUtils::toSimpleSingle)
.subscribe(new MySingleObserver<Bitmap>() {
@Override
public void onSuccess(Bitmap bitmap) {
zxingview.decodeQRCode(bitmap);
}
});
}
private void chooseFromGallery() {
try {
if (needScale){
ToastUtils.showInfo("选择图片仅支持扫描书籍分享图片");
}
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, REQUEST_QR_IMAGE);
} catch (Exception e) {
e.printStackTrace();
ToastUtils.showError(Objects.requireNonNull(e.getLocalizedMessage()));
}
}
}

@ -0,0 +1,271 @@
package xyz.fycz.myreader.ui.activity;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.widget.Toolbar;
import butterknife.BindView;
import com.google.android.material.textfield.TextInputLayout;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.model.backup.UserService;
import xyz.fycz.myreader.base.BaseActivity;
import xyz.fycz.myreader.webapi.callback.ResultCallback;
import xyz.fycz.myreader.ui.dialog.DialogCreator;
import xyz.fycz.myreader.util.CodeUtil;
import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.util.utils.StringUtils;
import java.util.HashMap;
import java.util.Map;
/**
* @author fengyue
* @date 2020/9/18 22:37
*/
public class RegisterActivity extends BaseActivity {
@BindView(R.id.et_username)
TextInputLayout etUsername;
@BindView(R.id.et_password)
TextInputLayout etPassword;
@BindView(R.id.et_rp_password)
TextInputLayout etRpPassword;
@BindView(R.id.et_captcha)
TextInputLayout etCaptcha;
@BindView(R.id.iv_captcha)
ImageView ivCaptcha;
@BindView(R.id.bt_register)
Button btRegister;
@BindView(R.id.tv_register_tip)
TextView tvRegisterTip;
@BindView(R.id.cb_agreement)
CheckBox cbAgreement;
@BindView(R.id.tv_agreement)
TextView tvAgreement;
private String code;
private String username = "";
private String password = "";
private String rpPassword = "";
private String inputCode = "";
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
@SuppressLint("HandlerLeak")
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
createCaptcha();
break;
case 2:
showTip((String) msg.obj);
break;
case 3:
tvRegisterTip.setVisibility(View.GONE);
break;
}
}
};
@Override
protected int getContentId() {
return R.layout.activity_register;
}
@Override
protected void setUpToolbar(Toolbar toolbar) {
super.setUpToolbar(toolbar);
setStatusBarColor(R.color.colorPrimary, true);
getSupportActionBar().setTitle("注册");
}
@Override
protected void initWidget() {
super.initWidget();
mHandler.sendMessage(mHandler.obtainMessage(1));
etUsername.requestFocus();
etUsername.getEditText().addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
StringUtils.isNotChinese(s);
username = s.toString();
if (username.length() < 6 || username.length() >14){
mHandler.sendMessage(mHandler.obtainMessage(2, "用户名必须在6-14位之间"));
} else if(!username.substring(0, 1).matches("^[A-Za-z]$")){
mHandler.sendMessage(mHandler.obtainMessage(2,
"用户名只能以字母开头"));
}else if(!username.matches("^[A-Za-z0-9-_]+$")){
mHandler.sendMessage(mHandler.obtainMessage(2,
"用户名只能由数字、字母、下划线、减号组成"));
}else {
mHandler.sendMessage(mHandler.obtainMessage(3));
}
checkNotNone();
}
});
etPassword.getEditText().addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
password = s.toString();
if (password.length() < 8 || password.length() > 16){
mHandler.sendMessage(mHandler.obtainMessage(2, "密码必须在8-16位之间"));
} else if(password.matches("^\\d+$")){
mHandler.sendMessage(mHandler.obtainMessage(2, "密码不能是纯数字"));
} else {
mHandler.sendMessage(mHandler.obtainMessage(3));
}
checkNotNone();
}
});
etRpPassword.getEditText().addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
rpPassword = s.toString();
if (!rpPassword.equals(password)){
mHandler.sendMessage(mHandler.obtainMessage(2, "两次输入的密码不一致"));
} else {
mHandler.sendMessage(mHandler.obtainMessage(3));
}
checkNotNone();
}
});
etCaptcha.getEditText().addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
inputCode = s.toString().trim().toLowerCase();
if (!inputCode.equals(code.toLowerCase())){
mHandler.sendMessage(mHandler.obtainMessage(2, "验证码错误"));
} else {
mHandler.sendMessage(mHandler.obtainMessage(3));
}
checkNotNone();
}
});
tvAgreement.setMovementMethod(LinkMovementMethod.getInstance());
}
@Override
protected void initClick() {
super.initClick();
ivCaptcha.setOnClickListener(v -> mHandler.sendMessage(mHandler.obtainMessage(1)));
btRegister.setOnClickListener(v -> {
if (!username.matches("^[A-Za-z][A-Za-z0-9]{5,13}$")){
DialogCreator.createTipDialog(this, "用户名格式错误",
"用户名必须在6-14位之间\n用户名只能以字母开头\n用户名只能由数字、字母、下划线、减号组成");
}else if(password.matches("^\\d+$") || !password.matches("^.{8,16}$")){
DialogCreator.createTipDialog(this, "密码格式错误",
"密码必须在8-16位之间\n密码不能是纯数字");
}else if(!password.equals(rpPassword)){
DialogCreator.createTipDialog(this, "重复密码错误",
"两次输入的密码不一致");
}else if(!inputCode.trim().toLowerCase().equals(code.toLowerCase())){
DialogCreator.createTipDialog(this, "验证码错误");
}else if(!cbAgreement.isChecked()){
DialogCreator.createTipDialog(this, "请勾选同意《用户服务协议》");
}else {
ProgressDialog dialog = DialogCreator.createProgressDialog(this, null, "正在注册...");
Map<String, String> userRegisterInfo = new HashMap<>();
userRegisterInfo.put("username", username);
userRegisterInfo.put("password", password);
UserService.register(userRegisterInfo, new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
String[] info = ((String) o).split(":");
int result = Integer.parseInt(info[0].trim());
if (result == 101){
UserService.writeUsername(username);
ToastUtils.showSuccess(info[1]);
finish();
}else {
ToastUtils.showWarring(info[1]);
}
dialog.dismiss();
}
@Override
public void onError(Exception e) {
ToastUtils.showError("注册失败:\n" + e.getLocalizedMessage());
dialog.dismiss();
}
});
}
mHandler.sendMessage(mHandler.obtainMessage(1));
});
}
public void createCaptcha() {
code = CodeUtil.getInstance().createCode();
Bitmap codeBitmap = CodeUtil.getInstance().createBitmap(code);
ivCaptcha.setImageBitmap(codeBitmap);
}
public void showTip(String tip) {
tvRegisterTip.setVisibility(View.VISIBLE);
tvRegisterTip.setText(tip);
}
public void checkNotNone(){
if ("".equals(username) || "".equals(password) || "".equals(rpPassword) || "".equals(inputCode)){
btRegister.setEnabled(false);
}else {
btRegister.setEnabled(true);
}
}
}

@ -13,16 +13,24 @@ import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.*;
import androidx.appcompat.widget.AppCompatRadioButton;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import me.gujun.android.taggroup.TagGroup;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.MyApplication;
import xyz.fycz.myreader.application.SysManager;
import xyz.fycz.myreader.base.BaseActivity;
import xyz.fycz.myreader.entity.Setting;
import xyz.fycz.myreader.util.utils.StringUtils;
import xyz.fycz.myreader.webapi.callback.ResultCallback;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.model.SearchEngine;
@ -44,6 +52,7 @@ import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
@ -79,6 +88,14 @@ public class SearchBookActivity extends BaseActivity {
SmartRefreshLayout srlSearchBookList;
@BindView(R.id.fabSearchStop)
FloatingActionButton fabSearchStop;
@BindView(R.id.rg_search_filter)
RadioGroup rbSearchFilter;
@BindView(R.id.rb_all_search)
AppCompatRadioButton rbAllSearch;
@BindView(R.id.rb_fuzzy_search)
AppCompatRadioButton rbFuzzySearch;
@BindView(R.id.rb_precise_search)
AppCompatRadioButton rbPreciseSearch;
private SearchBookAdapter mSearchBookAdapter;
@ -103,6 +120,8 @@ public class SearchBookActivity extends BaseActivity {
private SearchEngine searchEngine;
private Setting mSetting;
private static String[] suggestion = {"第一序列", "大道朝天", "伏天氏", "终极斗罗", "我师兄实在太稳健了", "烂柯棋缘", "诡秘之主"};
private static String[] suggestion2 = {"不朽凡人", "圣墟", "我是至尊", "龙王传说", "太古神王", "一念永恒", "雪鹰领主", "大主宰"};
@ -145,10 +164,9 @@ public class SearchBookActivity extends BaseActivity {
@Override
protected void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
mSetting = SysManager.getSetting();
mSearchHistoryService = SearchHistoryService.getInstance();
for (int i = 0; i < suggestion.length; i++) {
mSuggestions.add(suggestion[i]);
}
Collections.addAll(mSuggestions, suggestion);
searchEngine = new SearchEngine();
searchEngine.setOnSearchListener(new SearchEngine.OnSearchListener() {
@ -193,6 +211,38 @@ public class SearchBookActivity extends BaseActivity {
}
return false;
});
switch (mSetting.getSearchFilter()) {
case 0:
rbAllSearch.setChecked(true);
break;
case 1:
default:
rbFuzzySearch.setChecked(true);
break;
case 2:
rbPreciseSearch.setChecked(true);
break;
}
rbSearchFilter.setOnCheckedChangeListener((group, checkedId) -> {
int searchFilter;
switch (checkedId){
case R.id.rb_all_search:
default:
searchFilter = 0;
break;
case R.id.rb_fuzzy_search:
searchFilter = 1;
break;
case R.id.rb_precise_search:
searchFilter = 2;
break;
}
mSetting.setSearchFilter(searchFilter);
SysManager.saveSetting(mSetting);
});
//搜索框改变事件
etSearchKey.addTextChangedListener(new TextWatcher() {
@ -216,6 +266,7 @@ public class SearchBookActivity extends BaseActivity {
}
});
rvSearchBooksList.setLayoutManager(new LinearLayoutManager(this));
//上拉刷新
@ -314,8 +365,6 @@ public class SearchBookActivity extends BaseActivity {
}
/**
* 获取搜索数据
*/

@ -75,6 +75,11 @@ public class SplashActivity extends BaseActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 避免从桌面启动程序后,会重新实例化入口类的activity
if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
finish();
return;
}
ImmersionBar.with(this)
.fullScreen(true)
.init();

@ -1,6 +1,10 @@
package xyz.fycz.myreader.ui.adapter;
import android.app.Activity;
import android.os.Handler;
import java.util.List;
import xyz.fycz.myreader.base.adapter.BaseListAdapter;
import xyz.fycz.myreader.base.adapter.IViewHolder;
import xyz.fycz.myreader.greendao.entity.Book;
@ -21,4 +25,17 @@ public class BookStoreBookAdapter extends BaseListAdapter<Book> {
protected IViewHolder<Book> createViewHolder(int viewType) {
return new BookStoreBookHolder(hasImg, mActivity);
}
@Override
public void addItems(List<Book> values) {
mList.addAll(values);
Handler handler = new Handler();
handler.post(new Runnable() {
@Override
public void run() {
notifyDataSetChanged();
}
});
}
}

@ -1,5 +1,6 @@
package xyz.fycz.myreader.ui.adapter;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;

@ -1,5 +1,6 @@
package xyz.fycz.myreader.ui.adapter;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;

@ -4,12 +4,14 @@ import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
@ -94,7 +96,7 @@ public class FontsAdapter extends ArrayAdapter<Font> {
convertView = LayoutInflater.from(getContext()).inflate(mResourceId, null);
viewHolder.tvFontName = (TextView) convertView.findViewById(R.id.tv_font_name);
viewHolder.btnFontUse = (ProgressButton) convertView.findViewById(R.id.btn_font_use);
//viewHolder.tvExample = (TextView)convertView.findViewById(R.id.tv_font_example);
viewHolder.ivExample = (ImageView) convertView.findViewById(R.id.iv_font_example);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
@ -105,20 +107,22 @@ public class FontsAdapter extends ArrayAdapter<Font> {
private void initView(int position, final ViewHolder viewHolder) {
final Font font = getItem(position);
/*Typeface typeFace = null;
if (font != Font.默认字体) {
if (!mTypefaceMap.containsKey(font)){
typeFace = Typeface.createFromAsset(getContext().getAssets(), font.path);
mTypefaceMap.put(font,typeFace);
}else {
typeFace = mTypefaceMap.get(font);
if (font != Font.本地字体 && font != Font.默认字体) {
try {
viewHolder.ivExample.setVisibility(View.VISIBLE);
viewHolder.ivExample.setImageBitmap(BitmapFactory.decodeStream(mFontsActivity.getAssets().open("font_img/" + font.toString() + ".png")));
} catch (IOException e) {
e.printStackTrace();
viewHolder.ivExample.setVisibility(View.GONE);
}
}*/
//viewHolder.tvExample.setTypeface(typeFace);
// viewHolder.tvExample.setTypeface(mTypefaceMap.get(font));
} else {
viewHolder.ivExample.setVisibility(View.GONE);
}
viewHolder.tvFontName.setText(font.toString());
viewHolder.tvFontName.setTextColor(mFontsActivity.getResources().getColor(R.color.textPrimary));
File fontFile = new File(APPCONST.FONT_BOOK_DIR + font.fileName);
File fontFile = new File(APPCONST.FONT_BOOK_DIR + font.toString() + ".ttf");
if (font == Font.本地字体) {
if (setting.getFont() == Font.本地字体) {
viewHolder.tvFontName.setText(setting.getLocalFontName());
@ -129,50 +133,46 @@ public class FontsAdapter extends ArrayAdapter<Font> {
viewHolder.btnFontUse.setButtonColor(mFontsActivity.getResources().getColor(R.color.sys_blue_littler));
}
viewHolder.btnFontUse.setEnabled(true);
viewHolder.btnFontUse.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/*ArrayList<File> localFontFiles = getLocalFontList();
if (localFontFiles == null || localFontFiles.size() == 0) {
DialogCreator.createTipDialog(getContext(), getContext().getString(R.string.font_select_tip));
return;
}
final CharSequence[] fontNames = new CharSequence[localFontFiles.size()];
int checkedItem = 0;
for (int i = 0; i < fontNames.length; i++) {
fontNames[i] = localFontFiles.get(i).getName();
if (font.fileName.equals(fontNames[i])) {
checkedItem = i;
}
viewHolder.btnFontUse.setOnClickListener(v -> {
/*ArrayList<File> localFontFiles = getLocalFontList();
if (localFontFiles == null || localFontFiles.size() == 0) {
DialogCreator.createTipDialog(getContext(), getContext().getString(R.string.font_select_tip));
return;
}
final CharSequence[] fontNames = new CharSequence[localFontFiles.size()];
int checkedItem = 0;
for (int i = 0; i < fontNames.length; i++) {
fontNames[i] = localFontFiles.get(i).getName();
if (font.fileName.equals(fontNames[i])) {
checkedItem = i;
}
MyAlertDialog dialog = new MyAlertDialog.Builder(getContext())
.setTitle(getContext().getString(R.string.font_select))
.setCancelable(true)
.setSingleChoiceItems(fontNames, checkedItem, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
font.fileName = (String) fontNames[which];
setting.setFont(font);
setting.setLocalFontName(font.fileName);
SysManager.saveSetting(setting);
notifyDataSetChanged();
Intent intent = new Intent();
intent.putExtra(APPCONST.FONT, font);
((Activity) getContext()).setResult(Activity.RESULT_OK, intent);
dialog.dismiss();
}
}).create();
dialog.show();*/
ToastUtils.showInfo("请选择一个ttf格式的字体文件");
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
mFontsActivity.startActivityForResult(intent, APPCONST.SELECT_FILE_CODE);
}
MyAlertDialog dialog = new MyAlertDialog.Builder(getContext())
.setTitle(getContext().getString(R.string.font_select))
.setCancelable(true)
.setSingleChoiceItems(fontNames, checkedItem, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
font.fileName = (String) fontNames[which];
setting.setFont(font);
setting.setLocalFontName(font.fileName);
SysManager.saveSetting(setting);
notifyDataSetChanged();
Intent intent = new Intent();
intent.putExtra(APPCONST.FONT, font);
((Activity) getContext()).setResult(Activity.RESULT_OK, intent);
dialog.dismiss();
}
}).create();
dialog.show();*/
ToastUtils.showInfo("请选择一个ttf格式的字体文件");
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
mFontsActivity.startActivityForResult(intent, APPCONST.SELECT_FILE_CODE);
});
return;
}
if (font != Font.默认字体 && !fontFile.exists()) {
viewHolder.btnFontUse.setEnabled(true);
viewHolder.btnFontUse.setButtonColor(mFontsActivity.getResources().getColor(R.color.sys_blue_littler));
@ -206,7 +206,7 @@ public class FontsAdapter extends ArrayAdapter<Font> {
mHandler.sendMessage(mHandler.obtainMessage(3));
return;
}
final String[] url = {URLCONST.FONT_DOWNLOAD_URL + font.fileName};
final String[] url = {URLCONST.FONT_DOWNLOAD_URL + font.toString() + ".ttf"};
viewHolder.btnFontUse.setText("获取连接...");
CommonApi.getUrl(font.downloadPath, new ResultCallback() {
@Override
@ -237,7 +237,7 @@ public class FontsAdapter extends ArrayAdapter<Font> {
con = (HttpURLConnection) webUrl.openConnection();
is = con.getInputStream();
int fileLength = con.getContentLength();
String filePath = APPCONST.FONT_BOOK_DIR + font.fileName + ".temp";
String filePath = APPCONST.FONT_BOOK_DIR + font.toString() + ".ttf.temp";
fontFile = FileUtils.getFile(filePath);
fos = new FileOutputStream(fontFile);
byte[] tem = new byte[1024];
@ -300,7 +300,7 @@ public class FontsAdapter extends ArrayAdapter<Font> {
if (font == Font.本地字体) {
continue;
}
if (font.fileName.equals(fontFile.getName())) {
if ((font.toString() + ".ttf").equals(fontFile.getName())) {
continue fontFilesFor;
}
}
@ -311,7 +311,7 @@ public class FontsAdapter extends ArrayAdapter<Font> {
return localFontFiles;
}
public void saveLocalFontName(String fontName){
public void saveLocalFontName(String fontName) {
setting.setFont(Font.本地字体);
setting.setLocalFontName(fontName);
SysManager.saveSetting(setting);
@ -322,7 +322,7 @@ public class FontsAdapter extends ArrayAdapter<Font> {
}
class ViewHolder {
//TextView tvExample;
ImageView ivExample;
TextView tvFontName;
ProgressButton btnFontUse;
}

@ -2,7 +2,9 @@ package xyz.fycz.myreader.ui.adapter;
import android.app.Activity;
import android.text.TextUtils;
import xyz.fycz.myreader.application.MyApplication;
import xyz.fycz.myreader.application.SysManager;
import xyz.fycz.myreader.base.adapter.BaseListAdapter;
import xyz.fycz.myreader.base.adapter.IViewHolder;
import xyz.fycz.myreader.entity.SearchBookBean;
@ -10,6 +12,7 @@ import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.model.SearchEngine;
import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap;
import xyz.fycz.myreader.ui.adapter.holder.SearchBookHolder;
import xyz.fycz.myreader.util.utils.StringUtils;
import java.util.ArrayList;
import java.util.List;
@ -38,13 +41,38 @@ public class SearchBookAdapter extends BaseListAdapter<SearchBookBean> {
public synchronized void addAll(List<SearchBookBean> newDataS, String keyWord) {
List<SearchBookBean> copyDataS = mList;
if (newDataS != null && newDataS.size() > 0) {
List<SearchBookBean> filterDataS = new ArrayList<>();
switch (SysManager.getSetting().getSearchFilter()) {
case 0:
filterDataS.addAll(newDataS);
break;
case 1:
default:
for (SearchBookBean ssb : newDataS) {
if (StringUtils.isContainEachOther(ssb.getName(), keyWord) ||
StringUtils.isContainEachOther(ssb.getAuthor(), keyWord)) {
filterDataS.add(ssb);
}
}
break;
case 2:
for (SearchBookBean ssb : newDataS) {
if (StringUtils.isEqual(ssb.getName(), keyWord) ||
StringUtils.isEqual(ssb.getAuthor(), keyWord)) {
filterDataS.add(ssb);
}
}
break;
}
if (filterDataS != null && filterDataS.size() > 0) {
List<SearchBookBean> searchBookBeansAdd = new ArrayList<>();
if (copyDataS.size() == 0) {
copyDataS.addAll(newDataS);
copyDataS.addAll(filterDataS);
} else {
//存在
for (SearchBookBean temp : newDataS) {
for (SearchBookBean temp : filterDataS) {
boolean hasSame = false;
for (int i = 0, size = copyDataS.size(); i < size; i++) {
SearchBookBean searchBook = copyDataS.get(i);

@ -16,6 +16,7 @@ import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.enums.BookSource;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.ui.activity.BookDetailedActivity;
import xyz.fycz.myreader.util.StringHelper;
import xyz.fycz.myreader.widget.CoverImageView;
/**
@ -59,7 +60,8 @@ public class BookStoreBookHolder extends ViewHolderImpl<Book> {
public void onBind(Book data, int pos) {
tvBookName.setText(data.getName());
tvBookAuthor.setText(data.getAuthor());
tvBookNewestChapter.setText(data.getNewestChapterTitle());
tvBookNewestChapter.setText(StringHelper.isEmpty(data.getNewestChapterTitle()) ?
data.getDesc() : data.getNewestChapterTitle());
tvBookTime.setText(data.getUpdateDate());
if (hasImg){
tvBookImg.setVisibility(View.VISIBLE);
@ -68,7 +70,7 @@ public class BookStoreBookHolder extends ViewHolderImpl<Book> {
}
}
if (data.getSource() != null) {
tvBookSource.setText("书源:" + BookSource.fromString(data.getSource()).text);
tvBookSource.setText(String.format("书源:%s", BookSource.fromString(data.getSource()).text));
}else {
tvBookSource.setText(data.getNewestChapterId());
}

@ -4,22 +4,17 @@ import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Handler;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.MyApplication;
import xyz.fycz.myreader.base.adapter.ViewHolderImpl;
import xyz.fycz.myreader.model.SearchEngine;
import xyz.fycz.myreader.webapi.callback.ResultCallback;
import xyz.fycz.myreader.entity.SearchBookBean;
import xyz.fycz.myreader.enums.BookSource;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap;
import xyz.fycz.myreader.util.StringHelper;
import xyz.fycz.myreader.webapi.CommonApi;
import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil;
import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler;
import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler;
@ -40,7 +35,7 @@ public class SearchBookHolder extends ViewHolderImpl<SearchBookBean> {
case 1:
Book book = (Book) message.obj;
int pos = message.arg1;
initOtherInfo(book, pos);
initOtherInfo(book);
break;
}
return false;
@ -84,7 +79,6 @@ public class SearchBookHolder extends ViewHolderImpl<SearchBookBean> {
if (StringHelper.isEmpty(book.getImgUrl())){
book.setImgUrl("");
}
if (!StringHelper.isEmpty(book.getDesc())) {
tvDesc.setText("简介:" + book.getDesc());
}
@ -104,7 +98,7 @@ public class SearchBookHolder extends ViewHolderImpl<SearchBookBean> {
if (tvBookName.getTag() == null || !(Boolean) tvBookName.getTag()) {
tvBookName.setTag(true);
} else {
initOtherInfo(book, pos);
initOtherInfo(book);
return;
}
Log.i(book.getName(), "initOtherInfo");
@ -116,11 +110,11 @@ public class SearchBookHolder extends ViewHolderImpl<SearchBookBean> {
tvBookName.setTag(false);
});
}else {
initOtherInfo(book, pos);
initOtherInfo(book);
}
}
private void initOtherInfo(Book book, int pos){
private void initOtherInfo(Book book){
//简介
if (StringHelper.isEmpty(tvDesc.getText().toString())) {
tvDesc.setText("简介:" + book.getDesc());

@ -254,6 +254,7 @@ public class AudioPlayerDialog extends Dialog{
public void readAloud() {
mPageLoader.resetReadAloudParagraph();
aloudNextPage = false;
String unReadContent = mPageLoader.getUnReadContent();
ReadAloudService.setReadEvent(new ReadEvent());

@ -24,6 +24,7 @@ import xyz.fycz.myreader.application.SysManager;
import xyz.fycz.myreader.common.URLCONST;
import xyz.fycz.myreader.entity.Setting;
import xyz.fycz.myreader.enums.BookSource;
import xyz.fycz.myreader.enums.Language;
import xyz.fycz.myreader.enums.ReadStyle;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.entity.Chapter;
@ -35,280 +36,8 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import static xyz.fycz.myreader.enums.ReadStyle.blueDeep;
import static xyz.fycz.myreader.enums.ReadStyle.breen;
import static xyz.fycz.myreader.enums.ReadStyle.common;
import static xyz.fycz.myreader.enums.ReadStyle.leather;
import static xyz.fycz.myreader.enums.ReadStyle.protectedEye;
public class DialogCreator {
private static ImageView ivLastSelectd = null;
/**
* 阅读详细设置对话框
* @param context
* @param setting
* @param onReadStyleChangeListener
* @param reduceSizeListener
* @param increaseSizeListener
* @param languageChangeListener
* @param onFontClickListener
* @return
*/
public static Dialog createReadDetailSetting(final Context context, final Setting setting,
final OnReadStyleChangeListener onReadStyleChangeListener,
final View.OnClickListener reduceSizeListener,
final View.OnClickListener increaseSizeListener,
final View.OnClickListener languageChangeListener,
final View.OnClickListener onFontClickListener,
final OnPageModeChangeListener onModeClickListener,
View.OnClickListener autoScrollListener,
View.OnClickListener moreSettingListener) {
final Dialog dialog = new Dialog(context, R.style.jmui_default_dialog_style);
final View view = LayoutInflater.from(context).inflate(R.layout.dialog_read_setting_detail, null);
dialog.setContentView(view);
dialog.setCancelable(true);
dialog.setCanceledOnTouchOutside(true);
//触摸外部关闭
view.findViewById(R.id.ll_bottom_view).setOnClickListener(null);
view.setOnTouchListener(new View.OnTouchListener() {
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
dialog.dismiss();
return false;
}
});
//设置全屏
Window window = dialog.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
window.setWindowAnimations(R.style.dialogWindowAnim);
//阅读背景风格
final ImageView ivCommonStyle = (ImageView) view.findViewById(R.id.iv_common_style);
final ImageView ivLeatherStyle = (ImageView) view.findViewById(R.id.iv_leather_style);
final ImageView ivProtectEyeStyle = (ImageView) view.findViewById(R.id.iv_protect_eye_style);
final ImageView ivBreenStyle = (ImageView) view.findViewById(R.id.iv_breen_style);
final ImageView ivBlueDeepStyle = (ImageView) view.findViewById(R.id.iv_blue_deep_style);
switch (setting.getReadStyle()) {
case common:
ivCommonStyle.setSelected(true);
ivLastSelectd = ivCommonStyle;
break;
case leather:
ivLeatherStyle.setSelected(true);
ivLastSelectd = ivLeatherStyle;
break;
case protectedEye:
ivProtectEyeStyle.setSelected(true);
ivLastSelectd = ivProtectEyeStyle;
break;
case breen:
ivBreenStyle.setSelected(true);
ivLastSelectd = ivBreenStyle;
break;
case blueDeep:
ivBlueDeepStyle.setSelected(true);
ivLastSelectd = ivBlueDeepStyle;
break;
}
ivCommonStyle.setOnClickListener(v -> selectedStyle(ivCommonStyle, common, onReadStyleChangeListener));
ivLeatherStyle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
selectedStyle(ivLeatherStyle, leather, onReadStyleChangeListener);
}
});
ivProtectEyeStyle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
selectedStyle(ivProtectEyeStyle, protectedEye, onReadStyleChangeListener);
}
});
ivBlueDeepStyle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
selectedStyle(ivBlueDeepStyle, blueDeep, onReadStyleChangeListener);
}
});
ivBreenStyle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
selectedStyle(ivBreenStyle, breen, onReadStyleChangeListener);
}
});
//字体大小
TextView tvSizeReduce = (TextView) view.findViewById(R.id.tv_reduce_text_size);
TextView tvSizeIncrease = (TextView) view.findViewById(R.id.tv_increase_text_size);
final TextView tvSize = (TextView) view.findViewById(R.id.tv_text_size);
tvSize.setText(String.valueOf((int) setting.getReadWordSize()));
tvSizeReduce.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (setting.getReadWordSize() > 1) {
tvSize.setText(String.valueOf((int) setting.getReadWordSize() - 1));
if (reduceSizeListener != null) {
reduceSizeListener.onClick(v);
}
}
}
});
tvSizeIncrease.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (setting.getReadWordSize() < 41) {
tvSize.setText(String.valueOf((int) setting.getReadWordSize() + 1));
if (increaseSizeListener != null) {
increaseSizeListener.onClick(v);
}
}
}
});
//亮度调节
SeekBar seekBar = (SeekBar) view.findViewById(R.id.sb_brightness_progress);
final TextView tvBrightFollowSystem = (TextView) view.findViewById(R.id.tv_system_brightness);
seekBar.setProgress(setting.getBrightProgress());
tvBrightFollowSystem.setSelected(setting.isBrightFollowSystem());
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
BrightUtil.setBrightness((AppCompatActivity) context, BrightUtil.progressToBright(progress));
tvBrightFollowSystem.setSelected(false);
setting.setBrightProgress(progress);
setting.setBrightFollowSystem(false);
SysManager.saveSetting(setting);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
//亮度跟随系统
tvBrightFollowSystem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tvBrightFollowSystem.setSelected(!tvBrightFollowSystem.isSelected());
if (tvBrightFollowSystem.isSelected()) {
BrightUtil.followSystemBright((AppCompatActivity) context);
setting.setBrightFollowSystem(true);
SysManager.saveSetting(setting);
} else {
BrightUtil.setBrightness((AppCompatActivity) context, BrightUtil.progressToBright(setting.getBrightProgress()));
setting.setBrightFollowSystem(false);
SysManager.saveSetting(setting);
}
}
});
//音量键翻页
final TextView tvIsVolumeTurnPage = (TextView) view.findViewById(R.id.tv_isVolumeTurnPage);
if (setting.isVolumeTurnPage()) {
tvIsVolumeTurnPage.setText("关");
} else {
tvIsVolumeTurnPage.setText("开");
}
tvIsVolumeTurnPage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (tvIsVolumeTurnPage.getText().toString().equals("关")) {
tvIsVolumeTurnPage.setText("开");
} else {
tvIsVolumeTurnPage.setText("关");
}
if (languageChangeListener != null) {
languageChangeListener.onClick(v);
}
}
});
//选择字体
TextView tvFont = (TextView)view.findViewById(R.id.tv_text_font);
tvFont.setOnClickListener(onFontClickListener);
//选择翻页模式
TextView tvMode = view.findViewById(R.id.tv_page_mode);
tvMode.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onModeClickListener != null){
onModeClickListener.onChange((TextView) v);
}
}
});
switch (setting.getPageMode()) {
case COVER:
tvMode.setText("覆盖");
break;
case SIMULATION:
tvMode.setText("仿真");
break;
case SLIDE:
tvMode.setText("滑动");
break;
case SCROLL:
tvMode.setText("滚动");
break;
case NONE:
tvMode.setText("无");
break;
}
//自动滚屏速度
SeekBar sbScrollSpeed = view.findViewById(R.id.sb_auto_scroll_progress);
TextView tvAutoScroll = view.findViewById(R.id.tv_auto_scroll);
TextView tvAutoScrollSpeed = view.findViewById(R.id.tv_auto_scroll_speed);
sbScrollSpeed.setProgress(setting.getAutoScrollSpeed() / 3);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
sbScrollSpeed.setMin(100);
}
tvAutoScrollSpeed.setText("每分钟阅读字数(CPM):" + setting.getAutoScrollSpeed() + "CPM");
sbScrollSpeed.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int speed = progress == 0 ? 300 : progress * 3;
setting.setAutoScrollSpeed(speed);
tvAutoScrollSpeed.setText("每分钟阅读字数(CPM):" + speed + "CPM");
SysManager.saveSetting(setting);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
tvAutoScroll.setOnClickListener(autoScrollListener);
view.findViewById(R.id.tv_read_setting_more).setOnClickListener(moreSettingListener);
return dialog;
}
private static void selectedStyle(ImageView curSelected, ReadStyle readStyle, OnReadStyleChangeListener listener) {
ivLastSelectd.setSelected(false);
ivLastSelectd = curSelected;
curSelected.setSelected(true);
if (listener != null) {
listener.onChange(readStyle);
}
}
/**
* 创建一个普通对话框包含确定取消按键
*

@ -11,6 +11,7 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import androidx.appcompat.app.AlertDialog;
import com.google.android.material.textfield.TextInputLayout;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.MyApplication;
@ -83,6 +84,7 @@ public class MyAlertDialog {
return createInputDia(context, title, hint, initText, InputType.TYPE_CLASS_TEXT, cancelable, maxLen, oic, posListener);
}
public interface onInputChangeListener{
void onChange(String text);
}

@ -8,8 +8,12 @@ import xyz.fycz.myreader.base.BaseFragment;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.ui.activity.BookstoreActivity;
import xyz.fycz.myreader.webapi.crawler.base.FindCrawler;
import xyz.fycz.myreader.webapi.crawler.find.XS7Rank;
import xyz.fycz.myreader.webapi.crawler.read.Ben100ReadCrawler;
import xyz.fycz.myreader.webapi.crawler.read.MiaoBiReadCrawler;
import xyz.fycz.myreader.webapi.crawler.read.QB5ReadCrawler;
import xyz.fycz.myreader.webapi.crawler.find.QiDianMobileRank;
import xyz.fycz.myreader.webapi.crawler.read.XS7ReadCrawler;
/**
* @author fengyue
@ -20,14 +24,20 @@ public class FindFragment extends BaseFragment {
RelativeLayout mRlQiDianTop;
@BindView(R.id.find_rl_qidian_ns_top)
RelativeLayout mRlQiDianNSTop;
@BindView(R.id.find_rl_xs7_top)
RelativeLayout mRlXS7Top;
@BindView(R.id.find_rl_qidian_sort)
RelativeLayout mRlQiDianSort;
@BindView(R.id.find_rl_qidian_ns_sort)
RelativeLayout mRlQiDianNSSort;
@BindView(R.id.find_rl_qb5_store)
RelativeLayout mRlQB5Store;
@BindView(R.id.find_rl_biquge_store)
RelativeLayout mRlBiQuGeStore;
@BindView(R.id.find_rl_ben100_store)
RelativeLayout mRlBen100Store;
@BindView(R.id.find_rl_miaoqu_store)
RelativeLayout mRlMiaoQuStore;
@BindView(R.id.find_rl_xs7_store)
RelativeLayout mRlXS7Store;
@Override
protected int getContentId() {
@ -39,9 +49,13 @@ public class FindFragment extends BaseFragment {
super.initClick();
mRlQiDianTop.setOnClickListener(v -> comeToBookstore(new QiDianMobileRank(false)));
mRlQiDianNSTop.setOnClickListener(v -> comeToBookstore(new QiDianMobileRank(true)));
mRlXS7Top.setOnClickListener(v -> comeToBookstore(new XS7Rank()));
mRlQiDianSort.setOnClickListener(v -> comeToBookstore(new QiDianMobileRank(false, true)));
mRlQiDianNSSort.setOnClickListener(v -> comeToBookstore(new QiDianMobileRank(true, true)));
mRlQB5Store.setOnClickListener(v -> comeToBookstore(new QB5ReadCrawler()));
mRlBen100Store.setOnClickListener(v -> comeToBookstore(new Ben100ReadCrawler()));
mRlMiaoQuStore.setOnClickListener(v -> comeToBookstore(new MiaoBiReadCrawler()));
mRlXS7Store.setOnClickListener(v -> comeToBookstore(new XS7ReadCrawler()));
}

@ -8,11 +8,13 @@ import android.os.Message;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import butterknife.BindView;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.MyApplication;
import xyz.fycz.myreader.application.SysManager;
import xyz.fycz.myreader.model.backup.UserService;
import xyz.fycz.myreader.base.BaseFragment;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.model.storage.Backup;
@ -23,28 +25,45 @@ import xyz.fycz.myreader.entity.Setting;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.service.BookService;
import xyz.fycz.myreader.ui.activity.AboutActivity;
import xyz.fycz.myreader.ui.activity.LoginActivity;
import xyz.fycz.myreader.ui.activity.MoreSettingActivity;
import xyz.fycz.myreader.util.SharedPreUtils;
import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.webapi.callback.ResultCallback;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import static android.app.Activity.RESULT_OK;
/**
* @author fengyue
* @date 2020/9/13 13:20
*/
public class MineFragment extends BaseFragment {
@BindView(R.id.mine_rl_user)
RelativeLayout mRlUser;
@BindView(R.id.tv_user)
TextView mTvUser;
@BindView(R.id.mine_rl_backup)
RelativeLayout mRlBackup;
@BindView(R.id.mine_rl_syn)
RelativeLayout mRlSyn;
@BindView(R.id.mine_rl_setting)
RelativeLayout mRlSetting;
@BindView(R.id.mine_rl_theme_mode)
RelativeLayout mRlThemeMode;
@BindView(R.id.tv_theme_mode_select)
TextView tvThemeModeSelect;
@BindView(R.id.mine_rl_feedback)
RelativeLayout mRlFeedback;
@BindView(R.id.mine_rl_about)
RelativeLayout mRlAbout;
private boolean isLogin;
private Setting mSetting;
private String[] webSynMenu;
private String[] backupMenu;
@ -57,7 +76,7 @@ public class MineFragment extends BaseFragment {
public void handleMessage(@NonNull Message msg) {
switch (msg.what) {
case 1:
mTvUser.setText("登录/注册");
break;
case 2:
backup();
@ -80,6 +99,7 @@ public class MineFragment extends BaseFragment {
@Override
protected void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
isLogin = UserService.isLogin();
mSetting = SysManager.getSetting();
webSynMenu = new String[]{
MyApplication.getmContext().getString(R.string.menu_backup_webBackup),
@ -97,12 +117,35 @@ public class MineFragment extends BaseFragment {
@Override
protected void initWidget(Bundle savedInstanceState) {
super.initWidget(savedInstanceState);
if (isLogin) {
mTvUser.setText(UserService.readUsername());
}
tvThemeModeSelect.setText(themeModeArr[themeMode]);
}
@Override
protected void initClick() {
super.initClick();
mRlUser.setOnClickListener(v -> {
if (isLogin) {
DialogCreator.createCommonDialog(getActivity(), "退出登录", "确定要退出登录吗?"
, true, (dialog, which) -> {
File file = MyApplication.getApplication().getFileStreamPath("userConfig.fy");
if (file.delete()) {
ToastUtils.showSuccess("退出成功");
isLogin = false;
mHandler.sendEmptyMessage(1);
Intent intent = new Intent(getActivity(), LoginActivity.class);
getActivity().startActivityForResult(intent, APPCONST.REQUEST_LOGIN);
} else {
ToastUtils.showError("退出失败(Error:file.delete())");
}
}, (dialog, which) -> dialog.dismiss());
} else {
Intent intent = new Intent(getActivity(), LoginActivity.class);
getActivity().startActivityForResult(intent, APPCONST.REQUEST_LOGIN);
}
});
mRlBackup.setOnClickListener(v -> {
AlertDialog bookDialog = MyAlertDialog.build(getContext())
.setTitle(getContext().getResources().getString(R.string.menu_bookcase_backup))
@ -121,6 +164,46 @@ public class MineFragment extends BaseFragment {
.create();
bookDialog.show();
});
mRlSyn.setOnClickListener(v -> {
if (!UserService.isLogin()) {
ToastUtils.showWarring("请先登录!");
Intent loginIntent = new Intent(getActivity(), LoginActivity.class);
getActivity().startActivityForResult(loginIntent, APPCONST.REQUEST_LOGIN);
return;
}
if (mSetting.isAutoSyn()) {
webSynMenu[2] = MyApplication.getmContext().getString(R.string.menu_backup_autoSyn) + "已开启";
} else {
webSynMenu[2] = MyApplication.getmContext().getString(R.string.menu_backup_autoSyn) + "已关闭";
}
MyAlertDialog.build(getContext())
.setTitle(getActivity().getString(R.string.menu_bookcase_syn))
.setItems(webSynMenu, (dialog, which) -> {
switch (which) {
case 0:
synBookcaseToWeb(false);
break;
case 1:
webRestore();
break;
case 2:
String tip = "";
if (mSetting.isAutoSyn()) {
mSetting.setAutoSyn(false);
tip = "每日自动同步已关闭!";
} else {
mSetting.setAutoSyn(true);
tip = "每日自动同步已开启!";
}
SysManager.saveSetting(mSetting);
ToastUtils.showSuccess(tip);
break;
}
})
.setNegativeButton(null, null)
.setPositiveButton(null, null)
.show();
});
mRlSetting.setOnClickListener(v -> {
Intent settingIntent = new Intent(getActivity(), MoreSettingActivity.class);
startActivity(settingIntent);
@ -169,6 +252,20 @@ public class MineFragment extends BaseFragment {
startActivity(aboutIntent);
});
mRlFeedback.setOnClickListener(v -> {
DialogCreator.createCommonDialog(getContext(), "问题反馈", "请加入QQ群(1085028304)反馈问题!", true,
"加入QQ群", "取消", (dialog, which) -> {
if (!MyApplication.joinQQGroup(getContext(), "8PIOnHFuH6A38hgxvD_Rp2Bu-Ke1ToBn")) {
ClipboardManager mClipboardManager = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
//数据
ClipData mClipData = ClipData.newPlainText("Label", "1085028304");
//把数据设置到剪切板上
assert mClipboardManager != null;
mClipboardManager.setPrimaryClip(mClipData);
ToastUtils.showError("未安装手Q或安装的版本不支持!\n已复制QQ群号,您可自行前往QQ添加!");
}
}, null);
});
}
@Override
@ -229,7 +326,7 @@ public class MineFragment extends BaseFragment {
mHandler.sendMessage(mHandler.obtainMessage(7));
// DialogCreator.createTipDialog(mMainActivity,
// "恢复成功!\n注意:本功能属于实验功能,书架恢复后,书籍初次加载时可能加载失败,返回重新加载即可!");
mSetting = SysManager.getSetting();
SysManager.regetmSetting();
ToastUtils.showSuccess("书架恢复成功!");
}
@ -241,6 +338,112 @@ public class MineFragment extends BaseFragment {
}, (dialogInterface, i) -> dialogInterface.dismiss());
}
/**
* 同步书架
*/
private void synBookcaseToWeb(boolean isAutoSyn) {
if (!NetworkUtils.isNetWorkAvailable()) {
if (!isAutoSyn) {
ToastUtils.showWarring("无网络连接!");
}
return;
}
ArrayList<Book> mBooks = (ArrayList<Book>) BookService.getInstance().getAllBooks();
if (mBooks.size() == 0) {
if (!isAutoSyn) {
ToastUtils.showWarring("当前书架无任何书籍,无法同步!");
}
return;
}
Date nowTime = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd");
String nowTimeStr = sdf.format(nowTime);
SharedPreUtils spb = SharedPreUtils.getInstance();
String synTime = spb.getString(getString(R.string.synTime));
if (!nowTimeStr.equals(synTime) || !isAutoSyn) {
UserService.webBackup(new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
if ((boolean) o) {
spb.putString(getString(R.string.synTime), nowTimeStr);
if (!isAutoSyn) {
DialogCreator.createTipDialog(getContext(), "成功将书架同步至网络!");
}
} else {
if (!isAutoSyn) {
DialogCreator.createTipDialog(getContext(), "同步失败,请重试!");
}
}
}
@Override
public void onError(Exception e) {
if (!isAutoSyn) {
DialogCreator.createTipDialog(getContext(), "同步失败,请重试!\n" + e.getLocalizedMessage());
}
}
});
}
}
/**
* 恢复
*/
private void webRestore() {
if (!NetworkUtils.isNetWorkAvailable()) {
ToastUtils.showWarring("无网络连接!");
return;
}
DialogCreator.createCommonDialog(getContext(), "确认同步吗?", "将书架从网络同步至本地会覆盖原有书架!", true,
(dialogInterface, i) -> {
dialogInterface.dismiss();
MyApplication.getApplication().newThread(() -> {
/*if (UserService.webRestore()) {
mHandler.sendMessage(mHandler.obtainMessage(7));
// DialogCreator.createTipDialog(mMainActivity,
// "恢复成功!\n注意:本功能属于实验功能,书架恢复后,书籍初次加载时可能加载失败,返回重新加载即可!");、
mSetting = SysManager.getSetting();
ToastUtils.showSuccess("成功将书架从网络同步至本地!");
} else {
DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!");
}*/
UserService.webRestore(new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
if ((boolean) o) {
mHandler.sendMessage(mHandler.obtainMessage(7));
// DialogCreator.createTipDialog(mMainActivity,
// "恢复成功!\n注意:本功能属于实验功能,书架恢复后,书籍初次加载时可能加载失败,返回重新加载即可!");、
SysManager.regetmSetting();
ToastUtils.showSuccess("成功将书架从网络同步至本地!");
} else {
DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!");
}
}
@Override
public void onError(Exception e) {
DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!\n" + e.getLocalizedMessage());
}
});
});
}, (dialogInterface, i) -> dialogInterface.dismiss());
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (resultCode == RESULT_OK) {
switch (requestCode) {
case APPCONST.REQUEST_LOGIN:
assert data != null;
isLogin = data.getBooleanExtra("isLogin", false);
if (isLogin) {
mTvUser.setText(UserService.readUsername());
}
break;
}
}
}
public boolean isRecreate() {
return unbinder == null;

@ -0,0 +1,86 @@
package xyz.fycz.myreader.ui.popmenu;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import butterknife.BindView;
import butterknife.ButterKnife;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.SysManager;
import xyz.fycz.myreader.entity.Setting;
public class AutoPageMenu extends FrameLayout {
@BindView(R.id.tv_auto_scroll_speed)
TextView tvAutoPageSpeed;
@BindView(R.id.sb_auto_scroll_progress)
SeekBar sbAutoPageSpeed;
@BindView(R.id.tv_exit_auto_page)
TextView tvExitAutoPage;
@BindView(R.id.vwNavigationBar)
View vwNavigationBar;
public AutoPageMenu(@NonNull Context context) {
super(context);
init(context);
}
public AutoPageMenu(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public AutoPageMenu(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
View view = LayoutInflater.from(context).inflate(R.layout.menu_auto_page, this);
ButterKnife.bind(this, view);
}
public void setListener(Callback callback) {
Setting setting = SysManager.getSetting();
sbAutoPageSpeed.setProgress(110 - setting.getAutoScrollSpeed());
tvAutoPageSpeed.setText(String.format("翻页速度:%s %%", 110 - setting.getAutoScrollSpeed()));
sbAutoPageSpeed.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
tvAutoPageSpeed.setText(String.format("翻页速度:%s %%", progress));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
int progress = seekBar.getProgress();
int speed = 110 - progress;
setting.setAutoScrollSpeed(speed);
SysManager.saveSetting(setting);
callback.onSpeedChange();
}
});
tvExitAutoPage.setOnClickListener(v -> callback.onExitClick());
}
public void setNavigationBarHeight(int height) {
vwNavigationBar.getLayoutParams().height = height;
}
public interface Callback{
void onSpeedChange();
void onExitClick();
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save