diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml new file mode 100644 index 0000000..c6c5118 --- /dev/null +++ b/.idea/assetWizardSettings.xml @@ -0,0 +1,37 @@ + + + + + + \ No newline at end of file diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 2ecfeb2..c3dfe1e 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/.idea/modules.xml b/.idea/modules.xml index bf5d30b..53c4500 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,8 +2,8 @@ - - + + \ No newline at end of file diff --git a/.idea/navEditor.xml b/.idea/navEditor.xml new file mode 100644 index 0000000..5931864 --- /dev/null +++ b/.idea/navEditor.xml @@ -0,0 +1,55 @@ + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 727332d..dbc9ca2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -99,10 +99,11 @@ dependencies { implementation 'org.jsoup:jsoup:1.11.3' + //SmartRefreshLayout implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.2' - implementation 'com.scwang.smartrefresh:SmartRefreshHeader:1.1.2' + implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.3' implementation 'me.gujun.android.taggroup:library:1.4@aar' @@ -124,10 +125,12 @@ dependencies { //字符串比较 implementation 'net.ricecode:string-similarity:1.0.0' + + implementation 'com.jayway.jsonpath:json-path:2.4.0' } greendao { - schemaVersion 11 + schemaVersion 14 daoPackage 'xyz.fycz.myreader.greendao.gen' // targetGenDir 'src/main/java' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1bb3d26..dd10e23 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -63,7 +63,7 @@ android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher" android:supportsRtl="true" - android:theme="@style/AppDayTheme" + android:theme="@style/MAppTheme" android:requestLegacyExternalStorage="true" android:networkSecurityConfig="@xml/network_security_config"> @@ -72,6 +72,11 @@ + + + @@ -86,7 +91,8 @@ + android:launchMode="singleTask" + android:alwaysRetainTaskState="true"/> @@ -94,6 +100,7 @@ @@ -101,7 +108,6 @@ - @@ -115,6 +121,7 @@ + diff --git a/app/src/main/assets/_csrfToken.fy b/app/src/main/assets/_csrfToken.fy new file mode 100644 index 0000000..5633865 --- /dev/null +++ b/app/src/main/assets/_csrfToken.fy @@ -0,0 +1,10 @@ +_csrfToken=AfAoas8MBYmg6LNiXTCqRB4GqdvAIjLhoMhq0dMR; newstatisticUUID=1600428458_1590109905, +_csrfToken=JoeVbiYLyXUa1F1afAe7vopVMTCIAy9gjYjgs3vG; newstatisticUUID=1600428473_81078399, +_csrfToken=HrhdGbLO43Q1sqYB3fE2HFxTOgjA06Qb4tMdk4oP; newstatisticUUID=1600428493_975004371, +_csrfToken=ipGWAeoYVu786drUzlLunN24Z9aujs5nh5n9BRkO; newstatisticUUID=1600428519_644819972, +_csrfToken=XagcA1H7EuyKRlcCnYxBEXh96LdxehdF79bAshVq; newstatisticUUID=1600428535_1734949593, +_csrfToken=b6ZsEBvH8DizXhKHa7XG9s6kPN81vo0FujgQkBss; newstatisticUUID=1600428547_1240575899, +_csrfToken=AN09KVoEyMW1b7A2h0WICDw0iZRh10YJPHrPMyuF; newstatisticUUID=1600428559_1890659047, +_csrfToken=NPv5rB13eOhAw2PM5GKUbMCrpPXMHEozqs6fTIA7; newstatisticUUID=1600428572_110329628, +_csrfToken=it9IyUnSOXK7xC8fQXADlyrem8ZtGNKFSPt65kj1; newstatisticUUID=1600428591_1594511991, +_csrfToken=HJPozY5Rdj0Ij0HcyXT3L3VW3OLqeOQooCayuMLG; newstatisticUUID=1600428602_278088659 \ No newline at end of file diff --git a/app/src/main/assets/fonts/_csrfToken.fy b/app/src/main/assets/fonts/_csrfToken.fy new file mode 100644 index 0000000..aa26275 --- /dev/null +++ b/app/src/main/assets/fonts/_csrfToken.fy @@ -0,0 +1,10 @@ +_csrfToken=6aY1oV18xaiLFe342vi6RRTJ1CsuZ7PZPqz2Tl9A; newstatisticUUID=1600427331_759036854, +_csrfToken=PnRLboRVY2ag0eGbG3e3dA3X4B96SpihEkCDGle7; newstatisticUUID=1600427449_1941387289, +_csrfToken=Ia5w2vTL03IHyPKiS5PJFgocvzHWbMgi4dBEvrox; newstatisticUUID=1600427497_1599098587, +_csrfToken=GjyWEsVXIta60t4YXkbtO0hsDc2VVBbfKy6GIBRg; newstatisticUUID=1600427528_887702937, +_csrfToken=iPjMCVKGnvL8QrbsdYIxCDNQZkJVSscN1CQFFSdF; newstatisticUUID=1600427557_1213608979, +_csrfToken=Iby8oSKxp767d25frgCGjOAWFWbYwwyRA36nBaxO; newstatisticUUID=1600427589_1737201533, +_csrfToken=IR81KoIAQxXYb6e9Agv8WuXDkAKukMLnlLe9BYha; newstatisticUUID=1600427619_487685580, +_csrfToken=YM1F8lgqaePVMceunc7z7ndjys5ngAx5sYsemg60; newstatisticUUID=1600427643_2022665645, +_csrfToken=8bRnXJseSCajlTcG6lhyWOF0rWwDCiMVpCGvKvQj; newstatisticUUID=1600427644_1615074434, +_csrfToken=AehQ3WVD6wLbFGhFsnSW4DRF6BS1wqVvHU6PbiiX; newstatisticUUID=1600427644_575162687 \ No newline at end of file diff --git a/app/src/main/assets/updatelog.fy b/app/src/main/assets/updatelog.fy index 4d023b4..70b2f9b 100644 --- a/app/src/main/assets/updatelog.fy +++ b/app/src/main/assets/updatelog.fy @@ -1,3 +1,32 @@ +2020.09.26 +风月读书v1.20.092617 +1、新增书架自定义分组功能(点击编辑书架即可选择书籍加入指定分组[需要自行添加分组]) +2、修复夜间模式下部分界面显示移除的bug +3、修复主题模式切换后菜单栏失效的bug + +2020.09.19 +风月读书v1.20.091922 +1、优化全局UI +2、适配全局夜间模式 +3、新增主题模式设置 +4、新增发现界面(排行榜、分类、书城) +5、部分菜单移至"我的"界面 +6、新增QQ反馈群(1085028304),可在"关于"界面加入QQ群 + +2020.09.07 +风月读书v1.20.090722 +1、新增书源"全本小说网(www.qb5.com)" +2、新增简易书城(实验版,默认开启,可在设置关闭) +3、新增换源后历史阅读章节智能匹配机制 +4、新增设置界面 + (1)阅读设置:音量键翻页、息屏时间 + (2)书架设置:自动刷新、禁用更新 + (3)搜索设置:禁用书源 + (4)换源设置:历史章节智能匹配、智能匹配度 + (5)缓存设置:章节缓存间隔、一键缓存、清除缓存 + (6)其他设置:开启书城 +注:因笔趣阁书源经常宕机,导致无法搜索到书籍,故默认禁用该书源 + 2020.08.24 风月读书v1.20.082422 1、重做书籍详情界面 diff --git a/app/src/main/java/xyz/fycz/myreader/ActivityManage.java b/app/src/main/java/xyz/fycz/myreader/ActivityManage.java index 9c1546c..b7f0ad3 100644 --- a/app/src/main/java/xyz/fycz/myreader/ActivityManage.java +++ b/app/src/main/java/xyz/fycz/myreader/ActivityManage.java @@ -1,7 +1,9 @@ package xyz.fycz.myreader; +import android.app.Activity; import androidx.appcompat.app.AppCompatActivity; +import java.lang.ref.WeakReference; import java.util.ArrayList; /** @@ -9,7 +11,7 @@ import java.util.ArrayList; */ public class ActivityManage { - private static ArrayList activities = new ArrayList(); + private static ArrayList activities = new ArrayList<>(); public static void addActivity(AppCompatActivity activity){ activities.add(activity); @@ -34,6 +36,18 @@ public class ActivityManage { return activities.get(activities.size() - 1); } - + /** + * 判断指定Activity是否存在 + */ + public static Boolean isExist(Class activityClass) { + boolean result = false; + for (AppCompatActivity item : activities) { + if (null != item && item.getClass() == activityClass) { + result = true; + break; + } + } + return result; + } } diff --git a/app/src/main/java/xyz/fycz/myreader/application/MyApplication.java b/app/src/main/java/xyz/fycz/myreader/application/MyApplication.java index 42a4c55..07ff6d9 100644 --- a/app/src/main/java/xyz/fycz/myreader/application/MyApplication.java +++ b/app/src/main/java/xyz/fycz/myreader/application/MyApplication.java @@ -18,8 +18,10 @@ import android.os.Build; import android.os.Environment; import android.os.Handler; +import android.util.Log; import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; @@ -43,8 +45,10 @@ import xyz.fycz.myreader.creator.APPDownloadTip; import xyz.fycz.myreader.creator.DialogCreator; import xyz.fycz.myreader.entity.Setting; 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.utils.NetworkUtils; public class MyApplication extends Application { @@ -66,7 +70,39 @@ public class MyApplication extends Application { mFixedThreadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());//初始化线程池 BaseActivity.setCloseAntiHijacking(true); + initNightTheme(); + } + + public void initNightTheme() { + if (isNightFS()){ + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); + }else { + if (isNightTheme()) { + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); + } else { + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); + } + } + } + + protected boolean isNightTheme() { + return !SysManager.getSetting().isDayStyle(); + } + public boolean isNightFS() { + return SharedPreUtils.getInstance().getBoolean("isNightFS", false); + } + + /** + * 设置夜间模式 + * @param isNightMode + */ + public void setNightTheme(boolean isNightMode) { + SharedPreUtils.getInstance().putBoolean("isNightFS", false); + Setting setting = SysManager.getSetting(); + setting.setDayStyle(!isNightMode); + SysManager.saveSetting(setting); + MyApplication.getApplication().initNightTheme(); } @SuppressLint("TrulyRandom") @@ -109,7 +145,7 @@ public class MyApplication extends Application { try { mFixedThreadPool.execute(runnable); } catch (Exception e) { - e.printStackTrace(); + //e.printStackTrace(); mFixedThreadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());//初始化线程池 mFixedThreadPool.execute(runnable); } @@ -244,7 +280,7 @@ public class MyApplication extends Application { } }); }*/ - public static void checkVersionByServer(final BaseActivity activity, final boolean isManualCheck, + public static void checkVersionByServer(final AppCompatActivity activity, final boolean isManualCheck, final BookcaseFragment mBookcaseFragment) { MyApplication.getApplication().newThread(() -> { Document doc = null; @@ -256,7 +292,9 @@ public class MyApplication extends Application { doc = Jsoup.connect(url).get(); String content = doc.getElementsByClass("ql-editor").text(); if (StringHelper.isEmpty(content)) { - ToastUtils.showError("检查更新失败!"); + if (isManualCheck || NetworkUtils.isNetWorkAvailable()) { + ToastUtils.showError("检查更新失败!"); + } return; } String[] contents = content.split(";"); @@ -282,6 +320,7 @@ public class MyApplication extends Application { s.append("\n"); } int versionCode = getVersionCode(); + Log.i("检查更新,最新版本", newestVersion + ""); if (newestVersion > versionCode) { MyApplication m = new MyApplication(); Setting setting = SysManager.getSetting(); @@ -296,7 +335,10 @@ public class MyApplication extends Application { } } catch (Exception e) { e.printStackTrace(); - ToastUtils.showError("检查更新失败!"); + Log.e("检查更新失败!", e.getLocalizedMessage()); + if (isManualCheck || NetworkUtils.isNetWorkAvailable()) { + ToastUtils.showError("检查更新失败!"); + } } }); } @@ -307,7 +349,7 @@ public class MyApplication extends Application { * @param activity * @param versionCode */ - public void updateApp(final BaseActivity activity, final String url, final int versionCode, String message, + public void updateApp(final AppCompatActivity activity, final String url, final int versionCode, String message, final boolean isForceUpdate, final BookcaseFragment mBookcaseFragment) { //String version = (versionCode / 100 % 10) + "." + (versionCode / 10 % 10) + "." + (versionCode % 10); String cancelTitle; @@ -328,6 +370,10 @@ public class MyApplication extends Application { activity.finish(); } }, (dialog, which) -> { + if (activity instanceof MainActivity){ + MainActivity mainActivity = (MainActivity) activity; + mainActivity.getViewPagerMain().setCurrentItem(0); + } if (url == null || "".equals(url)) { ToastUtils.showError("获取链接失败,请前往浏览器下载!"); Intent intent = new Intent(); @@ -381,4 +427,25 @@ public class MyApplication extends Application { return mActivity == null || mActivity.isFinishing() || mActivity.isDestroyed(); } + + /**************** + * + * 发起添加群流程。群号:风月读书交流群(1085028304) 的 key 为: 8PIOnHFuH6A38hgxvD_Rp2Bu-Ke1ToBn + * 调用 joinQQGroup(8PIOnHFuH6A38hgxvD_Rp2Bu-Ke1ToBn) 即可发起手Q客户端申请加群 风月读书交流群(1085028304) + * + * @param key 由官网生成的key + * @return 返回true表示呼起手Q成功,返回false表示呼起失败 + ******************/ + public static boolean joinQQGroup(Context context, String key) { + Intent intent = new Intent(); + intent.setData(Uri.parse("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26jump_from%3Dwebapi%26k%3D" + key)); + // 此Flag可根据具体产品需要自定义,如设置,则在加群界面按返回,返回手Q主界面,不设置,按返回会返回到呼起产品界面 //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + try { + context.startActivity(intent); + return true; + } catch (Exception e) { + // 未安装手Q或安装的版本不支持 + return false; + } + } } diff --git a/app/src/main/java/xyz/fycz/myreader/application/SysManager.java b/app/src/main/java/xyz/fycz/myreader/application/SysManager.java index 40cf371..05e8b87 100644 --- a/app/src/main/java/xyz/fycz/myreader/application/SysManager.java +++ b/app/src/main/java/xyz/fycz/myreader/application/SysManager.java @@ -65,7 +65,8 @@ public class SysManager { setting.setMatchChapter(true); setting.setMatchChapterSuitability(0.7f); setting.setCatheGap(150); - setting.setRefreshWhenStart(false); + setting.setRefreshWhenStart(true); + setting.setOpenBookStore(true); setting.setSettingVersion(APPCONST.SETTING_VERSION); return setting; } @@ -79,6 +80,8 @@ public class SysManager { Setting setting = getSetting(); setting.setVolumeTurnPage(true); setting.setMatchChapter(true); + setting.setRefreshWhenStart(true); + setting.setOpenBookStore(true); setting.setResetScreen(3); setting.setSettingVersion(APPCONST.SETTING_VERSION); saveSetting(setting); diff --git a/app/src/main/java/xyz/fycz/myreader/backup/BackupAndRestore.java b/app/src/main/java/xyz/fycz/myreader/backup/BackupAndRestore.java index 5e2ddb3..f22dbde 100644 --- a/app/src/main/java/xyz/fycz/myreader/backup/BackupAndRestore.java +++ b/app/src/main/java/xyz/fycz/myreader/backup/BackupAndRestore.java @@ -83,6 +83,7 @@ public class BackupAndRestore { String source = "null"; boolean isCloseUpdate = false; boolean isDownloadAll = true; + String group = "allBook"; if(!sBookFields[2].contains("novel.fycz.xyz")){ source = sBookFields[17]; } @@ -95,11 +96,14 @@ public class BackupAndRestore { if (sBookFields.length >= 20){ isDownloadAll = Boolean.parseBoolean(sBookFields[19]); } + if (sBookFields.length >= 21){ + group = sBookFields[20]; + } Book book = new Book(sBookFields[0], sBookFields[1], sBookFields[2], sBookFields[3], sBookFields[4], sBookFields[5], sBookFields[6], sBookFields[7], sBookFields[8], sBookFields[9], sBookFields[10], sBookFields[11], Integer.parseInt(sBookFields[12]), Integer.parseInt(sBookFields[13]), Integer.parseInt(sBookFields[14]), Integer.parseInt(sBookFields[15]), Integer.parseInt(sBookFields[16]) - , source, isCloseUpdate, isDownloadAll); + , source, isCloseUpdate, isDownloadAll, group, 0); books.add(book); } mBookService.deleteAllBooks(); diff --git a/app/src/main/java/xyz/fycz/myreader/base/BaseActivity2.java b/app/src/main/java/xyz/fycz/myreader/base/BaseActivity2.java index 88fe9c1..cdfe6b1 100644 --- a/app/src/main/java/xyz/fycz/myreader/base/BaseActivity2.java +++ b/app/src/main/java/xyz/fycz/myreader/base/BaseActivity2.java @@ -12,6 +12,7 @@ import androidx.annotation.LayoutRes; import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; import androidx.appcompat.widget.Toolbar; import butterknife.ButterKnife; import butterknife.Unbinder; @@ -20,6 +21,9 @@ import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.Disposable; import xyz.fycz.myreader.ActivityManage; import xyz.fycz.myreader.R; +import xyz.fycz.myreader.application.MyApplication; +import xyz.fycz.myreader.application.SysManager; +import xyz.fycz.myreader.entity.Setting; import xyz.fycz.myreader.util.StatusBarUtil; import java.lang.reflect.Method; @@ -37,6 +41,8 @@ public abstract class BaseActivity2 extends AppCompatActivity { private Toolbar mToolbar; private Unbinder unbinder; + + private int curNightMode; /****************************abstract area*************************************/ @LayoutRes @@ -75,12 +81,32 @@ public abstract class BaseActivity2 extends AppCompatActivity { */ protected void processLogic(){ } + /** + * @return 是否夜间模式 + */ + protected boolean isNightTheme() { + return !SysManager.getSetting().isDayStyle(); + } + + /** + * 设置夜间模式 + * @param isNightMode + */ + protected void setNightTheme(boolean isNightMode) { + Setting setting = SysManager.getSetting(); + setting.setDayStyle(!isNightMode); + MyApplication.getApplication().initNightTheme(); + } + + + /*************************lifecycle area*****************************************************/ @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + initTheme(); ActivityManage.addActivity(this); setContentView(getContentId()); initData(savedInstanceState); @@ -100,6 +126,13 @@ public abstract class BaseActivity2 extends AppCompatActivity { } } + @Override + protected void onResume() { + super.onResume(); + if (isThemeChange()){ + recreate(); + } + } @Override protected void onDestroy() { @@ -110,7 +143,22 @@ public abstract class BaseActivity2 extends AppCompatActivity { mDisposable.dispose(); } } + /** + * 初始化主题 + */ + public void initTheme() { + //if (isNightTheme()) { + //setTheme(R.style.AppNightTheme); + curNightMode = AppCompatDelegate.getDefaultNightMode(); + /*} else { + //curNightMode = false; + //setTheme(R.style.AppDayTheme); + }*/ + } + protected boolean isThemeChange(){ + return curNightMode != AppCompatDelegate.getDefaultNightMode(); + } /**************************used method area*******************************************/ protected void startActivity(Class activity){ @@ -148,6 +196,19 @@ public abstract class BaseActivity2 extends AppCompatActivity { StatusBarUtil.setStatusBarColor(this, 0x55000000); } } + } /** + * 设置MENU图标颜色 + */ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + for (int i = 0; i < menu.size(); i++) { + Drawable drawable = menu.getItem(i).getIcon(); + if (drawable != null) { + drawable.mutate(); + drawable.setColorFilter(getColor(R.color.textPrimary), PorterDuff.Mode.SRC_ATOP); + } + } + return super.onCreateOptionsMenu(menu); } @SuppressLint("PrivateApi") @@ -168,7 +229,7 @@ public abstract class BaseActivity2 extends AppCompatActivity { Drawable drawable = menuItem.getIcon(); if (drawable != null) { drawable.mutate(); - drawable.setColorFilter(getResources().getColor(R.color.black), PorterDuff.Mode.SRC_ATOP); + drawable.setColorFilter(getResources().getColor(R.color.textPrimary), PorterDuff.Mode.SRC_ATOP); } } } diff --git a/app/src/main/java/xyz/fycz/myreader/base/BaseFragment.java b/app/src/main/java/xyz/fycz/myreader/base/BaseFragment.java index bceacfe..39ee26b 100644 --- a/app/src/main/java/xyz/fycz/myreader/base/BaseFragment.java +++ b/app/src/main/java/xyz/fycz/myreader/base/BaseFragment.java @@ -23,7 +23,7 @@ public abstract class BaseFragment extends Fragment { protected CompositeDisposable mDisposable; private View root = null; - private Unbinder unbinder; + protected Unbinder unbinder; @LayoutRes protected abstract int getContentId(); diff --git a/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java b/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java index f914478..031a6fa 100644 --- a/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java +++ b/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java @@ -10,10 +10,10 @@ import java.io.File; public class APPCONST { - public static String publicKey = "fyds1.0";//服务端公钥 + public static String publicKey = "";//服务端公钥 public static String privateKey;//app私钥 public final static String s = "11940364935628058505"; - public static final String KEY = "readerByFengyue"; + public static final String KEY = ""; public static final String ALARM_SCHEDULE_MSG = "alarm_schedule_msg"; @@ -33,6 +33,8 @@ public class APPCONST { public static final int exitConfirmTime = 2000; public static final String BOOK = "book"; + public static final String TITLE = "title"; + public static final String FIND_CRAWLER = "findCrawler"; public static final String CHAPTER_PAGE = "chapter_page"; public static final String SETTING = "setting"; public static final String SEARCH_BOOK_BEAN = "SearchBookBean"; @@ -57,6 +59,7 @@ public class APPCONST { 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_READ = 1; diff --git a/app/src/main/java/xyz/fycz/myreader/common/URLCONST.java b/app/src/main/java/xyz/fycz/myreader/common/URLCONST.java index 6a832c8..14f6320 100644 --- a/app/src/main/java/xyz/fycz/myreader/common/URLCONST.java +++ b/app/src/main/java/xyz/fycz/myreader/common/URLCONST.java @@ -1,15 +1,15 @@ package xyz.fycz.myreader.common; -/** - * Created by zhao on 2016/10/20. - */ - public class URLCONST { // 命名空间 public static String nameSpace_FY = "https://novel.fycz.xyz"; - public static String nameSpace_biquge = "https://www.52bqg.com/"; + public static String nameSpace_biquge = "https://www.52bqg.com/"; + + public static String nameSpace_qb5 = "https://www.qb5.tw"; + + public static String qidian_rank = "https://www.qidian.com/rank"; public static String nameSpace_system = "https://novel.fycz.xyz"; @@ -17,6 +17,7 @@ public class URLCONST { // 搜索小说 public static String method_fengyue_search = "https://novel.fycz.xyz/search.html"; + public static String method_buxiu_search = "https://www.23txt.com/search.php"; // 获取最新版本号 diff --git a/app/src/main/java/xyz/fycz/myreader/creator/APPDownloadTip.java b/app/src/main/java/xyz/fycz/myreader/creator/APPDownloadTip.java index 424ffbb..e589529 100644 --- a/app/src/main/java/xyz/fycz/myreader/creator/APPDownloadTip.java +++ b/app/src/main/java/xyz/fycz/myreader/creator/APPDownloadTip.java @@ -2,14 +2,13 @@ package xyz.fycz.myreader.creator; import android.annotation.SuppressLint; -import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.os.Handler; import android.os.Message; import android.view.View; +import androidx.appcompat.app.AppCompatActivity; import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.base.BaseActivity; import xyz.fycz.myreader.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.ui.activity.MainActivity; @@ -38,7 +37,7 @@ public class APPDownloadTip { private MainActivity activity; private boolean isForceUpdate; - public APPDownloadTip(String url, BookcaseFragment mBookcaseFragment, BaseActivity activity, boolean isForceUpdate) { + public APPDownloadTip(String url, BookcaseFragment mBookcaseFragment, AppCompatActivity activity, boolean isForceUpdate) { this.url = url; this.mBookcaseFragment = mBookcaseFragment; this.activity = (MainActivity) activity; @@ -49,25 +48,27 @@ public class APPDownloadTip { private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { - switch (msg.what) { - case 1: - mBookcaseFragment.getTvDownloadTip().setText("获取下载链接失败,请前往浏览器下载!"); - mBookcaseFragment.getRlDownloadTip().setVisibility(View.GONE); - break; - case 2: - mBookcaseFragment.getTvDownloadTip().setText("连接中..."); - break; - case 3: - updateDownloadPro((double) msg.obj); - break; - case 4: - mBookcaseFragment.getRlDownloadTip().setVisibility(View.GONE); - break; + if (!MyApplication.isDestroy(activity)) { + switch (msg.what) { + case 1: + mBookcaseFragment.getTvDownloadTip().setText("获取下载链接失败,请前往浏览器下载!"); + mBookcaseFragment.getRlDownloadTip().setVisibility(View.GONE); + break; + case 2: + mBookcaseFragment.getTvDownloadTip().setText("连接中..."); + break; + case 3: + updateDownloadPro((double) msg.obj); + break; + case 4: + mBookcaseFragment.getRlDownloadTip().setVisibility(View.GONE); + break; + } } } }; - public void downloadApp(){ + public void downloadApp() { mBookcaseFragment.getTvStopDownload().setVisibility(View.GONE); mBookcaseFragment.getRlDownloadTip().setVisibility(View.VISIBLE); mBookcaseFragment.getPbDownload().setProgress(0); @@ -108,20 +109,20 @@ public class APPDownloadTip { if (fileLength == appFile.length()) { String newPath = filePath.replace(".temp", ""); final File newFile = new File(newPath); - if (appFile.renameTo(newFile)){ + if (appFile.renameTo(newFile)) { mHandler.sendMessage(mHandler.obtainMessage(4)); DialogCreator.createCommonDialog(activity, "提示", "风月读书下载完成,安装包路径:" + newPath, !isForceUpdate, "取消", "立即安装", (dialog, which) -> { - if (isForceUpdate){ + if (isForceUpdate) { activity.finish(); } }, (dialog, which) -> activity.installProcess(newFile, isForceUpdate)); activity.installProcess(newFile, isForceUpdate); - }else { + } else { appFile.delete(); error(); } - }else { + } else { appFile.delete(); error(); } @@ -148,7 +149,7 @@ public class APPDownloadTip { } - private void error(){ + private void error() { mHandler.sendMessage(mHandler.obtainMessage(1)); ToastUtils.showError("获取下载链接失败,请前往浏览器下载!"); Intent intent = new Intent(); @@ -159,6 +160,7 @@ public class APPDownloadTip { activity.finish(); } } + @SuppressLint({"SetTextI18n"}) private void updateDownloadPro(double progress) { mBookcaseFragment.getPbDownload().setProgress((int) progress); diff --git a/app/src/main/java/xyz/fycz/myreader/creator/ChangeSourceDialog.java b/app/src/main/java/xyz/fycz/myreader/creator/ChangeSourceDialog.java index 543ec1a..8715384 100644 --- a/app/src/main/java/xyz/fycz/myreader/creator/ChangeSourceDialog.java +++ b/app/src/main/java/xyz/fycz/myreader/creator/ChangeSourceDialog.java @@ -4,7 +4,9 @@ import android.annotation.SuppressLint; import android.content.Context; import android.os.Handler; import android.os.Message; +import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.util.ToastUtils; import xyz.fycz.myreader.webapi.crawler.*; import xyz.fycz.myreader.entity.SearchBookBean; import xyz.fycz.myreader.greendao.entity.Book; @@ -30,21 +32,33 @@ public class ChangeSourceDialog { private boolean isSearchSuccess; private int threadCount; private ResultCallback rc; + private boolean isGetOneBook = false; + private Book oneBook; @SuppressLint("HandlerLeak") private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 1: - if (threadCount == 0) { - createaBooks(); + if (isGetOneBook){ + rc.onFinish(oneBook, 0); + }else { + if (threadCount == 0) { + createaBooks(); + } } break; case 2: if (!isSearchSuccess && threadCount == 0) { - rc.onError(new Exception()); + if (!isGetOneBook|| oneBook == null) { + rc.onError(new Exception()); + } }else if (threadCount == 0){ - createaBooks(); + if (isGetOneBook){ + rc.onFinish(oneBook, 0); + }else { + createaBooks(); + } } break; } @@ -62,17 +76,32 @@ public class ChangeSourceDialog { getData(); } + public void initOneBook(ResultCallback rc){ + this.rc = rc; + getData(); + isGetOneBook = true; + } + /** * 获取搜索数据 */ private void getData() { mBooks.clear(); - threadCount = 4; + ArrayList readCrawlers = ReadCrawlerUtil.getReadCrawlers(); + threadCount = readCrawlers.size(); + if (threadCount == 0){ + if (isGetOneBook){ + ToastUtils.showWarring("当前书源已全部禁用,无法搜索!"); + }else { + ToastUtils.showWarring("当前书源已全部禁用,无法换源!"); + } + rc.onError(new Exception()); + return; + } isSearchSuccess = false; - searchBookByCrawler(new BiQuGe44ReadCrawler(), ""); - searchBookByCrawler(new TianLaiReadCrawler(), ""); - searchBookByCrawler(new BiQuGeReadCrawler(), "gbk"); - searchBookByCrawler(new PinShuReadCrawler(), "gbk"); + for (ReadCrawler readCrawler : readCrawlers){ + searchBookByCrawler(readCrawler, readCrawler.getSearchCharset()); + } } private void searchBookByCrawler(final ReadCrawler rc, String charset) { @@ -89,6 +118,16 @@ public class ChangeSourceDialog { public void onFinish(Object o, int code) { final ConcurrentMultiValueMap cmvm = (ConcurrentMultiValueMap) o; + if (isGetOneBook){ + if (oneBook != null){ + return; + } + oneBook = cmvm.getValue(sbb, 0); + threadCount--; + mHandler.sendMessage(mHandler.obtainMessage(1)); + MyApplication.getApplication().shutdownThreadPool(); + return; + } if (rc instanceof BookInfoCrawler) { BookInfoCrawler bic = (BookInfoCrawler) rc; final List aBooks = cmvm.getValues(sbb); @@ -140,4 +179,5 @@ public class ChangeSourceDialog { aBooks = (ArrayList) mBooks.getValues(sbb); rc.onFinish(aBooks, 1); } + } diff --git a/app/src/main/java/xyz/fycz/myreader/creator/DialogCreator.java b/app/src/main/java/xyz/fycz/myreader/creator/DialogCreator.java index 614702d..e09f6b4 100644 --- a/app/src/main/java/xyz/fycz/myreader/creator/DialogCreator.java +++ b/app/src/main/java/xyz/fycz/myreader/creator/DialogCreator.java @@ -18,6 +18,7 @@ import android.widget.*; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.AppCompatImageView; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.application.SysManager; @@ -115,12 +116,7 @@ public class DialogCreator { ivLastSelectd = ivBlueDeepStyle; break; } - ivCommonStyle.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - selectedStyle(ivCommonStyle, common, onReadStyleChangeListener); - } - }); + ivCommonStyle.setOnClickListener(v -> selectedStyle(ivCommonStyle, common, onReadStyleChangeListener)); ivLeatherStyle.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -371,7 +367,7 @@ public class DialogCreator { Window window = dialog.getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); if (Build.VERSION.SDK_INT >= 21) { - window.setStatusBarColor(dialog.getContext().getResources().getColor(R.color.sys_dialog_setting_bg)); + window.setStatusBarColor(dialog.getContext().getColor(R.color.sys_dialog_setting_bg)); } view.setOnTouchListener(new View.OnTouchListener() { @@ -452,7 +448,7 @@ public class DialogCreator { tvNightAndDay.setText(context.getString(R.string.day)); } if (onClickNightAndDayListener != null) { - onClickNightAndDayListener.onClick(dialog, view1, isDay); + onClickNightAndDayListener.onClick(dialog, view, isDay); } }); @@ -486,7 +482,7 @@ public class DialogCreator { public static AlertDialog createCommonDialog(Context context, String title, String mesage, boolean isCancelable, DialogInterface.OnClickListener positiveListener, DialogInterface.OnClickListener negativeListener) { - final AlertDialog.Builder normalDialog = new AlertDialog.Builder(context); + final AlertDialog.Builder normalDialog = MyAlertDialog.build(context); // normalDialog.setIcon(R.drawable.icon_dialog); normalDialog.setTitle(title); normalDialog.setCancelable(isCancelable); @@ -518,35 +514,32 @@ public class DialogCreator { * @param mesage * @param key1 * @param key2 - * @param positiveListener key1按键动作 - * @param negativeListener key2按键动作 + * @param key1Listener key1按键动作 + * @param key2Listener key2按键动作 */ public static void createCommonDialog(Context context, String title, String mesage, boolean isCancelable, String key1, String key2, - DialogInterface.OnClickListener positiveListener, - DialogInterface.OnClickListener negativeListener) { + DialogInterface.OnClickListener key1Listener, + DialogInterface.OnClickListener key2Listener) { try { - final AlertDialog.Builder normalDialog = new AlertDialog.Builder(context); + final AlertDialog.Builder normalDialog = MyAlertDialog.build(context); // normalDialog.setIcon(R.drawable.icon_dialog); normalDialog.setTitle(title); normalDialog.setCancelable(isCancelable); if (mesage != null) { normalDialog.setMessage(mesage); } - normalDialog.setPositiveButton(key1, positiveListener); - normalDialog.setNegativeButton(key2, negativeListener); + normalDialog.setPositiveButton(key1, key1Listener); + normalDialog.setNegativeButton(key2, key2Listener); // 显示 -// final AlertDialog alertDialog = normalDialog.create(); - MyApplication.runOnUiThread(new Runnable() { - @Override - public void run() { - try { -// final AlertDialog alertDialog = normalDialog.create(); - normalDialog.show(); - } catch (Exception e) { - e.printStackTrace(); - } +// final MyAlertDialog alertDialog = normalDialog.create(); + MyApplication.runOnUiThread(() -> { + try { +// final MyAlertDialog alertDialog = normalDialog.create(); + normalDialog.show(); + } catch (Exception e) { + e.printStackTrace(); } }); } catch (Exception e) { @@ -568,7 +561,7 @@ public class DialogCreator { String key, DialogInterface.OnClickListener positiveListener ) { try { - final AlertDialog.Builder normalDialog = new AlertDialog.Builder(context); + final AlertDialog.Builder normalDialog = MyAlertDialog.build(context); // normalDialog.setIcon(R.drawable.icon_dialog); normalDialog.setTitle(title); normalDialog.setCancelable(isCancelable); @@ -578,12 +571,12 @@ public class DialogCreator { normalDialog.setPositiveButton(key, positiveListener); // 显示 -// final AlertDialog alertDialog = normalDialog.create(); +// final MyAlertDialog alertDialog = normalDialog.create(); MyApplication.runOnUiThread(new Runnable() { @Override public void run() { try { -// final AlertDialog alertDialog = normalDialog.create(); +// final MyAlertDialog alertDialog = normalDialog.create(); normalDialog.show(); } catch (Exception e) { e.printStackTrace(); @@ -609,7 +602,7 @@ public class DialogCreator { (Context context, String title, String message/*, DialogInterface.OnClickListener positiveListener,DialogInterface.OnClickListener negativeListener*/) { - final ProgressDialog progressDialog = new ProgressDialog(context); + final ProgressDialog progressDialog = new ProgressDialog(context, R.style.alertDialogTheme); // normalDialog.setIcon(R.drawable.icon_dialog); if (!StringHelper.isEmpty(title)) { progressDialog.setTitle(title); @@ -654,7 +647,7 @@ public class DialogCreator { DialogInterface.OnClickListener positiveListener) { /* final EditText et = new EditText(context);*/ try { - final AlertDialog.Builder dialog = new AlertDialog.Builder(context); + final AlertDialog.Builder dialog = MyAlertDialog.build(context); dialog.setTitle(title); if (!StringHelper.isEmpty(msg)) { dialog.setMessage(msg); @@ -670,7 +663,7 @@ public class DialogCreator { @Override public void run() { try { -// final AlertDialog alertDialog = normalDialog.create(); +// final MyAlertDialog alertDialog = normalDialog.create(); dialog.show(); } catch (Exception e) { e.printStackTrace(); diff --git a/app/src/main/java/xyz/fycz/myreader/creator/MultiChoiceDialog.java b/app/src/main/java/xyz/fycz/myreader/creator/MultiChoiceDialog.java index 8c82f94..1f42589 100644 --- a/app/src/main/java/xyz/fycz/myreader/creator/MultiChoiceDialog.java +++ b/app/src/main/java/xyz/fycz/myreader/creator/MultiChoiceDialog.java @@ -5,6 +5,7 @@ import android.content.DialogInterface; import android.widget.Button; import android.widget.ListView; import androidx.appcompat.app.AlertDialog; +import xyz.fycz.myreader.R; /** * @author fengyue @@ -22,10 +23,13 @@ public class MultiChoiceDialog { DialogCreator.OnMultiDialogListener onMultiDialogListener) { this.checkedCount = checkedCount; int itemsCount = checkedItems.length; - AlertDialog multiChoiceDialog = new AlertDialog.Builder(context) + AlertDialog multiChoiceDialog = MyAlertDialog.build(context) .setTitle(title) + .setCancelable(false) .setMultiChoiceItems(items, checkedItems, (dialog, which, isChecked) -> { - onMultiDialogListener.onItemClick(dialog, which, isChecked); + if (onMultiDialogListener != null) { + onMultiDialogListener.onItemClick(dialog, which, isChecked); + } if(isChecked){ this.checkedCount++; }else { @@ -57,7 +61,9 @@ public class MultiChoiceDialog { checkedItems[i] = false; itemList.setItemChecked(i, false); } - onMultiDialogListener.onSelectAll(false); + if (onMultiDialogListener != null) { + onMultiDialogListener.onSelectAll(false); + } } else { this.checkedCount = itemsCount; selectAll.setText("取消全选"); @@ -65,7 +71,9 @@ public class MultiChoiceDialog { checkedItems[i] = true; itemList.setItemChecked(i, true); } - onMultiDialogListener.onSelectAll(true); + if (onMultiDialogListener != null) { + onMultiDialogListener.onSelectAll(true); + } } }); diff --git a/app/src/main/java/xyz/fycz/myreader/creator/MyAlertDialog.java b/app/src/main/java/xyz/fycz/myreader/creator/MyAlertDialog.java new file mode 100644 index 0000000..b8f748c --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/creator/MyAlertDialog.java @@ -0,0 +1,15 @@ +package xyz.fycz.myreader.creator; + +import android.content.Context; +import androidx.appcompat.app.AlertDialog; +import xyz.fycz.myreader.R; + +/** + * @author fengyue + * @date 2020/9/20 9:48 + */ +public class MyAlertDialog { + public static AlertDialog.Builder build(Context context){ + return new AlertDialog.Builder(context, R.style.alertDialogTheme); + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/entity/Setting.java b/app/src/main/java/xyz/fycz/myreader/entity/Setting.java index fb1c9d5..c4dd0ea 100644 --- a/app/src/main/java/xyz/fycz/myreader/entity/Setting.java +++ b/app/src/main/java/xyz/fycz/myreader/entity/Setting.java @@ -51,6 +51,8 @@ public class Setting implements Serializable { private boolean refreshWhenStart;//打开软件自动更新书籍 + private boolean openBookStore;//是否开启书城 + private int settingVersion;//设置版本号 public int getAutoScrollSpeed() { @@ -212,4 +214,12 @@ public class Setting implements Serializable { public void setRefreshWhenStart(boolean refreshWhenStart) { this.refreshWhenStart = refreshWhenStart; } + + public boolean isOpenBookStore() { + return openBookStore; + } + + public void setOpenBookStore(boolean openBookStore) { + this.openBookStore = openBookStore; + } } diff --git a/app/src/main/java/xyz/fycz/myreader/entity/bookstore/QDBook.java b/app/src/main/java/xyz/fycz/myreader/entity/bookstore/QDBook.java new file mode 100644 index 0000000..0191092 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/entity/bookstore/QDBook.java @@ -0,0 +1,80 @@ +package xyz.fycz.myreader.entity.bookstore; + +/** + * @author fengyue + * @date 2020/9/18 20:46 + */ +public class QDBook { + protected String bid; + protected String bName; + protected String bAuth; + protected String img; + protected String cat; + protected int catId; + protected String cnt; + protected String desc; + + public String getBid() { + return bid; + } + + public void setBid(String bid) { + this.bid = bid; + } + + public String getbName() { + return bName; + } + + public void setbName(String bName) { + this.bName = bName; + } + + public String getbAuth() { + return bAuth; + } + + public void setbAuth(String bAuth) { + this.bAuth = bAuth; + } + + public String getImg() { + return img; + } + + public void setImg(String img) { + this.img = img; + } + + public String getCat() { + return cat; + } + + public void setCat(String cat) { + this.cat = cat; + } + + public int getCatId() { + return catId; + } + + public void setCatId(int catId) { + this.catId = catId; + } + + public String getCnt() { + return cnt; + } + + public void setCnt(String cnt) { + this.cnt = cnt; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/entity/bookstore/RankBook.java b/app/src/main/java/xyz/fycz/myreader/entity/bookstore/RankBook.java new file mode 100644 index 0000000..8c11102 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/entity/bookstore/RankBook.java @@ -0,0 +1,38 @@ +package xyz.fycz.myreader.entity.bookstore; + +/** + * @author fengyue + * @date 2020/9/16 22:56 + */ +public class RankBook extends QDBook{ + /*bAuth: "净无痕" + bName: "伏天氏" + bid: "1011058239" + cat: "玄幻" + catId: 21 + cnt: "636.1万字" + desc: "东方神州,有人皇立道统,有圣贤宗门传道,有诸侯雄踞一方王国,诸强林立,神州动乱千万载,值此之时,一代天骄叶青帝及东凰大帝横空出世,东方神州一统!然,叶青帝忽然暴毙,世间雕像尽皆被毁,于世间除名,沦为禁忌;从此神州唯东凰大帝独尊!十五年后,东海青州城,一名为叶伏天的少年,开启了他的传奇之路…" + rankCnt: "5996月票" + rankNum: 21*/ + + + private String rankCnt; + private int rankNum; + + + public String getRankCnt() { + return rankCnt; + } + + public void setRankCnt(String rankCnt) { + this.rankCnt = rankCnt; + } + + public int getRankNum() { + return rankNum; + } + + public void setRankNum(int rankNum) { + this.rankNum = rankNum; + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/entity/bookstore/SortBook.java b/app/src/main/java/xyz/fycz/myreader/entity/bookstore/SortBook.java new file mode 100644 index 0000000..c2d7929 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/entity/bookstore/SortBook.java @@ -0,0 +1,27 @@ +package xyz.fycz.myreader.entity.bookstore; + +/** + * @author fengyue + * @date 2020/9/18 20:43 + */ +public class SortBook extends QDBook{ + /*bAuth: "老鸡吃蘑菇" + bName: "全世界都不知道我多强" + bid: 1021781295 + cat: "玄幻" + catId: 21 + cid: 406957810 + cnt: "72.68万字" + desc: "【日更过万,质量保证!】当梁凡从地底爬出来之后,才发现不是变秃才能变强!我要控制我自己,要是不小心一拳打爆这个星球怎么办?安静的隐藏在世俗,全世界都不知道我有多强,虽然这个世界妖魔鬼怪很变态,但苟着享" + state: "连载"*/ + + private String state; + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/enums/BookSource.java b/app/src/main/java/xyz/fycz/myreader/enums/BookSource.java index 560f91c..4c7fe71 100644 --- a/app/src/main/java/xyz/fycz/myreader/enums/BookSource.java +++ b/app/src/main/java/xyz/fycz/myreader/enums/BookSource.java @@ -12,6 +12,7 @@ public enum BookSource { biquge44("笔趣阁44"), pinshu("品书网"), biquge("笔趣阁"), + qb5("全本小说"), local("本地书籍"); public String text; @@ -19,6 +20,15 @@ public enum BookSource { this.text = text; } + public static String getFromName(String name){ + for (BookSource bookSource : BookSource.values()){ + if (bookSource.text.equals(name)){ + return bookSource.toString(); + } + } + return null; + } + public static BookSource get(int var0) { return values()[var0]; } diff --git a/app/src/main/java/xyz/fycz/myreader/enums/FindType.java b/app/src/main/java/xyz/fycz/myreader/enums/FindType.java new file mode 100644 index 0000000..02c5704 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/enums/FindType.java @@ -0,0 +1,40 @@ +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"), + qidianns("排行榜[起点女生网]", "https://www.qidian.com/mm/rank"), + qb5("书城[全本小说]", "https://www.qb5.tw"), + biquge("书城[笔趣阁]", "https://www.52bqg.com"); + private String text; + private String url; + private static final long serialVersionUID = 1L; + + FindType(String text, String url) { + this.text = text; + this.url = url; + } + + public static FindType get(int var0) { + return values()[var0]; + } + + public static FindType fromString(String string) { + return valueOf(string); + } + + public String getText() { + return text; + } + + public String getUrl() { + return url; + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/Book.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/Book.java index 534d727..50c510f 100644 --- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/Book.java +++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/Book.java @@ -60,14 +60,19 @@ public class Book implements Serializable { @Nullable private boolean isDownLoadAll = true;//是否一键缓存 - @Generated(hash = 1839780644) + private String groupId;//分组id + + private int groupSort;//分组排序 + + @Generated(hash = 1308680987) public Book(String id, String name, String chapterUrl, 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) { + boolean isCloseUpdate, boolean isDownLoadAll, String groupId, + int groupSort) { this.id = id; this.name = name; this.chapterUrl = chapterUrl; @@ -88,6 +93,8 @@ public class Book implements Serializable { this.source = source; this.isCloseUpdate = isCloseUpdate; this.isDownLoadAll = isDownLoadAll; + this.groupId = groupId; + this.groupSort = groupSort; } public Book(Book book) { @@ -111,6 +118,7 @@ public class Book implements Serializable { this.source = book.source; this.isCloseUpdate = book.isCloseUpdate; this.isDownLoadAll = book.isDownLoadAll; + this.groupId = book.groupId; } @Generated(hash = 1839243756) @@ -236,6 +244,21 @@ public class Book implements Serializable { this.isCloseUpdate = isCloseUpdate; } + public boolean getIsDownLoadAll() { + return this.isDownLoadAll; + } + + public void setIsDownLoadAll(boolean isDownLoadAll) { + this.isDownLoadAll = isDownLoadAll; + } + public String getGroupId() { + return this.groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + @Override public String toString() { @@ -260,6 +283,7 @@ public class Book implements Serializable { ",\nsource='" + source + '\'' + ",\nisCloseUpdate='" + isCloseUpdate + '\'' + ",\nisDownLoadAll='" + isDownLoadAll + '\'' + + ",\ngroupId='" + groupId + '\'' + "\n}"; } @@ -279,12 +303,12 @@ public class Book implements Serializable { return Objects.hash(name, chapterUrl, author, source); } - public boolean getIsDownLoadAll() { - return this.isDownLoadAll; + public int getGroupSort() { + return this.groupSort; } - public void setIsDownLoadAll(boolean isDownLoadAll) { - this.isDownLoadAll = isDownLoadAll; + public void setGroupSort(int groupSort) { + this.groupSort = groupSort; } @@ -292,4 +316,7 @@ public class Book implements Serializable { + + + } diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/BookGroup.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/BookGroup.java new file mode 100644 index 0000000..fd1c6fc --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/BookGroup.java @@ -0,0 +1,70 @@ +package xyz.fycz.myreader.greendao.entity; + +import org.greenrobot.greendao.annotation.Entity; +import org.greenrobot.greendao.annotation.Id; +import org.greenrobot.greendao.annotation.NotNull; +import org.greenrobot.greendao.annotation.Generated; + +/** + * @author fengyue + * @date 2020/9/23 22:18 + */ +@Entity +public class BookGroup { + @Id + private String id; + + @NotNull + private int num; + + @NotNull + private String name; + + private String desc; + + @Generated(hash = 1387727906) + public BookGroup(String id, int num, @NotNull String name, String desc) { + this.id = id; + this.num = num; + this.name = name; + this.desc = desc; + } + + @Generated(hash = 511810489) + public BookGroup() { + } + + public String getId() { + return this.id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDesc() { + return this.desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public int getNum() { + return this.num; + } + + public void setNum(int num) { + this.num = num; + } + + +} diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/service/BookGroupService.java b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookGroupService.java new file mode 100644 index 0000000..388776e --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookGroupService.java @@ -0,0 +1,77 @@ +package xyz.fycz.myreader.greendao.service; + +import xyz.fycz.myreader.greendao.GreenDaoManager; +import xyz.fycz.myreader.greendao.entity.BookGroup; +import xyz.fycz.myreader.greendao.gen.BookGroupDao; +import xyz.fycz.myreader.greendao.gen.BookMarkDao; +import xyz.fycz.myreader.util.StringHelper; + +import java.util.List; + +/** + * @author fengyue + * @date 2020/9/26 12:14 + */ +public class BookGroupService extends BaseService{ + private static volatile BookGroupService sInstance; + + public static BookGroupService getInstance() { + if (sInstance == null){ + synchronized (BookGroupService.class){ + if (sInstance == null){ + sInstance = new BookGroupService(); + } + } + } + return sInstance; + } + + /** + * 获取所有书籍分组 + * @return + */ + public List getAllGroups(){ + return GreenDaoManager.getInstance().getSession().getBookGroupDao() + .queryBuilder() + .orderAsc(BookGroupDao.Properties.Num) + .list(); + } + + /** + * 通过I的获取书籍分组 + * @param groupId + * @return + */ + public BookGroup getGroupById(String groupId){ + return GreenDaoManager.getInstance().getSession().getBookGroupDao() + .queryBuilder() + .where(BookGroupDao.Properties.Id.eq(groupId)) + .unique(); + } + + /** + * 添加书籍分组 + * @param bookGroup + */ + public void addBookGroup(BookGroup bookGroup){ + bookGroup.setNum(countBookGroup()); + bookGroup.setId(StringHelper.getStringRandom(25)); + addEntity(bookGroup); + } + + /** + * 删除书籍分组 + * @param bookGroup + */ + public void deleteBookGroup(BookGroup bookGroup){ + deleteEntity(bookGroup); + } + + + private int countBookGroup(){ + return (int) GreenDaoManager.getInstance().getSession().getBookGroupDao() + .queryBuilder() + .count(); + } + +} diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/service/BookMarkService.java b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookMarkService.java index c5a5da7..5d8d66e 100644 --- a/app/src/main/java/xyz/fycz/myreader/greendao/service/BookMarkService.java +++ b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookMarkService.java @@ -31,27 +31,6 @@ public class BookMarkService extends BaseService { } return sInstance; } - private ArrayList findBookMarks(String sql, String[] selectionArgs) { - ArrayList bookMarks = new ArrayList<>(); - try { - Cursor cursor = selectBySql(sql, selectionArgs); - if (cursor == null) return bookMarks; - while (cursor.moveToNext()) { - BookMark bookMark = new BookMark(); - bookMark.setId(cursor.getString(0)); - bookMark.setBookId(cursor.getString(1)); - bookMark.setNumber(cursor.getInt(2)); - bookMark.setTitle(cursor.getString(3)); - bookMark.setBookMarkChapterNum(cursor.getInt(4)); - bookMark.setBookMarkReadPosition(cursor.getInt(5)); - bookMarks.add(bookMark); - } - } catch (Exception e) { - e.printStackTrace(); - return bookMarks; - } - return bookMarks; - } /** * 通过ID查书签 @@ -69,20 +48,10 @@ public class BookMarkService extends BaseService { * @return */ public BookMark findBookMarkByTitle(String title){ - BookMark bookMark = null; - String sql = "select * from book_mark where title = ?"; - Cursor cursor = selectBySql(sql,new String[]{title}); - if (cursor == null) return null; - if (cursor.moveToNext()){ - bookMark = new BookMark(); - bookMark.setId(cursor.getString(0)); - bookMark.setBookId(cursor.getString(1)); - bookMark.setNumber(cursor.getInt(2)); - bookMark.setTitle(cursor.getString(3)); - bookMark.setBookMarkChapterNum(cursor.getInt(4)); - bookMark.setBookMarkReadPosition(cursor.getInt(5)); - } - return bookMark; + return GreenDaoManager.getInstance().getSession().getBookMarkDao() + .queryBuilder() + .where(BookMarkDao.Properties.Title.eq(title)) + .unique(); } /** * 获取书的所有书签 @@ -90,12 +59,11 @@ public class BookMarkService extends BaseService { * @return */ public List findBookAllBookMarkByBookId(String bookId) { - - if (StringHelper.isEmpty(bookId)) return new ArrayList<>(); - - String sql = "select * from book_mark where book_id = ? order by number"; - - return findBookMarks(sql, new String[]{bookId}); + return GreenDaoManager.getInstance().getSession().getBookMarkDao() + .queryBuilder() + .where(BookMarkDao.Properties.BookId.eq(bookId)) + .orderAsc(BookMarkDao.Properties.Number) + .list(); } @@ -155,7 +123,7 @@ public class BookMarkService extends BaseService { * @return */ public int countBookMarkTotalNumByBookId(String bookId){ - int num = 0; + /*int num = 0; try { Cursor cursor = selectBySql("select count(*) n from book where book_id = " + bookId,null); if (cursor.moveToNext()){ @@ -163,8 +131,12 @@ public class BookMarkService extends BaseService { } } catch (Exception e) { e.printStackTrace(); - } - return num; + }*/ + + return (int) GreenDaoManager.getInstance().getSession().getBookMarkDao() + .queryBuilder() + .where(BookMarkDao.Properties.BookId.eq(bookId)) + .count(); } /** diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/service/BookService.java b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookService.java index 338dec0..ba4346d 100644 --- a/app/src/main/java/xyz/fycz/myreader/greendao/service/BookService.java +++ b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookService.java @@ -10,6 +10,7 @@ import xyz.fycz.myreader.application.SysManager; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.greendao.entity.Chapter; import xyz.fycz.myreader.greendao.gen.BookDao; +import xyz.fycz.myreader.greendao.gen.ChapterDao; import xyz.fycz.myreader.util.*; import xyz.fycz.myreader.greendao.GreenDaoManager; import xyz.fycz.myreader.greendao.entity.Book; @@ -50,39 +51,6 @@ public class BookService extends BaseService { return sInstance; } - private List findBooks(String sql, String[] selectionArgs) { - ArrayList books = new ArrayList<>(); - try { - Cursor cursor = selectBySql(sql, selectionArgs); - while (cursor.moveToNext()) { - Book book = new Book(); - book.setId(cursor.getString(0)); - book.setName(cursor.getString(1)); - book.setChapterUrl(cursor.getString(2)); - book.setImgUrl(cursor.getString(3)); - book.setDesc(cursor.getString(4)); - book.setAuthor(cursor.getString(5)); - book.setType(cursor.getString(6)); - book.setUpdateDate(cursor.getString(7)); - book.setNewestChapterId(cursor.getString(8)); - book.setNewestChapterTitle(cursor.getString(9)); - book.setNewestChapterUrl(cursor.getString(10)); - book.setHistoryChapterId(cursor.getString(11)); - book.setHisttoryChapterNum(cursor.getInt(12)); - book.setSortCode(cursor.getInt(13)); - book.setNoReadNum(cursor.getInt(14)); - book.setChapterTotalNum(cursor.getInt(15)); - book.setLastReadPosition(cursor.getInt(16)); - book.setSource(cursor.getString(17)); - book.setIsCloseUpdate(cursor.getShort(18) != 0); - book.setIsDownLoadAll(cursor.getShort(19) != 0); - books.add(book); - } - } catch (Exception e) { - e.printStackTrace(); - } - return books; - } /** * 通过ID查书 @@ -101,8 +69,26 @@ public class BookService extends BaseService { * @return */ public List getAllBooks() { - String sql = "select * from book order by sort_code"; - return findBooks(sql, null); + return GreenDaoManager.getInstance().getSession().getBookDao() + .queryBuilder() + .orderAsc(BookDao.Properties.SortCode) + .list(); + } + + /** + * 获取特定分组的书 + * + * @return + */ + public List getGroupBooks(String groupId) { + if (StringHelper.isEmpty(groupId)){ + return getAllBooks(); + } + return GreenDaoManager.getInstance().getSession().getBookDao() + .queryBuilder() + .where(BookDao.Properties.GroupId.eq(groupId)) + .orderAsc(BookDao.Properties.GroupSort) + .list(); } /** @@ -112,7 +98,9 @@ public class BookService extends BaseService { */ public void addBook(Book book) { // book.setSortCode(countBookTotalNum() + 1); + book.setSortCode(0); + book.setGroupSort(0); if (StringHelper.isEmpty(book.getId())) { book.setId(StringHelper.getStringRandom(25)); } @@ -138,17 +126,10 @@ public class BookService extends BaseService { * @return */ public Book findBookByAuthorAndName(String bookName, String author) { - Book book = null; - try { - Cursor cursor = selectBySql("select id from book where author = ? and name = ?", new String[]{author, bookName}); - if (cursor.moveToNext()) { - String id = cursor.getString(0); - book = getBookById(id); - } - } catch (Exception e) { - e.printStackTrace(); - } - return book; + return GreenDaoManager.getInstance().getSession().getBookDao() + .queryBuilder() + .where(BookDao.Properties.Name.eq(bookName), BookDao.Properties.Author.eq(author)) + .unique(); } /** @@ -158,17 +139,10 @@ public class BookService extends BaseService { * @return */ public Book findBookByPath(String path) { - Book book = null; - try { - Cursor cursor = selectBySql("select id from book where CHAPTER_URL = ?", new String[]{path}); - if (cursor.moveToNext()) { - String id = cursor.getString(0); - book = getBookById(id); - } - } catch (Exception e) { - e.printStackTrace(); - } - return book; + return GreenDaoManager.getInstance().getSession().getBookDao() + .queryBuilder() + .where(BookDao.Properties.ChapterUrl.eq(path)) + .unique(); } /** diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/util/MySQLiteOpenHelper.java b/app/src/main/java/xyz/fycz/myreader/greendao/util/MySQLiteOpenHelper.java index d55651a..3afa632 100644 --- a/app/src/main/java/xyz/fycz/myreader/greendao/util/MySQLiteOpenHelper.java +++ b/app/src/main/java/xyz/fycz/myreader/greendao/util/MySQLiteOpenHelper.java @@ -34,7 +34,7 @@ public class MySQLiteOpenHelper extends DaoMaster.OpenHelper { DaoMaster.dropAllTables(db, ifExists); } }, - BookDao.class, ChapterDao.class, SearchHistoryDao.class, BookMarkDao.class + BookDao.class, ChapterDao.class, SearchHistoryDao.class, BookMarkDao.class, BookGroupDao.class ); } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java index e2b47ba..b1efd92 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java @@ -1,25 +1,28 @@ package xyz.fycz.myreader.ui.activity; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; import android.os.Bundle; -import android.widget.LinearLayout; import android.widget.TextView; +import androidx.appcompat.widget.Toolbar; import androidx.cardview.widget.CardView; import butterknife.BindView; -import butterknife.ButterKnife; import xyz.fycz.myreader.R; -import xyz.fycz.myreader.base.BaseActivity; -import xyz.fycz.myreader.ui.presenter.AboutPresenter; +import xyz.fycz.myreader.application.MyApplication; +import xyz.fycz.myreader.base.BaseActivity2; +import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.util.ShareUtils; +import xyz.fycz.myreader.util.SharedPreUtils; +import xyz.fycz.myreader.util.ToastUtils; /** * @author fengyue - * @date 2020/7/31 11:32 + * @date 2020/9/18 22:21 */ -public class AboutActivity extends BaseActivity { - - @BindView(R.id.ll_title_back) - LinearLayout llTitleBack; - @BindView(R.id.tv_title_text) - TextView tvTitleText; +public class AboutActivity extends BaseActivity2 { @BindView(R.id.tv_version_name) TextView tvVersionName; @BindView(R.id.vm_author) @@ -30,57 +33,72 @@ 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) CardView vmDisclaimer; - private AboutPresenter mAboutPresenter; - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_about); - ButterKnife.bind(this); - setStatusBar(R.color.white, false); - mAboutPresenter = new AboutPresenter(this); - mAboutPresenter.start(); - } - - - public LinearLayout getLlTitleBack() { - return llTitleBack; + protected int getContentId() { + return R.layout.activity_about; } - public TextView getTvTitleText() { - return tvTitleText; + @Override + protected void setUpToolbar(Toolbar toolbar) { + super.setUpToolbar(toolbar); + setStatusBarColor(R.color.colorPrimary, true); + getSupportActionBar().setTitle("关于"); } - public TextView getTvVersionName() { - return tvVersionName; - } - public CardView getVmAuthor() { - return vmAuthor; + @Override + protected void initWidget() { + super.initWidget(); + tvVersionName.setText("风月读书v" + MyApplication.getStrVersionName()); } - public CardView getVmShare() { - return vmShare; - } + @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("downloadLink"))); + 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")); - public CardView getVmUpdate() { - return vmUpdate; } - public CardView getVmUpdateLog() { - return vmUpdateLog; + void openIntent(String intentName, String address) { + try { + Intent intent = new Intent(intentName); + intent.setData(Uri.parse(address)); + startActivity(intent); + } catch (Exception e) { + ToastUtils.showError(e.getLocalizedMessage()); + } } - public CardView getVmGit() { - return vmGit; - } - public CardView getVmDisclaimer() { - return vmDisclaimer; - } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java index 957b559..f83a396 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java @@ -2,6 +2,7 @@ package xyz.fycz.myreader.ui.activity; import android.annotation.SuppressLint; import android.content.Intent; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.Handler; @@ -9,6 +10,7 @@ import android.os.Message; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.view.WindowManager; import android.widget.*; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.Toolbar; @@ -17,7 +19,9 @@ 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.load.resource.bitmap.RoundedCorners; +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; import com.bumptech.glide.request.RequestOptions; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; @@ -25,7 +29,9 @@ import xyz.fycz.myreader.application.SysManager; import xyz.fycz.myreader.base.BaseActivity2; import xyz.fycz.myreader.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; +import xyz.fycz.myreader.creator.MyAlertDialog; import xyz.fycz.myreader.util.ToastUtils; +import xyz.fycz.myreader.util.utils.BlurTransformation; import xyz.fycz.myreader.webapi.crawler.BookInfoCrawler; import xyz.fycz.myreader.webapi.crawler.ReadCrawler; import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; @@ -50,6 +56,8 @@ import java.util.ArrayList; public class BookDetailedActivity extends BaseActivity2 { @BindView(R.id.book_detail_iv_cover) ImageView mIvCover; + /* @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) @@ -108,6 +116,7 @@ public class BookDetailedActivity extends BaseActivity2 { DialogCreator.createTipDialog(BookDetailedActivity.this, "未搜索到该书籍,书源加载失败!"); break; case 4: + pbLoading.setVisibility(View.GONE); initOtherInfo(); break; } @@ -139,6 +148,7 @@ public class BookDetailedActivity extends BaseActivity2 { @Override protected void setUpToolbar(Toolbar toolbar) { super.setUpToolbar(toolbar); + //getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); setStatusBarColor(R.color.colorPrimary, true); getSupportActionBar().setTitle(mBook.getName()); } @@ -230,22 +240,29 @@ public class BookDetailedActivity extends BaseActivity2 { } assert mBook.getNewestChapterTitle() != null; mTvDesc.setText(""); - mTvType.setText(""); + if (mBook.getType() != null) { + mTvType.setText(mBook.getType()); + } else { + mTvType.setText(""); + } if (!"null".equals(mBook.getSource())) { mTvSource.setText("书源:" + BookSource.fromString(mBook.getSource()).text); } ReadCrawler rc = ReadCrawlerUtil.getReadCrawler(mBook.getSource()); if (rc instanceof BookInfoCrawler && StringHelper.isEmpty(mBook.getImgUrl())) { + pbLoading.setVisibility(View.VISIBLE); BookInfoCrawler bic = (BookInfoCrawler) rc; CommonApi.getBookInfo(mBook, bic, new ResultCallback() { @Override public void onFinish(Object o, int code) { - mHandler.sendMessage(mHandler.obtainMessage(4)); + if (!MyApplication.isDestroy(BookDetailedActivity.this)) { + mHandler.sendMessage(mHandler.obtainMessage(4)); + } } @Override public void onError(Exception e) { - + ToastUtils.showError("书籍详情加载失败!"); } }); } else { @@ -267,9 +284,22 @@ public class BookDetailedActivity extends BaseActivity2 { //设置圆角 .apply(RequestOptions.bitmapTransform(new RoundedCorners(8))) .into(mIvCover); + /*Glide.with(this) + .load(mBook.getImgUrl()) + .transition(DrawableTransitionOptions.withCrossFade(1500)) + .thumbnail(defaultCover()) + .centerCrop() + .apply(RequestOptions.bitmapTransform(new BlurTransformation(this, 25))) + .into(mIvBlurCover);*/ } } + private RequestBuilder defaultCover() { + return Glide.with(this) + .load(R.mipmap.no_image) + .apply(RequestOptions.bitmapTransform(new BlurTransformation(this, 25))); + } + /** * 创建换源对话框 */ @@ -290,7 +320,7 @@ public class BookDetailedActivity extends BaseActivity2 { } } final int finalCheckedItem = checkedItem; - AlertDialog dialog = new AlertDialog.Builder(this) + AlertDialog dialog = MyAlertDialog.build(this) .setTitle("切换书源") .setCancelable(true) .setSingleChoiceItems(sources, checkedItem, (dialog1, which) -> { @@ -314,7 +344,7 @@ public class BookDetailedActivity extends BaseActivity2 { String tip = null; if (SysManager.getSetting().isMatchChapter()) { tip = getString(R.string.change_source_tip1); - }else { + } else { tip = getString(R.string.change_source_tip2); } DialogCreator.createTipDialog(this, tip); diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/BookstoreActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/BookstoreActivity.java new file mode 100644 index 0000000..926757c --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/BookstoreActivity.java @@ -0,0 +1,420 @@ +package xyz.fycz.myreader.ui.activity; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.ProgressBar; +import androidx.appcompat.widget.Toolbar; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import butterknife.BindView; +import com.scwang.smartrefresh.layout.SmartRefreshLayout; +import xyz.fycz.myreader.R; +import xyz.fycz.myreader.application.MyApplication; +import xyz.fycz.myreader.base.BaseActivity2; +import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.common.APPCONST; +import xyz.fycz.myreader.creator.ChangeSourceDialog; +import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.entity.bookstore.BookType; +import xyz.fycz.myreader.entity.bookstore.QDBook; +import xyz.fycz.myreader.entity.bookstore.RankBook; +import xyz.fycz.myreader.entity.bookstore.SortBook; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.greendao.service.BookService; +import xyz.fycz.myreader.ui.adapter.BookStoreBookAdapter; +import xyz.fycz.myreader.ui.adapter.BookStoreBookTypeAdapter; +import xyz.fycz.myreader.util.SharedPreUtils; +import xyz.fycz.myreader.util.ToastUtils; +import xyz.fycz.myreader.webapi.BookStoreApi; +import xyz.fycz.myreader.webapi.crawler.FindCrawler; +import xyz.fycz.myreader.webapi.crawler.find.ABC; +import xyz.fycz.myreader.widget.RefreshLayout; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author fengyue + * @date 2020/9/13 21:11 + */ +public class BookstoreActivity extends BaseActivity2 { + @BindView(R.id.refresh_layout) + RefreshLayout mRlRefresh; + @BindView(R.id.rv_type_list) + RecyclerView rvTypeList; + @BindView(R.id.rv_book_list) + RecyclerView rvBookList; + @BindView(R.id.srl_book_list) + SmartRefreshLayout srlBookList; + @BindView(R.id.pb_loading) + ProgressBar pbLoading; + + private FindCrawler findCrawler; + private LinearLayoutManager mLinearLayoutManager; + private BookStoreBookTypeAdapter mBookStoreBookTypeAdapter; + private List mBookTypes; + + private BookStoreBookAdapter mBookStoreBookAdapter; + private List bookList = new ArrayList<>(); + + private BookType curType; + + private int page = 1; + + private String title = ""; + + @SuppressLint("HandlerLeak") + private Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (!MyApplication.isDestroy(BookstoreActivity.this)) { + switch (msg.what) { + case 1: + initTypeList(); + mRlRefresh.showFinish(); + break; + case 2: + List bookList = (List) msg.obj; + initBookList(bookList); + srlBookList.setEnableRefresh(true); + srlBookList.setEnableLoadMore(true); + pbLoading.setVisibility(View.GONE); + break; + case 3: + pbLoading.setVisibility(View.VISIBLE); + break; + case 4: + pbLoading.setVisibility(View.GONE); + srlBookList.finishRefresh(false); + srlBookList.finishLoadMore(false); + break; + case 5: + mRlRefresh.showError(); + break; + case 6: + DialogCreator.createTipDialog(BookstoreActivity.this, + getResources().getString(R.string.top_sort_tip, title)); + break; + } + } + } + }; + + @Override + protected int getContentId() { + return R.layout.actiity_bookstore; + } + + @Override + protected void setUpToolbar(Toolbar toolbar) { + super.setUpToolbar(toolbar); + setStatusBarColor(R.color.colorPrimary, true); + String subTitle = ""; + if (findCrawler != null) { + String name = findCrawler.getFindName(); + title = name.substring(0, name.indexOf("[")); + subTitle = name.substring(name.indexOf("[") + 1, name.length() - 1); + } + getSupportActionBar().setTitle(title); + getSupportActionBar().setSubtitle(subTitle); + } + + @Override + protected void initData(Bundle savedInstanceState) { + super.initData(savedInstanceState); + findCrawler = (FindCrawler) getIntent().getSerializableExtra(APPCONST.FIND_CRAWLER); + } + + @Override + protected void initWidget() { + super.initWidget(); + srlBookList.setEnableRefresh(false); + srlBookList.setEnableLoadMore(false); + //小说列表下拉加载更多事件 + srlBookList.setOnLoadMoreListener(refreshLayout -> { + page++; + getBooksData(); + }); + + //小说列表上拉刷新事件 + srlBookList.setOnRefreshListener(refreshLayout -> { + page = 1; + getBooksData(); + }); + + mBookStoreBookAdapter = new BookStoreBookAdapter(findCrawler.hasImg(), this); + rvBookList.setLayoutManager(new LinearLayoutManager(this)); + rvBookList.setAdapter(mBookStoreBookAdapter); + mRlRefresh.setOnReloadingListener(this::getData); + } + + @Override + protected void initClick() { + super.initClick(); + mBookStoreBookAdapter.setOnItemClickListener((view, pos) -> { + Book book = bookList.get(pos); + if (!findCrawler.hasImg()) { + goToBookDetail(book); + } else { + if (BookService.getInstance().isBookCollected(book)) { + goToBookDetail(book); + return; + } + mHandler.sendMessage(mHandler.obtainMessage(3)); + ChangeSourceDialog csd = new ChangeSourceDialog(this, book); + csd.initOneBook(new ResultCallback() { + @Override + public void onFinish(Object o, int code) { + Book searchBook = (Book) o; + book.setChapterUrl(searchBook.getChapterUrl()); + book.setSource(searchBook.getSource()); + goToBookDetail(book); + mHandler.sendMessage(mHandler.obtainMessage(4)); + } + + @Override + public void onError(Exception e) { + DialogCreator.createTipDialog(BookstoreActivity.this, "未搜索到该书籍,无法进入书籍详情!"); + mHandler.sendMessage(mHandler.obtainMessage(4)); + } + }); + } + }); + } + + @Override + protected void processLogic() { + super.processLogic(); + getData(); + if (findCrawler.hasImg()) { + SharedPreUtils spu = SharedPreUtils.getInstance(); + boolean isReadTopTip = spu.getBoolean("isReadTopTip", false); + if (!isReadTopTip) { + DialogCreator.createCommonDialog(this, "提示", getResources().getString(R.string.top_sort_tip, title), + true, "知道了", "不再提示", null, + (dialog, which) -> spu.putBoolean("isReadTopTip", true)); + } + } + } + + /** + * 获取页面数据 + */ + private void getData() { + if (findCrawler instanceof ABC) { + SharedPreUtils spu = SharedPreUtils.getInstance(); + if (spu.getString("qdCookie", "").equals("")) { + ((ABC) findCrawler).initCookie(this, new ResultCallback() { + @Override + public void onFinish(Object o, int code) { + spu.putString("qdCookie", (String) o); + mBookTypes = ((ABC) findCrawler).getRankTypes(); + curType = mBookTypes.get(0); + mHandler.sendMessage(mHandler.obtainMessage(1)); + page = 1; + getBooksData(); + } + + @Override + public void onError(Exception e) { + mRlRefresh.showError(); + e.printStackTrace(); + } + }); + } else { + mBookTypes = ((ABC) findCrawler).getRankTypes(); + curType = mBookTypes.get(0); + mHandler.sendMessage(mHandler.obtainMessage(1)); + page = 1; + getBooksData(); + } + } else { + BookStoreApi.getBookTypeList(findCrawler, new ResultCallback() { + @Override + public void onFinish(Object o, int code) { + mBookTypes = (ArrayList) o; + curType = mBookTypes.get(0); + mHandler.sendMessage(mHandler.obtainMessage(1)); + page = 1; + getBooksData(); + } + + @Override + public void onError(Exception e) { + e.printStackTrace(); + mHandler.sendEmptyMessage(5); + } + }); + } + + } + + /** + * 获取小数列表数据 + */ + private void getBooksData() { + if (findCrawler.getTypePage(curType, page)) { + srlBookList.finishLoadMoreWithNoMoreData(); + return; + } + + mHandler.sendEmptyMessage(3); + if (findCrawler instanceof ABC) { + ((ABC) findCrawler).getRankBooks(curType, new ResultCallback() { + @Override + public void onFinish(Object o, int code) { + List books = new ArrayList<>(); + for (QDBook rb : (List) o) { + Book book = new Book(); + book.setName(rb.getbName()); + book.setAuthor(rb.getbAuth()); + book.setImgUrl(rb.getImg()); + String cat = rb.getCat(); + book.setType(cat.contains("小说") || cat.length() >= 4 ? cat : cat + "小说"); + book.setNewestChapterTitle(rb.getDesc()); + book.setDesc(rb.getDesc()); + if (rb instanceof RankBook) { + boolean hasRankCnt = !((RankBook) rb).getRankCnt().equals("null") && + MyApplication.isApkInDebug(BookstoreActivity.this); + book.setUpdateDate(hasRankCnt ? book.getType() + "-" + rb.getCnt() : rb.getCnt()); + book.setNewestChapterId(hasRankCnt ? ((RankBook) rb).getRankCnt() : book.getType()); + } else if (rb instanceof SortBook) { + book.setUpdateDate(rb.getCnt()); + book.setNewestChapterId(((SortBook) rb).getState()); + } + books.add(book); + } + mHandler.sendMessage(mHandler.obtainMessage(2, books)); + } + + @Override + public void onError(Exception e) { + mHandler.sendMessage(mHandler.obtainMessage(4)); + ToastUtils.showError("数据加载失败!\n" + e.getMessage()); + e.printStackTrace(); + } + }); + } else { + BookStoreApi.getBookRankList(curType.getUrl(), findCrawler, new ResultCallback() { + @Override + public void onFinish(Object o, int code) { + mHandler.sendMessage(mHandler.obtainMessage(2, o)); + } + + @Override + public void onError(Exception e) { + mHandler.sendMessage(mHandler.obtainMessage(4)); + ToastUtils.showError("数据加载失败!\n" + e.getMessage()); + e.printStackTrace(); + } + }); + } + } + + + /** + * 初始化类别列表 + */ + private void initTypeList() { + + //设置布局管理器 + mLinearLayoutManager = new LinearLayoutManager(this); + mLinearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + rvTypeList.setLayoutManager(mLinearLayoutManager); + mBookStoreBookTypeAdapter = new BookStoreBookTypeAdapter(this, mBookTypes); + rvTypeList.setAdapter(mBookStoreBookTypeAdapter); + + //点击事件 + mBookStoreBookTypeAdapter.setOnItemClickListener((pos, view) -> { + if (curType.equals(mBookTypes.get(pos))) { + return; + } + page = 1; + curType = mBookTypes.get(pos); + srlBookList.resetNoMoreData(); + getBooksData(); + }); + + + } + + + /** + * 初始化小说列表 + */ + private void initBookList(List bookList) { + if (page == 1) { + mBookStoreBookAdapter.refreshItems(bookList); + this.bookList.clear(); + this.bookList.addAll(bookList); + rvBookList.scrollToPosition(0); + } else { + this.bookList.addAll(bookList); + mBookStoreBookAdapter.addItems(bookList); + } + + //刷新动作完成 + srlBookList.finishRefresh(); + //加载更多完成 + srlBookList.finishLoadMore(); + + } + + /** + * 前往书籍详情 + * + * @param book + */ + private void goToBookDetail(Book book) { + Intent intent = new Intent(this, BookDetailedActivity.class); + intent.putExtra(APPCONST.BOOK, book); + BookstoreActivity.this.startActivity(intent); + } + + /********************************Event***************************************/ + /** + * 创建菜单 + * + * @param menu + * @return + */ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_store, menu); + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + if (findCrawler.hasImg()) { + menu.findItem(R.id.action_tip).setVisible(true); + } + return true; + } + + /** + * 导航栏菜单点击事件 + * + * @param item + * @return + */ + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_tip: + mHandler.sendEmptyMessage(6); + return true; + case R.id.action_refresh: + mRlRefresh.showLoading(); + getData(); + return true; + } + return false; + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/CatalogActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/CatalogActivity.java index f20122e..06c6efb 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/CatalogActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/CatalogActivity.java @@ -1,77 +1,117 @@ package xyz.fycz.myreader.ui.activity; import android.os.Bundle; -import android.widget.EditText; -import android.widget.ImageView; -import android.widget.RelativeLayout; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import androidx.appcompat.widget.SearchView; +import androidx.appcompat.widget.Toolbar; import androidx.viewpager.widget.ViewPager; import butterknife.BindView; -import butterknife.ButterKnife; import com.google.android.material.tabs.TabLayout; import xyz.fycz.myreader.R; -import xyz.fycz.myreader.base.BaseActivity; -import xyz.fycz.myreader.ui.presenter.CatalogActivityPresenter; +import xyz.fycz.myreader.base.BaseActivity2; +import xyz.fycz.myreader.common.APPCONST; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.ui.adapter.TabFragmentPageAdapter; +import xyz.fycz.myreader.ui.fragment.BookMarkFragment; +import xyz.fycz.myreader.ui.fragment.CatalogFragment; /** - * @author fengyue - * @date 2020/7/22 8:04 + * 书籍目录activity */ -public class CatalogActivity extends BaseActivity { - @BindView(R.id.tl_tab_menu) - TabLayout tlTabMenu; - @BindView(R.id.iv_search) - ImageView ivSearch; - @BindView(R.id.rl_common_title) - RelativeLayout rlCommonTitle; - @BindView(R.id.vp_content) - ViewPager vpContent; - @BindView(R.id.iv_back) - ImageView tvBack; - - @BindView(R.id.et_search) - EditText etSearch; - @BindView(R.id.iv_cancel) - ImageView ivCancel; - - - private CatalogActivityPresenter mCatalogPresenter; +public class CatalogActivity extends BaseActivity2 { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_catalog); - ButterKnife.bind(this); - setStatusBar(0, false); - mCatalogPresenter = new CatalogActivityPresenter(this); - mCatalogPresenter.start(); - } - public TabLayout getTlTabMenu() { - return tlTabMenu; + @BindView(R.id.catalog_tab) + TabLayout catalogTab; + @BindView(R.id.toolbar) + Toolbar toolbar; + @BindView(R.id.catalog_vp) + ViewPager viewPager; + private SearchView searchView; + + private Book mBook; + + private TabFragmentPageAdapter tabAdapter; + + /*******************Public**********************************/ + + public Book getmBook() { + return mBook; } - public ImageView getIvSearch() { - return ivSearch; + /*********************Initialization****************************/ + + + @Override + protected void initData(Bundle savedInstanceState) { + super.initData(savedInstanceState); + mBook = (Book) getIntent().getSerializableExtra(APPCONST.BOOK); } - public RelativeLayout getRlCommonTitle() { - return rlCommonTitle; + @Override + protected int getContentId() { + return R.layout.activity_catalog; } - public ViewPager getVpContent() { - return vpContent; + @Override + protected void setUpToolbar(Toolbar toolbar) { + super.setUpToolbar(toolbar); + setStatusBarColor(R.color.colorPrimary, true); + tabAdapter = new TabFragmentPageAdapter(getSupportFragmentManager()); + tabAdapter.addFragment(new CatalogFragment(), "目录"); + tabAdapter.addFragment(new BookMarkFragment(), "书签"); } - public ImageView getTvBack() { - return tvBack; + @Override + protected void initWidget() { + super.initWidget(); + viewPager.setAdapter(tabAdapter); + viewPager.setOffscreenPageLimit(2); + catalogTab.setupWithViewPager(viewPager); } - public EditText getEtSearch() { - return etSearch; + /*************************************************************************/ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.menu_view_search, menu); + MenuItem search = menu.findItem(R.id.action_search); + searchView = (SearchView) search.getActionView(); + searchView.setMaxWidth(getResources().getDisplayMetrics().widthPixels); + searchView.onActionViewCollapsed(); + searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String query) { + return false; + } + + @Override + public boolean onQueryTextChange(String newText) { + switch (viewPager.getCurrentItem()){ + case 0: + ((CatalogFragment) tabAdapter.getItem(0)).getmCatalogPresent().startSearch(newText); + break; + case 1: + ((BookMarkFragment) tabAdapter.getItem(1)).getmBookMarkPresenter().startSearch(newText); + break; + } + return false; + } + }); + return super.onCreateOptionsMenu(menu); } - public ImageView getIvCancel() { - return ivCancel; + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.home: + + return true; + } + return super.onOptionsItemSelected(item); } + } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/FileSystemActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/FileSystemActivity.java index 554f0b6..bd4b330 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/FileSystemActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/FileSystemActivity.java @@ -81,7 +81,7 @@ public class FileSystemActivity extends BaseTabActivity { @Override protected void setUpToolbar(Toolbar toolbar) { super.setUpToolbar(toolbar); - setStatusBarColor(R.color.white, false); + setStatusBarColor(R.color.colorPrimary, true); getSupportActionBar().setTitle("添加本地"); } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/FontsActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/FontsActivity.java index 0fd869e..91c6353 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/FontsActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/FontsActivity.java @@ -1,49 +1,135 @@ package xyz.fycz.myreader.ui.activity; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.view.View; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; - -import xyz.fycz.myreader.R; -import xyz.fycz.myreader.base.BaseActivity; - -import butterknife.ButterKnife; +import androidx.appcompat.widget.Toolbar; import butterknife.BindView; +import xyz.fycz.myreader.R; +import xyz.fycz.myreader.base.BaseActivity2; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.ui.presenter.FontsPresenter; +import xyz.fycz.myreader.enums.Font; +import xyz.fycz.myreader.ui.adapter.FontsAdapter; +import xyz.fycz.myreader.util.IOUtils; +import xyz.fycz.myreader.util.ToastUtils; +import xyz.fycz.myreader.util.utils.FileUtils; -import static xyz.fycz.myreader.util.UriFileUtil.getPath; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; -public class FontsActivity extends BaseActivity { +import static xyz.fycz.myreader.util.UriFileUtil.getPath; - @BindView(R.id.ll_title_back) - LinearLayout llTitleBack; - @BindView(R.id.tv_title_text) - TextView tvTitleText; - @BindView(R.id.system_title) - LinearLayout systemTitle; +/** + * @author fengyue + * @date 2020/9/19 12:04 + */ +public class FontsActivity extends BaseActivity2 { @BindView(R.id.lv_fonts) ListView lvFonts; @BindView(R.id.pb_loading) ProgressBar pbLoading; + private ArrayList mFonts; + private FontsAdapter mFontsAdapter; - private FontsPresenter mFontsPresenter; + @SuppressLint("HandlerLeak") + private Handler mHandler = new Handler(){ + @Override + public void handleMessage(Message msg) { + switch (msg.what){ + case 1: + initWidget(); + break; + } + } + }; @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_fonts); - ButterKnife.bind(this); - setStatusBar(R.color.white, false); - mFontsPresenter = new FontsPresenter(this); - mFontsPresenter.start(); + protected int getContentId() { + return R.layout.activity_fonts; } + @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); + initFonts(); + } + + @Override + protected void initWidget() { + super.initWidget(); + mFontsAdapter = new FontsAdapter(this, R.layout.listview_font_item, mFonts, this); + lvFonts.setAdapter(mFontsAdapter); + pbLoading.setVisibility(View.GONE); + } + + 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.本地字体); + } + + public void saveLocalFont(String path){ + File fontFile = new File(path); + if (!fontFile.exists()){ + ToastUtils.showWarring("未找到字体文件!"); + return; + } + String fontName = fontFile.getName(); + if (!fontName.endsWith(".ttf")){ + ToastUtils.showError("字体更换失败,请选择ttf格式的字体文件!"); + return; + } + String dirPath = fontFile.getParentFile().getAbsolutePath() + "/"; + if (dirPath.equals(APPCONST.FONT_BOOK_DIR)){ + mFontsAdapter.saveLocalFontName(fontName); + return; + } + FileInputStream fis = null; + FileOutputStream fos = null; + try { + fis = new FileInputStream(fontFile); + fos = new FileOutputStream(FileUtils.getFile(APPCONST.FONT_BOOK_DIR + fontName)); + byte[] bytes = new byte[1021]; + int len = -1; + while ((len = fis.read(bytes)) != -1){ + fos.write(bytes, 0, len); + } + fos.flush(); + mFontsAdapter.saveLocalFontName(fontName); + } catch (IOException e) { + e.printStackTrace(); + ToastUtils.showError("读取字体文件出错!\n" + e.getLocalizedMessage()); + }finally { + IOUtils.close(fis, fos); + } + } + + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { String path; @@ -54,32 +140,12 @@ public class FontsActivity extends BaseActivity { }else { path = getPath(this, uri); } - mFontsPresenter.saveLocalFont(path); + saveLocalFont(path); } } @Override protected void onResume() { super.onResume(); - mFontsPresenter.notifyChange(); - } - - public ProgressBar getPbLoading() { - return pbLoading; - } - - public LinearLayout getLlTitleBack() { - return llTitleBack; - } - - public TextView getTvTitleText() { - return tvTitleText; - } - - public LinearLayout getSystemTitle() { - return systemTitle; - } - - public ListView getLvFonts() { - return lvFonts; + mFontsAdapter.notifyDataSetChanged(); } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/LoginActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/LoginActivity.java index 10c2bd0..8f5d88e 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/LoginActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/LoginActivity.java @@ -1,33 +1,44 @@ package xyz.fycz.myreader.ui.activity; -/** - * @author fengyue - * @date 2020/4/26 18:49 - */ - 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.*; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; +import androidx.appcompat.widget.Toolbar; import butterknife.BindView; -import butterknife.ButterKnife; import com.google.android.material.textfield.TextInputLayout; import xyz.fycz.myreader.R; -import xyz.fycz.myreader.base.BaseActivity; -import xyz.fycz.myreader.ui.presenter.LoginPresenter; +import xyz.fycz.myreader.backup.UserService; +import xyz.fycz.myreader.base.BaseActivity2; +import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.common.APPCONST; +import xyz.fycz.myreader.creator.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; -@SuppressLint("Registered") -public class LoginActivity extends BaseActivity implements TextWatcher { - @BindView(R.id.ll_title_back) - LinearLayout llTitleBack; - @BindView(R.id.tv_title_text) - TextView tvTitleText; +/** + * @author fengyue + * @date 2020/9/18 22:27 + */ +public class LoginActivity extends BaseActivity2 implements TextWatcher { @BindView(R.id.et_user) TextInputLayout user; @BindView(R.id.et_password) @@ -40,15 +51,122 @@ public class LoginActivity extends BaseActivity implements TextWatcher { TextInputLayout etCaptcha; @BindView(R.id.iv_captcha) ImageView ivCaptcha; - private LoginPresenter mLoginPresenter; + + 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 void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_login); - ButterKnife.bind(this); - setStatusBar(R.color.white, false); - mLoginPresenter = new LoginPresenter(this); - mLoginPresenter.start(); + 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 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); } @@ -110,37 +228,4 @@ public class LoginActivity extends BaseActivity implements TextWatcher { loginBtn.setEnabled(false); } } - - - public EditText getUser() { - return user.getEditText(); - } - - public EditText getPassword() { - return password.getEditText(); - } - - public Button getLoginBtn() { - return loginBtn; - } - - public TextView getTvTitleText() { - return tvTitleText; - } - - public LinearLayout getLlTitleBack() { - return llTitleBack; - } - - public TextView getTvRegister() { - return tvRegister; - } - - public EditText getEtCaptcha() { - return etCaptcha.getEditText(); - } - - public ImageView getIvCaptcha() { - return ivCaptcha; - } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/MainActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/MainActivity.java index 6f4b063..21ef4f2 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/MainActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/MainActivity.java @@ -1,77 +1,260 @@ package xyz.fycz.myreader.ui.activity; - import android.content.Intent; import android.content.pm.PackageManager; 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; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; import androidx.core.content.FileProvider; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.TextView; - +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentPagerAdapter; import androidx.viewpager.widget.ViewPager; -import com.google.android.material.tabs.TabLayout; +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.base.BaseActivity; +import xyz.fycz.myreader.application.SysManager; +import xyz.fycz.myreader.base.BaseActivity2; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.creator.DialogCreator; -import xyz.fycz.myreader.custom.CircleImageView; -import xyz.fycz.myreader.ui.presenter.MainPresenter; - -import butterknife.BindView; -import butterknife.ButterKnife; +import xyz.fycz.myreader.ui.fragment.BookStoreFragment; +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.ui.presenter.BookcasePresenter; +import xyz.fycz.myreader.util.SharedPreUtils; import xyz.fycz.myreader.util.ToastUtils; import java.io.File; +import java.util.ArrayList; +import java.util.List; -import static xyz.fycz.myreader.util.UriFileUtil.getPath; +import static androidx.fragment.app.FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT; +import static xyz.fycz.myreader.application.MyApplication.checkVersionByServer; +/** + * @author fengyue + * @date 2020/9/13 13:03 + */ +public class MainActivity extends BaseActivity2 { + @BindView(R.id.bottom_navigation_view) + BottomNavigationView bottomNavigation; + @BindView(R.id.view_pager_main) + ViewPager viewPagerMain; -public class MainActivity extends BaseActivity { + private List mFragments = new ArrayList<>(); + private String[] titles; + private String groupName; + private File appFile; + private boolean isForceUpdate; + private BookcaseFragment mBookcaseFragment; + private FindFragment mFindFragment; + private MineFragment mMineFragment; + + @Override + protected int getContentId() { + return R.layout.activity_main; + } + @Override + protected void setUpToolbar(Toolbar toolbar) { + super.setUpToolbar(toolbar); + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(false); + actionBar.setDisplayShowHomeEnabled(false); + } + getSupportActionBar().setTitle(titles[0]); + getSupportActionBar().setSubtitle(groupName); + setStatusBarColor(R.color.colorPrimary, true); + } - @BindView(R.id.civ_avatar) - CircleImageView civAvatar; - @BindView(R.id.tl_tab_menu) - TabLayout tlTabMenu; - @BindView(R.id.iv_search) - ImageView ivSearch; - @BindView(R.id.iv_more) - ImageView ivMore; - @BindView(R.id.rl_common_title) - RelativeLayout rlCommonTitle; - @BindView(R.id.tv_edit_finish) - TextView tvEditFinish; - @BindView(R.id.rl_edit_titile) - RelativeLayout rlEditTitle; - @BindView(R.id.vp_content) - ViewPager vpContent; - private MainPresenter mMainPrensenter; + @Override + protected void initData(Bundle savedInstanceState) { + super.initData(savedInstanceState); + groupName = SharedPreUtils.getInstance().getString("curBookGroupName", ""); + titles = new String[]{"书架", "发现", "我的"}; + mBookcaseFragment = new BookcaseFragment(); + mFindFragment = new FindFragment(); + mMineFragment = new MineFragment(); + mFragments.add(mBookcaseFragment); + mFragments.add(mFindFragment); + mFragments.add(mMineFragment); + } + @Override + protected void initWidget() { + super.initWidget(); + viewPagerMain.setOffscreenPageLimit(2); + viewPagerMain.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager(), BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { + @Override + public int getCount() { + return mFragments.size(); + } - private File appFile; - private boolean isForceUpdate; + @NonNull + @Override + public Fragment getItem(int position) { + return mFragments.get(position); + } + }); + + } @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - ButterKnife.bind(this); - setStatusBar(R.color.white, false); - mMainPrensenter = new MainPresenter(this); - mMainPrensenter.start(); + protected void initClick() { + super.initClick(); + //BottomNavigationView 点击事件监听 + bottomNavigation.setOnNavigationItemSelectedListener(menuItem -> { + int menuId = menuItem.getItemId(); + // 跳转指定页面:Fragment + switch (menuId) { + case R.id.menu_bookshelf: + viewPagerMain.setCurrentItem(0); + break; + case R.id.menu_find_book: + viewPagerMain.setCurrentItem(1); + break; + case R.id.menu_my_config: + viewPagerMain.setCurrentItem(2); + break; + } + return false; + }); + + // ViewPager 滑动事件监听 + viewPagerMain.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int i, float v, int i1) { + + } + + @Override + public void onPageSelected(int i) { + //将滑动到的页面对应的 menu 设置为选中状态 + bottomNavigation.getMenu().getItem(i).setChecked(true); + getSupportActionBar().setTitle(titles[i]); + if (i == 0) { + getSupportActionBar().setSubtitle(groupName); + }else { + getSupportActionBar().setSubtitle(""); + } + invalidateOptionsMenu(); + /*if (i == 1){ + ((BookStoreFragment) mFragments.get(i)).lazyLoad(); + }*/ + } + + @Override + public void onPageScrollStateChanged(int i) { + + } + }); + + } + + @Override + protected void processLogic() { + super.processLogic(); + try { + int settingVersion = SysManager.getSetting().getSettingVersion(); + if (settingVersion < APPCONST.SETTING_VERSION){ + SysManager.resetSetting(); + } + }catch (Exception e){ + SysManager.resetSetting(); + } + } + + private void reLoadFragment() { + List fragments = getSupportFragmentManager().getFragments(); + mBookcaseFragment = (BookcaseFragment) fragments.get(0); + mFindFragment = (FindFragment) fragments.get(1); + mMineFragment = (MineFragment) fragments.get(2); + } + + public ViewPager getViewPagerMain() { + return viewPagerMain; + } + + /********************************Event***************************************/ + /** + * 创建菜单 + * + * @param menu + * @return + */ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_book, menu); + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + if (viewPagerMain.getCurrentItem() == 0) { + + if (mBookcaseFragment.getmBookcasePresenter() != null && mBookcaseFragment.getmBookcasePresenter().ismEditState()) { + menu.findItem(R.id.action_finish).setVisible(true); + menu.setGroupVisible(R.id.bookcase_menu, false); + } else { + menu.setGroupVisible(R.id.bookcase_menu, true); + menu.findItem(R.id.action_finish).setVisible(false); + } + } else { + menu.setGroupVisible(R.id.bookcase_menu, false); + menu.findItem(R.id.action_finish).setVisible(false); + } + return super.onPrepareOptionsMenu(menu); + } + + /** + * 导航栏菜单点击事件 + * + * @param item + * @return + */ + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (mBookcaseFragment.isRecreate()) { + reLoadFragment(); + } + switch (item.getItemId()) { + case R.id.action_search: + Intent searchBookIntent = new Intent(this, SearchBookActivity.class); + startActivity(searchBookIntent); + return true; + case R.id.action_finish: + mBookcaseFragment.getmBookcasePresenter().cancelEdit(); + invalidateOptionsMenu(); + return true; + case R.id.action_change_group: + mBookcaseFragment.getmBookcasePresenter() + .showBookGroupMenu(findViewById(R.id.action_change_group), () -> { + groupName = SharedPreUtils.getInstance().getString("curBookGroupName", "所有书籍"); + getSupportActionBar().setSubtitle(groupName); + }); + case R.id.action_edit: + invalidateOptionsMenu(); + break; + } + return mBookcaseFragment.getmBookcasePresenter().onOptionsItemSelected(item); } @Override public void onBackPressed() { - if (mMainPrensenter.ismEditState()){ - mMainPrensenter.cancelEdit(); + if (mBookcaseFragment.getmBookcasePresenter() != null && mBookcaseFragment.getmBookcasePresenter().ismEditState()) { + mBookcaseFragment.getmBookcasePresenter().cancelEdit(); + invalidateOptionsMenu(); return; } if (System.currentTimeMillis() - APPCONST.exitTime > APPCONST.exitConfirmTime) { @@ -88,26 +271,28 @@ public class MainActivity extends BaseActivity { // MyApplication.checkVersionByServer(this); } + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if ((resultCode == RESULT_OK || resultCode == RESULT_CANCELED) && requestCode == APPCONST.APP_INSTALL_CODE) { installProcess(appFile, isForceUpdate);//再次执行安装流程,包含权限判等 - }else if (resultCode == RESULT_OK && requestCode == APPCONST.SELECT_FILE_CODE){ - String path; - Uri uri = data.getData(); - if ("file".equalsIgnoreCase(uri.getScheme())){//使用第三方应用打开 - path = uri.getPath(); - }else { - path = getPath(this, uri); + } + if (resultCode == RESULT_OK) { + switch (requestCode) { + case APPCONST.REQUEST_LOGIN: + if (mMineFragment.isRecreate()){ + reLoadFragment(); + } + mMineFragment.onActivityResult(requestCode, resultCode, data); + break; } - mMainPrensenter.addLocalBook(path); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); - switch (requestCode){ + switch (requestCode) { case APPCONST.PERMISSIONS_REQUEST_STORAGE: { // 如果取消权限,则返回的值为0 if (grantResults.length > 0 @@ -119,7 +304,6 @@ public class MainActivity extends BaseActivity { } else { ToastUtils.showWarring("用户拒绝开启读写权限"); } - return; } } } @@ -165,6 +349,7 @@ public class MainActivity extends BaseActivity { /** * 安装应用 + * * @param file * @param isForceUpdate */ @@ -181,40 +366,12 @@ public class MainActivity extends BaseActivity { intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); } startActivity(intent); - if (isForceUpdate){ + if (isForceUpdate) { finish(); } } - public CircleImageView getCivAvatar() { - return civAvatar; - } - - public TabLayout getTlTabMenu() { - return tlTabMenu; - } - - public ImageView getIvSearch() { - return ivSearch; - } - - public ViewPager getVpContent() { - return vpContent; - } - - public RelativeLayout getRlCommonTitle() { - return rlCommonTitle; - } - - public TextView getTvEditFinish() { - return tvEditFinish; - } - - public RelativeLayout getRlEditTitle() { - return rlEditTitle; - } - - public ImageView getIvMore() { - return ivMore; + public interface OnGroupChangeListener{ + void onChange(); } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/MoreSettingActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/MoreSettingActivity.java index 01606bf..abb8179 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/MoreSettingActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/MoreSettingActivity.java @@ -18,13 +18,21 @@ import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.creator.DialogCreator; import xyz.fycz.myreader.creator.MultiChoiceDialog; import xyz.fycz.myreader.entity.Setting; +import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.service.BookService; +import xyz.fycz.myreader.util.utils.FileUtils; +import xyz.fycz.myreader.util.SharedPreUtils; import xyz.fycz.myreader.util.ToastUtils; +import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; +import java.io.File; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; +import static xyz.fycz.myreader.common.APPCONST.BOOK_CACHE_PATH; + /** * Created by newbiechen on 17-6-6. * 阅读界面的更多设置 @@ -45,6 +53,8 @@ public class MoreSettingActivity extends BaseActivity2 { SwitchCompat mScAutoRefresh; @BindView(R.id.more_setting_ll_close_refresh) LinearLayout mLlCloseRefresh; + @BindView(R.id.more_setting_ll_disable_source) + LinearLayout mLlDisableSource; @BindView(R.id.more_setting_iv_match_chapter_tip) ImageView mIvMatchChapterTip; @BindView(R.id.more_setting_rl_match_chapter) @@ -63,11 +73,16 @@ public class MoreSettingActivity extends BaseActivity2 { RelativeLayout mRlDeleteCathe; @BindView(R.id.more_setting_ll_download_all) LinearLayout mLlDownloadAll; + /*@BindView(R.id.more_setting_rl_bookstore) + RelativeLayout mRlBookstore; + @BindView(R.id.more_setting_sc_bookstore) + SwitchCompat mScBookstore;*/ private Setting mSetting; private boolean isVolumeTurnPage; private int resetScreenTime; private boolean autoRefresh; private boolean isMatchChapter; + private boolean openBookStore; private float matchChapterSuitability; private int catheCap; @@ -77,8 +92,12 @@ public class MoreSettingActivity extends BaseActivity2 { //选择禁用更新书籍对话框 private AlertDialog mCloseRefreshDia; + //选择禁用更新书源对话框 + private AlertDialog mDisableSourceDia; //选择一键缓存书籍对话框 private AlertDialog mDownloadAllDia; + //选择清除缓存对话框 + private AlertDialog mDeleteCatheDia; @Override protected int getContentId() { @@ -95,6 +114,7 @@ public class MoreSettingActivity extends BaseActivity2 { matchChapterSuitability = mSetting.getMatchChapterSuitability(); catheCap = mSetting.getCatheGap(); autoRefresh = mSetting.isRefreshWhenStart(); + openBookStore = mSetting.isOpenBookStore(); } @Override @@ -119,6 +139,7 @@ public class MoreSettingActivity extends BaseActivity2 { mScVolume.setChecked(isVolumeTurnPage); mScMatchChapter.setChecked(isMatchChapter); mScAutoRefresh.setChecked(autoRefresh); + //mScBookstore.setChecked(openBookStore); } @Override @@ -151,14 +172,14 @@ public class MoreSettingActivity extends BaseActivity2 { mLlCloseRefresh.setOnClickListener(v -> { MyApplication.runOnUiThread(() -> { - if (mCloseRefreshDia != null){ + if (mCloseRefreshDia != null) { mCloseRefreshDia.show(); return; } initmBooks(); - if (mBooks.size() == 0){ + if (mBooks.size() == 0) { ToastUtils.showWarring("当前书架没有支持禁用更新的书籍!"); return; } @@ -169,7 +190,7 @@ public class MoreSettingActivity extends BaseActivity2 { for (int i = 0; i < booksCount; i++) { Book book = mBooks.get(i); isCloseRefresh[i] = book.getIsCloseUpdate(); - if (isCloseRefresh[i]){ + if (isCloseRefresh[i]) { crBookCount++; } } @@ -185,7 +206,7 @@ public class MoreSettingActivity extends BaseActivity2 { @Override public void onSelectAll(boolean isSelectAll) { - for (Book book : mBooks){ + for (Book book : mBooks) { book.setIsCloseUpdate(isSelectAll); } } @@ -194,6 +215,52 @@ public class MoreSettingActivity extends BaseActivity2 { }); }); + mLlDisableSource.setOnClickListener(v -> { + if (mDisableSourceDia != null) { + mDisableSourceDia.show(); + return; + } + + HashMap mSources = ReadCrawlerUtil.getDisableSources(); + CharSequence[] mSourcesName = new CharSequence[mSources.keySet().size()]; + boolean[] isDisables = new boolean[mSources.keySet().size()]; + int dSourceCount = 0; + int i = 0; + for (CharSequence sourceName : mSources.keySet()) { + mSourcesName[i] = sourceName; + Boolean isDisable = mSources.get(sourceName); + if (isDisable == null) isDisable = false; + if (isDisable) dSourceCount++; + isDisables[i++] = isDisable; + } + + mDisableSourceDia = new MultiChoiceDialog().create(this, "选择禁用的书源", + mSourcesName, isDisables, dSourceCount, (dialog, which) -> { + SharedPreUtils spu = SharedPreUtils.getInstance(); + StringBuilder sb = new StringBuilder(); + for (CharSequence sourceName : mSources.keySet()) { + if (!mSources.get(sourceName)) { + sb.append(BookSource.getFromName(String.valueOf(sourceName))); + sb.append(","); + } + } + if (sb.lastIndexOf(",") >= 0) sb.deleteCharAt(sb.lastIndexOf(",")); + spu.putString("searchSource", sb.toString()); + }, null, new DialogCreator.OnMultiDialogListener() { + @Override + public void onItemClick(DialogInterface dialog, int which, boolean isChecked) { + mSources.put(mSourcesName[which], isChecked); + } + + @Override + public void onSelectAll(boolean isSelectAll) { + for (CharSequence sourceName : mSources.keySet()) { + mSources.put(sourceName, isSelectAll); + } + } + }); + }); + mRlMatchChapter.setOnClickListener( (v) -> { if (isMatchChapter) { @@ -212,14 +279,14 @@ public class MoreSettingActivity extends BaseActivity2 { mLlDownloadAll.setOnClickListener(v -> { MyApplication.runOnUiThread(() -> { - if (mDownloadAllDia != null){ + if (mDownloadAllDia != null) { mDownloadAllDia.show(); return; } initmBooks(); - if (mBooks.size() == 0){ + if (mBooks.size() == 0) { ToastUtils.showWarring("当前书架没有支持缓存的书籍!"); return; } @@ -232,7 +299,7 @@ public class MoreSettingActivity extends BaseActivity2 { Book book = mBooks.get(i); mBooksName[i] = book.getName(); isDownloadAll[i] = book.getIsDownLoadAll(); - if (isDownloadAll[i]){ + if (isDownloadAll[i]) { daBookCount++; } } @@ -248,7 +315,7 @@ public class MoreSettingActivity extends BaseActivity2 { @Override public void onSelectAll(boolean isSelectAll) { - for (Book book : mBooks){ + for (Book book : mBooks) { book.setIsDownLoadAll(isSelectAll); } } @@ -264,12 +331,52 @@ public class MoreSettingActivity extends BaseActivity2 { mRlCatheGap.setOnClickListener(v -> mScCatheGap.performClick()); mRlDeleteCathe.setOnClickListener(v -> { - DialogCreator.createCommonDialog(this, "清除缓存", "确定要清除全部书籍缓存吗?", - true, (dialog, which) -> { - BookService.getInstance().deleteAllBookCathe(); - ToastUtils.showSuccess("清除缓存成功!"); - }, null); + MyApplication.runOnUiThread(() -> { + File catheFile = getCacheDir(); + String catheFileSize = FileUtils.getFileSize(FileUtils.getDirSize(catheFile)); + + File eCatheFile = new File(BOOK_CACHE_PATH); + String eCatheFileSize; + if (eCatheFile.exists() && eCatheFile.isDirectory()) { + eCatheFileSize = FileUtils.getFileSize(FileUtils.getDirSize(eCatheFile)); + }else { + eCatheFileSize = "0"; + } + CharSequence[] cathes = {"章节缓存:" + eCatheFileSize, "图片缓存:" + catheFileSize}; + boolean[] catheCheck = {true, true}; + mDeleteCatheDia = new MultiChoiceDialog().create(this, "清除缓存", cathes, catheCheck, 2, + (dialog, which) -> { + String tip = ""; + if (catheCheck[0]) { + BookService.getInstance().deleteAllBookCathe(); + tip += "章节缓存 "; + } + if (catheCheck[1]) { + FileUtils.deleteFile(catheFile.getAbsolutePath()); + tip += "图片缓存 "; + } + if (tip.length() > 0) { + tip += "清除成功"; + ToastUtils.showSuccess(tip); + } + }, null, null); + }); }); + + + /*mRlBookstore.setOnClickListener( + (v) -> { + if (openBookStore) { + openBookStore = false; + } else { + openBookStore = true; + } + mScBookstore.setChecked(openBookStore); + mSetting.setOpenBookStore(openBookStore); + SysManager.saveSetting(mSetting); + ToastUtils.showInfo("重启后生效!"); + } + );*/ } @Override @@ -281,8 +388,8 @@ public class MoreSettingActivity extends BaseActivity2 { private void initSpinner() { // initSwitchStatus() be called earlier than onCreate(), so setSelection() won't work ArrayAdapter resetScreenAdapter = ArrayAdapter.createFromResource(this, - R.array.reset_screen_time, android.R.layout.simple_spinner_item); - resetScreenAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + R.array.reset_screen_time, R.layout.spinner); + resetScreenAdapter.setDropDownViewResource(R.layout.spinner_item); mScResetScreen.setAdapter(resetScreenAdapter); int resetScreenSelection = 0; @@ -332,8 +439,8 @@ public class MoreSettingActivity extends BaseActivity2 { ArrayAdapter matchSuiAdapter = ArrayAdapter.createFromResource(this, - R.array.match_chapter_suitability, android.R.layout.simple_spinner_item); - matchSuiAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + R.array.match_chapter_suitability, R.layout.spinner); + matchSuiAdapter.setDropDownViewResource(R.layout.spinner_item); mScMatchChapterSuitability.setAdapter(matchSuiAdapter); if (matchChapterSuitability == 0.0) { @@ -360,8 +467,8 @@ public class MoreSettingActivity extends BaseActivity2 { ArrayAdapter catheGapAdapter = ArrayAdapter.createFromResource(this, - R.array.cathe_chapter_gap, android.R.layout.simple_spinner_item); - catheGapAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + R.array.cathe_chapter_gap, R.layout.spinner); + catheGapAdapter.setDropDownViewResource(R.layout.spinner_item); mScCatheGap.setAdapter(catheGapAdapter); if (catheCap == 0) { @@ -387,14 +494,14 @@ public class MoreSettingActivity extends BaseActivity2 { }); } - private void initmBooks(){ + private void initmBooks() { if (mBooks != null) { return; } mBooks = (ArrayList) BookService.getInstance().getAllBooks(); Iterator mBooksIter = mBooks.iterator(); - while (mBooksIter.hasNext()){ + while (mBooksIter.hasNext()) { Book book = mBooksIter.next(); if ("本地书籍".equals(book.getType())) { mBooksIter.remove(); diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java index 7f9179a..616f9f1 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java @@ -15,6 +15,7 @@ import androidx.appcompat.app.AppCompatActivity; import butterknife.BindView; import butterknife.ButterKnife; import com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBar; +import xyz.fycz.myreader.ActivityManage; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.SysManager; import xyz.fycz.myreader.base.BaseActivity; @@ -25,7 +26,6 @@ import xyz.fycz.myreader.widget.page.PageView; public class ReadActivity extends BaseActivity { - @BindView(R.id.pb_loading) ProgressBar pbLoading; @BindView(R.id.read_pv_page) @@ -117,9 +117,14 @@ public class ReadActivity extends BaseActivity { result.putExtra(APPCONST.RESULT_HISTORY_CHAPTER, mReadPresenter.getmPageLoader().getChapterPos()); } setResult(AppCompatActivity.RESULT_OK, result); + if (!ActivityManage.isExist(MainActivity.class)) { + Intent intent = new Intent(this, MainActivity.class); + startActivity(intent); + } super.onBackPressed(); } + @Override public boolean onKeyDown(int keyCode, KeyEvent event) { boolean isVolumeTurnPage = SysManager.getSetting().isVolumeTurnPage(); diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/RegisterActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/RegisterActivity.java index e726c2c..daa38ff 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/RegisterActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/RegisterActivity.java @@ -1,27 +1,39 @@ package xyz.fycz.myreader.ui.activity; -/** - * @author fengyue - * @date 2020/4/26 18:49 - */ - import android.annotation.SuppressLint; +import android.app.ProgressDialog; +import android.graphics.Bitmap; import android.os.Bundle; -import android.widget.*; +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 butterknife.ButterKnife; import com.google.android.material.textfield.TextInputLayout; import xyz.fycz.myreader.R; -import xyz.fycz.myreader.base.BaseActivity; -import xyz.fycz.myreader.ui.presenter.RegisterPresenter; +import xyz.fycz.myreader.backup.UserService; +import xyz.fycz.myreader.base.BaseActivity2; +import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.creator.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; -@SuppressLint("Registered") -public class RegisterActivity extends BaseActivity{ - @BindView(R.id.ll_title_back) - LinearLayout llTitleBack; - @BindView(R.id.tv_title_text) - TextView tvTitleText; +/** + * @author fengyue + * @date 2020/9/18 22:37 + */ +public class RegisterActivity extends BaseActivity2 { @BindView(R.id.et_username) TextInputLayout etUsername; @BindView(R.id.et_password) @@ -40,58 +52,221 @@ public class RegisterActivity extends BaseActivity{ CheckBox cbAgreement; @BindView(R.id.tv_agreement) TextView tvAgreement; - private RegisterPresenter mRegisterPresenter; + 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 void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_register); - ButterKnife.bind(this); - setStatusBar(R.color.white, false); - mRegisterPresenter = new RegisterPresenter(this); - mRegisterPresenter.start(); + protected int getContentId() { + return R.layout.activity_register; } - public LinearLayout getLlTitleBack() { - return llTitleBack; + @Override + protected void setUpToolbar(Toolbar toolbar) { + super.setUpToolbar(toolbar); + setStatusBarColor(R.color.colorPrimary, true); + getSupportActionBar().setTitle("注册"); } - public TextView getTvTitleText() { - return tvTitleText; - } + @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) { - public EditText getEtUsername() { - return etUsername.getEditText(); - } + } - public EditText getEtPassword() { - return etPassword.getEditText(); - } + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { - public EditText getEtRpPassword() { - return etRpPassword.getEditText(); - } + } - public EditText getEtCaptcha() { - return etCaptcha.getEditText(); - } + @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()); - public ImageView getIvCaptcha() { - return ivCaptcha; } - public Button getBtRegister() { - return btRegister; + @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 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 TextView getTvRegisterTip() { - return tvRegisterTip; + public void createCaptcha() { + code = CodeUtil.getInstance().createCode(); + Bitmap codeBitmap = CodeUtil.getInstance().createBitmap(code); + ivCaptcha.setImageBitmap(codeBitmap); } - public CheckBox getCbAgreement() { - return cbAgreement; + public void showTip(String tip) { + tvRegisterTip.setVisibility(View.VISIBLE); + tvRegisterTip.setText(tip); } - public TextView getTvAgreement() { - return tvAgreement; + public void checkNotNone(){ + if ("".equals(username) || "".equals(password) || "".equals(rpPassword) || "".equals(inputCode)){ + btRegister.setEnabled(false); + }else { + btRegister.setEnabled(true); + } } + } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java index da97c3d..514ca85 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java @@ -1,36 +1,59 @@ package xyz.fycz.myreader.ui.activity; - +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.os.Build; import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; import android.widget.*; - -import com.scwang.smartrefresh.layout.SmartRefreshLayout; -import xyz.fycz.myreader.R; -import xyz.fycz.myreader.base.BaseActivity; - -import butterknife.ButterKnife; +import androidx.appcompat.widget.Toolbar; import butterknife.BindView; +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.base.BaseActivity2; +import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.custom.DragSortGridView; -import xyz.fycz.myreader.ui.presenter.SearchBookPrensenter; +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.greendao.entity.SearchHistory; +import xyz.fycz.myreader.greendao.service.SearchHistoryService; +import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.ui.adapter.SearchBookAdapter; +import xyz.fycz.myreader.ui.adapter.SearchHistoryAdapter; +import xyz.fycz.myreader.util.StringHelper; +import xyz.fycz.myreader.util.ToastUtils; +import xyz.fycz.myreader.webapi.CommonApi; +import xyz.fycz.myreader.webapi.crawler.ReadCrawler; +import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; -public class SearchBookActivity extends BaseActivity { +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; - @BindView(R.id.ll_title_back) - LinearLayout llTitleBack; - @BindView(R.id.tv_title_text) - TextView tvTitleText; - @BindView(R.id.system_title) - LinearLayout systemTitle; +/** + * @author fengyue + * @date 2020/9/18 21:58 + */ +public class SearchBookActivity extends BaseActivity2 { @BindView(R.id.et_search_key) EditText etSearchKey; @BindView(R.id.tv_search_conform) TextView tvSearchConform; - @BindView(R.id.ll_refresh_suggest_books) LinearLayout llRefreshSuggestBooks; - /*@BindView(R.id.lv_search_books_list) - ListView lvSearchBooksList;*/ @BindView(R.id.gv_search_books_list) DragSortGridView gvSearchBooksList; @BindView(R.id.ll_suggest_books_view) @@ -53,90 +76,344 @@ public class SearchBookActivity extends BaseActivity { SmartRefreshLayout srlSearchBookList; - private SearchBookPrensenter mSearchBookPrensenter; + private SearchBookAdapter mSearchBookAdapter; + private String searchKey;//搜索关键字 + private ArrayList mBooksBean = new ArrayList<>(); + private ConcurrentMultiValueMap mBooks = new ConcurrentMultiValueMap<>(); + private ArrayList mAdapterBooks = new ArrayList<>(); + private ArrayList mSearchHistories = new ArrayList<>(); + private ArrayList mSuggestions = new ArrayList<>(); + + private SearchHistoryService mSearchHistoryService; + private SearchHistoryAdapter mSearchHistoryAdapter; + + private int curThreadCount; + + private int allThreadCount; + + private boolean isStopSearch; + + private int inputConfirm = 0;//搜索输入确认 + private int confirmTime = 1000;//搜索输入确认时间(毫秒) + + private static String[] suggestion = {"第一序列", "大道朝天", "伏天氏", "终极斗罗", "我师兄实在太稳健了", "烂柯棋缘", "诡秘之主"}; + private static String[] suggestion2 = {"不朽凡人", "圣墟", "我是至尊", "龙王传说", "太古神王", "一念永恒", "雪鹰领主", "大主宰"}; + + @SuppressLint("HandlerLeak") + private Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case 1: + search(); + break; + case 2: + if (curThreadCount == 0 && !isStopSearch) { + initSearchList(); + srlSearchBookList.finishRefresh(); + pbLoading.setVisibility(View.GONE); + }/*else { + notifyDataSetChanged(); + mSearchBookActivity.getSrlSearchBookList().finishRefresh(); + }*/ + break; + } + } + }; @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_search_book); - ButterKnife.bind(this); - setStatusBar(R.color.white, false); - mSearchBookPrensenter = new SearchBookPrensenter(this); - mSearchBookPrensenter.start(); + protected int getContentId() { + return R.layout.activity_search_book; } @Override - public void onBackPressed() { - if (!mSearchBookPrensenter.onBackPressed()){ - super.onBackPressed(); - } + protected void setUpToolbar(Toolbar toolbar) { + super.setUpToolbar(toolbar); + setStatusBarColor(R.color.colorPrimary, true); + getSupportActionBar().setTitle("搜索"); } - public LinearLayout getLlTitleBack() { - return llTitleBack; + @Override + protected void initData(Bundle savedInstanceState) { + super.initData(savedInstanceState); + mSearchHistoryService = SearchHistoryService.getInstance(); + for (int i = 0; i < suggestion.length; i++) { + mSuggestions.add(suggestion[i]); + } } - public TextView getTvTitleText() { - return tvTitleText; - } + @Override + protected void initWidget() { + super.initWidget(); + etSearchKey.requestFocus();//get the focus + //enter事件 + etSearchKey.setOnEditorActionListener((textView, i, keyEvent) -> { + if (i == EditorInfo.IME_ACTION_UNSPECIFIED) { + mHandler.sendMessage(mHandler.obtainMessage(1)); + return (keyEvent.getKeyCode() == KeyEvent.KEYCODE_ENTER); + } + return false; + }); + //搜索框改变事件 + etSearchKey.addTextChangedListener(new TextWatcher() { - public LinearLayout getSystemTitle() { - return systemTitle; - } + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { - public EditText getEtSearchKey() { - return etSearchKey; - } + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { - public TextView getTvSearchConform() { - return tvSearchConform; + } + + @Override + public void afterTextChanged(final Editable editable) { + searchKey = editable.toString(); + if (StringHelper.isEmpty(searchKey)) { + mHandler.sendMessage(mHandler.obtainMessage(1)); + } + + } + + }); + //上拉刷新 + srlSearchBookList.setOnRefreshListener(refreshLayout -> mHandler.sendMessage(mHandler.obtainMessage(1))); + srlSearchBookList.setEnableRefresh(false); + gvSearchBooksList.setNumColumns(1); + gvSearchBooksList.setDragModel(-1); + initSuggestionBook(); + initHistoryList(); } - public TagGroup getTgSuggestBook() { - return tgSuggestBook; + @Override + protected void initClick() { + super.initClick(); + + //换一批点击事件 + renewByImage.setOnClickListener(new RenewSuggestionBook()); + //换一批点击事件 + renewByText.setOnClickListener(new RenewSuggestionBook()); + //进入书籍详情页 + gvSearchBooksList.setOnItemClickListener((adapterView, view, i, l) -> { + Intent intent = new Intent(this, BookDetailedActivity.class); + intent.putExtra(APPCONST.SEARCH_BOOK_BEAN, new ArrayList<>(mBooks.getValues(mBooksBean.get(i)))); + startActivity(intent); + }); + //搜索按钮点击事件 + tvSearchConform.setOnClickListener(view -> mHandler.sendMessage(mHandler.obtainMessage(1))); + //suggestion搜索事件 + tgSuggestBook.setOnTagClickListener(tag -> { + etSearchKey.setText(tag); + etSearchKey.setSelection(tag.length()); + mHandler.sendMessage(mHandler.obtainMessage(1)); + }); + //历史记录搜索事件 + lvHistoryList.setOnItemClickListener((parent, view, position, id) -> { + etSearchKey.setText(mSearchHistories.get(position).getContent()); + etSearchKey.setSelection(mSearchHistories.get(position).getContent().length()); + mHandler.sendMessage(mHandler.obtainMessage(1)); + }); + //清空历史记录 + llClearHistory.setOnClickListener(v -> { + mSearchHistoryService.clearHistory(); + initHistoryList(); + }); + //清除单个历史记录 + lvHistoryList.setOnItemLongClickListener((parent, view, position, id) -> { + if (mSearchHistories.get(position) != null) { + mSearchHistoryService.deleteHistory(mSearchHistories.get(position)); + initHistoryList(); + } + return true; + }); } - public LinearLayout getLlRefreshSuggestBooks() { - return llRefreshSuggestBooks; + + /** + * 初始化建议书目 + */ + private void initSuggestionBook() { + tgSuggestBook.setTags(suggestion); } -// public ListView getLvSearchBooksList() { -// return lvSearchBooksList; -// } + private class RenewSuggestionBook implements View.OnClickListener { + @Override + public void onClick(View v) { + String[] s = tgSuggestBook.getTags(); + if (Arrays.equals(s, suggestion)) { + tgSuggestBook.setTags(suggestion2); + } else { + tgSuggestBook.setTags(suggestion); + } + } + } - public DragSortGridView getGvSearchBooksList() { - return gvSearchBooksList; + /** + * 初始化历史列表 + */ + private void initHistoryList() { + mSearchHistories = mSearchHistoryService.findAllSearchHistory(); + if (mSearchHistories == null || mSearchHistories.size() == 0) { + llHistoryView.setVisibility(View.GONE); + } else { + mSearchHistoryAdapter = new SearchHistoryAdapter(this, R.layout.listview_search_history_item, mSearchHistories); + lvHistoryList.setAdapter(mSearchHistoryAdapter); + llHistoryView.setVisibility(View.VISIBLE); + } } - public LinearLayout getLlSuggestBooksView() { - return llSuggestBooksView; + /** + * 初始化搜索列表 + */ + private void initSearchList() { + initmBooksBean(); + mSearchBookAdapter = new SearchBookAdapter(this, + R.layout.listview_search_book_item, mBooksBean, mBooks); + gvSearchBooksList.setAdapter(mSearchBookAdapter); + gvSearchBooksList.setVisibility(View.VISIBLE); + llSuggestBooksView.setVisibility(View.GONE); + llSuggestBooksView.setVisibility(View.GONE); } - public ProgressBar getPbLoading() { - return pbLoading; + /** + * 更新搜索列表 + */ + private void notifyDataSetChanged() { + if (curThreadCount == 0) { + pbLoading.setVisibility(View.GONE); + } + initmBooksBean(); } - public ListView getLvHistoryList() { - return lvHistoryList; + /** + * 初始化mBooksBean + */ + private void initmBooksBean() { + synchronized (this) { + mBooksBean.clear(); + mBooksBean.addAll(mBooks.keySet()); + //排序,基于最符合关键字的搜书结果应该是最短的 + //TODO ;这里只做了简单的比较排序,还需要继续完善 + Collections.sort(mBooksBean, (o1, o2) -> { + if (searchKey.equals(o1.getName())) + return -1; + if (searchKey.equals(o2.getName())) + return 1; + if (searchKey.equals(o1.getAuthor())) + return -1; + if (searchKey.equals(o2.getAuthor())) + return 1; + if (o1.getName().length() < o2.getName().length()) + return -1; + if (o1.getName().length() == o2.getName().length()) + return 0; + return 1; + }); + /*MyApplication.runOnUiThread(new Runnable() { + @Override + public void run() { + mSearchBookAdapter.notifyDataSetChanged(); + } + });*/ + } } - public LinearLayout getLlClearHistory() { - return llClearHistory; + /** + * 获取搜索数据 + */ + private void getData() { + mBooksBean.clear(); + mBooks.clear(); + ArrayList readCrawlers = ReadCrawlerUtil.getReadCrawlers(); + allThreadCount = readCrawlers.size(); + if (allThreadCount == 0){ + ToastUtils.showWarring("当前书源已全部禁用,无法搜索!"); + pbLoading.setVisibility(View.GONE); + return; + } + curThreadCount = allThreadCount; + for (ReadCrawler readCrawler : readCrawlers){ + searchBookByCrawler(readCrawler, readCrawler.getSearchCharset()); + } } - public LinearLayout getLlHistoryView() { - return llHistoryView; + /** + * 搜索 + */ + private void search() { + pbLoading.setVisibility(View.VISIBLE); + if (StringHelper.isEmpty(searchKey)) { + isStopSearch = true; + pbLoading.setVisibility(View.GONE); + gvSearchBooksList.setVisibility(View.GONE); + llSuggestBooksView.setVisibility(View.VISIBLE); + initHistoryList(); + gvSearchBooksList.setAdapter(null); + srlSearchBookList.setEnableRefresh(false); + } else { + isStopSearch = false; + gvSearchBooksList.setVisibility(View.VISIBLE); + llSuggestBooksView.setVisibility(View.GONE); + llHistoryView.setVisibility(View.GONE); + getData(); + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (gvSearchBooksList.getmScrollView().getScrollY() == 0){ + srlSearchBookList.setEnableRefresh(true); + } + //滑动监听器 + gvSearchBooksList.getmScrollView().setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> { + srlSearchBookList.setEnableRefresh(scrollY == 0); + }); + } + mSearchHistoryService.addOrUpadteHistory(searchKey); + //收起软键盘 + InputMethodManager imm = (InputMethodManager) MyApplication.getmContext().getSystemService(Context.INPUT_METHOD_SERVICE); + assert imm != null; + imm.hideSoftInputFromWindow(etSearchKey.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + } } - public ImageView getRenewByImage() { - return renewByImage; + @Override + public void onBackPressed() { + if (StringHelper.isEmpty(searchKey)) { + super.onBackPressed(); + } else { + etSearchKey.setText(""); + } } - public TextView getRenewByText() { - return renewByText; + private void searchBookByCrawler(ReadCrawler rc, String charset) { + String searchKey = this.searchKey; + if (charset.toLowerCase().equals("gbk")) { + try { + searchKey = URLEncoder.encode(this.searchKey, charset); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + CommonApi.search(searchKey, rc, new ResultCallback() { + @Override + public void onFinish(Object o, int code) { + ConcurrentMultiValueMap sbb = + (ConcurrentMultiValueMap) o; + mBooks.addAll(sbb); + curThreadCount--; + mHandler.sendMessage(mHandler.obtainMessage(2)); + } + + @Override + public void onError(Exception e) { + curThreadCount--; + mHandler.sendMessage(mHandler.obtainMessage(2)); + } + }); } - public SmartRefreshLayout getSrlSearchBookList() { - return srlSearchBookList; + + @Override + protected void onDestroy() { + super.onDestroy(); + isStopSearch = true; } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookMarkAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookMarkAdapter.java index b6c635a..e12cdc0 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookMarkAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookMarkAdapter.java @@ -64,12 +64,13 @@ public class BookMarkAdapter extends ArrayAdapter { } else { viewHolder.tvTitle.setCompoundDrawablesWithIntrinsicBounds(getContext().getResources().getDrawable(R.drawable.selector_category_unload),null,null,null); } - if (!setting.isDayStyle()) { + viewHolder.tvTitle.setTextColor(getContext().getColor(R.color.textSecondary)); + /*if (!setting.isDayStyle()) { viewHolder.tvTitle.setTextColor(getContext().getResources().getColor(R.color.sys_night_word)); viewHolder.vLine.setBackground(getContext().getDrawable(R.color.sys_dialog_setting_line)); }else { viewHolder.tvTitle.setTextColor(getContext().getColor(R.color.title_black)); - } + }*/ } /** diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookStoreBookAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookStoreBookAdapter.java index ce02e4a..c91050f 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookStoreBookAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookStoreBookAdapter.java @@ -1,6 +1,8 @@ package xyz.fycz.myreader.ui.adapter; +import android.app.Activity; import android.content.Context; +import android.content.Intent; import android.os.Handler; import android.os.Message; import android.view.LayoutInflater; @@ -8,14 +10,23 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.recyclerview.widget.RecyclerView; 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.base.adapter.BaseListAdapter; +import xyz.fycz.myreader.base.adapter.IViewHolder; import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.common.APPCONST; +import xyz.fycz.myreader.custom.DragAdapter; +import xyz.fycz.myreader.greendao.entity.Chapter; +import xyz.fycz.myreader.ui.activity.BookDetailedActivity; +import xyz.fycz.myreader.ui.adapter.holder.BookStoreBookHolder; import xyz.fycz.myreader.webapi.crawler.BiQuGeReadCrawler; import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.greendao.entity.Book; @@ -26,142 +37,18 @@ import xyz.fycz.myreader.webapi.CommonApi; import java.util.List; -public class BookStoreBookAdapter extends RecyclerView.Adapter { +public class BookStoreBookAdapter extends BaseListAdapter { + private boolean hasImg; + private Activity mActivity; - private LayoutInflater mInflater; - private View view; - private List mDatas; - private Context mContext; - private RecyclerView rvContent; - - - private OnItemClickListener onItemClickListener; - - - private Handler mHandle = new Handler(new Handler.Callback() { - @Override - public boolean handleMessage(Message message) { - - switch (message.what) { - case 1: - ViewHolder holder = (ViewHolder) message.obj; - int pos = message.arg1; - BookStoreBookAdapter.this.initOtherInfo(pos, holder); - break; - } - - return false; - - } - }); - - - public BookStoreBookAdapter(Context context, List datas) { - mInflater = LayoutInflater.from(context); - mDatas = datas; - mContext = context; - } - - class ViewHolder extends RecyclerView.ViewHolder { - TextView tvBookName; - TextView tvBookAuthor; - TextView tvBookDesc; - TextView tvBookNewestChapter; - TextView tvBookSource; - ImageView ivBookImg; - ViewHolder() { - super(view); - } - - - } - - @NonNull - @Override - public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - if (rvContent == null) rvContent = (RecyclerView) parent; - view = mInflater.inflate(R.layout.listview_book_store_book_item, parent, false); - ViewHolder viewHolder = new ViewHolder(); - viewHolder.tvBookName = view.findViewById(R.id.tv_book_name); - viewHolder.tvBookAuthor = view.findViewById(R.id.tv_book_author); - viewHolder.tvBookDesc = view.findViewById(R.id.tv_book_desc); - viewHolder.ivBookImg = view.findViewById(R.id.iv_book_img); - viewHolder.tvBookNewestChapter = view.findViewById(R.id.tv_book_newest_chapter); - viewHolder.tvBookSource = view.findViewById(R.id.tv_book_source); - return viewHolder; + public BookStoreBookAdapter(boolean hasImg, Activity mActivity) { + this.hasImg = hasImg; + this.mActivity = mActivity; } @Override - public void onBindViewHolder(@NonNull ViewHolder holder, final int position) { - initView(position, holder); - if (onItemClickListener != null){ - holder.itemView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - onItemClickListener.onClick(position, view); - } - }); - - } - } - - @Override - public int getItemCount() { - return mDatas.size(); - } - - private void initView(final int position, final ViewHolder holder) { - Book book = mDatas.get(position); - holder.tvBookName.setText(book.getName()); - holder.tvBookAuthor.setText(book.getAuthor()); - holder.tvBookNewestChapter.setText(""); - holder.tvBookSource.setText("书源:" + BookSource.fromString(book.getSource()).text); - holder.tvBookDesc.setText(""); - if (StringHelper.isEmpty(book.getImgUrl())){ - //获取小说详情 - CommonApi.getBookInfo(book, new BiQuGeReadCrawler(), new ResultCallback() { - @Override - public void onFinish(Object o, int code) { - mDatas.set(position,(Book) o); - //防止列表快速滑动时出现书的信息加载混乱的问题 - if (holder.tvBookName.getTag() == null || (int) holder.tvBookName.getTag() == position) { - mHandle.sendMessage(mHandle.obtainMessage(1,position,0,holder)); - } - } - @Override - public void onError(Exception e) { - } - }); - }else{ - initOtherInfo(position,holder); - } - } - - private void initOtherInfo(final int position, final ViewHolder holder){ - Book book = mDatas.get(position); - //图片 - Glide.with(mContext) - .load(book.getImgUrl()) -// .override(DipPxUtil.dip2px(getContext(), 80), DipPxUtil.dip2px(getContext(), 150)) - .error(R.mipmap.no_image) - .placeholder(R.mipmap.no_image) - //设置圆角 - .apply(RequestOptions.bitmapTransform(new RoundedCorners(8))) - .into(holder.ivBookImg); - //简介 - holder.tvBookDesc.setText("简介:" + book.getDesc()); - holder.tvBookNewestChapter.setText("最新章节:" + book.getNewestChapterTitle()); + protected IViewHolder createViewHolder(int viewType) { + return new BookStoreBookHolder(hasImg, mActivity); } - - public void setOnItemClickListener(OnItemClickListener onItemClickListener) { - this.onItemClickListener = onItemClickListener; - } - - public interface OnItemClickListener{ - void onClick(int pos, View view); - } - - - } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookStoreBookTypeAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookStoreBookTypeAdapter.java index 86cfee4..0f17413 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookStoreBookTypeAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookStoreBookTypeAdapter.java @@ -57,9 +57,15 @@ public class BookStoreBookTypeAdapter extends RecyclerView.Adapter isLoading = new HashMap<>(); + private final Map mCheckMap = new LinkedHashMap<>(); + private int mCheckedCount = 0; + protected OnBookCheckedListener mListener; + protected boolean isCheckedAll; protected int mResourceId; protected ArrayList list; protected Context mContext; @@ -47,6 +48,7 @@ public abstract class BookcaseAdapter extends DragAdapter { protected BookService mBookService; protected ChapterService mChapterService; protected BookcasePresenter mBookcasePresenter; + protected boolean isGroup; protected String[] menu = { MyApplication.getmContext().getResources().getString(R.string.menu_book_Top), MyApplication.getmContext().getResources().getString(R.string.menu_book_download), @@ -56,7 +58,7 @@ public abstract class BookcaseAdapter extends DragAdapter { public BookcaseAdapter(Context context, int textViewResourceId, ArrayList objects - , boolean editState, BookcasePresenter bookcasePresenter) { + , boolean editState, BookcasePresenter bookcasePresenter, boolean isGroup) { mContext = context; mResourceId = textViewResourceId; list = objects; @@ -64,6 +66,7 @@ public abstract class BookcaseAdapter extends DragAdapter { mBookService = BookService.getInstance(); mChapterService = ChapterService.getInstance(); mBookcasePresenter = bookcasePresenter; + this.isGroup = isGroup; } @@ -72,7 +75,11 @@ public abstract class BookcaseAdapter extends DragAdapter { Book b = list.remove(from); list.add(to, b); for (int i = 0; i < list.size(); i++) { - list.get(i).setSortCode(i); + if (!isGroup) { + list.get(i).setSortCode(i); + }else { + list.get(i).setGroupSort(i); + } } mBookService.updateBooks(list); } @@ -89,7 +96,7 @@ public abstract class BookcaseAdapter extends DragAdapter { @Override public long getItemId(int position) { - return list.get(position).getSortCode(); + return !isGroup ? list.get(position).getSortCode() : list.get(position).getGroupSort(); } @@ -104,19 +111,43 @@ public abstract class BookcaseAdapter extends DragAdapter { notifyDataSetChanged(); mBookService.addBook(item); } - protected void showDeleteBookDialog(final Book book){ - DialogCreator.createCommonDialog(mContext, "删除书籍", "确定删除《" + book.getName() + "》及其所有缓存吗?", - true, (dialogInterface, i) -> { - remove(book); - dialogInterface.dismiss(); - }, (dialogInterface, i) -> dialogInterface.dismiss()); + + protected void showDeleteBookDialog(final Book book) { + if (!isGroup) { + DialogCreator.createCommonDialog(mContext, "删除书籍", "确定删除《" + book.getName() + "》及其所有缓存吗?", + true, (dialogInterface, i) -> { + remove(book); + ToastUtils.showSuccess("书籍删除成功!"); + mBookcasePresenter.init(); + }, null); + }else { + DialogCreator.createCommonDialog(mContext, "删除/移除书籍", "您是希望删除《" + book.getName() + "》及其所有缓存还是从分组中移除该书籍(不会删除书籍)呢?", + true, "删除书籍", "从分组中移除书籍",(dialogInterface, i) -> { + remove(book); + ToastUtils.showSuccess("书籍删除成功!"); + mBookcasePresenter.init(); + }, (dialog, which) -> { + book.setGroupId(""); + mBookService.updateEntity(book); + ToastUtils.showSuccess("书籍已从分组中移除!"); + mBookcasePresenter.init(); + }); + } } /** * 设置是否处于编辑状态 + * * @param mEditState */ public void setmEditState(boolean mEditState) { + if (mEditState) { + mCheckMap.clear(); + for (Book book : list) { + mCheckMap.put(book.getId(), false); + } + mCheckedCount = 0; + } this.mEditState = mEditState; notifyDataSetChanged(); } @@ -124,15 +155,17 @@ public abstract class BookcaseAdapter extends DragAdapter { public boolean ismEditState() { return mEditState; } + /** * getter方法 + * * @return */ public Map getIsLoading() { return isLoading; } - public boolean isBookLoading(String bookID){ + public boolean isBookLoading(String bookID) { return isLoading.get(bookID); } @@ -141,21 +174,21 @@ public abstract class BookcaseAdapter extends DragAdapter { BufferedReader br = null; BufferedWriter bw = null; bw = new BufferedWriter(new FileWriter(FileUtils.getFile(APPCONST.TXT_BOOK_DIR + book.getName() + ".txt"))); - if (chapters.size() == 0){ + if (chapters.size() == 0) { return false; } File bookFile = new File(APPCONST.BOOK_CACHE_PATH + book.getId()); - if (!bookFile.exists()){ + if (!bookFile.exists()) { return false; } - for (Chapter chapter : chapters){ - if(ChapterService.isChapterCached(chapter.getBookId(), chapter.getTitle())){ + for (Chapter chapter : chapters) { + if (ChapterService.isChapterCached(chapter.getBookId(), chapter.getTitle())) { bw.write("\t" + chapter.getTitle()); bw.newLine(); br = new BufferedReader(new FileReader(APPCONST.BOOK_CACHE_PATH + book.getId() + File.separator + chapter.getTitle() + FileUtils.SUFFIX_FY)); String line = null; - while ((line = br.readLine()) != null){ + while ((line = br.readLine()) != null) { bw.write(line); bw.newLine(); } @@ -167,6 +200,68 @@ public abstract class BookcaseAdapter extends DragAdapter { return true; } + + //设置点击切换 + public void setCheckedBook(String bookId) { + boolean isSelected = mCheckMap.get(bookId); + if (isSelected) { + mCheckMap.put(bookId, false); + --mCheckedCount; + } else { + mCheckMap.put(bookId, true); + ++mCheckedCount; + } + notifyDataSetChanged(); + } + + //全选 + public void setCheckedAll(boolean isChecked) { + mCheckedCount = isChecked ? mCheckMap.size() : 0; + for (String bookId : mCheckMap.keySet()) { + mCheckMap.put(bookId, isChecked); + } + mListener.onItemCheckedChange(true); + notifyDataSetChanged(); + } + + public boolean getBookIsChecked(String bookId) { + return mCheckMap.get(bookId); + } + + public int getmCheckedCount() { + return mCheckedCount; + } + + public int getmCheckableCount() { + return mCheckMap.size(); + } + + public boolean isCheckedAll() { + return isCheckedAll; + } + + public void setIsCheckedAll(boolean isCheckedAll) { + this.isCheckedAll = isCheckedAll; + } + + public List getSelectBooks() { + List mSelectBooks = new ArrayList<>(); + for (String bookId : mCheckMap.keySet()) { + if (mCheckMap.get(bookId)) { + mSelectBooks.add(mBookService.getBookById(bookId)); + } + } + return mSelectBooks; + } + + public boolean isGroup() { + return isGroup; + } + + public void setGroup(boolean group) { + isGroup = group; + } + /*******************************************缓存书籍*********************************************************/ private int selectedIndex;//对话框选择下标 @@ -175,13 +270,13 @@ public abstract class BookcaseAdapter extends DragAdapter { ToastUtils.showWarring("无网络连接!"); return; } - if ("本地书籍".equals(book.getType())){ + if ("本地书籍".equals(book.getType())) { ToastUtils.showWarring("《" + book.getName() + "》是本地书籍,不能缓存"); return; } final int[] begin = new int[1]; final int[] end = new int[1]; - new AlertDialog.Builder(mContext) + MyAlertDialog.build(mContext) .setTitle("缓存书籍") .setSingleChoiceItems(APPCONST.DIALOG_DOWNLOAD, selectedIndex, new DialogInterface.OnClickListener() { @Override @@ -192,7 +287,7 @@ public abstract class BookcaseAdapter extends DragAdapter { (dialog, which) -> { switch (selectedIndex) { case 0: - begin[0] = book.getHisttoryChapterNum(); + begin[0] = book.getHisttoryChapterNum(); end[0] = book.getHisttoryChapterNum() + 50; break; case 1: @@ -217,10 +312,19 @@ public abstract class BookcaseAdapter extends DragAdapter { } static class ViewHolder { + CheckBox cbBookChecked; ImageView ivBookImg; TextView tvBookName; BadgeView tvNoReadNum; - ImageView ivDelete; ProgressBar pbLoading; } + + public void setOnBookCheckedListener(OnBookCheckedListener listener) { + mListener = listener; + } + + //书籍点击监听器 + public interface OnBookCheckedListener { + void onItemCheckedChange(boolean isChecked); + } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDetailedAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDetailedAdapter.java index 7619d0c..f1b2ecf 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDetailedAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDetailedAdapter.java @@ -22,6 +22,7 @@ import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.creator.MyAlertDialog; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.ui.activity.BookDetailedActivity; import xyz.fycz.myreader.ui.activity.ReadActivity; @@ -39,8 +40,8 @@ public class BookcaseDetailedAdapter extends BookcaseAdapter { ViewHolder viewHolder = null; public BookcaseDetailedAdapter(Context context, int textViewResourceId, ArrayList objects, - boolean editState, BookcasePresenter bookcasePresenter) { - super(context, textViewResourceId, objects, editState, bookcasePresenter); + boolean editState, BookcasePresenter bookcasePresenter, boolean isGroup) { + super(context, textViewResourceId, objects, editState, bookcasePresenter, isGroup); } @Override @@ -48,10 +49,10 @@ public class BookcaseDetailedAdapter extends BookcaseAdapter { if (convertView == null || convertView.getTag() instanceof BookcaseDragAdapter.ViewHolder) { viewHolder = new ViewHolder(); convertView = LayoutInflater.from(mContext).inflate(mResourceId, null); + viewHolder.cbBookChecked = convertView.findViewById(R.id.cb_book_select); viewHolder.ivBookImg = convertView.findViewById(R.id.iv_book_img); viewHolder.tvBookName = convertView.findViewById(R.id.tv_book_name); viewHolder.tvNoReadNum = convertView.findViewById(R.id.tv_no_read_num); - viewHolder.ivDelete = convertView.findViewById(R.id.iv_delete); viewHolder.tvBookAuthor = convertView.findViewById(R.id.tv_book_author); viewHolder.tvHistoryChapter = convertView.findViewById(R.id.tv_book_history_chapter); viewHolder.tvNewestChapter = convertView.findViewById(R.id.tv_book_newest_chapter); @@ -79,7 +80,6 @@ public class BookcaseDetailedAdapter extends BookcaseAdapter { .into(viewHolder.ivBookImg); viewHolder.tvBookName.setText(book.getName()); - viewHolder.ivDelete.setOnClickListener(v -> showDeleteBookDialog(book)); viewHolder.tvBookAuthor.setText(book.getAuthor()); viewHolder.tvHistoryChapter.setText(book.getHistoryChapterId()); @@ -88,21 +88,34 @@ public class BookcaseDetailedAdapter extends BookcaseAdapter { if (mEditState) { viewHolder.tvNoReadNum.setVisibility(View.GONE); - viewHolder.ivDelete.setVisibility(View.VISIBLE); viewHolder.ivBookImg.setOnClickListener(null); viewHolder.llBookRead.setOnClickListener(null); viewHolder.pbLoading.setVisibility(View.GONE); + viewHolder.cbBookChecked.setVisibility(View.VISIBLE); + viewHolder.cbBookChecked.setChecked(getBookIsChecked(book.getId())); + viewHolder.llBookRead.setOnClickListener(v -> { + setCheckedBook(book.getId()); + mListener.onItemCheckedChange(getBookIsChecked(book.getId())); + }); + viewHolder.ivBookImg.setOnClickListener(v -> { + setCheckedBook(book.getId()); + mListener.onItemCheckedChange(getBookIsChecked(book.getId())); + }); + viewHolder.cbBookChecked.setOnClickListener(v -> { + setCheckedBook(book.getId()); + mListener.onItemCheckedChange(getBookIsChecked(book.getId())); + }); } else { - viewHolder.ivDelete.setVisibility(View.GONE); + viewHolder.cbBookChecked.setVisibility(View.GONE); boolean isLoading = false; try { isLoading = isBookLoading(book.getId()); - }catch (Exception ignored){ + } catch (Exception ignored) { } - if (isLoading){ + if (isLoading) { viewHolder.pbLoading.setVisibility(View.VISIBLE); viewHolder.tvNoReadNum.setVisibility(View.GONE); - }else { + } else { viewHolder.pbLoading.setVisibility(View.GONE); int notReadNum = book.getChapterTotalNum() - book.getHisttoryChapterNum() + book.getNoReadNum() - 1; if (notReadNum != 0) { @@ -133,44 +146,46 @@ public class BookcaseDetailedAdapter extends BookcaseAdapter { }); viewHolder.llBookRead.setOnLongClickListener(v -> { if (!ismEditState()) { - AlertDialog bookDialog = new AlertDialog.Builder(mContext) + AlertDialog bookDialog = MyAlertDialog.build(mContext) .setTitle(book.getName()) - .setAdapter(new ArrayAdapter<>(mContext, - android.R.layout.simple_list_item_1, menu), - (dialog, which) -> { - switch (which) { - case 0: - book.setSortCode(0); - mBookService.updateEntity(book); - mBookcasePresenter.init(); - ToastUtils.showSuccess("书籍《" + book.getName() + "》移至顶部成功!"); - break; - case 1: - downloadBook(book); - break; - case 2: - MyApplication.getApplication().newThread(() -> { - try { - if (unionChapterCathe(book)) { - DialogCreator.createTipDialog(mContext, - "缓存导出成功,导出目录:" - + APPCONST.TXT_BOOK_DIR); - } else { - DialogCreator.createTipDialog(mContext, - "章节目录为空或未找到缓存文件,缓存导出失败!"); - } - } catch (IOException e) { - e.printStackTrace(); - DialogCreator.createTipDialog(mContext, - "章节目录为空或未找到缓存文件,缓存导出失败!"); - } - }); - break; - case 3: - showDeleteBookDialog(book); - break; + .setItems(menu, (dialog, which) -> { + switch (which) { + case 0: + if (!isGroup) { + book.setSortCode(0); + }else { + book.setGroupSort(0); } - }) + mBookService.updateEntity(book); + mBookcasePresenter.init(); + ToastUtils.showSuccess("书籍《" + book.getName() + "》移至顶部成功!"); + break; + case 1: + downloadBook(book); + break; + case 2: + MyApplication.getApplication().newThread(() -> { + try { + if (unionChapterCathe(book)) { + DialogCreator.createTipDialog(mContext, + "缓存导出成功,导出目录:" + + APPCONST.TXT_BOOK_DIR); + } else { + DialogCreator.createTipDialog(mContext, + "章节目录为空或未找到缓存文件,缓存导出失败!"); + } + } catch (IOException e) { + e.printStackTrace(); + DialogCreator.createTipDialog(mContext, + "章节目录为空或未找到缓存文件,缓存导出失败!"); + } + }); + break; + case 3: + showDeleteBookDialog(book); + break; + } + }) .setNegativeButton(null, null) .setPositiveButton(null, null) .create(); @@ -181,7 +196,7 @@ public class BookcaseDetailedAdapter extends BookcaseAdapter { }); } } - + static class ViewHolder extends BookcaseAdapter.ViewHolder { TextView tvBookAuthor; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java index 43dc41f..48a9c99 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java @@ -21,6 +21,7 @@ import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.creator.MyAlertDialog; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.ui.activity.BookDetailedActivity; import xyz.fycz.myreader.ui.activity.ReadActivity; @@ -39,8 +40,8 @@ public class BookcaseDragAdapter extends BookcaseAdapter { MyApplication.getmContext().getResources().getString(R.string.menu_book_delete) }; public BookcaseDragAdapter(Context context, int textViewResourceId, ArrayList objects, - boolean editState, BookcasePresenter bookcasePresenter) { - super(context, textViewResourceId, objects, editState, bookcasePresenter); + boolean editState, BookcasePresenter bookcasePresenter, boolean isGroup) { + super(context, textViewResourceId, objects, editState, bookcasePresenter, isGroup); } @@ -49,10 +50,10 @@ public class BookcaseDragAdapter extends BookcaseAdapter { if (convertView == null || convertView.getTag() instanceof BookcaseDetailedAdapter.ViewHolder) { viewHolder = new ViewHolder(); convertView = LayoutInflater.from(mContext).inflate(mResourceId, null); + viewHolder.cbBookChecked = convertView.findViewById(R.id.cb_book_select); viewHolder.ivBookImg = convertView.findViewById(R.id.iv_book_img); viewHolder.tvBookName = convertView.findViewById(R.id.tv_book_name); viewHolder.tvNoReadNum = convertView.findViewById(R.id.tv_no_read_num); - viewHolder.ivDelete = convertView.findViewById(R.id.iv_delete); viewHolder.pbLoading = convertView.findViewById(R.id.pb_loading); convertView.setTag(viewHolder); } else { @@ -77,16 +78,18 @@ public class BookcaseDragAdapter extends BookcaseAdapter { .into(viewHolder.ivBookImg); viewHolder.tvBookName.setText(book.getName()); - viewHolder.ivDelete.setOnClickListener(v -> showDeleteBookDialog(book)); - if (mEditState) { viewHolder.tvNoReadNum.setVisibility(View.GONE); - viewHolder.ivDelete.setVisibility(View.VISIBLE); viewHolder.pbLoading.setVisibility(View.GONE); - viewHolder.ivBookImg.setOnClickListener(null); + viewHolder.ivBookImg.setOnClickListener(v -> { + setCheckedBook(book.getId()); + mListener.onItemCheckedChange(getBookIsChecked(book.getId())); + }); + viewHolder.cbBookChecked.setVisibility(View.VISIBLE); + viewHolder.cbBookChecked.setChecked(getBookIsChecked(book.getId())); } else { - viewHolder.ivDelete.setVisibility(View.GONE); + viewHolder.cbBookChecked.setVisibility(View.GONE); boolean isLoading = false; try { isLoading = isBookLoading(book.getId()); @@ -121,11 +124,9 @@ public class BookcaseDragAdapter extends BookcaseAdapter { }); viewHolder.ivBookImg.setOnLongClickListener(v -> { if (!ismEditState()) { - AlertDialog bookDialog = new AlertDialog.Builder(mContext) + AlertDialog bookDialog = MyAlertDialog.build(mContext) .setTitle(book.getName()) - .setAdapter(new ArrayAdapter<>(mContext, - android.R.layout.simple_list_item_1, menu), - (dialog, which) -> { + .setItems(menu, (dialog, which) -> { switch (which) { case 0: Intent intent = new Intent(mContext, BookDetailedActivity.class); @@ -133,7 +134,11 @@ public class BookcaseDragAdapter extends BookcaseAdapter { mContext.startActivity(intent); break; case 1: - book.setSortCode(0); + if (!isGroup) { + book.setSortCode(0); + }else { + book.setGroupSort(0); + } mBookService.updateEntity(book); mBookcasePresenter.init(); ToastUtils.showSuccess("书籍《" + book.getName() + "》移至顶部成功!"); diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/ChapterTitleAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/ChapterTitleAdapter.java index 73aa402..e097d59 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/ChapterTitleAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/ChapterTitleAdapter.java @@ -71,12 +71,13 @@ public class ChapterTitleAdapter extends ArrayAdapter { } else { viewHolder.tvTitle.setCompoundDrawablesWithIntrinsicBounds(getContext().getResources().getDrawable(R.drawable.selector_category_unload), null, null, null); } - if (!setting.isDayStyle()) { + viewHolder.tvTitle.setTextColor(getContext().getColor(R.color.textSecondary)); + /*if (!setting.isDayStyle()) { viewHolder.tvTitle.setTextColor(getContext().getResources().getColor(R.color.sys_night_word)); viewHolder.vLine.setBackground(getContext().getDrawable(R.color.sys_dialog_setting_line)); }else { viewHolder.tvTitle.setTextColor(getContext().getColor(R.color.title_black)); - } + }*/ if (chapter.getNumber() == mBook.getHisttoryChapterNum()) { viewHolder.tvTitle.setTextColor(getContext().getResources().getColor(R.color.colorAccent)); diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/FontsAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/FontsAdapter.java index 1bf71e0..5601a6c 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/FontsAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/FontsAdapter.java @@ -10,7 +10,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; -import android.widget.Button; import android.widget.TextView; import androidx.annotation.NonNull; @@ -118,6 +117,7 @@ public class FontsAdapter extends ArrayAdapter { //viewHolder.tvExample.setTypeface(typeFace); // viewHolder.tvExample.setTypeface(mTypefaceMap.get(font)); viewHolder.tvFontName.setText(font.toString()); + viewHolder.tvFontName.setTextColor(mFontsActivity.getColor(R.color.textPrimary)); File fontFile = new File(APPCONST.FONT_BOOK_DIR + font.fileName); if (font == Font.本地字体) { if (setting.getFont() == Font.本地字体) { @@ -145,7 +145,7 @@ public class FontsAdapter extends ArrayAdapter { checkedItem = i; } } - AlertDialog dialog = new AlertDialog.Builder(getContext()) + MyAlertDialog dialog = new MyAlertDialog.Builder(getContext()) .setTitle(getContext().getString(R.string.font_select)) .setCancelable(true) .setSingleChoiceItems(fontNames, checkedItem, new DialogInterface.OnClickListener() { diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/TabFragmentPageAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/TabFragmentPageAdapter.java new file mode 100644 index 0000000..5d0ae37 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/TabFragmentPageAdapter.java @@ -0,0 +1,54 @@ +package xyz.fycz.myreader.ui.adapter; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Zhouas666 on 2019-03-28 + * Github: https://github.com/zas023 + */ +public class TabFragmentPageAdapter extends FragmentPagerAdapter { + + private List mFragmentList; + private List mTitleList; + + public TabFragmentPageAdapter(@NonNull FragmentManager fm) { + super(fm); + mFragmentList = new ArrayList<>(); + mTitleList = new ArrayList<>(); + } + + public void addFragment(Fragment fragment) { + mFragmentList.add(fragment); + } + + public void addFragment(Fragment fragment,String title) { + mFragmentList.add(fragment); + mTitleList.add(title); + } + + public void addTitle(String title) { + mTitleList.add(title); + } + + @NonNull + @Override + public Fragment getItem(int position) { + return mFragmentList.get(position); + } + + @Override + public int getCount() { + return mFragmentList.size(); + } + + @Override + public CharSequence getPageTitle(int position) { + return mTitleList.get(position); + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/BookStoreBookHolder.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/BookStoreBookHolder.java new file mode 100644 index 0000000..7a6a9e4 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/BookStoreBookHolder.java @@ -0,0 +1,82 @@ +package xyz.fycz.myreader.ui.adapter.holder; + +import android.app.Activity; +import android.content.Intent; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +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.common.APPCONST; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.ui.activity.BookDetailedActivity; + +/** + * @author fengyue + * @date 2020/9/7 7:35 + */ +public class BookStoreBookHolder extends ViewHolderImpl { + + private ImageView tvBookImg; + private TextView tvBookName; + private TextView tvBookAuthor; + private TextView tvBookTime; + private TextView tvBookNewestChapter; + private TextView tvBookSource; + + private boolean hasImg; + private Activity mActivity; + + public BookStoreBookHolder(boolean hasImg, Activity mActivity) { + this.hasImg = hasImg; + this.mActivity = mActivity; + } + + + @Override + protected int getItemLayoutId() { + return R.layout.listview_book_store_book_item; + } + + @Override + public void initView() { + tvBookImg = findById(R.id.iv_book_img); + tvBookName = findById(R.id.tv_book_name); + tvBookAuthor = findById(R.id.tv_book_author); + tvBookNewestChapter = findById(R.id.tv_book_newest_chapter); + tvBookTime = findById(R.id.tv_book_time); + tvBookSource = findById(R.id.tv_book_source); + } + + @Override + public void onBind(Book data, int pos) { + tvBookName.setText(data.getName()); + tvBookAuthor.setText(data.getAuthor()); + tvBookNewestChapter.setText(data.getNewestChapterTitle()); + tvBookTime.setText(data.getUpdateDate()); + if (hasImg){ + tvBookImg.setVisibility(View.VISIBLE); + if (!MyApplication.isDestroy(mActivity)) { + Glide.with(getContext()) + .load(data.getImgUrl()) + .error(R.mipmap.no_image) + .placeholder(R.mipmap.no_image) + //设置圆角 + .apply(RequestOptions.bitmapTransform(new RoundedCorners(8))) + .into(tvBookImg); + } + } + if (data.getSource() != null) { + tvBookSource.setText("书源:" + BookSource.fromString(data.getSource()).text); + }else { + tvBookSource.setText(data.getNewestChapterId()); + } + } + +} diff --git a/app/src/main/java/xyz/fycz/myreader/ui/fragment/BookStoreFragment.java b/app/src/main/java/xyz/fycz/myreader/ui/fragment/BookStoreFragment.java index cbdaffa..bf1fb1c 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/fragment/BookStoreFragment.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/fragment/BookStoreFragment.java @@ -2,9 +2,14 @@ package xyz.fycz.myreader.ui.fragment; import android.os.Bundle; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.webkit.CookieManager; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.ProgressBar; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.RecyclerView; import butterknife.BindView; @@ -12,22 +17,30 @@ import butterknife.ButterKnife; import butterknife.Unbinder; import com.scwang.smartrefresh.layout.SmartRefreshLayout; import xyz.fycz.myreader.R; +import xyz.fycz.myreader.custom.DragSortGridView; import xyz.fycz.myreader.ui.presenter.BookStorePresenter; +import xyz.fycz.myreader.util.SharedPreUtils; +import xyz.fycz.myreader.util.StringHelper; +import xyz.fycz.myreader.widget.RefreshLayout; /** * A simple {@link Fragment} subclass. */ public class BookStoreFragment extends Fragment { + @BindView(R.id.refresh_layout) + RefreshLayout mRlRefresh; @BindView(R.id.rv_type_list) RecyclerView rvTypeList; @BindView(R.id.rv_book_list) RecyclerView rvBookList; @BindView(R.id.srl_book_list) SmartRefreshLayout srlBookList; + @BindView(R.id.pb_loading) + ProgressBar pbLoading; Unbinder unbinder; private BookStorePresenter mBookStorePresenter; - + private boolean isFirstInit; public BookStoreFragment() { // Required empty public constructor @@ -40,12 +53,22 @@ public class BookStoreFragment extends Fragment { // Inflate the layout for this fragment View view = inflater.inflate(R.layout.fragment_book_store, container, false); unbinder = ButterKnife.bind(this, view); - mBookStorePresenter = new BookStorePresenter(this); - mBookStorePresenter.start(); + /*mBookStorePresenter = new BookStorePresenter(this); + mBookStorePresenter.start();*/ + isFirstInit = true; return view; } + + public void lazyLoad() { + if (isFirstInit) { + mBookStorePresenter = new BookStorePresenter(this); + mBookStorePresenter.start(); + isFirstInit = false; + } + } + public RecyclerView getRvTypeList() { return rvTypeList; } @@ -58,4 +81,11 @@ public class BookStoreFragment extends Fragment { return srlBookList; } + public ProgressBar getPbLoading() { + return pbLoading; + } + + public RefreshLayout getmRlRefresh() { + return mRlRefresh; + } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/fragment/BookcaseFragment.java b/app/src/main/java/xyz/fycz/myreader/ui/fragment/BookcaseFragment.java index d537f01..4ec8508 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/fragment/BookcaseFragment.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/fragment/BookcaseFragment.java @@ -3,17 +3,16 @@ package xyz.fycz.myreader.ui.fragment; import android.os.Build; import android.os.Bundle; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.LinearLayout; +import android.widget.*; -import android.widget.ProgressBar; -import android.widget.RelativeLayout; -import android.widget.TextView; import androidx.fragment.app.Fragment; import com.scwang.smartrefresh.layout.SmartRefreshLayout; import xyz.fycz.myreader.R; +import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.custom.DragSortGridView; import butterknife.ButterKnife; @@ -39,6 +38,14 @@ public class BookcaseFragment extends Fragment { TextView tvStopDownload; @BindView(R.id.pb_download) ProgressBar pbDownload; + @BindView(R.id.rl_book_edit) + RelativeLayout rlBookEdit; + @BindView(R.id.book_selected_all) + CheckBox mCbSelectAll; + @BindView(R.id.book_btn_delete) + Button mBtnDelete; + @BindView(R.id.book_add_group) + Button mBtnAddGroup; Unbinder unbinder; @@ -108,4 +115,24 @@ public class BookcaseFragment extends Fragment { public BookcasePresenter getmBookcasePresenter() { return mBookcasePresenter; } + + public boolean isRecreate() { + return unbinder == null; + } + + public RelativeLayout getRlBookEdit() { + return rlBookEdit; + } + + public CheckBox getmCbSelectAll() { + return mCbSelectAll; + } + + public Button getmBtnDelete() { + return mBtnDelete; + } + + public Button getmBtnAddGroup() { + return mBtnAddGroup; + } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/fragment/FindFragment.java b/app/src/main/java/xyz/fycz/myreader/ui/fragment/FindFragment.java new file mode 100644 index 0000000..5e23e2a --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/ui/fragment/FindFragment.java @@ -0,0 +1,57 @@ +package xyz.fycz.myreader.ui.fragment; + +import android.content.Intent; +import android.widget.RelativeLayout; +import butterknife.BindView; +import xyz.fycz.myreader.R; +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.FindCrawler; +import xyz.fycz.myreader.webapi.crawler.QB5ReadCrawler; +import xyz.fycz.myreader.webapi.crawler.find.ABC; + +/** + * @author fengyue + * @date 2020/9/13 21:07 + */ +public class FindFragment extends BaseFragment { + @BindView(R.id.find_rl_qidian_top) + RelativeLayout mRlQiDianTop; + @BindView(R.id.find_rl_qidian_ns_top) + RelativeLayout mRlQiDianNSTop; + @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; + + @Override + protected int getContentId() { + return R.layout.fragment_find; + } + + @Override + protected void initClick() { + super.initClick(); + mRlQiDianTop.setOnClickListener(v -> comeToBookstore(new ABC(false))); + mRlQiDianNSTop.setOnClickListener(v -> comeToBookstore(new ABC(true))); + mRlQiDianSort.setOnClickListener(v -> comeToBookstore(new ABC(false, true))); + mRlQiDianNSSort.setOnClickListener(v -> comeToBookstore(new ABC(true, true))); + mRlQB5Store.setOnClickListener(v -> comeToBookstore(new QB5ReadCrawler())); + } + + + private void comeToBookstore(FindCrawler findCrawler){ + Intent intent = new Intent(getContext(), BookstoreActivity.class); + intent.putExtra(APPCONST.FIND_CRAWLER, findCrawler); + startActivity(intent); + } + + public boolean isRecreate() { + return unbinder == null; + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java b/app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java new file mode 100644 index 0000000..da741f4 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java @@ -0,0 +1,397 @@ +package xyz.fycz.myreader.ui.fragment; + +import android.annotation.SuppressLint; +import android.content.*; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.widget.ArrayAdapter; +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.backup.BackupAndRestore; +import xyz.fycz.myreader.backup.UserService; +import xyz.fycz.myreader.base.BaseFragment; +import xyz.fycz.myreader.common.APPCONST; +import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.creator.MyAlertDialog; +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 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 BackupAndRestore mBackupAndRestore; + private Setting mSetting; + private String[] webSynMenu; + private String[] backupMenu; + private AlertDialog themeModeDia; + private int themeMode; + private String[] themeModeArr; + @SuppressLint("HandlerLeak") + private Handler mHandler = new Handler() { + @Override + public void handleMessage(@NonNull Message msg) { + switch (msg.what) { + case 1: + mTvUser.setText("登录/注册"); + break; + case 2: + backup(); + break; + case 3: + restore(); + break; + } + } + }; + + public MineFragment() { + } + + @Override + protected int getContentId() { + return R.layout.fragment_mine; + } + + @Override + protected void initData(Bundle savedInstanceState) { + super.initData(savedInstanceState); + isLogin = UserService.isLogin(); + mBackupAndRestore = new BackupAndRestore(); + mSetting = SysManager.getSetting(); + webSynMenu = new String[]{ + MyApplication.getmContext().getString(R.string.menu_backup_webBackup), + MyApplication.getmContext().getString(R.string.menu_backup_webRestore), + MyApplication.getmContext().getString(R.string.menu_backup_autoSyn) + }; + backupMenu = new String[]{ + MyApplication.getmContext().getResources().getString(R.string.menu_backup_backup), + MyApplication.getmContext().getResources().getString(R.string.menu_backup_restore), + }; + themeMode = MyApplication.getApplication().isNightFS() ? 0 : mSetting.isDayStyle() ? 1 : 2; + themeModeArr = getResources().getStringArray(R.array.theme_mode_arr); + } + + @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)) + .setItems(backupMenu, (dialog, which) -> { + switch (which) { + case 0: + mHandler.sendMessage(mHandler.obtainMessage(2)); + break; + case 1: + mHandler.sendMessage(mHandler.obtainMessage(3)); + break; + } + }) + .setNegativeButton(null, null) + .setPositiveButton(null, null) + .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); + }); + mRlThemeMode.setOnClickListener(v -> { + if (themeModeDia != null) { + themeModeDia.show(); + return; + } + themeModeDia = MyAlertDialog.build(getContext()) + .setTitle("主题模式") + .setSingleChoiceItems(themeModeArr, themeMode + , (dialog, which) -> { + if (themeMode == which) { + dialog.dismiss(); + return; + } + themeMode = which; + switch (which) { + case 0: + SharedPreUtils.getInstance().putBoolean("isNightFS", true); + break; + case 1: + SharedPreUtils.getInstance().putBoolean("isNightFS", false); + mSetting.setDayStyle(true); + SysManager.saveSetting(mSetting); + break; + case 2: + SharedPreUtils.getInstance().putBoolean("isNightFS", false); + mSetting.setDayStyle(false); + SysManager.saveSetting(mSetting); + break; + } + dialog.dismiss(); + tvThemeModeSelect.setText(themeModeArr[themeMode]); + MyApplication.getApplication().initNightTheme(); + }) + .setNegativeButton("取消", null) + .create(); + themeModeDia.show(); + + }); + + mRlAbout.setOnClickListener(v -> { + Intent aboutIntent = new Intent(getActivity(), AboutActivity.class); + 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 + protected void processLogic() { + super.processLogic(); + } + + /** + * 备份 + */ + private void backup() { + ArrayList mBooks = (ArrayList) BookService.getInstance().getAllBooks(); + if (mBooks.size() == 0) { + ToastUtils.showWarring("当前书架无任何书籍,无法备份!"); + return; + } + DialogCreator.createCommonDialog(getContext(), "确认备份吗?", "新备份会替换原有备份!", true, + (dialogInterface, i) -> { + dialogInterface.dismiss(); + if (mBackupAndRestore.backup("localBackup")) { + DialogCreator.createTipDialog(getContext(), "备份成功,备份文件路径:" + APPCONST.BACKUP_FILE_DIR); + } else { + DialogCreator.createTipDialog(getContext(), "未给予储存权限,备份失败!"); + } + }, (dialogInterface, i) -> dialogInterface.dismiss()); + } + + /** + * 恢复 + */ + private void restore() { + DialogCreator.createCommonDialog(getContext(), "确认恢复吗?", "恢复书架会覆盖原有书架!", true, + (dialogInterface, i) -> { + dialogInterface.dismiss(); + if (mBackupAndRestore.restore("localBackup")) { + mHandler.sendMessage(mHandler.obtainMessage(7)); +// DialogCreator.createTipDialog(mMainActivity, +// "恢复成功!\n注意:本功能属于实验功能,书架恢复后,书籍初次加载时可能加载失败,返回重新加载即可!"); + mSetting = SysManager.getSetting(); + ToastUtils.showSuccess("书架恢复成功!"); + } else { + DialogCreator.createTipDialog(getContext(), "未找到备份文件或未给予储存权限,恢复失败!"); + } + }, (dialogInterface, i) -> dialogInterface.dismiss()); + } + + /** + * 同步书架 + */ + private void synBookcaseToWeb(boolean isAutoSyn) { + if (!NetworkUtils.isNetWorkAvailable()) { + if (!isAutoSyn) { + ToastUtils.showWarring("无网络连接!"); + } + return; + } + ArrayList mBooks = (ArrayList) 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("synTime"); + if (!nowTimeStr.equals(synTime) || !isAutoSyn) { + MyApplication.getApplication().newThread(() -> { + if (UserService.webBackup()) { + spb.putString("synTime", nowTimeStr); + if (!isAutoSyn) { + DialogCreator.createTipDialog(getContext(), "成功将书架同步至网络!"); + } + } else { + if (!isAutoSyn) { + DialogCreator.createTipDialog(getContext(), "同步失败,请重试!"); + } + } + }); + } + } + + /** + * 恢复 + */ + 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(), "未找到同步文件,同步失败!"); + } + }); + }, (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; + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/AboutPresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/AboutPresenter.java deleted file mode 100644 index 390b65c..0000000 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/AboutPresenter.java +++ /dev/null @@ -1,62 +0,0 @@ -package xyz.fycz.myreader.ui.presenter; - -import android.annotation.SuppressLint; -import android.content.ClipData; -import android.content.ClipboardManager; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import xyz.fycz.myreader.R; -import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.base.BasePresenter; -import xyz.fycz.myreader.creator.DialogCreator; -import xyz.fycz.myreader.ui.activity.AboutActivity; -import xyz.fycz.myreader.util.ShareUtils; -import xyz.fycz.myreader.util.SharedPreUtils; -import xyz.fycz.myreader.util.ToastUtils; - -/** - * @author fengyue - * @date 2020/7/31 11:39 - */ -public class AboutPresenter implements BasePresenter { - - private AboutActivity mAboutActivity; - - public AboutPresenter(AboutActivity mAboutActivity) { - this.mAboutActivity = mAboutActivity; - } - - @SuppressLint("SetTextI18n") - @Override - public void start() { - mAboutActivity.getLlTitleBack().setOnClickListener(v -> mAboutActivity.finish()); - mAboutActivity.getTvTitleText().setText("关于"); - mAboutActivity.getTvVersionName().setText("风月读书v" + MyApplication.getStrVersionName()); - mAboutActivity.getVmAuthor().setOnClickListener(v -> { - ClipboardManager mClipboardManager = (ClipboardManager) mAboutActivity.getSystemService(Context.CLIPBOARD_SERVICE); - //数据 - ClipData mClipData = ClipData.newPlainText("Label", "fy@fycz.xyz"); - //把数据设置到剪切板上 - assert mClipboardManager != null; - mClipboardManager.setPrimaryClip(mClipData); - ToastUtils.showSuccess("邮箱复制成功!"); - }); - mAboutActivity.getVmShare().setOnClickListener(v -> ShareUtils.share(mAboutActivity, mAboutActivity.getString(R.string.share_text) + - SharedPreUtils.getInstance().getString("downloadLink"))); - mAboutActivity.getVmUpdate().setOnClickListener(v -> MyApplication.checkVersionByServer(mAboutActivity, true, null)); - mAboutActivity.getVmUpdateLog().setOnClickListener(v -> DialogCreator.createAssetTipDialog(mAboutActivity, "更新日志", "updatelog.fy")); - mAboutActivity.getVmGit().setOnClickListener(v -> openIntent(Intent.ACTION_VIEW, mAboutActivity.getString(R.string.this_github_url))); - mAboutActivity.getVmDisclaimer().setOnClickListener(v -> DialogCreator.createAssetTipDialog(mAboutActivity, "免责声明", "disclaimer.fy")); - } - - void openIntent(String intentName, String address) { - try { - Intent intent = new Intent(intentName); - intent.setData(Uri.parse(address)); - mAboutActivity.startActivity(intent); - } catch (Exception e) { - ToastUtils.showError(e.getLocalizedMessage()); - } - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookMarkPresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookMarkPresenter.java index c0a38b6..ffe664f 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookMarkPresenter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookMarkPresenter.java @@ -9,6 +9,7 @@ import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.entity.BookMark; import xyz.fycz.myreader.greendao.service.BookMarkService; +import xyz.fycz.myreader.ui.activity.CatalogActivity; import xyz.fycz.myreader.ui.adapter.BookMarkAdapter; import xyz.fycz.myreader.ui.fragment.BookMarkFragment; @@ -32,10 +33,7 @@ public class BookMarkPresenter implements BasePresenter { @Override public void start() { - mBook = (Book) mBookMarkFragment.getActivity().getIntent().getSerializableExtra(APPCONST.BOOK); - if (!SysManager.getSetting().isDayStyle()) { - mBookMarkFragment.getLvBookmarkList().setBackground(mBookMarkFragment.getActivity().getDrawable(R.color.sys_dialog_setting_bg)); - } + mBook = ((CatalogActivity) mBookMarkFragment.getActivity()).getmBook();; initBookMarkList(); mBookMarkFragment.getLvBookmarkList().setOnItemClickListener((parent, view, position, id) -> { BookMark bookMark = mBookMarks.get(position); diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookStorePresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookStorePresenter.java index 3add5d1..11aa653 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookStorePresenter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookStorePresenter.java @@ -5,15 +5,14 @@ import android.content.Intent; import android.os.Handler; import android.os.Message; import android.view.View; -import androidx.annotation.NonNull; import androidx.recyclerview.widget.LinearLayoutManager; -import com.scwang.smartrefresh.layout.api.RefreshLayout; -import com.scwang.smartrefresh.layout.listener.OnRefreshListener; import xyz.fycz.myreader.base.BasePresenter; import xyz.fycz.myreader.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.common.URLCONST; +import xyz.fycz.myreader.creator.ChangeSourceDialog; +import xyz.fycz.myreader.creator.DialogCreator; import xyz.fycz.myreader.entity.bookstore.BookType; +import xyz.fycz.myreader.entity.bookstore.RankBook; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.ui.activity.BookDetailedActivity; import xyz.fycz.myreader.ui.activity.MainActivity; @@ -21,7 +20,7 @@ import xyz.fycz.myreader.ui.adapter.BookStoreBookAdapter; import xyz.fycz.myreader.ui.adapter.BookStoreBookTypeAdapter; import xyz.fycz.myreader.ui.fragment.BookStoreFragment; import xyz.fycz.myreader.util.ToastUtils; -import xyz.fycz.myreader.webapi.BookStoreApi; +import xyz.fycz.myreader.webapi.crawler.find.ABC; import java.util.ArrayList; @@ -39,14 +38,13 @@ public class BookStorePresenter implements BasePresenter { private BookStoreBookTypeAdapter mBookStoreBookTypeAdapter; private List mBookTypes; - private BookStoreBookAdapter mBookStoreBookAdapter; - private List bookList; + private List bookList = new ArrayList<>(); private BookType curType; + private ABC findCrawler; - - + private int page = 1; @SuppressLint("HandlerLeak") private Handler mHandler = new Handler() { @@ -55,40 +53,88 @@ public class BookStorePresenter implements BasePresenter { switch (msg.what) { case 1: initTypeList(); - + mBookStoreFragment.getmRlRefresh().showFinish(); break; - case 2: - initBookList(); - + List bookList = (List) msg.obj; + initBookList(bookList); + mBookStoreFragment.getSrlBookList().setEnableRefresh(true); + mBookStoreFragment.getSrlBookList().setEnableLoadMore(true); + mBookStoreFragment.getPbLoading().setVisibility(View.GONE); + break; + case 3: + mBookStoreFragment.getPbLoading().setVisibility(View.VISIBLE); + break; + case 4: + mBookStoreFragment.getPbLoading().setVisibility(View.GONE); + mBookStoreFragment.getSrlBookList().finishRefresh(false); + mBookStoreFragment.getSrlBookList().finishLoadMore(false); + break; + case 5: + mBookStoreFragment.getmRlRefresh().showError(); break; - - } } }; - public BookStorePresenter(BookStoreFragment bookStoreFragment){ - mBookStoreFragment = bookStoreFragment; - mMainActivity = ((MainActivity) (mBookStoreFragment.getActivity())); + public BookStorePresenter(BookStoreFragment bookStoreFragment) { + mBookStoreFragment = bookStoreFragment; + mMainActivity = ((MainActivity) (mBookStoreFragment.getActivity())); } @Override public void start() { + mBookStoreFragment.getSrlBookList().setEnableRefresh(false); + mBookStoreFragment.getSrlBookList().setEnableLoadMore(false); + findCrawler = new ABC(true); + //小说列表下拉加载更多事件 + mBookStoreFragment.getSrlBookList().setOnLoadMoreListener(refreshLayout -> { + page++; + BookStorePresenter.this.getBooksData(); + }); + + //小说列表上拉刷新事件 + mBookStoreFragment.getSrlBookList().setOnRefreshListener(refreshLayout -> { + page = 1; + BookStorePresenter.this.getBooksData(); + }); - //无需加载更多 - mBookStoreFragment.getSrlBookList().setEnableLoadMore(false); - //小说列表上拉刷新事件 - mBookStoreFragment.getSrlBookList().setOnRefreshListener(new OnRefreshListener() { - @Override - public void onRefresh(@NonNull RefreshLayout refreshLayout) { - BookStorePresenter.this.getBooksData(); - } - }); + mBookStoreBookAdapter = new BookStoreBookAdapter(findCrawler.hasImg(), mMainActivity); + mBookStoreFragment.getRvBookList().setLayoutManager(new LinearLayoutManager(mMainActivity)); + mBookStoreFragment.getRvBookList().setAdapter(mBookStoreBookAdapter); + mBookStoreBookAdapter.setOnItemClickListener((view, pos) -> { + Book book = bookList.get(pos); + if (!findCrawler.hasImg()) { + Intent intent = new Intent(mMainActivity, BookDetailedActivity.class); + intent.putExtra(APPCONST.BOOK, book); + mMainActivity.startActivity(intent); + } else { + mHandler.sendMessage(mHandler.obtainMessage(3)); + ChangeSourceDialog csd = new ChangeSourceDialog(mMainActivity, bookList.get(pos)); + csd.initOneBook(new ResultCallback() { + @Override + public void onFinish(Object o, int code) { + Book searchBook = (Book) o; + book.setChapterUrl(searchBook.getChapterUrl()); + book.setSource(searchBook.getSource()); + Intent intent = new Intent(mMainActivity, BookDetailedActivity.class); + intent.putExtra(APPCONST.BOOK, book); + mMainActivity.startActivity(intent); + mHandler.sendMessage(mHandler.obtainMessage(4)); + } + + @Override + public void onError(Exception e) { + DialogCreator.createTipDialog(mMainActivity,"未搜索到该书籍,无法进入书籍详情!"); + } + }); + } + }); - getData(); + getData(); + mBookStoreFragment.getmRlRefresh().setOnReloadingListener(this::getData); } @@ -96,21 +142,29 @@ public class BookStorePresenter implements BasePresenter { /** * 获取页面数据 */ - private void getData(){ - BookStoreApi.getBookTypeList(URLCONST.nameSpace_biquge, new ResultCallback() { - @Override - public void onFinish(Object o, int code) { - mBookTypes = (ArrayList)o; - curType = mBookTypes.get(0); - mHandler.sendMessage(mHandler.obtainMessage(1)); - getBooksData(); - } - - @Override - public void onError(Exception e) { - ToastUtils.showError(e.getMessage()); - } - }); + private void getData() { + /*BookStoreApi.getBookTypeList(findCrawler, new ResultCallback() { + @Override + public void onFinish(Object o, int code) { + mBookTypes = (ArrayList) o; + curType = mBookTypes.get(0); + mHandler.sendMessage(mHandler.obtainMessage(1)); + page = 1; + getBooksData(); + } + + @Override + public void onError(Exception e) { + e.printStackTrace(); + mHandler.sendEmptyMessage(5); + } + });*/ + mBookTypes = findCrawler.getRankTypes(); + curType = mBookTypes.get(0); + mHandler.sendMessage(mHandler.obtainMessage(1)); + page = 1; + getBooksData(); + } @@ -118,30 +172,58 @@ public class BookStorePresenter implements BasePresenter { /** * 获取小数列表数据 */ - private void getBooksData(){ - BookStoreApi.getBookRankList(curType.getUrl(), new ResultCallback() { + private void getBooksData() { + if (findCrawler.getTypePage(curType, page)) { + mBookStoreFragment.getSrlBookList().finishLoadMoreWithNoMoreData(); + return; + } + mHandler.sendEmptyMessage(3); + /*BookStoreApi.getBookRankList(curType.getUrl(), findCrawler, new ResultCallback() { @Override public void onFinish(Object o, int code) { - bookList= (ArrayList)o; - mHandler.sendMessage(mHandler.obtainMessage(2)); + mHandler.sendMessage(mHandler.obtainMessage(2, o)); } @Override public void onError(Exception e) { - ToastUtils.showError(e.getMessage()); + mHandler.sendMessage(mHandler.obtainMessage(4)); + ToastUtils.showError("数据加载失败!\n" + e.getMessage()); + e.printStackTrace(); + } + });*/ + findCrawler.getRankBooks(curType, new ResultCallback() { + @Override + public void onFinish(Object o, int code) { + List books = new ArrayList<>(); + for (RankBook rb : (List) o){ + Book book = new Book(); + book.setName(rb.getbName()); + book.setAuthor(rb.getbAuth()); + book.setImgUrl(rb.getImg()); + String cat = rb.getCat(); + book.setType(cat.contains("小说") || cat.length() >= 4 ? cat : cat + "小说"); + book.setNewestChapterTitle(rb.getDesc()); + book.setDesc(rb.getDesc()); + book.setUpdateDate(rb.getCnt()); + books.add(book); + } + mHandler.sendMessage(mHandler.obtainMessage(2, books)); + } + @Override + public void onError(Exception e) { + mHandler.sendMessage(mHandler.obtainMessage(4)); + ToastUtils.showError("数据加载失败!\n" + e.getMessage()); + e.printStackTrace(); } }); } - - - /** * 初始化类别列表 */ - private void initTypeList(){ + private void initTypeList() { //设置布局管理器 mLinearLayoutManager = new LinearLayoutManager(mBookStoreFragment.getActivity()); @@ -151,40 +233,38 @@ public class BookStorePresenter implements BasePresenter { mBookStoreFragment.getRvTypeList().setAdapter(mBookStoreBookTypeAdapter); //点击事件 - mBookStoreBookTypeAdapter.setOnItemClickListener(new BookStoreBookTypeAdapter.OnItemClickListener() { - @Override - public void onClick(int pos, View view) { - curType = mBookTypes.get(pos); - BookStorePresenter.this.getBooksData(); + mBookStoreBookTypeAdapter.setOnItemClickListener((pos, view) -> { + if (curType.equals(mBookTypes.get(pos))) { + return; } + page = 1; + curType = mBookTypes.get(pos); + mBookStoreFragment.getSrlBookList().resetNoMoreData(); + BookStorePresenter.this.getBooksData(); }); } - /** * 初始化小说列表 */ - private void initBookList(){ - //设置布局管理器 - mLinearLayoutManager = new LinearLayoutManager(mBookStoreFragment.getActivity()); - mLinearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); - mBookStoreFragment.getRvBookList().setLayoutManager(mLinearLayoutManager); - mBookStoreBookAdapter = new BookStoreBookAdapter(mBookStoreFragment.getActivity(), bookList); - mBookStoreFragment.getRvBookList().setAdapter(mBookStoreBookAdapter); - //点击事件 - mBookStoreBookAdapter.setOnItemClickListener(new BookStoreBookAdapter.OnItemClickListener() { - @Override - public void onClick(int pos, View view) { - Intent intent = new Intent(mBookStoreFragment.getActivity(), BookDetailedActivity.class); - intent.putExtra(APPCONST.BOOK, bookList.get(pos)); - mBookStoreFragment.getActivity().startActivity(intent); - } - }); + private void initBookList(List bookList) { + if (page == 1) { + mBookStoreBookAdapter.refreshItems(bookList); + this.bookList.clear(); + this.bookList.addAll(bookList); + mBookStoreFragment.getRvBookList().scrollToPosition(0); + } else { + this.bookList.addAll(bookList); + mBookStoreBookAdapter.addItems(bookList); + } + //刷新动作完成 mBookStoreFragment.getSrlBookList().finishRefresh(); + //加载更多完成 + mBookStoreFragment.getSrlBookList().finishLoadMore(); } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java index d5f4013..fc78970 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java @@ -9,17 +9,22 @@ import android.graphics.BitmapFactory; import android.os.Build; import android.os.Handler; import android.os.Message; -import android.view.Menu; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.MenuItem; import android.view.View; -import android.widget.ArrayAdapter; -import android.widget.PopupMenu; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.PopupMenu; import androidx.appcompat.app.AlertDialog; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import java.io.File; -import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; @@ -27,6 +32,8 @@ import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import com.google.android.material.textfield.TextInputEditText; +import com.google.android.material.textfield.TextInputLayout; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.application.SysManager; @@ -35,6 +42,10 @@ import xyz.fycz.myreader.backup.UserService; import xyz.fycz.myreader.base.BasePresenter; import xyz.fycz.myreader.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; +import xyz.fycz.myreader.creator.MultiChoiceDialog; +import xyz.fycz.myreader.creator.MyAlertDialog; +import xyz.fycz.myreader.greendao.entity.BookGroup; +import xyz.fycz.myreader.greendao.service.BookGroupService; import xyz.fycz.myreader.ui.activity.*; import xyz.fycz.myreader.webapi.crawler.ReadCrawler; import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; @@ -56,14 +67,19 @@ import xyz.fycz.myreader.util.notification.NotificationUtil; import xyz.fycz.myreader.util.utils.NetworkUtils; import xyz.fycz.myreader.webapi.CommonApi; +import static xyz.fycz.myreader.application.MyApplication.checkVersionByServer; + public class BookcasePresenter implements BasePresenter { private final BookcaseFragment mBookcaseFragment; private final ArrayList mBooks = new ArrayList<>();//书目数组 + private ArrayList mBookGroups = new ArrayList<>();//书籍分组 + private CharSequence[] mGroupNames;//书籍分组名称 private BookcaseAdapter mBookcaseAdapter; private final BookService mBookService; private final ChapterService mChapterService; + private final BookGroupService mBookGroupService; private final MainActivity mMainActivity; private PermissionsChecker mPermissionsChecker; private boolean isBookcaseStyleChange; @@ -91,22 +107,11 @@ public class BookcasePresenter implements BasePresenter { private int tempCount;//下载超时时间 private int downloadInterval = 150;//下载间隔 private Runnable sendDownloadNotification;//发送通知的线程 - private PopupMenu pm;//菜单 private boolean isFirstRefresh = true;//是否首次进入刷新 + private boolean isGroup; public static final String CANCEL_ACTION = "cancelAction"; - private final String[] backupMenu = { - MyApplication.getmContext().getResources().getString(R.string.menu_backup_backup), - MyApplication.getmContext().getResources().getString(R.string.menu_backup_restore), - }; - - private final String[] webSynMenu = { - MyApplication.getmContext().getString(R.string.menu_backup_webBackup), - MyApplication.getmContext().getString(R.string.menu_backup_webRestore), - MyApplication.getmContext().getString(R.string.menu_backup_autoSyn) - }; - static final String[] PERMISSIONS = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE @@ -118,9 +123,11 @@ public class BookcasePresenter implements BasePresenter { public void handleMessage(Message msg) { switch (msg.what) { case 1: - MyApplication.runOnUiThread(() -> mBookcaseAdapter.notifyDataSetChanged()); - finishLoadBookCount++; - mBookcaseFragment.getSrlContent().finishRefresh(); + if (!MyApplication.isDestroy(mMainActivity)) { + MyApplication.runOnUiThread(() -> mBookcaseAdapter.notifyDataSetChanged()); + finishLoadBookCount++; + mBookcaseFragment.getSrlContent().finishRefresh(); + } break; case 2: mBookcaseFragment.getSrlContent().finishRefresh(); @@ -139,10 +146,8 @@ public class BookcasePresenter implements BasePresenter { } break; case 5: - backup(); break; case 6: - restore(); break; case 7: init(); @@ -151,7 +156,7 @@ public class BookcasePresenter implements BasePresenter { sendNotification(); break; case 9: - mBookcaseFragment.getRlDownloadTip().setVisibility(View.GONE); + //mBookcaseFragment.getRlDownloadTip().setVisibility(View.GONE); isDownloadFinish = true; break; case 10: @@ -160,9 +165,6 @@ public class BookcasePresenter implements BasePresenter { mBookcaseFragment.getRlDownloadTip().setVisibility(View.VISIBLE); break; case 11: - MyApplication.runOnUiThread(() -> createMenu()); - break; - case 12: ToastUtils.showInfo("正在后台缓存书籍,具体进度可查看通知栏!"); notificationUtil.requestNotificationPermissionDialog(mMainActivity); break; @@ -170,19 +172,22 @@ public class BookcasePresenter implements BasePresenter { } }; + //构造方法 public BookcasePresenter(BookcaseFragment bookcaseFragment) { mBookcaseFragment = bookcaseFragment; mBookService = BookService.getInstance(); - ; mChapterService = ChapterService.getInstance(); - mMainActivity = ((MainActivity) (mBookcaseFragment.getActivity())); + mBookGroupService = BookGroupService.getInstance(); + mMainActivity = (MainActivity) (mBookcaseFragment.getActivity()); // mChapterService = new ChapterService(); mSetting = SysManager.getSetting(); mBackupAndRestore = new BackupAndRestore(); } + //启动 @Override public void start() { + checkVersionByServer(mMainActivity, false, mBookcaseFragment); if (mSetting.getBookcaseStyle() == null) { mSetting.setBookcaseStyle(BookcaseStyle.listMode); } @@ -213,12 +218,6 @@ public class BookcasePresenter implements BasePresenter { //长按事件监听 mBookcaseFragment.getGvBook().setOnItemLongClickListener((parent, view, position, id) -> false); - //更多按钮监听器 - mMainActivity.getIvMore().setOnClickListener(v -> mHandler.sendMessage(mHandler.obtainMessage(11))); - - //完成按钮监听器 - mMainActivity.getTvEditFinish().setOnClickListener(v -> editBookcase(false)); - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { //滑动监听器 mBookcaseFragment.getGvBook().getmScrollView().setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> { @@ -228,44 +227,61 @@ public class BookcasePresenter implements BasePresenter { }); } + //全选监听器 + mBookcaseFragment.getmCbSelectAll().setOnClickListener(v -> { + //设置全选状态 + boolean isChecked = mBookcaseFragment.getmCbSelectAll().isChecked(); + mBookcaseAdapter.setCheckedAll(isChecked); + }); + + //删除监听器 + mBookcaseFragment.getmBtnDelete().setOnClickListener(v -> { + DialogCreator.createCommonDialog(mMainActivity, "批量删除书籍", + "确定要删除这些书籍吗?", true, (dialog, which) -> { + for (Book book : mBookcaseAdapter.getSelectBooks()) { + mBookService.deleteBook(book); + } + ToastUtils.showSuccess("书籍删除成功!"); + init(); + }, null); + }); + + //加入分组监听器 + mBookcaseFragment.getmBtnAddGroup().setOnClickListener(v -> { + initBookGroups(true); + showSelectGroupDia((dialog, which) -> { + if (which < mBookGroups.size()) { + BookGroup bookGroup = mBookGroups.get(which); + ArrayList mSelectBooks = (ArrayList) mBookcaseAdapter.getSelectBooks(); + for (Book book : mSelectBooks) { + book.setGroupId(bookGroup.getId()); + } + mBookService.updateBooks(mSelectBooks); + ToastUtils.showSuccess("成功将《" + mSelectBooks.get(0).getName() + "》" + + (mSelectBooks.size() > 1 ? "等" : "") + + "加入[" + bookGroup.getName() + "]分组"); + init(); + } else if (which == mBookGroups.size()) { + showAddOrRenameGroupDia(false, 0); + } + }); + }); } - /** - * 编辑书架 - * - * @param isEdit - */ - private void editBookcase(boolean isEdit) { - if (isEdit) { - if (mBooks.size() > 0) { - mBookcaseFragment.getSrlContent().setEnableRefresh(false); - mBookcaseAdapter.setmEditState(true); - mBookcaseFragment.getGvBook().setDragModel(DragSortGridView.DRAG_BY_LONG_CLICK); - mBookcaseAdapter.notifyDataSetChanged(); - mMainActivity.getRlCommonTitle().setVisibility(View.GONE); - mMainActivity.getRlEditTitle().setVisibility(View.VISIBLE); - mMainActivity.getIvMore().setVisibility(View.GONE); -// VibratorUtil.Vibrate(mBookcaseFragment.getActivity(), 100); - } else { - ToastUtils.showWarring("当前无任何书籍,无法编辑书架!"); - } - } else { - mMainActivity.getRlCommonTitle().setVisibility(View.VISIBLE); - mMainActivity.getIvMore().setVisibility(View.VISIBLE); - mMainActivity.getRlEditTitle().setVisibility(View.GONE); - if (mBookcaseFragment.getGvBook().getmScrollView().getScrollY() == 0 - && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - mBookcaseFragment.getSrlContent().setEnableRefresh(true); - } - mBookcaseFragment.getGvBook().setDragModel(-1); - mBookcaseAdapter.setmEditState(false); - mBookcaseAdapter.notifyDataSetChanged(); + + //获取数据 + public void getData() { + init(); + initBookGroups(true); + if (mSetting.isRefreshWhenStart() || android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + initNoReadNum(); } } - + //初始化 public void init() { initBook(); + mSetting = SysManager.getSetting(); if (mBooks.size() == 0) { mBookcaseFragment.getGvBook().setVisibility(View.GONE); mBookcaseFragment.getLlNoDataTips().setVisibility(View.VISIBLE); @@ -273,16 +289,21 @@ public class BookcasePresenter implements BasePresenter { if (mBookcaseAdapter == null || isBookcaseStyleChange) { switch (mSetting.getBookcaseStyle()) { case listMode: - mBookcaseAdapter = new BookcaseDetailedAdapter(mBookcaseFragment.getContext(), R.layout.gridview_book_detailed_item, mBooks, false, this); + mBookcaseAdapter = new BookcaseDetailedAdapter(mBookcaseFragment.getContext(), R.layout.gridview_book_detailed_item, mBooks, false, this, isGroup); mBookcaseFragment.getGvBook().setNumColumns(1); break; case threePalaceMode: - mBookcaseAdapter = new BookcaseDragAdapter(mBookcaseFragment.getContext(), R.layout.gridview_book_item, mBooks, false, this); + mBookcaseAdapter = new BookcaseDragAdapter(mBookcaseFragment.getContext(), R.layout.gridview_book_item, mBooks, false, this, isGroup); mBookcaseFragment.getGvBook().setNumColumns(3); break; } + mBookcaseAdapter.setOnBookCheckedListener(isChecked -> { + changeCheckedAllStatus(); + //设置删除和加入分组按钮是否可用 + setBtnClickable(mBookcaseAdapter.getmCheckedCount() > 0); + }); mBookcaseFragment.getGvBook().setDragModel(-1); - mBookcaseFragment.getGvBook().setTouchClashparent(((MainActivity) (mBookcaseFragment.getActivity())).getVpContent()); + mBookcaseFragment.getGvBook().setTouchClashparent(((MainActivity) (mBookcaseFragment.getActivity())).getViewPagerMain()); mBookcaseFragment.getGvBook().setAdapter(mBookcaseAdapter); isBookcaseStyleChange = false; } else { @@ -293,25 +314,43 @@ public class BookcasePresenter implements BasePresenter { } } - - public void getData() { - init(); - if (mSetting.isRefreshWhenStart() || android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - initNoReadNum(); - } - } - + //初始化书籍 private void initBook() { mBooks.clear(); - mBooks.addAll(mBookService.getAllBooks()); + String curBookGroupId = SharedPreUtils.getInstance().getString("curBookGroupId", ""); + isGroup = !"".equals(curBookGroupId); + if (mBookcaseAdapter != null) { + mBookcaseAdapter.setGroup(isGroup); + } + mBooks.addAll(mBookService.getGroupBooks(curBookGroupId)); for (int i = 0; i < mBooks.size(); i++) { - if (mBooks.get(i).getSortCode() != i + 1) { - mBooks.get(i).setSortCode(i + 1); + int sort = !isGroup ? mBooks.get(i).getSortCode() : mBooks.get(i).getGroupSort(); + if (sort != i + 1) { + if (!isGroup) { + mBooks.get(i).setSortCode(i + 1); + }else { + mBooks.get(i).setGroupSort(i + 1); + } mBookService.updateEntity(mBooks.get(i)); } } } + //初始化书籍分组 + private void initBookGroups(boolean isAdd) { + mBookGroups.clear(); + mBookGroups.addAll(mBookGroupService.getAllGroups()); + mGroupNames = new CharSequence[isAdd ? mBookGroups.size() + 1 : mBookGroups.size()]; + for (int i = 0; i < mBookGroups.size(); i++) { + String groupName = mBookGroups.get(i).getName(); + mGroupNames[i] = groupName.getBytes().length > 20 ? groupName.substring(0, 8) + "···" : groupName; + } + if (isAdd) { + mGroupNames[mBookGroups.size()] = "添加分组"; + } + } + + //检查书籍更新 private void initNoReadNum() { errorLoadingBooks.clear(); finishLoadBookCount = 0; @@ -364,15 +403,6 @@ public class BookcasePresenter implements BasePresenter { }); } - - private void setThemeColor(int colorPrimary, int colorPrimaryDark) { -// mToolbar.setBackgroundResource(colorPrimary); - mBookcaseFragment.getSrlContent().setPrimaryColorsId(colorPrimary, android.R.color.white); - if (Build.VERSION.SDK_INT >= 21) { - mBookcaseFragment.getActivity().getWindow().setStatusBarColor(ContextCompat.getColor(mBookcaseFragment.getContext(), colorPrimaryDark)); - } - } - /** * 显示更新失败的书籍信息 */ @@ -389,224 +419,233 @@ public class BookcasePresenter implements BasePresenter { } } - /** - * 创建菜单栏 - */ - private void createMenu() { - //如果菜单栏已经创建直接show - if (pm != null) { - pm.show(); - return; - } - pm = new PopupMenu(mMainActivity, mMainActivity.getIvMore()); - pm.getMenuInflater().inflate(R.menu.menu_book, pm.getMenu()); - setIconEnable(pm.getMenu(), true); - if (MyApplication.isApkInDebug(mMainActivity)) { - pm.getMenu().getItem(5).setVisible(true); - } - pm.setOnMenuItemClickListener(item -> { - switch (item.getItemId()) { - case R.id.action_edit: - editBookcase(true); - return true; - case R.id.action_styleChange: - mBookcaseFragment.getGvBook().getmScrollView().setScrollY(0); - if (mSetting.getBookcaseStyle().equals(BookcaseStyle.listMode)) { - mSetting.setBookcaseStyle(BookcaseStyle.threePalaceMode); - ToastUtils.show("已切换为三列网格视图!"); - } else { - mSetting.setBookcaseStyle(BookcaseStyle.listMode); - ToastUtils.show("已切换为列表视图!"); + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_edit: + editBookcase(true); + return true; + case R.id.action_styleChange: + mBookcaseFragment.getGvBook().getmScrollView().setScrollY(0); + if (mSetting.getBookcaseStyle().equals(BookcaseStyle.listMode)) { + mSetting.setBookcaseStyle(BookcaseStyle.threePalaceMode); + ToastUtils.show("已切换为三列网格视图!"); + } else { + mSetting.setBookcaseStyle(BookcaseStyle.listMode); + ToastUtils.show("已切换为列表视图!"); + } + isBookcaseStyleChange = true; + SysManager.saveSetting(mSetting); + init(); + return true; + case R.id.action_group_man: + showGroupManDia(); + return true; + case R.id.action_addLocalBook: + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { + if (mPermissionsChecker == null) { + mPermissionsChecker = new PermissionsChecker(mMainActivity); } - isBookcaseStyleChange = true; - SysManager.saveSetting(mSetting); - init(); - return true; - case R.id.action_addLocalBook: - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { - if (mPermissionsChecker == null) { - mPermissionsChecker = new PermissionsChecker(mMainActivity); - } - //获取读取和写入SD卡的权限 - if (mPermissionsChecker.lacksPermissions(PERMISSIONS)) { - //请求权限 - ActivityCompat.requestPermissions(mMainActivity, PERMISSIONS, APPCONST.PERMISSIONS_REQUEST_STORAGE); - return true; - } - } - Intent intent = new Intent(mMainActivity, FileSystemActivity.class); - mMainActivity.startActivity(intent); - break; - case R.id.action_syn: - if (!UserService.isLogin()) { - ToastUtils.showWarring("请先登录!"); - Intent loginIntent = new Intent(mMainActivity, LoginActivity.class); - mMainActivity.startActivity(loginIntent); + //获取读取和写入SD卡的权限 + if (mPermissionsChecker.lacksPermissions(PERMISSIONS)) { + //请求权限 + ActivityCompat.requestPermissions(mMainActivity, PERMISSIONS, APPCONST.PERMISSIONS_REQUEST_STORAGE); return true; } - if (mSetting.isAutoSyn()) { - webSynMenu[2] = MyApplication.getmContext().getString(R.string.menu_backup_autoSyn) + "已开启"; - } else { - webSynMenu[2] = MyApplication.getmContext().getString(R.string.menu_backup_autoSyn) + "已关闭"; - } - new AlertDialog.Builder(mMainActivity) - .setTitle(mMainActivity.getString(R.string.menu_bookcase_syn)) - .setAdapter(new ArrayAdapter<>(mMainActivity, - android.R.layout.simple_list_item_1, 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(); - break; - case R.id.action_download_all: - if (!SharedPreUtils.getInstance().getBoolean("isReadDownloadAllTip")) { - DialogCreator.createCommonDialog(mMainActivity, "一键缓存", - mMainActivity.getString(R.string.all_cathe_tip), true, - (dialog, which) -> { - downloadAll(true); - SharedPreUtils.getInstance().putBoolean("isReadDownloadAllTip", true); - }, null); - }else { - downloadAll(true); - } + } + Intent fileSystemIntent = new Intent(mMainActivity, FileSystemActivity.class); + mMainActivity.startActivity(fileSystemIntent); + break; + case R.id.action_download_all: + if (!SharedPreUtils.getInstance().getBoolean("isReadDownloadAllTip")) { + DialogCreator.createCommonDialog(mMainActivity, "一键缓存", + mMainActivity.getString(R.string.all_cathe_tip), true, + (dialog, which) -> { + downloadAll(true); + SharedPreUtils.getInstance().putBoolean("isReadDownloadAllTip", true); + }, null); + } else { + downloadAll(true); + } + return true; + + } + return false; + } - return true; - case R.id.action_backup: - AlertDialog bookDialog = new AlertDialog.Builder(mMainActivity) - .setTitle(mMainActivity.getResources().getString(R.string.menu_bookcase_backup)) - .setAdapter(new ArrayAdapter<>(mMainActivity, - android.R.layout.simple_list_item_1, backupMenu), - (dialog, which) -> { - switch (which) { - case 0: - mHandler.sendMessage(mHandler.obtainMessage(5)); - break; - case 1: - mHandler.sendMessage(mHandler.obtainMessage(6)); - break; - } - }) - .setNegativeButton(null, null) - .setPositiveButton(null, null) - .create(); - bookDialog.show(); - return true; - case R.id.action_setting: - Intent settingIntent = new Intent(mMainActivity, MoreSettingActivity.class); - mMainActivity.startActivity(settingIntent); - return true; - case R.id.action_about: - Intent aboutIntent = new Intent(mMainActivity, AboutActivity.class); - mMainActivity.startActivity(aboutIntent); - return true; + //显示书籍分组菜单 + public void showBookGroupMenu(View view, MainActivity.OnGroupChangeListener ogcl) { + initBookGroups(false); + PopupMenu popupMenu = new PopupMenu(mMainActivity, view, Gravity.END); + popupMenu.getMenu().add(0, 0, 0, "所有书籍"); + for (int i = 0; i < mGroupNames.length; i++) { + popupMenu.getMenu().add(0, 0, i + 1, mGroupNames[i]); + } + popupMenu.setOnMenuItemClickListener(menuItem -> { + String curBookGroupId = ""; + String curBookGroupName = ""; + if (menuItem.getOrder() > 0) { + curBookGroupId = mBookGroups.get(menuItem.getOrder() - 1).getId(); + curBookGroupName = mBookGroups.get(menuItem.getOrder() - 1).getName(); } - return false; + SharedPreUtils.getInstance().putString("curBookGroupId", curBookGroupId); + SharedPreUtils.getInstance().putString("curBookGroupName", curBookGroupName); + ogcl.onChange(); + init(); + return true; }); - pm.show(); + popupMenu.show(); } /** - * 显示菜单图标 + * 编辑书架 * - * @param menu 菜单 - * @param enable 是否显示图标 + * @param isEdit */ - private void setIconEnable(Menu menu, boolean enable) { - try { - Class clazz = Class.forName("com.android.internal.view.menu.MenuBuilder"); - Method m = clazz.getDeclaredMethod("setOptionalIconsVisible", boolean.class); - m.setAccessible(true); - //MenuBuilder实现Menu接口,创建菜单时,传进来的menu其实就是MenuBuilder对象(java的多态特征) - m.invoke(menu, enable); - } catch (Exception e) { - e.printStackTrace(); + private void editBookcase(boolean isEdit) { + if (isEdit) { + if (mBooks.size() > 0) { + mBookcaseFragment.getSrlContent().setEnableRefresh(false); + mBookcaseAdapter.setmEditState(true); + mBookcaseFragment.getGvBook().setDragModel(DragSortGridView.DRAG_BY_LONG_CLICK); + + mBookcaseFragment.getRlBookEdit().setVisibility(View.VISIBLE); + setBtnClickable(false); + changeCheckedAllStatus(); + mBookcaseAdapter.notifyDataSetChanged(); + } else { + ToastUtils.showWarring("当前无任何书籍,无法编辑书架!"); + } + } else { + if (mBookcaseFragment.getGvBook().getmScrollView().getScrollY() == 0 + && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + mBookcaseFragment.getSrlContent().setEnableRefresh(true); + } + mBookcaseFragment.getGvBook().setDragModel(-1); + mBookcaseAdapter.setmEditState(false); + mBookcaseFragment.getRlBookEdit().setVisibility(View.GONE); + mBookcaseAdapter.notifyDataSetChanged(); } } /** - * 备份 + * 分组管理对话框 */ - private void backup() { - if (mBooks.size() == 0){ - ToastUtils.showWarring("当前书架无任何书籍,无法备份!"); - return; - } - DialogCreator.createCommonDialog(mMainActivity, "确认备份吗?", "新备份会替换原有备份!", true, - (dialogInterface, i) -> { - dialogInterface.dismiss(); - if (mBackupAndRestore.backup("localBackup")) { - DialogCreator.createTipDialog(mMainActivity, "备份成功,备份文件路径:" + APPCONST.BACKUP_FILE_DIR); - } else { - DialogCreator.createTipDialog(mMainActivity, "未给予储存权限,备份失败!"); + private void showGroupManDia() { + MyAlertDialog.build(mMainActivity) + .setTitle("分组管理") + .setItems(mMainActivity.getResources().getStringArray(R.array.group_man) + , (dialog, which) -> { + initBookGroups(false); + switch (which){ + case 0: + showAddOrRenameGroupDia(false, 0); + break; + case 1: + showSelectGroupDia((dialog1, which1) -> { + showAddOrRenameGroupDia(true, which1); + }); + break; + case 2: + showDeleteGroupDia(); + break; } - }, (dialogInterface, i) -> dialogInterface.dismiss()); + }).show(); } + /** - * 恢复 + * 添加/重命名分组对话框 */ - private void restore() { - DialogCreator.createCommonDialog(mMainActivity, "确认恢复吗?", "恢复书架会覆盖原有书架!", true, - (dialogInterface, i) -> { - dialogInterface.dismiss(); - if (mBackupAndRestore.restore("localBackup")) { - mHandler.sendMessage(mHandler.obtainMessage(7)); -// DialogCreator.createTipDialog(mMainActivity, -// "恢复成功!\n注意:本功能属于实验功能,书架恢复后,书籍初次加载时可能加载失败,返回重新加载即可!"); - mSetting = SysManager.getSetting(); - ToastUtils.showSuccess("书架恢复成功!"); - } else { - DialogCreator.createTipDialog(mMainActivity, "未找到备份文件或未给予储存权限,恢复失败!"); - } - }, (dialogInterface, i) -> dialogInterface.dismiss()); - } + private void showAddOrRenameGroupDia(boolean isRename, int groupNum){ + View view = LayoutInflater.from(mMainActivity).inflate(R.layout.edit_dialog, null); + TextInputLayout textInputLayout = view.findViewById(R.id.text_input_lay); + EditText editText = textInputLayout.getEditText(); + editText.setHint("请输入分组名"); + BookGroup bookGroup = !isRename ? new BookGroup() : mBookGroups.get(groupNum); + String oldName = bookGroup.getName(); + if (isRename) { + editText.setText(oldName); + } + editText.requestFocus(); + mHandler.postDelayed(() ->{ + InputMethodManager imm = (InputMethodManager) mMainActivity + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED); + }, 220); + AlertDialog newGroupDia = MyAlertDialog.build(mMainActivity) + .setTitle(!isRename ? "新建分组" : "重命名分组") + .setView(view) + .setCancelable(false) + .setPositiveButton("确认", null) + .setNegativeButton("取消", null) + .show(); + Button posBtn = newGroupDia.getButton(AlertDialog.BUTTON_POSITIVE); + posBtn.setEnabled(false); + posBtn.setOnClickListener(v1 -> { + bookGroup.setName(editText.getText().toString()); + if (!isRename) { + mBookGroupService.addBookGroup(bookGroup); + }else { + mBookGroupService.updateEntity(bookGroup); + } + ToastUtils.showSuccess("成功" + + (!isRename ? "添加分组[" : "成功将[" + oldName + "]重命名为[") + + bookGroup.getName() + "]"); + newGroupDia.dismiss(); + }); + editText.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) { + String text = editText.getText().toString(); + if (editText.getText().length() > 0 && editText.getText().length() <= 10 && !text.equals(oldName)) { + posBtn.setEnabled(true); + } else { + posBtn.setEnabled(false); + } + } + }); + } /** - * 恢复 + * 删除分组对话框 */ - private void webRestore() { - if (!NetworkUtils.isNetWorkAvailable()) { - ToastUtils.showWarring("无网络连接!"); - return; - } - DialogCreator.createCommonDialog(mMainActivity, "确认同步吗?", "将书架从网络同步至本地会覆盖原有书架!", 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(mMainActivity, "未找到同步文件,同步失败!"); + private void showDeleteGroupDia() { + boolean[] checkedItems = new boolean[mGroupNames.length]; + new MultiChoiceDialog().create(mMainActivity, "删除分组", mGroupNames + , checkedItems, 0, (dialog, which) -> { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < checkedItems.length; i++) { + if (checkedItems[i]) { + mBookGroupService.deleteEntity(mBookGroups.get(i)); + sb.append(mBookGroups.get(i).getName()).append("、"); } - }); - }, (dialogInterface, i) -> dialogInterface.dismiss()); + } + if (sb.length() > 0){ + sb.deleteCharAt(sb.lastIndexOf("、")); + } + ToastUtils.showSuccess("分组[" + sb.toString() + "]删除成功!"); + }, null, null); + } + + //显示选择书籍对话框 + private void showSelectGroupDia(DialogInterface.OnClickListener onClickListener){ + MyAlertDialog.build(mMainActivity) + .setTitle("选择分组") + .setItems(mGroupNames, onClickListener) + .setCancelable(false) + .setPositiveButton("取消", null) + .show(); } /**********************************************缓存书籍***************************************************************/ @@ -618,7 +657,7 @@ public class BookcasePresenter implements BasePresenter { ToastUtils.showWarring("无网络连接!"); return; } - if (mBooks.size() == 0){ + if (mBooks.size() == 0) { ToastUtils.showWarring("当前书架没有任何书籍,无法一键缓存!"); return; } @@ -626,16 +665,16 @@ public class BookcasePresenter implements BasePresenter { ArrayList needDownloadBooks = new ArrayList<>(); for (Book book : mBooks) { if (!BookSource.pinshu.toString().equals(book.getSource()) && !"本地书籍".equals(book.getType()) - && book.getIsDownLoadAll()) { + && book.getIsDownLoadAll()) { needDownloadBooks.add(book); } } - if(needDownloadBooks.size() == 0){ + if (needDownloadBooks.size() == 0) { ToastUtils.showWarring("当前书架书籍不支持/已关闭(可在设置开启)一键缓存!"); return; } if (isDownloadAllChapters) { - mHandler.sendEmptyMessage(12); + mHandler.sendEmptyMessage(11); } downloadFor: for (final Book book : needDownloadBooks) { @@ -702,7 +741,7 @@ public class BookcasePresenter implements BasePresenter { } return; } - if (SysManager.getSetting().getCatheGap() != 0){ + if (SysManager.getSetting().getCatheGap() != 0) { downloadInterval = SysManager.getSetting().getCatheGap(); } //取消之前下载 @@ -735,7 +774,7 @@ public class BookcasePresenter implements BasePresenter { } needCacheChapterNum = needDownloadChapters.size(); if (!isDownloadAll && needCacheChapterNum > 0) { - mHandler.sendEmptyMessage(12); + mHandler.sendEmptyMessage(11); } mHandler.postDelayed(sendDownloadNotification, 2 * downloadInterval); for (Chapter chapter : needDownloadChapters) { @@ -839,36 +878,6 @@ public class BookcasePresenter implements BasePresenter { } } - /** - * 添加本地书籍 - * - * @param path - */ - public void addLocalBook(String path) { - File file = new File(path); - if (!file.exists()) { - return; - } - Book book = new Book(); - book.setName(file.getName().replace(".txt", "")); - book.setChapterUrl(path); - book.setType("本地书籍"); - book.setHistoryChapterId("未开始阅读"); - book.setNewestChapterTitle("未拆分章节"); - book.setAuthor("本地书籍"); - book.setSource(BookSource.local.toString()); - book.setDesc(""); - - //判断书籍是否已经添加 - Book existsBook = mBookService.findBookByAuthorAndName(book.getName(), book.getAuthor()); - if (book.equals(existsBook)) { - ToastUtils.showWarring("该书籍已存在,请勿重复添加!"); - return; - } - mBookService.addBook(book); - ToastUtils.showSuccess("本地书籍添加成功"); - init(); - } /** * 同步书架 @@ -880,7 +889,7 @@ public class BookcasePresenter implements BasePresenter { } return; } - if (mBooks.size() == 0){ + if (mBooks.size() == 0) { if (!isAutoSyn) { ToastUtils.showWarring("当前书架无任何书籍,无法同步!"); } @@ -928,7 +937,7 @@ public class BookcasePresenter implements BasePresenter { } /** - * + * 销毁 */ public void destroy() { notificationUtil.cancelAll(); @@ -939,28 +948,30 @@ public class BookcasePresenter implements BasePresenter { } - /*class NotificationService extends Service{ + /********************************编辑状态下下方按钮********************************************/ + private void setBtnClickable(boolean isClickable) { + mBookcaseFragment.getmBtnDelete().setEnabled(isClickable); + mBookcaseFragment.getmBtnDelete().setClickable(isClickable); + mBookcaseFragment.getmBtnAddGroup().setEnabled(isClickable); + mBookcaseFragment.getmBtnAddGroup().setClickable(isClickable); + } - @Nullable - @Override - public IBinder onBind(Intent intent) { - return null; - } - public void sendNotification(Book book, String chapterTitle){ - //创建 Notification.Builder 对象 - NotificationCompat.Builder builder = new NotificationCompat.Builder(mMainActivity, "channel_download") - .setSmallIcon(R.drawable.ic_download) - //通知栏大图标 - .setLargeIcon(BitmapFactory.decodeResource(mMainActivity.getResources(), R.mipmap.ic_launcher)) - //点击通知后自动清除 - .setAutoCancel(true) - .setContentTitle("正在下载:" + book.getName()) - .setContentText(chapterTitle); - builder.addAction(R.drawable.ic_stop_black_24dp, "取消", null); - //发送通知 - startForeground(1, builder.build()); + /** + * 改变全选按钮的状态 + */ + private void changeCheckedAllStatus() { + //设置是否全选 + if (mBookcaseAdapter.getmCheckedCount() == mBookcaseAdapter.getmCheckableCount()) { + mBookcaseAdapter.setIsCheckedAll(true); + } else if (mBookcaseAdapter.isCheckedAll()) { + mBookcaseAdapter.setIsCheckedAll(false); + } + mBookcaseFragment.getmCbSelectAll().setChecked(mBookcaseAdapter.isCheckedAll()); + //重置全选的文字 + if (mBookcaseAdapter.isCheckedAll()) { + mBookcaseFragment.getmCbSelectAll().setText("取消"); + } else { + mBookcaseFragment.getmCbSelectAll().setText("全选"); } - }*/ - - + } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/CatalogActivityPresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/CatalogActivityPresenter.java deleted file mode 100644 index 389f759..0000000 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/CatalogActivityPresenter.java +++ /dev/null @@ -1,134 +0,0 @@ -package xyz.fycz.myreader.ui.presenter; - -import android.content.Context; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.View; -import android.view.inputmethod.InputMethodManager; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentPagerAdapter; -import xyz.fycz.myreader.R; -import xyz.fycz.myreader.application.SysManager; -import xyz.fycz.myreader.base.BasePresenter; -import xyz.fycz.myreader.entity.Setting; -import xyz.fycz.myreader.ui.activity.CatalogActivity; -import xyz.fycz.myreader.ui.fragment.CatalogFragment; -import xyz.fycz.myreader.ui.fragment.BookMarkFragment; - -import java.util.ArrayList; - -import static androidx.fragment.app.FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT; - -/** - * @author fengyue - * @date 2020/7/22 8:10 - */ -public class CatalogActivityPresenter implements BasePresenter { - - private CatalogActivity mCatalogActivity; - private ArrayList mFragments = new ArrayList<>(); - private String[] tabTitle = {"目录", "书签"}; - private boolean isDayStyle; - private FragmentPagerAdapter tabAdapter; - - public CatalogActivityPresenter(CatalogActivity mCatalogActivity) { - this.mCatalogActivity = mCatalogActivity; - } - - @Override - public void start() { - Setting setting = SysManager.getSetting(); - isDayStyle = setting.isDayStyle(); - //设置日夜间 - if (!isDayStyle){ - mCatalogActivity.setStatusBar(R.color.sys_dialog_setting_bg, true); - mCatalogActivity.getRlCommonTitle().setBackground(mCatalogActivity.getDrawable(R.color.sys_dialog_setting_bg)); - mCatalogActivity.getTvBack().setImageDrawable(mCatalogActivity.getDrawable(R.mipmap.larrow_white2)); - mCatalogActivity.getIvCancel().setImageDrawable(mCatalogActivity.getDrawable(R.mipmap.ic_cha_black)); - mCatalogActivity.getIvSearch().setImageDrawable(mCatalogActivity.getDrawable(R.mipmap.b9)); - mCatalogActivity.getEtSearch().setTextColor(mCatalogActivity.getResources().getColor(R.color.sys_night_word)); - mCatalogActivity.getEtSearch().setHintTextColor(mCatalogActivity.getResources().getColor(R.color.sys_night_word)); - } - init(); - - InputMethodManager manager = ((InputMethodManager) mCatalogActivity.getSystemService(Context.INPUT_METHOD_SERVICE)); - - mCatalogActivity.getTvBack().setOnClickListener(v -> mCatalogActivity.finish()); - mCatalogActivity.getIvSearch().setOnClickListener(v -> { - mCatalogActivity.getTlTabMenu().setVisibility(View.GONE); - mCatalogActivity.getIvSearch().setVisibility(View.GONE); - mCatalogActivity.getEtSearch().setVisibility(View.VISIBLE); - mCatalogActivity.getIvCancel().setVisibility(View.VISIBLE); - mCatalogActivity.getEtSearch().setFocusable(true); - mCatalogActivity.getEtSearch().setFocusableInTouchMode(true); - mCatalogActivity.getEtSearch().requestFocus(); - }); - - mCatalogActivity.getEtSearch().setOnFocusChangeListener((v, hasFocus) -> { - if (hasFocus){ - if (manager != null) manager.showSoftInput(v, InputMethodManager.SHOW_IMPLICIT); - }else { - if (manager != null) manager.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); - } - }); - - mCatalogActivity.getIvCancel().setOnClickListener(v -> { - mCatalogActivity.getTlTabMenu().setVisibility(View.VISIBLE); - mCatalogActivity.getIvSearch().setVisibility(View.VISIBLE); - mCatalogActivity.getEtSearch().setVisibility(View.GONE); - mCatalogActivity.getIvCancel().setVisibility(View.GONE); - if(!"".equals(mCatalogActivity.getEtSearch().getText().toString())){ - mCatalogActivity.getEtSearch().setText(""); - } - }); - - mCatalogActivity.getEtSearch().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) { - switch (mCatalogActivity.getVpContent().getCurrentItem()){ - case 0: - ((CatalogFragment) tabAdapter.getItem(0)).getmCatalogPresent().startSearch(s.toString()); - break; - case 1: - ((BookMarkFragment) tabAdapter.getItem(1)).getmBookMarkPresenter().startSearch(s.toString()); - break; - } - } - }); - } - - private void init(){ - mFragments.add(new CatalogFragment()); - mFragments.add(new BookMarkFragment()); - tabAdapter = new FragmentPagerAdapter(mCatalogActivity.getSupportFragmentManager(),BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { - @Override - public Fragment getItem(int position) { - return mFragments.get(position); - } - - @Override - public int getCount() { - return mFragments.size(); - } - - @Override - public CharSequence getPageTitle(int position) { - return tabTitle[position]; - } - - }; - mCatalogActivity.getVpContent().setAdapter(tabAdapter); - mCatalogActivity.getTlTabMenu().setupWithViewPager(mCatalogActivity.getVpContent()); - mCatalogActivity.getVpContent().setCurrentItem(0); - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/CatalogPresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/CatalogPresenter.java index 7517171..752a95b 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/CatalogPresenter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/presenter/CatalogPresenter.java @@ -9,6 +9,7 @@ import xyz.fycz.myreader.application.SysManager; import xyz.fycz.myreader.base.BasePresenter; import xyz.fycz.myreader.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; +import xyz.fycz.myreader.ui.activity.CatalogActivity; import xyz.fycz.myreader.util.ToastUtils; import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; import xyz.fycz.myreader.greendao.entity.Book; @@ -42,11 +43,7 @@ public class CatalogPresenter implements BasePresenter { @Override public void start() { - mBook = (Book) mCatalogFragment.getActivity().getIntent().getSerializableExtra(APPCONST.BOOK); - isDayStyle = SysManager.getSetting().isDayStyle(); - if (!isDayStyle) { - mCatalogFragment.getLvChapterList().setBackground(mCatalogFragment.getActivity().getDrawable(R.color.sys_dialog_setting_bg)); - } + mBook = ((CatalogActivity) mCatalogFragment.getActivity()).getmBook(); mCatalogFragment.getFcChangeSort().setOnClickListener(view -> { if (curSortflag == 0) {//当前正序 curSortflag = 1; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/FontsPresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/FontsPresenter.java deleted file mode 100644 index 3696047..0000000 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/FontsPresenter.java +++ /dev/null @@ -1,118 +0,0 @@ -package xyz.fycz.myreader.ui.presenter; - -import android.annotation.SuppressLint; -import android.os.Handler; -import android.os.Message; -import android.view.View; - -import xyz.fycz.myreader.R; -import xyz.fycz.myreader.base.BasePresenter; -import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.enums.Font; -import xyz.fycz.myreader.ui.activity.FontsActivity; -import xyz.fycz.myreader.ui.adapter.FontsAdapter; -import xyz.fycz.myreader.util.IOUtils; -import xyz.fycz.myreader.util.ToastUtils; -import xyz.fycz.myreader.util.utils.FileUtils; - -import java.io.*; -import java.util.ArrayList; - -/** - * Created by zhao on 2017/8/7. - */ - -public class FontsPresenter implements BasePresenter { - - private FontsActivity mFontsActivity; - private ArrayList mFonts; - private FontsAdapter mFontsAdapter; - - - @SuppressLint("HandlerLeak") - private Handler mHandler = new Handler(){ - @Override - public void handleMessage(Message msg) { - switch (msg.what){ - case 1: - init(); - break; - } - } - }; - - public FontsPresenter(FontsActivity fontsActivity) { - mFontsActivity = fontsActivity; - } - - @Override - public void start() { - mFontsActivity.getLlTitleBack().setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - mFontsActivity.finish(); - } - }); - mFontsActivity.getTvTitleText().setText(mFontsActivity.getString(R.string.font)); - init(); - } - - private void init() { - initFonts(); - mFontsAdapter = new FontsAdapter(mFontsActivity, R.layout.listview_font_item, mFonts, mFontsActivity); - mFontsActivity.getLvFonts().setAdapter(mFontsAdapter); - mFontsActivity.getPbLoading().setVisibility(View.GONE); - } - - 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.本地字体); - } - - public void notifyChange(){ - mFontsAdapter.notifyDataSetChanged(); - } - - public void saveLocalFont(String path){ - File fontFile = new File(path); - if (!fontFile.exists()){ - ToastUtils.showWarring("未找到字体文件!"); - return; - } - String fontName = fontFile.getName(); - if (!fontName.endsWith(".ttf")){ - ToastUtils.showError("字体更换失败,请选择ttf格式的字体文件!"); - return; - } - String dirPath = fontFile.getParentFile().getAbsolutePath() + "/"; - if (dirPath.equals(APPCONST.FONT_BOOK_DIR)){ - mFontsAdapter.saveLocalFontName(fontName); - return; - } - FileInputStream fis = null; - FileOutputStream fos = null; - try { - fis = new FileInputStream(fontFile); - fos = new FileOutputStream(FileUtils.getFile(APPCONST.FONT_BOOK_DIR + fontName)); - byte[] bytes = new byte[1021]; - int len = -1; - while ((len = fis.read(bytes)) != -1){ - fos.write(bytes, 0, len); - } - fos.flush(); - mFontsAdapter.saveLocalFontName(fontName); - } catch (IOException e) { - e.printStackTrace(); - ToastUtils.showError("读取字体文件出错!\n" + e.getLocalizedMessage()); - }finally { - IOUtils.close(fis, fos); - } - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/LoginPresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/LoginPresenter.java deleted file mode 100644 index f86189b..0000000 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/LoginPresenter.java +++ /dev/null @@ -1,137 +0,0 @@ -package xyz.fycz.myreader.ui.presenter; - -import android.annotation.SuppressLint; -import android.app.ProgressDialog; -import android.content.Intent; -import android.graphics.Bitmap; -import android.os.Handler; -import android.os.Message; -import android.view.View; -import xyz.fycz.myreader.backup.UserService; -import xyz.fycz.myreader.base.BasePresenter; -import xyz.fycz.myreader.callback.ResultCallback; -import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.creator.DialogCreator; -import xyz.fycz.myreader.ui.activity.LoginActivity; -import xyz.fycz.myreader.ui.activity.RegisterActivity; -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 java.util.HashMap; -import java.util.Map; - -/** - * @author fengyue - * @date 2020/4/26 20:31 - */ - -public class LoginPresenter implements BasePresenter { - private LoginActivity mLoginActivity; - private String code; - - public LoginPresenter(LoginActivity mLoginActivity) { - this.mLoginActivity = mLoginActivity; - } - - @SuppressLint("HandlerLeak") - private Handler mHandler = new Handler() { - @SuppressLint("HandlerLeak") - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case 1: - mLoginActivity.getLoginBtn().setEnabled(true); - break; - case 2: - createCaptcha(); - break; - } - } - }; - - @Override - public void start() { - mHandler.sendMessage(mHandler.obtainMessage(2)); - mLoginActivity.getTvTitleText().setText("登录"); - mLoginActivity.getLlTitleBack().setOnClickListener(v -> mLoginActivity.finish()); - String username = UserService.readUsername(); - mLoginActivity.getUser().setText(username); - mLoginActivity.getUser().requestFocus(username.length()); - //监听内容改变 -> 控制按钮的点击状态 - mLoginActivity.getUser().addTextChangedListener(mLoginActivity); - mLoginActivity.getPassword().addTextChangedListener(mLoginActivity); - mLoginActivity.getEtCaptcha().addTextChangedListener(mLoginActivity); - - mLoginActivity.getIvCaptcha().setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - mHandler.sendMessage(mHandler.obtainMessage(2)); - } - }); - - mLoginActivity.getLoginBtn().setOnClickListener(v -> { - mHandler.sendMessage(mHandler.obtainMessage(2)); - if (!code.toLowerCase().equals(mLoginActivity.getEtCaptcha().getText().toString().toLowerCase())){ - DialogCreator.createTipDialog(mLoginActivity, "验证码错误!"); - return; - } - if (!NetworkUtils.isNetWorkAvailable()) { - ToastUtils.showError("无网络连接!"); - return; - } - ProgressDialog dialog = DialogCreator.createProgressDialog(mLoginActivity, null, "正在登陆..."); - mLoginActivity.getLoginBtn().setEnabled(false); - final String loginName = mLoginActivity.getUser().getText().toString().trim(); - String loginPwd = mLoginActivity.getPassword().getText().toString(); - final Map 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); - mLoginActivity.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(); - } - }); - - }); - - mLoginActivity.getTvRegister().setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(mLoginActivity, RegisterActivity.class); - mLoginActivity.startActivity(intent); - } - }); - } - - public void createCaptcha() { - code = CodeUtil.getInstance().createCode(); - Bitmap codeBitmap = CodeUtil.getInstance().createBitmap(code); - mLoginActivity.getIvCaptcha().setImageBitmap(codeBitmap); - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/MainPresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/MainPresenter.java deleted file mode 100644 index 20789de..0000000 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/MainPresenter.java +++ /dev/null @@ -1,134 +0,0 @@ -package xyz.fycz.myreader.ui.presenter; - -import android.content.DialogInterface; -import android.content.Intent; - -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentPagerAdapter; -import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.application.SysManager; -import xyz.fycz.myreader.base.BasePresenter; -import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.creator.DialogCreator; -import xyz.fycz.myreader.entity.Setting; -import xyz.fycz.myreader.ui.activity.MainActivity; -import xyz.fycz.myreader.ui.fragment.BookcaseFragment; -import xyz.fycz.myreader.ui.activity.SearchBookActivity; -import xyz.fycz.myreader.ui.activity.LoginActivity; -import xyz.fycz.myreader.util.ToastUtils; - -import java.io.File; -import java.util.ArrayList; - -import static androidx.fragment.app.FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT; -import static xyz.fycz.myreader.application.MyApplication.checkVersionByServer; - - -public class MainPresenter implements BasePresenter { - - private MainActivity mMainActivity; - private ArrayList mFragments = new ArrayList<>(); - - private String[] tabTitle = {"书架"}; - - private BookcaseFragment mBookcaseFragment; - - public MainPresenter(MainActivity mainActivity) { - mMainActivity = mainActivity; - } - - @Override - public void start() { - try { - Setting mSetting = SysManager.getSetting(); - int settingVersion = mSetting.getSettingVersion(); - if (settingVersion < APPCONST.SETTING_VERSION){ - SysManager.resetSetting(); - //DialogCreator.createTipDialog(mMainActivity, "因组件升级,阅读字体及背景颜色已恢复默认颜色!"); - } - }catch (Exception e){ - SysManager.resetSetting(); - //DialogCreator.createTipDialog(mMainActivity, "因组件升级,阅读字体及背景颜色已恢复默认颜色"); - } - init(); - checkVersionByServer(mMainActivity, false, (BookcaseFragment) mFragments.get(0)); - mMainActivity.getIvSearch().setOnClickListener(view -> { - Intent intent = new Intent(mMainActivity, SearchBookActivity.class); - mMainActivity.startActivity(intent); - }); - mMainActivity.getCivAvatar().setOnClickListener(v -> { - final File file = MyApplication.getApplication().getFileStreamPath("userConfig.fy"); - if (file.exists()) { - DialogCreator.createCommonDialog(mMainActivity, "退出登录", "确定要退出登录吗?" - , true, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (file.delete()) { - ToastUtils.showSuccess("退出成功"); - Intent intent = new Intent(mMainActivity, LoginActivity.class); - mMainActivity.startActivity(intent); - } else { - ToastUtils.showError("退出失败(Error:file.delete())"); - } - } - }, (dialog, which) -> dialog.dismiss()); - } else { - Intent intent = new Intent(mMainActivity, LoginActivity.class); - mMainActivity.startActivity(intent); - } - }); - } - - /** - * 初始化 - */ - private void init() { - mBookcaseFragment = new BookcaseFragment(); - mFragments.add(mBookcaseFragment); - mMainActivity.getVpContent().setAdapter(new FragmentPagerAdapter(mMainActivity.getSupportFragmentManager(), BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { - @Override - public Fragment getItem(int position) { - return mFragments.get(position); - } - - @Override - public int getCount() { - return mFragments.size(); - } - - @Override - public CharSequence getPageTitle(int position) { - return tabTitle[position]; - } - - }); - mMainActivity.getTlTabMenu().setupWithViewPager(mMainActivity.getVpContent()); - mMainActivity.getVpContent().setCurrentItem(0); - } - - /** - * 添加本地书籍 - * @param path - */ - public void addLocalBook(String path){ - mBookcaseFragment.getmBookcasePresenter().addLocalBook(path); - } - - /** - * 取消编辑状态 - */ - public void cancelEdit(){ - mBookcaseFragment.getmBookcasePresenter().cancelEdit(); - } - - /** - * 判断是否处于编辑状态 - * @return - */ - public boolean ismEditState(){ - if (mBookcaseFragment.getmBookcasePresenter() == null) { - return false; - } - return mBookcaseFragment.getmBookcasePresenter().ismEditState(); - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/ReadPresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/ReadPresenter.java index 4bb12a2..34e696e 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/ReadPresenter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/presenter/ReadPresenter.java @@ -17,8 +17,6 @@ import android.view.WindowManager; import android.widget.SeekBar; import android.widget.TextView; -import androidx.appcompat.app.AlertDialog; - import java.io.File; import java.util.ArrayList; import java.util.List; @@ -30,8 +28,10 @@ import xyz.fycz.myreader.base.BasePresenter; import xyz.fycz.myreader.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.common.URLCONST; -import xyz.fycz.myreader.ui.activity.MoreSettingActivity; +import xyz.fycz.myreader.creator.MyAlertDialog; +import xyz.fycz.myreader.ui.activity.*; import xyz.fycz.myreader.util.*; +import xyz.fycz.myreader.util.utils.ColorUtil; import xyz.fycz.myreader.webapi.crawler.ReadCrawler; import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; import xyz.fycz.myreader.creator.DialogCreator; @@ -45,9 +45,6 @@ import xyz.fycz.myreader.greendao.entity.Chapter; import xyz.fycz.myreader.greendao.service.BookMarkService; import xyz.fycz.myreader.greendao.service.BookService; import xyz.fycz.myreader.greendao.service.ChapterService; -import xyz.fycz.myreader.ui.activity.FontsActivity; -import xyz.fycz.myreader.ui.activity.ReadActivity; -import xyz.fycz.myreader.ui.activity.CatalogActivity; import xyz.fycz.myreader.util.notification.NotificationClickReceiver; import xyz.fycz.myreader.util.notification.NotificationUtil; import xyz.fycz.myreader.util.utils.NetworkUtils; @@ -214,6 +211,9 @@ public class ReadPresenter implements BasePresenter { @Override public void start() { + if (SharedPreUtils.getInstance().getBoolean("isNightFS", false)) { + mSetting.setDayStyle(!ColorUtil.isColorLight(mReadActivity.getColor(R.color.textPrimary))); + } //息屏时间 screenTimeOut = mSetting.getResetScreen() * 60; @@ -237,23 +237,19 @@ public class ReadPresenter implements BasePresenter { BrightUtil.setBrightness(mReadActivity, BrightUtil.progressToBright(mSetting.getBrightProgress())); } - //是否直接打开本地txt文件 - String path = null; - if (Intent.ACTION_VIEW.equals(mReadActivity.getIntent().getAction())) { - Uri uri = mReadActivity.getIntent().getData(); - path = getPath(mReadActivity, uri); - } - if (!StringHelper.isEmpty(path)) { - //本地txt文件路径不为空,添加书籍 - addLocalBook(path); - } else { - //路径为空,说明不是直接打开txt文件 - mBook = (Book) mReadActivity.getIntent().getSerializableExtra(APPCONST.BOOK); + if (!loadBook()){ + mReadActivity.finish(); + return; } - isCollected = mReadActivity.getIntent().getBooleanExtra("isCollected", true); + //当书籍Collected且书籍id不为空的时候保存上次阅读信息 + if (isCollected && !StringHelper.isEmpty(mBook.getId())) { + //保存上次阅读信息 + SharedPreUtils.getInstance().putString("lastRead", mBook.getId()); + } + mReadCrawler = ReadCrawlerUtil.getReadCrawler(mBook.getSource()); mPageLoader = mReadActivity.getSrlContent().getPageLoader(mBook, mReadCrawler, mSetting); @@ -264,6 +260,47 @@ public class ReadPresenter implements BasePresenter { getData(); } + /** + * 进入阅读书籍有三种方式: + * 1、直接从书架进入,这种方式书籍一定Collected + * 2、从外部打开txt文件,这种方式会添加进书架 + * 3、从快捷图标打开上次阅读书籍 + * @return 是否加载成功 + */ + private boolean loadBook() { + //是否直接打开本地txt文件 + String path = null; + if (Intent.ACTION_VIEW.equals(mReadActivity.getIntent().getAction())) { + Uri uri = mReadActivity.getIntent().getData(); + if (uri != null) { + path = getPath(mReadActivity, uri); + } + } + if (!StringHelper.isEmpty(path)) { + //本地txt文件路径不为空,添加书籍 + addLocalBook(path); + } else { + //路径为空,说明不是直接打开txt文件 + mBook = (Book) mReadActivity.getIntent().getSerializableExtra(APPCONST.BOOK); + //mBook为空,说明是从快捷方式启动 + if (mBook == null){ + String bookId = SharedPreUtils.getInstance().getString("lastRead", ""); + if ("".equals(bookId)){//没有上次阅读信息 + ToastUtils.showWarring("当前没有阅读任何书籍,无法加载上次阅读书籍!"); + mReadActivity.finish(); + return false; + }else {//有信息 + mBook = mBookService.getBookById(bookId); + if (mBook == null){//上次阅读的书籍不存在 + ToastUtils.showWarring("上次阅读书籍已不存在/移除书架,无法加载!"); + mReadActivity.finish(); + return false; + }//存在就继续执行 + } + } + } + return true; + } /** * 保存最后阅读章节的进度 @@ -342,6 +379,7 @@ public class ReadPresenter implements BasePresenter { intent.putExtra(APPCONST.BOOK, mBook); mReadActivity.startActivityForResult(intent, APPCONST.REQUEST_CHAPTER_PAGE); }, (dialog, view, isDayStyle) -> {//日夜切换 + dialog.dismiss(); changeNightAndDaySetting(isDayStyle); }, view -> {//设置 showSettingDetailView(); @@ -477,7 +515,7 @@ public class ReadPresenter implements BasePresenter { default: checkedItem = 0; } - mPageModeDialog = new AlertDialog.Builder(mReadActivity) + mPageModeDialog = MyAlertDialog.build(mReadActivity) .setTitle("翻页模式") .setSingleChoiceItems(pageMode, checkedItem, (dialog, which) -> { switch (which) { @@ -770,7 +808,7 @@ public class ReadPresenter implements BasePresenter { return; } MyApplication.runOnUiThread(() -> { - new AlertDialog.Builder(mReadActivity) + MyAlertDialog.build(mReadActivity) .setTitle("缓存书籍") .setSingleChoiceItems(APPCONST.DIALOG_DOWNLOAD, selectedIndex, (dialog, which) -> selectedIndex = which).setNegativeButton("取消", ((dialog, which) -> dialog.dismiss())).setPositiveButton("确定", (dialog, which) -> { @@ -957,8 +995,9 @@ public class ReadPresenter implements BasePresenter { private void changeNightAndDaySetting(boolean isCurDayStyle) { mSetting.setDayStyle(!isCurDayStyle); SysManager.saveSetting(mSetting); + MyApplication.getApplication().setNightTheme(isCurDayStyle); settingChange = true; - mPageLoader.setPageStyle(!isCurDayStyle); + //mPageLoader.setPageStyle(!isCurDayStyle); } /** @@ -992,11 +1031,14 @@ public class ReadPresenter implements BasePresenter { */ private void changeStyle(ReadStyle readStyle) { settingChange = true; - if (!mSetting.isDayStyle()) { - mSetting.setDayStyle(true); - } mSetting.setReadStyle(readStyle); SysManager.saveSetting(mSetting); + if (!mSetting.isDayStyle()) { + DialogCreator.createCommonDialog(mReadActivity, "提示", "是否希望切换为日间模式?", + false, "确定", "取消", (dialog, which) -> { + changeNightAndDaySetting(false); + }, null); + } MyApplication.runOnUiThread(() -> mPageLoader.setPageStyle(true)); } @@ -1083,7 +1125,6 @@ public class ReadPresenter implements BasePresenter { book.setSource(BookSource.local.toString()); book.setDesc("无"); book.setIsCloseUpdate(true); - //判断书籍是否已经添加 Book existsBook = mBookService.findBookByAuthorAndName(book.getName(), book.getAuthor()); if (book.equals(existsBook)) { @@ -1220,7 +1261,9 @@ public class ReadPresenter implements BasePresenter { for (int i = 0; i < 9; i++) { mHandler.removeMessages(i + 1); } - mPageLoader.closeBook(); - mPageLoader = null; + if (mPageLoader != null) { + mPageLoader.closeBook(); + mPageLoader = null; + } } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/RegisterPresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/RegisterPresenter.java deleted file mode 100644 index 7c9d2ae..0000000 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/RegisterPresenter.java +++ /dev/null @@ -1,244 +0,0 @@ -package xyz.fycz.myreader.ui.presenter; - -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 xyz.fycz.myreader.backup.UserService; -import xyz.fycz.myreader.base.BasePresenter; -import xyz.fycz.myreader.callback.ResultCallback; -import xyz.fycz.myreader.creator.DialogCreator; -import xyz.fycz.myreader.ui.activity.RegisterActivity; -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/4/26 20:31 - */ - -public class RegisterPresenter implements BasePresenter { - private RegisterActivity mRegisterActivity; - private String code; - private String username = ""; - private String password = ""; - private String rpPassword = ""; - private String inputCode = ""; - - public RegisterPresenter(RegisterActivity mRegisterActivity) { - this.mRegisterActivity = mRegisterActivity; - } - - @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: - mRegisterActivity.getTvRegisterTip().setVisibility(View.GONE); - break; - } - } - }; - - @Override - public void start() { - mHandler.sendMessage(mHandler.obtainMessage(1)); - mRegisterActivity.getTvTitleText().setText("注册"); - mRegisterActivity.getEtUsername().requestFocus(); - mRegisterActivity.getLlTitleBack().setOnClickListener(v -> mRegisterActivity.finish()); - - mRegisterActivity.getEtUsername().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(); - } - }); - - mRegisterActivity.getEtPassword().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(); - } - }); - - mRegisterActivity.getEtRpPassword().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(); - } - }); - - mRegisterActivity.getEtCaptcha().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(); - } - }); - - mRegisterActivity.getIvCaptcha().setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - mHandler.sendMessage(mHandler.obtainMessage(1)); - } - }); - - mRegisterActivity.getBtRegister().setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (!username.matches("^[A-Za-z][A-Za-z0-9]{5,13}$")){ - DialogCreator.createTipDialog(mRegisterActivity, "用户名格式错误", - "用户名必须在6-14位之间\n用户名只能以字母开头\n用户名只能由数字、字母、下划线、减号组成"); - }else if(password.matches("^\\d+$") || !password.matches("^.{8,16}$")){ - DialogCreator.createTipDialog(mRegisterActivity, "密码格式错误", - "密码必须在8-16位之间\n密码不能是纯数字"); - }else if(!password.equals(rpPassword)){ - DialogCreator.createTipDialog(mRegisterActivity, "重复密码错误", - "两次输入的密码不一致"); - }else if(!inputCode.trim().toLowerCase().equals(code.toLowerCase())){ - DialogCreator.createTipDialog(mRegisterActivity, "验证码错误"); - }else if(!mRegisterActivity.getCbAgreement().isChecked()){ - DialogCreator.createTipDialog(mRegisterActivity, "请勾选同意《用户服务协议》"); - }else { - ProgressDialog dialog = DialogCreator.createProgressDialog(mRegisterActivity, null, "正在注册..."); - Map 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]); - mRegisterActivity.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)); - } - }); - - mRegisterActivity.getTvAgreement().setMovementMethod(LinkMovementMethod.getInstance()); - } - - - public void createCaptcha() { - code = CodeUtil.getInstance().createCode(); - Bitmap codeBitmap = CodeUtil.getInstance().createBitmap(code); - mRegisterActivity.getIvCaptcha().setImageBitmap(codeBitmap); - } - - public void showTip(String tip) { - mRegisterActivity.getTvRegisterTip().setVisibility(View.VISIBLE); - mRegisterActivity.getTvRegisterTip().setText(tip); - } - - public void checkNotNone(){ - if ("".equals(username) || "".equals(password) || "".equals(rpPassword) || "".equals(inputCode)){ - mRegisterActivity.getBtRegister().setEnabled(false); - }else { - mRegisterActivity.getBtRegister().setEnabled(true); - } - } - -} diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/SearchBookPrensenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/SearchBookPrensenter.java deleted file mode 100644 index 501a9b4..0000000 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/SearchBookPrensenter.java +++ /dev/null @@ -1,354 +0,0 @@ -package xyz.fycz.myreader.ui.presenter; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.Intent; -import android.os.Build; -import android.os.Handler; -import android.os.Message; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.KeyEvent; -import android.view.View; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.InputMethodManager; - -import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.webapi.crawler.*; -import xyz.fycz.myreader.entity.SearchBookBean; -import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; -import xyz.fycz.myreader.ui.activity.BookDetailedActivity; -import xyz.fycz.myreader.R; -import xyz.fycz.myreader.base.BasePresenter; -import xyz.fycz.myreader.callback.ResultCallback; -import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.greendao.entity.Book; -import xyz.fycz.myreader.greendao.entity.SearchHistory; -import xyz.fycz.myreader.greendao.service.SearchHistoryService; -import xyz.fycz.myreader.ui.activity.SearchBookActivity; -import xyz.fycz.myreader.ui.adapter.SearchBookAdapter; -import xyz.fycz.myreader.ui.adapter.SearchHistoryAdapter; -import xyz.fycz.myreader.util.StringHelper; -import xyz.fycz.myreader.webapi.CommonApi; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; - - -public class SearchBookPrensenter implements BasePresenter { - - private SearchBookActivity mSearchBookActivity; - private SearchBookAdapter mSearchBookAdapter; - private String searchKey;//搜索关键字 - private ArrayList mBooksBean = new ArrayList<>(); - private ConcurrentMultiValueMap mBooks = new ConcurrentMultiValueMap<>(); - private ArrayList mAdapterBooks = new ArrayList<>(); - private ArrayList mSearchHistories = new ArrayList<>(); - private ArrayList mSuggestions = new ArrayList<>(); - - private SearchHistoryService mSearchHistoryService; - - private SearchHistoryAdapter mSearchHistoryAdapter; - - private int curThreadCount; - - private int allThreadCount; - - private int inputConfirm = 0;//搜索输入确认 - private int confirmTime = 1000;//搜索输入确认时间(毫秒) - - private static String[] suggestion = {"第一序列", "大道朝天", "伏天氏", "终极斗罗", "我师兄实在太稳健了", "烂柯棋缘", "诡秘之主"}; - private static String[] suggestion2 = {"不朽凡人", "圣墟", "我是至尊", "龙王传说", "太古神王", "一念永恒", "雪鹰领主", "大主宰"}; - - @SuppressLint("HandlerLeak") - private Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case 1: - search(); - break; - case 2: - if (curThreadCount == 0) { - initSearchList(); - mSearchBookActivity.getSrlSearchBookList().finishRefresh(); - mSearchBookActivity.getPbLoading().setVisibility(View.GONE); - }/*else { - notifyDataSetChanged(); - mSearchBookActivity.getSrlSearchBookList().finishRefresh(); - }*/ - break; - } - } - }; - - public SearchBookPrensenter(SearchBookActivity searchBookActivity) { - mSearchBookActivity = searchBookActivity; - mSearchHistoryService = SearchHistoryService.getInstance(); - for (int i = 0; i < suggestion.length; i++) { - mSuggestions.add(suggestion[i]); - } - } - - @Override - public void start() { - mSearchBookActivity.getTvTitleText().setText("搜索"); - mSearchBookActivity.getEtSearchKey().requestFocus();//get the focus - //enter事件 - mSearchBookActivity.getEtSearchKey().setOnEditorActionListener((textView, i, keyEvent) -> { - if (i == EditorInfo.IME_ACTION_UNSPECIFIED) { - mHandler.sendMessage(mHandler.obtainMessage(1)); - return (keyEvent.getKeyCode() == KeyEvent.KEYCODE_ENTER); - } - return false; - }); - //换一批点击事件 - mSearchBookActivity.getRenewByImage().setOnClickListener(new RenewSuggestionBook()); - //换一批点击事件 - mSearchBookActivity.getRenewByText().setOnClickListener(new RenewSuggestionBook()); - //返回 - mSearchBookActivity.getLlTitleBack().setOnClickListener(view -> mSearchBookActivity.finish()); - //搜索框改变事件 - mSearchBookActivity.getEtSearchKey().addTextChangedListener(new TextWatcher() { - - @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { - - } - - @Override - public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { - - } - - @Override - public void afterTextChanged(final Editable editable) { - searchKey = editable.toString(); - if (StringHelper.isEmpty(searchKey)) { - mHandler.sendMessage(mHandler.obtainMessage(1)); - } - - } - - }); - //进入书籍详情页 - mSearchBookActivity.getGvSearchBooksList().setOnItemClickListener((adapterView, view, i, l) -> { - Intent intent = new Intent(mSearchBookActivity, BookDetailedActivity.class); - intent.putExtra(APPCONST.SEARCH_BOOK_BEAN, new ArrayList<>(mBooks.getValues(mBooksBean.get(i)))); - mSearchBookActivity.startActivity(intent); - }); - //搜索按钮点击事件 - mSearchBookActivity.getTvSearchConform().setOnClickListener(view -> mHandler.sendMessage(mHandler.obtainMessage(1))); - //suggestion搜索事件 - mSearchBookActivity.getTgSuggestBook().setOnTagClickListener(tag -> { - mSearchBookActivity.getEtSearchKey().setText(tag); - mSearchBookActivity.getEtSearchKey().setSelection(tag.length()); - mHandler.sendMessage(mHandler.obtainMessage(1)); - }); - //历史记录搜索事件 - mSearchBookActivity.getLvHistoryList().setOnItemClickListener((parent, view, position, id) -> { - mSearchBookActivity.getEtSearchKey().setText(mSearchHistories.get(position).getContent()); - mSearchBookActivity.getEtSearchKey().setSelection(mSearchHistories.get(position).getContent().length()); - mHandler.sendMessage(mHandler.obtainMessage(1)); - }); - //清空历史记录 - mSearchBookActivity.getLlClearHistory().setOnClickListener(v -> { - mSearchHistoryService.clearHistory(); - initHistoryList(); - }); - //清除单个历史记录 - mSearchBookActivity.getLvHistoryList().setOnItemLongClickListener((parent, view, position, id) -> { - if (mSearchHistories.get(position) != null) { - mSearchHistoryService.deleteHistory(mSearchHistories.get(position)); - initHistoryList(); - } - return true; - }); - //上拉刷新 - mSearchBookActivity.getSrlSearchBookList().setOnRefreshListener(refreshLayout -> mHandler.sendMessage(mHandler.obtainMessage(1))); - mSearchBookActivity.getSrlSearchBookList().setEnableRefresh(false); - mSearchBookActivity.getGvSearchBooksList().setNumColumns(1); - mSearchBookActivity.getGvSearchBooksList().setDragModel(-1); - initSuggestionBook(); - initHistoryList(); - } - - - /** - * 初始化建议书目 - */ - private void initSuggestionBook() { - mSearchBookActivity.getTgSuggestBook().setTags(suggestion); - } - - private class RenewSuggestionBook implements View.OnClickListener { - @Override - public void onClick(View v) { - String[] s = mSearchBookActivity.getTgSuggestBook().getTags(); - if (Arrays.equals(s, suggestion)) { - mSearchBookActivity.getTgSuggestBook().setTags(suggestion2); - } else { - mSearchBookActivity.getTgSuggestBook().setTags(suggestion); - } - } - } - - /** - * 初始化历史列表 - */ - private void initHistoryList() { - mSearchHistories = mSearchHistoryService.findAllSearchHistory(); - if (mSearchHistories == null || mSearchHistories.size() == 0) { - mSearchBookActivity.getLlHistoryView().setVisibility(View.GONE); - } else { - mSearchHistoryAdapter = new SearchHistoryAdapter(mSearchBookActivity, R.layout.listview_search_history_item, mSearchHistories); - mSearchBookActivity.getLvHistoryList().setAdapter(mSearchHistoryAdapter); - mSearchBookActivity.getLlHistoryView().setVisibility(View.VISIBLE); - } - } - - /** - * 初始化搜索列表 - */ - private void initSearchList() { - initmBooksBean(); - mSearchBookAdapter = new SearchBookAdapter(mSearchBookActivity, - R.layout.listview_search_book_item, mBooksBean, mBooks); - mSearchBookActivity.getGvSearchBooksList().setAdapter(mSearchBookAdapter); - mSearchBookActivity.getGvSearchBooksList().setVisibility(View.VISIBLE); - mSearchBookActivity.getLlSuggestBooksView().setVisibility(View.GONE); - mSearchBookActivity.getLlHistoryView().setVisibility(View.GONE); - } - - /** - * 更新搜索列表 - */ - private void notifyDataSetChanged() { - if (curThreadCount == 0) { - mSearchBookActivity.getPbLoading().setVisibility(View.GONE); - } - initmBooksBean(); - } - - /** - * 初始化mBooksBean - */ - private void initmBooksBean() { - synchronized (this) { - mBooksBean.clear(); - mBooksBean.addAll(mBooks.keySet()); - //排序,基于最符合关键字的搜书结果应该是最短的 - //TODO ;这里只做了简单的比较排序,还需要继续完善 - Collections.sort(mBooksBean, (o1, o2) -> { - if (searchKey.equals(o1.getName())) - return -1; - if (searchKey.equals(o2.getName())) - return 1; - if (searchKey.equals(o1.getAuthor())) - return -1; - if (searchKey.equals(o2.getAuthor())) - return 1; - if (o1.getName().length() < o2.getName().length()) - return -1; - if (o1.getName().length() == o2.getName().length()) - return 0; - return 1; - }); - /*MyApplication.runOnUiThread(new Runnable() { - @Override - public void run() { - mSearchBookAdapter.notifyDataSetChanged(); - } - });*/ - } - } - - /** - * 获取搜索数据 - */ - private void getData() { - mBooksBean.clear(); - mBooks.clear(); - allThreadCount = 4; - curThreadCount = allThreadCount; - searchBookByCrawler(new BiQuGe44ReadCrawler(), ""); - searchBookByCrawler(new TianLaiReadCrawler(), ""); - searchBookByCrawler(new BiQuGeReadCrawler(), "gbk"); - searchBookByCrawler(new PinShuReadCrawler(), "gbk"); - } - - /** - * 搜索 - */ - private void search() { - mSearchBookActivity.getPbLoading().setVisibility(View.VISIBLE); - if (StringHelper.isEmpty(searchKey)) { - mSearchBookActivity.getPbLoading().setVisibility(View.GONE); - mSearchBookActivity.getGvSearchBooksList().setVisibility(View.GONE); - mSearchBookActivity.getLlSuggestBooksView().setVisibility(View.VISIBLE); - initHistoryList(); - mSearchBookActivity.getGvSearchBooksList().setAdapter(null); - mSearchBookActivity.getSrlSearchBookList().setEnableRefresh(false); - } else { - mSearchBookActivity.getGvSearchBooksList().setVisibility(View.VISIBLE); - mSearchBookActivity.getLlSuggestBooksView().setVisibility(View.GONE); - mSearchBookActivity.getLlHistoryView().setVisibility(View.GONE); - getData(); - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (mSearchBookActivity.getGvSearchBooksList().getmScrollView().getScrollY() == 0){ - mSearchBookActivity.getSrlSearchBookList().setEnableRefresh(true); - } - //滑动监听器 - mSearchBookActivity.getGvSearchBooksList().getmScrollView().setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> { - mSearchBookActivity.getSrlSearchBookList().setEnableRefresh(scrollY == 0); - }); - } - mSearchHistoryService.addOrUpadteHistory(searchKey); - //收起软键盘 - InputMethodManager imm = (InputMethodManager) MyApplication.getmContext().getSystemService(Context.INPUT_METHOD_SERVICE); - assert imm != null; - imm.hideSoftInputFromWindow(mSearchBookActivity.getEtSearchKey().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); - } - } - - public boolean onBackPressed() { - if (StringHelper.isEmpty(searchKey)) { - return false; - } else { - mSearchBookActivity.getEtSearchKey().setText(""); - return true; - } - } - - private void searchBookByCrawler(ReadCrawler rc, String charset) { - String searchKey = this.searchKey; - if (charset.toLowerCase().equals("gbk")) { - try { - searchKey = URLEncoder.encode(this.searchKey, charset); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - } - CommonApi.search(searchKey, rc, new ResultCallback() { - @Override - public void onFinish(Object o, int code) { - ConcurrentMultiValueMap sbb = - (ConcurrentMultiValueMap) o; - mBooks.addAll(sbb); - curThreadCount--; - mHandler.sendMessage(mHandler.obtainMessage(2)); - } - - @Override - public void onError(Exception e) { - curThreadCount--; - mHandler.sendMessage(mHandler.obtainMessage(2)); - } - }); - } - -} - diff --git a/app/src/main/java/xyz/fycz/myreader/util/HttpUtil.java b/app/src/main/java/xyz/fycz/myreader/util/HttpUtil.java index c98b0a1..486a8c2 100644 --- a/app/src/main/java/xyz/fycz/myreader/util/HttpUtil.java +++ b/app/src/main/java/xyz/fycz/myreader/util/HttpUtil.java @@ -5,6 +5,7 @@ import android.util.Base64; import android.util.Log; import com.google.gson.Gson; +import okhttp3.*; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.application.TrustAllCerts; import xyz.fycz.myreader.callback.HttpCallback; @@ -21,32 +22,18 @@ import java.net.URLConnection; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.Map; +import java.util.*; import java.util.concurrent.TimeUnit; -import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.MediaType; -import okhttp3.MultipartBody; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; - import static java.lang.String.valueOf; - public class HttpUtil { private static String sessionid; @@ -67,32 +54,30 @@ public class HttpUtil { return ssfFactory; } - private static synchronized OkHttpClient getOkHttpClient(){ - if (mClient == null){ + private static synchronized OkHttpClient getOkHttpClient() { + if (mClient == null) { OkHttpClient.Builder builder = new OkHttpClient.Builder(); - builder.connectTimeout(30000, TimeUnit.SECONDS); + builder.connectTimeout(30, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS); builder.sslSocketFactory(createSSLSocketFactory()); - builder.hostnameVerifier(new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; - } - }); - mClient = builder + builder.hostnameVerifier((hostname, session) -> true); + mClient = builder .build(); } return mClient; } + /** * 图片发送 + * * @param address * @param callback */ public static void sendBitmapGetRequest(final String address, final HttpCallback callback) { new Thread(new Runnable() { HttpURLConnection connection = null; + @Override public void run() { try { @@ -131,12 +116,14 @@ public class HttpUtil { /** * get请求 + * * @param address * @param callback */ public static void sendGetRequest(final String address, final HttpCallback callback) { new Thread(new Runnable() { HttpURLConnection connection = null; + @Override public void run() { try { @@ -175,6 +162,7 @@ public class HttpUtil { /** * 网络通信测试请求 + * * @param address * @param callback */ @@ -219,7 +207,7 @@ public class HttpUtil { } public static void sendGetRequest_okHttp(final String address, final HttpCallback callback) { - MyApplication.getApplication().newThread(() -> { + MyApplication.getApplication().newThread(() -> { /* HttpURLConnection connection = null; try { URL url = new URL(address); @@ -251,23 +239,57 @@ public class HttpUtil { connection.disconnect(); } }*/ - try{ - OkHttpClient client = getOkHttpClient(); - Request request = new Request.Builder() - .addHeader("User-Agent","Mozilla/4.0 (compatible; MSIE 7.0; Windows 7)") - .url(address) - .build(); - Response response = client.newCall(request).execute(); - callback.onFinish(response.body().byteStream()); - }catch(Exception e){ - e.printStackTrace(); - callback.onError(e); - } - }); + try { + OkHttpClient client = getOkHttpClient(); + /*HashMap> cookieStore = new HashMap<>(); + OkHttpClient client = new OkHttpClient.Builder() + .cookieJar(new CookieJar() { + @Override + public void saveFromResponse(HttpUrl httpUrl, List list) { + StringBuilder sb = new StringBuilder(); + for (Cookie cookie : list){ + sb.append(cookie.name()).append("=").append(cookie.value()).append("; "); + } + if (list.size() > 0){ + sb.deleteCharAt(sb.lastIndexOf("; ")); + } + Log.i("CookieStr", sb.toString()); + cookieStore.put(httpUrl.host(), list); + } + + @Override + public List loadForRequest(HttpUrl httpUrl) { + List cookies = cookieStore.get(httpUrl.host()); + return cookies != null ? cookies : new ArrayList<>(); + } + }) + .build();*/ + Request.Builder requestBuilder = new Request.Builder() + .addHeader("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9") + .addHeader("accept-language", "zh-CN,zh;q=0.9") + .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4168.3 Safari/537.36"); + if (address.contains("qidian.com")) { + SharedPreUtils spu = SharedPreUtils.getInstance(); + String cookie = spu.getString("qdCookie", ""); + if (cookie.equals("")) { + requestBuilder.addHeader("cookie", "_csrfToken=eXRDlZxmRDLvFAmdgzqvwWAASrxxp2WkVlH4ZM7e; newstatisticUUID=1595991935_2026387981"); + }else { + requestBuilder.addHeader("cookie", cookie); + } + } + requestBuilder.url(address); + Response response = client.newCall(requestBuilder.build()).execute(); + callback.onFinish(response.body().byteStream()); + } catch (Exception e) { + e.printStackTrace(); + callback.onError(e); + } + }); } /** * post请求 + * * @param address * @param output * @param callback @@ -315,6 +337,7 @@ public class HttpUtil { /** * post请求 获取蓝奏云直链 + * * @param address * @param output * @param callback @@ -360,10 +383,11 @@ public class HttpUtil { public static void sendPostRequest_okHttp(final String address, final String output, final HttpCallback callback) { new Thread(new Runnable() { HttpURLConnection connection = null; + @Override public void run() { try { - MediaType contentType = MediaType.parse("charset=utf-8"); + MediaType contentType = MediaType.parse("charset=utf-8"); OkHttpClient client = new OkHttpClient(); RequestBody body = RequestBody.create(contentType, output); Request request = new Request.Builder() @@ -387,17 +411,18 @@ public class HttpUtil { /** * 多文件上传请求 + * * @param url * @param files * @param params * @param callback */ - public static void uploadFile(String url, ArrayList files, Map params, final HttpCallback callback){ + public static void uploadFile(String url, ArrayList files, Map params, final HttpCallback callback) { OkHttpClient client = new OkHttpClient(); // form 表单形式上传 MultipartBody.Builder requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM); - for(File file : files){ - if(file != null){ + for (File file : files) { + if (file != null) { // MediaType.parse() 里面是上传的文件类型。 RequestBody body = RequestBody.create(MediaType.parse("*/*"), file); String filename = file.getName(); @@ -418,7 +443,7 @@ public class HttpUtil { @Override public void onFailure(Call call, IOException e) { callback.onError(e); - Log.i("Http" ,"onFailure"); + Log.i("Http", "onFailure"); } @Override @@ -432,7 +457,7 @@ public class HttpUtil { jsonModel.setSuccess(false); // jsonModel.setResult(response.body().string()); callback.onFinish(new Gson().toJson(jsonModel)); - Log.i("Http" ,response.message() + " error : body " + response.body().string()); + Log.i("Http", response.message() + " error : body " + response.body().string()); } } @@ -443,6 +468,7 @@ public class HttpUtil { /** * 生成URL + * * @param p_url * @param params * @return @@ -484,6 +510,7 @@ public class HttpUtil { /** * 生成URL(不加密) + * * @param p_url * @param params * @return @@ -513,6 +540,7 @@ public class HttpUtil { /** * 生成post输出参数串 + * * @param params * @return */ @@ -570,10 +598,11 @@ public class HttpUtil { /** * 测试URL可连接性 + * * @param url * @param connectionCallback */ - public static void isURLConnection(String url, final URLConnectionCallback connectionCallback){ + public static void isURLConnection(String url, final URLConnectionCallback connectionCallback) { sendTestGetRequest(url, new HttpCallback() { @Override public void onFinish(String response) { @@ -667,11 +696,11 @@ public class HttpUtil { } Log.i("http", "文件的大小:" + total); ds.writeBytes(end); - /* close streams */ + /* close streams */ fStream.close(); } ds.writeBytes(twoHyphens + boundary + twoHyphens + end); - /* close streams */ + /* close streams */ ds.flush(); if (httpURLConnection.getResponseCode() >= 300) { callback.onError(new Exception( @@ -734,17 +763,16 @@ public class HttpUtil { } - /** * Trust every server - dont check for any certificate */ public static void trustAllHosts() { final String TAG = "trustAllHosts"; // Create a trust manager that does not validate certificate chains - TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { + TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { - return new java.security.cert.X509Certificate[] {}; + return new java.security.cert.X509Certificate[]{}; } public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { @@ -754,7 +782,7 @@ public class HttpUtil { public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { Log.i(TAG, "checkServerTrusted"); } - } }; + }}; // Install the all-trusting trust manager try { @@ -767,6 +795,4 @@ public class HttpUtil { } - - } diff --git a/app/src/main/java/xyz/fycz/myreader/util/notification/NotificationUtil.java b/app/src/main/java/xyz/fycz/myreader/util/notification/NotificationUtil.java index 0e9b688..51d45c1 100644 --- a/app/src/main/java/xyz/fycz/myreader/util/notification/NotificationUtil.java +++ b/app/src/main/java/xyz/fycz/myreader/util/notification/NotificationUtil.java @@ -17,6 +17,7 @@ import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.creator.MyAlertDialog; import xyz.fycz.myreader.greendao.service.BookMarkService; import java.lang.reflect.Field; @@ -144,7 +145,7 @@ public class NotificationUtil { public void requestNotificationPermissionDialog(Context context){ if (!isNotificationEnabled(context)) { - new AlertDialog.Builder(context) + MyAlertDialog.build(context) .setTitle("开启通知") .setMessage("检测到未开启通知权限,无法在通知栏查看缓存进度,是否前往开启?") .setCancelable(true) diff --git a/app/src/main/java/xyz/fycz/myreader/util/utils/BlurTransformation.java b/app/src/main/java/xyz/fycz/myreader/util/utils/BlurTransformation.java new file mode 100644 index 0000000..ce3cda2 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/util/utils/BlurTransformation.java @@ -0,0 +1,61 @@ +package xyz.fycz.myreader.util.utils; + +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.Bitmap; +import android.os.Build; +import android.renderscript.Allocation; +import android.renderscript.Element; +import android.renderscript.RenderScript; +import android.renderscript.ScriptIntrinsicBlur; +import androidx.annotation.NonNull; +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; + +import java.security.MessageDigest; + +public class BlurTransformation extends BitmapTransformation { + private RenderScript rs; + private int radius; + + public BlurTransformation(Context context, int radius) { + super(); + rs = RenderScript.create(context); + this.radius = radius; + } + + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) + @Override + protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) { + Bitmap blurredBitmap = toTransform.copy(Bitmap.Config.ARGB_8888, true); + + // Allocate memory for Renderscript to work with + //分配用于渲染脚本的内存 + Allocation input = Allocation.createFromBitmap(rs, blurredBitmap, Allocation.MipmapControl.MIPMAP_FULL, Allocation.USAGE_SHARED); + Allocation output = Allocation.createTyped(rs, input.getType()); + + // Load up an instance of the specific script that we want to use. + //加载我们想要使用的特定脚本的实例。 + ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); + script.setInput(input); + + // Set the blur radius + //设置模糊半径 + script.setRadius(radius); + + // Start the ScriptIntrinsicBlur + //启动 ScriptIntrinsicBlur, + script.forEach(output); + + // Copy the output to the blurred bitmap + //将输出复制到模糊的位图 + output.copyTo(blurredBitmap); + + return blurredBitmap; + } + + @Override + public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) { + messageDigest.update("blur transformation".getBytes()); + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/util/utils/ColorUtil.java b/app/src/main/java/xyz/fycz/myreader/util/utils/ColorUtil.java new file mode 100644 index 0000000..b2d2b8c --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/util/utils/ColorUtil.java @@ -0,0 +1,80 @@ +package xyz.fycz.myreader.util.utils; + +import android.graphics.Color; +import androidx.annotation.ColorInt; +import androidx.annotation.FloatRange; + +@SuppressWarnings({"unused", "WeakerAccess"}) +public class ColorUtil { + + public static String intToString(int intColor) { + return String.format("#%06X", 0xFFFFFF & intColor); + } + + + public static int stripAlpha(@ColorInt int color) { + return 0xff000000 | color; + } + + @ColorInt + public static int shiftColor(@ColorInt int color, @FloatRange(from = 0.0f, to = 2.0f) float by) { + if (by == 1f) return color; + int alpha = Color.alpha(color); + float[] hsv = new float[3]; + Color.colorToHSV(color, hsv); + hsv[2] *= by; // value component + return (alpha << 24) + (0x00ffffff & Color.HSVToColor(hsv)); + } + + @ColorInt + public static int darkenColor(@ColorInt int color) { + return shiftColor(color, 0.9f); + } + + @ColorInt + public static int lightenColor(@ColorInt int color) { + return shiftColor(color, 1.1f); + } + + public static boolean isColorLight(@ColorInt int color) { + final double darkness = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255; + return darkness < 0.4; + } + + @ColorInt + public static int invertColor(@ColorInt int color) { + final int r = 255 - Color.red(color); + final int g = 255 - Color.green(color); + final int b = 255 - Color.blue(color); + return Color.argb(Color.alpha(color), r, g, b); + } + + @ColorInt + public static int adjustAlpha(@ColorInt int color, @FloatRange(from = 0.0, to = 1.0) float factor) { + int alpha = Math.round(Color.alpha(color) * factor); + int red = Color.red(color); + int green = Color.green(color); + int blue = Color.blue(color); + return Color.argb(alpha, red, green, blue); + } + + @ColorInt + public static int withAlpha(@ColorInt int baseColor, @FloatRange(from = 0.0, to = 1.0) float alpha) { + int a = Math.min(255, Math.max(0, (int) (alpha * 255))) << 24; + int rgb = 0x00ffffff & baseColor; + return a + rgb; + } + + /** + * Taken from CollapsingToolbarLayout's CollapsingTextHelper class. + */ + public static int blendColors(int color1, int color2, @FloatRange(from = 0.0, to = 1.0) float ratio) { + final float inverseRatio = 1f - ratio; + float a = (Color.alpha(color1) * inverseRatio) + (Color.alpha(color2) * ratio); + float r = (Color.red(color1) * inverseRatio) + (Color.red(color2) * ratio); + float g = (Color.green(color1) * inverseRatio) + (Color.green(color2) * ratio); + float b = (Color.blue(color1) * inverseRatio) + (Color.blue(color2) * ratio); + return Color.argb((int) a, (int) r, (int) g, (int) b); + } + +} diff --git a/app/src/main/java/xyz/fycz/myreader/util/utils/FileUtils.java b/app/src/main/java/xyz/fycz/myreader/util/utils/FileUtils.java index d0161cc..5f299fd 100644 --- a/app/src/main/java/xyz/fycz/myreader/util/utils/FileUtils.java +++ b/app/src/main/java/xyz/fycz/myreader/util/utils/FileUtils.java @@ -85,7 +85,7 @@ public class FileUtils { public static String getFileSize(long size) { if (size <= 0) return "0"; - final String[] units = new String[]{"b", "kb", "M", "G", "T"}; + final String[] units = new String[]{"b", "KB", "MB", "G", "T"}; //计算单位的,原理是利用lg,公式是 lg(1024^n) = nlg(1024),最后 nlg(1024)/lg(1024) = n。 int digitGroups = (int) (Math.log10(size) / Math.log10(1024)); //计算原理是,size/单位值。单位值指的是:比如说b = 1024,KB = 1024^2 diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/BookStoreApi.java b/app/src/main/java/xyz/fycz/myreader/webapi/BookStoreApi.java index ebeca3c..816e48e 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/BookStoreApi.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/BookStoreApi.java @@ -3,6 +3,8 @@ package xyz.fycz.myreader.webapi; import xyz.fycz.myreader.callback.ResultCallback; import xyz.fycz.myreader.webapi.crawler.BiQuGeReadCrawler; +import xyz.fycz.myreader.webapi.crawler.FindCrawler; +import xyz.fycz.myreader.webapi.crawler.QB5ReadCrawler; /** * Created by zhao on 2017/7/24. @@ -13,15 +15,15 @@ public class BookStoreApi extends BaseApi{ /** * 获取书城小说分类列表 - * @param url + * @param findCrawler * @param callback */ - public static void getBookTypeList(String url, final ResultCallback callback){ + public static void getBookTypeList(FindCrawler findCrawler, final ResultCallback callback){ - getCommonReturnHtmlStringApi(url, null, "GBK", new ResultCallback() { + getCommonReturnHtmlStringApi(findCrawler.getFindUrl(), null, findCrawler.getCharset(), new ResultCallback() { @Override public void onFinish(Object o, int code) { - callback.onFinish(BiQuGeReadCrawler.getBookTypeList((String) o),0); + callback.onFinish(findCrawler.getBookTypeList((String) o),0); } @Override @@ -35,15 +37,15 @@ public class BookStoreApi extends BaseApi{ /** * 获取某一分类小说排行榜列表 - * @param url + * @param findCrawler * @param callback */ - public static void getBookRankList(String url, final ResultCallback callback){ + public static void getBookRankList(String url, FindCrawler findCrawler, final ResultCallback callback){ - getCommonReturnHtmlStringApi(url, null, "GBK", new ResultCallback() { + getCommonReturnHtmlStringApi(url, null, findCrawler.getCharset(), new ResultCallback() { @Override public void onFinish(Object o, int code) { - callback.onFinish(BiQuGeReadCrawler.getBookRankList((String) o),0); + callback.onFinish(findCrawler.getRankBookList((String) o),0); } @Override diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/CommonApi.java b/app/src/main/java/xyz/fycz/myreader/webapi/CommonApi.java index 3804086..72b798b 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/CommonApi.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/CommonApi.java @@ -85,6 +85,8 @@ public class CommonApi extends BaseApi { params.put(rc.getSearchKey(), key); if (rc instanceof PinShuReadCrawler) { params.put("SearchClass", 1); + }else if (rc instanceof QB5ReadCrawler){ + params.put("submit", "%CB%D1%CB%F7"); } getCommonReturnHtmlStringApi(rc.getSearchLink(), params, charset, new ResultCallback() { @Override diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/BiQuGe44ReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/BiQuGe44ReadCrawler.java index 552fd9b..7cfb6b7 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/BiQuGe44ReadCrawler.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/BiQuGe44ReadCrawler.java @@ -20,6 +20,7 @@ public class BiQuGe44ReadCrawler implements ReadCrawler, BookInfoCrawler{ public static final String NOVEL_SEARCH = "https://www.wqge.cc/modules/article/search.php"; public static final String SEARCH_KEY = "searchkey"; public static final String CHARSET = "GBK"; + public static final String SEARCH_CHARSET = "utf-8"; @Override public String getSearchLink() { return NOVEL_SEARCH; @@ -40,6 +41,11 @@ public class BiQuGe44ReadCrawler implements ReadCrawler, BookInfoCrawler{ return SEARCH_KEY; } + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + /** * 从html中获取章节正文 * @param html diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/BiQuGeReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/BiQuGeReadCrawler.java index 9e647ed..3bad188 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/BiQuGeReadCrawler.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/BiQuGeReadCrawler.java @@ -24,6 +24,8 @@ public class BiQuGeReadCrawler implements ReadCrawler, BookInfoCrawler { private static final String NOVEL_SEARCH = "https://www.52bqg.net/modules/article/search.php"; private static final String SEARCH_KEY = "searchkey"; private static final String CHARSET = "GBK"; + public static final String SEARCH_CHARSET = "GBK"; + private ReadCrawler rc = new TianLaiReadCrawler(); @Override @@ -46,6 +48,11 @@ public class BiQuGeReadCrawler implements ReadCrawler, BookInfoCrawler { return CHARSET; } + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + /** * 获取书城小说分类列表 * @@ -108,6 +115,34 @@ public class BiQuGeReadCrawler implements ReadCrawler, BookInfoCrawler { } + public static List getLatestBookList(String html) { + List books = new ArrayList<>(); + Document doc = Jsoup.parse(html); + Element div = doc.getElementById("newscontent"); + Elements uls = div.getElementsByTag("ul"); + if (uls.size() > 0) { + for (Element li : uls.get(0).children()) { + Book book = new Book(); + Element scanS1 = li.getElementsByClass("s1").get(0); + Element scanS2 = li.getElementsByClass("s2").get(0); + Element scanS3 = li.getElementsByClass("s3").get(0); + Element scanS4 = li.getElementsByClass("s4").get(0); + Element scanS5 = li.getElementsByClass("s5").get(0); + book.setType(scanS1.text().replace("[", "").replace("]", "")); + Element a = scanS2.getElementsByTag("a").get(0); + book.setName(a.attr("title")); + book.setChapterUrl(a.attr("href")); + book.setNewestChapterTitle(scanS3.text()); + book.setAuthor(scanS4.text()); + book.setUpdateDate(scanS5.text()); + book.setSource(BookSource.biquge.toString()); + books.add(book); + } + } + + return books; + + } @Override public String getContentFormHtml(String html) { diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/FYReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/FYReadCrawler.java index 66f7029..eef038f 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/FYReadCrawler.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/FYReadCrawler.java @@ -26,6 +26,7 @@ public class FYReadCrawler implements ReadCrawler{ public static final String NOVEL_SEARCH = "https://novel.fycz.xyz/search.html"; public static final String SEARCH_KEY = "keyword"; public static final String CHARSET = "utf-8"; + public static final String SEARCH_CHARSET = "utf-8"; @Override public String getSearchLink() { return NOVEL_SEARCH; @@ -45,6 +46,11 @@ public class FYReadCrawler implements ReadCrawler{ return SEARCH_KEY; } + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + /** * 从html中获取章节正文 * diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/FindCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/FindCrawler.java new file mode 100644 index 0000000..3a46db6 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/FindCrawler.java @@ -0,0 +1,23 @@ +package xyz.fycz.myreader.webapi.crawler; + +import xyz.fycz.myreader.entity.bookstore.BookType; +import xyz.fycz.myreader.greendao.entity.Book; + +import java.io.Serializable; +import java.util.List; + +/** + * @author fengyue + * @date 2020/9/14 18:36 + */ +public abstract class FindCrawler implements Serializable { + private static final long serialVersionUID = 1L; + + public abstract String getCharset(); + public abstract String getFindName(); + public abstract String getFindUrl(); + public abstract boolean getTypePage(BookType curType, int page); + public abstract boolean hasImg(); + public abstract List getBookTypeList(String html); + public abstract List getRankBookList(String html); +} diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/PinShuReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/PinShuReadCrawler.java index bddefc3..173409e 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/PinShuReadCrawler.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/PinShuReadCrawler.java @@ -23,6 +23,7 @@ public class PinShuReadCrawler implements ReadCrawler, BookInfoCrawler { public static final String NOVEL_SEARCH = "https://www.vodtw.com/Book/Search.aspx"; public static final String SEARCH_KEY = "SearchKey"; public static final String CHARSET = "gbk"; + public static final String SEARCH_CHARSET = "gbk"; @Override public String getSearchLink() { @@ -43,7 +44,10 @@ public class PinShuReadCrawler implements ReadCrawler, BookInfoCrawler { public String getSearchKey() { return SEARCH_KEY; } - + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } /** * 从html中获取章节正文 * diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/PinShuReadCrawler2.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/PinShuReadCrawler2.java index b5a9798..55d8488 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/PinShuReadCrawler2.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/PinShuReadCrawler2.java @@ -23,6 +23,7 @@ public class PinShuReadCrawler2 implements ReadCrawler, BookInfoCrawler { public static final String NOVEL_SEARCH = "https://www.vodtw.la/search.html"; public static final String SEARCH_KEY = "q"; public static final String CHARSET = "UTF-8"; + public static final String SEARCH_CHARSET = "UTF-8"; @Override public String getSearchLink() { @@ -44,6 +45,11 @@ public class PinShuReadCrawler2 implements ReadCrawler, BookInfoCrawler { return SEARCH_KEY; } + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + /** * 从html中获取章节正文 * diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/QB5ReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/QB5ReadCrawler.java new file mode 100644 index 0000000..64fc7da --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/QB5ReadCrawler.java @@ -0,0 +1,287 @@ +package xyz.fycz.myreader.webapi.crawler; + +import android.text.Html; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.entity.bookstore.BookType; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.greendao.entity.Chapter; +import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.util.StringHelper; + +import java.util.ArrayList; +import java.util.List; + + +public class QB5ReadCrawler extends FindCrawler implements ReadCrawler, BookInfoCrawler { + private static final String NAME_SPACE = "https://www.qb5.tw"; + private static final String NOVEL_SEARCH = "https://www.qb5.tw/modules/article/search.php"; + public static final String FIND_URL = "https://www.qb5.tw"; + public static final String FIND_NAME = "书城[全本小说]"; + private static final String SEARCH_KEY = "searchkey"; + private static final String CHARSET = "GBK"; + public static final String SEARCH_CHARSET = "GBK"; + + @Override + public String getSearchLink() { + return NOVEL_SEARCH; + } + + @Override + public String getNameSpace() { + return NAME_SPACE; + } + + @Override + public String getSearchKey() { + return SEARCH_KEY; + } + + @Override + public String getCharset() { + return CHARSET; + } + + @Override + public String getFindName() { + return FIND_NAME; + } + + @Override + public String getFindUrl() { + return FIND_URL; + } + + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + + @Override + public boolean hasImg() { + return false; + } + /** + * 获取书城小说分类列表 + * + * @param html + * @return + */ + public List getBookTypeList(String html) { + List bookTypes = new ArrayList<>(); + Document doc = Jsoup.parse(html); + Elements divs = doc.getElementsByClass("nav_cont"); + if (divs.size() > 0) { + Elements uls = divs.get(0).getElementsByTag("ul"); + if (uls.size() > 0) { + for (Element li : uls.get(0).children()) { + Element a = li.child(0); + BookType bookType = new BookType(); + bookType.setTypeName(a.attr("title")); + bookType.setUrl(a.attr("href")); + if (bookType.getTypeName().contains("首页") || bookType.getTypeName().contains("热门小说")) continue; + if (!StringHelper.isEmpty(bookType.getTypeName())) { + bookTypes.add(bookType); + } + } + } + + } + return bookTypes; + } + + /** + * 获取某一分类小说排行榜列表 + * + * @param html + * @return + */ + public List getBookRankList(String html) { + List books = new ArrayList<>(); + Document doc = Jsoup.parse(html); + Elements divs = doc.getElementsByClass("r"); + if (divs.size() > 0) { + Elements uls = divs.get(0).getElementsByTag("ul"); + if (uls.size() > 0) { + for (Element li : uls.get(0).children()) { + Book book = new Book(); + Element scanS1 = li.getElementsByClass("s1").get(0); + Element scanS2 = li.getElementsByClass("s2").get(0); + Element scanS5 = li.getElementsByClass("s5").get(0); + book.setType(scanS1.html().replace("[", "").replace("]", "")); + Element a = scanS2.getElementsByTag("a").get(0); + book.setName(a.attr("title")); + book.setChapterUrl(a.attr("href")); + book.setAuthor(scanS5.html()); + book.setSource(BookSource.biquge.toString()); + books.add(book); + } + } + } + + return books; + } + + public List getRankBookList(String html) { + List books = new ArrayList<>(); + Document doc = Jsoup.parse(html); + String type = doc.select("meta[name=keywords]").attr("content").replace(",全本小说网", ""); + Element div = doc.getElementById("tlist"); + Elements uls = div.getElementsByTag("ul"); + if (uls.size() > 0) { + for (Element li : uls.get(0).children()) { + Book book = new Book(); + Element aName = li.getElementsByClass("name").get(0); + Element divZz = li.getElementsByClass("zz").get(0); + Element divAuthor = li.getElementsByClass("author").get(0); + Element divSj = li.getElementsByClass("sj").get(0); + book.setType(type); + book.setName(aName.attr("title")); + book.setChapterUrl(aName.attr("href")); + book.setNewestChapterTitle(divZz.text()); + book.setAuthor(divAuthor.text()); + book.setUpdateDate(divSj.text()); + book.setSource(BookSource.qb5.toString()); + books.add(book); + } + } + + return books; + + } + + @Override + public String getContentFormHtml(String html) { + Document doc = Jsoup.parse(html); + Element divBook = doc.getElementsByClass("nav-style").get(0); + String bookName = divBook.getElementsByTag("a").get(1).attr("title"); + Element divContent = doc.getElementById("content"); + if (divContent != null) { + String content = Html.fromHtml(divContent.html()).toString(); + char c = 160; + String spaec = "" + c; + content = content.replace(spaec, " "); + content = content.replace("全本小说网 www.qb5.tw,最快更新", "") + .replace(bookName, "") + .replace("最新章节!", ""); + return content; + } else { + return ""; + } + } + + + @Override + public ArrayList getChaptersFromHtml(String html) { + ArrayList chapters = new ArrayList<>(); + Document doc = Jsoup.parse(html); + String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); + int num = 0; + Element zjbox = doc.getElementsByClass("zjbox").get(0); + Elements as = zjbox.getElementsByTag("a"); + for (int i = 12; i < as.size(); i++) { + Element a = as.get(i); + Chapter chapter = new Chapter(); + chapter.setNumber(num++); + chapter.setTitle(a.text()); + chapter.setUrl(readUrl + a.attr("href")); + chapters.add(chapter); + } + + return chapters; + } + + /** + * 从搜索html中得到书列表 + * + * @param html + * @return + */ + public ConcurrentMultiValueMap getBooksFromSearchHtml(String html) { + final ConcurrentMultiValueMap books = new ConcurrentMultiValueMap<>(); + Document doc = Jsoup.parse(html); + String urlType = doc.select("meta[property=og:type]").attr("content"); + if ("novel".equals(urlType)) { + String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); + Book book = new Book(); + book.setChapterUrl(readUrl); + getBookInfo(html, book); + SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); + books.add(sbb, book); + } else { + Elements divs = doc.getElementsByClass("grid"); + Element div = divs.get(0); + Elements elementsByTag = div.getElementsByTag("tr"); + for (int i = 1; i < elementsByTag.size(); i++) { + Element element = elementsByTag.get(i); + Book book = new Book(); + Elements info = element.getElementsByTag("td"); + book.setName(info.get(0).text()); + book.setChapterUrl(info.get(0).getElementsByTag("a").attr("href")); + book.setNewestChapterTitle(info.get(1).text()); + book.setAuthor(info.get(2).text()); + book.setSource(BookSource.qb5.toString()); + SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); + books.add(sbb, book); + } + } + return books; + } + + /** + * 获取小说详细信息 + * + * @param html + * @return + */ + public Book getBookInfo(String html, Book book) { + //小说源 + book.setSource(BookSource.qb5.toString()); + Document doc = Jsoup.parse(html); + //书名 + String name = doc.select("meta[property=og:title]").attr("content"); + book.setName(name); + //作者 + String author = doc.select("meta[property=og:novel:author]").attr("content"); + book.setAuthor(author); + //最新章节 + String newestChapter = doc.select("meta[property=og:novel:latest_chapter_name]").attr("content"); + book.setNewestChapterTitle(newestChapter); + //更新时间 + String updateTime = doc.select("meta[property=og:novel:update_time]").attr("content"); + book.setUpdateDate(updateTime); + //图片url + Element divImg = doc.getElementsByClass("img_in").get(0); + Element img = divImg.getElementsByTag("img").get(0); + book.setImgUrl(img.attr("src")); + //简介 + Element divIntro = doc.getElementById("intro"); + book.setDesc(divIntro.text()); + //类型 + String type = doc.select("meta[property=og:novel:category]").attr("content"); + book.setType(type); + return book; + } + + + public boolean getTypePage(BookType curType, int page){ + if (page > 10){ + return true; + } + if (!curType.getTypeName().equals("完本小说")) { + curType.setUrl(curType.getUrl().substring(0, curType.getUrl().lastIndexOf("_") + 1) + page + "/"); + }else { + if (page > 1){ + return true; + } + } + return false; + } + + + +} diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/QiDianRankList.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/QiDianRankList.java deleted file mode 100644 index bb9dedd..0000000 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/QiDianRankList.java +++ /dev/null @@ -1,75 +0,0 @@ -package xyz.fycz.myreader.webapi.crawler; - -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import org.jsoup.select.Elements; -import xyz.fycz.myreader.entity.bookstore.BookType; -import xyz.fycz.myreader.greendao.entity.Book; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author fengyue - * @date 2020/5/27 11:17 - */ -public class QiDianRankList { - - public static final String[] TYPE_NAME = { - "月票榜", "畅销榜", "阅读榜", "推荐榜", "收藏榜" - }; - - /** - * 获取书城小说分类列表 - * - * @param html - * @return - */ - public static List getBookTypeList(String html) { - List bookTypes = new ArrayList<>(); - Document doc = Jsoup.parse(html); - Elements divs = doc.getElementsByClass("more"); - for (int i = 0; i < 5; i++) { - BookType bookType = new BookType(); - bookType.setTypeName(TYPE_NAME[i]); - bookType.setUrl("https:" + divs.get(i).attr("href")); - bookTypes.add(bookType); - } - return bookTypes; - } - - /** - * 获取某一分类小说排行榜列表 - * - * @param html - * @return - */ - public static List getBookRankList(String html) { - List books = new ArrayList<>(); - Document doc = Jsoup.parse(html); - Elements lis = doc.getElementsByTag("li"); - if (lis.size() > 0) { - Elements bookLis = lis.select("data-rid"); - if (bookLis.size() > 0) { - for (Element li : bookLis) { - Book book = new Book(); - String imgSrc = li.getElementsByClass("book-img-box").get(0) - .getElementsByTag("img").attr("src"); - book.setImgUrl("https:" + imgSrc); - Element bookInfo = li.getElementsByClass("book-mid-info").get(0); - Elements tagA = bookInfo.getElementsByTag("a"); - book.setName(tagA.get(0).text()); - book.setAuthor(tagA.get(1).text()); - book.setType(tagA.get(2).text()); - book.setNewestChapterTitle(tagA.get(3).text()); - String desc = bookInfo.getElementsByClass("intro").get(0).text(); - book.setDesc(desc); - books.add(book); - } - } - } - return books; - } - -} diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/ReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/ReadCrawler.java index b3abae3..91d25fa 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/ReadCrawler.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/ReadCrawler.java @@ -15,6 +15,7 @@ import java.util.ArrayList; public interface ReadCrawler { String getSearchLink(); String getCharset(); + String getSearchCharset(); String getNameSpace(); String getSearchKey(); String getContentFormHtml(String html); diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/ReadCrawlerUtil.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/ReadCrawlerUtil.java index bc26866..511f171 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/ReadCrawlerUtil.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/ReadCrawlerUtil.java @@ -1,6 +1,12 @@ package xyz.fycz.myreader.webapi.crawler; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.util.SharedPreUtils; +import xyz.fycz.myreader.util.StringHelper; + +import java.util.ArrayList; +import java.util.HashMap; import java.util.ResourceBundle; /** @@ -10,13 +16,70 @@ import java.util.ResourceBundle; public class ReadCrawlerUtil { private ReadCrawlerUtil() { } - public static ReadCrawler getReadCrawler(String bookSource){ - ResourceBundle rb = ResourceBundle.getBundle("bookcrawler"); - try{ + + public static ArrayList getReadCrawlers() { + SharedPreUtils spu = SharedPreUtils.getInstance(); + String searchSource = spu.getString("searchSource", null); + ArrayList readCrawlers = new ArrayList<>(); + if (searchSource == null) { + StringBuilder sb = new StringBuilder(); + for (BookSource bookSource : BookSource.values()) { + if (bookSource.equals(BookSource.fynovel) || bookSource.equals(BookSource.local) || bookSource.equals(BookSource.biquge)) + continue; + sb.append(bookSource.toString()); + sb.append(","); + readCrawlers.add(getReadCrawler(bookSource.toString())); + } + sb.deleteCharAt(sb.lastIndexOf(",")); + searchSource = sb.toString(); + spu.putString("searchSource", searchSource); + } else if (!"".equals(searchSource)){ + String[] sources = searchSource.split(","); + for (String source : sources) { + readCrawlers.add(getReadCrawler(source)); + } + } + return readCrawlers; + } + + public static HashMap getDisableSources() { + SharedPreUtils spu = SharedPreUtils.getInstance(); + String searchSource = spu.getString("searchSource", null); + HashMap mSources = new HashMap<>(); + if (searchSource == null) { + for (BookSource bookSource : BookSource.values()) { + if (bookSource.equals(BookSource.fynovel) || bookSource.equals(BookSource.local)) continue; + if (bookSource.equals(BookSource.biquge)) { + mSources.put(bookSource.text, true); + continue; + } + mSources.put(bookSource.text, false); + } + } else { + String[] ableSources = searchSource.split(","); + bookSourceFor: + for (BookSource bookSource : BookSource.values()) { + if (bookSource.equals(BookSource.fynovel) || bookSource.equals(BookSource.local)) continue; + for (String ableSource : ableSources) { + if (ableSource.equals(bookSource.toString())) { + mSources.put(bookSource.text, false); + continue bookSourceFor; + } + } + mSources.put(bookSource.text, true); + } + } + return mSources; + + } + + public static ReadCrawler getReadCrawler(String bookSource) { + ResourceBundle rb = ResourceBundle.getBundle("crawler"); + try { String readCrawlerPath = rb.getString(bookSource); Class clz = Class.forName(readCrawlerPath); return (ReadCrawler) clz.newInstance(); - }catch (Exception e){ + } catch (Exception e) { return new FYReadCrawler(); } } diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/TianLaiReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/TianLaiReadCrawler.java index 2840906..bfdd692 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/TianLaiReadCrawler.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/TianLaiReadCrawler.java @@ -25,6 +25,8 @@ public class TianLaiReadCrawler implements ReadCrawler{ public static final String NOVEL_SEARCH = "https://www.23txt.com/search.php"; public static final String SEARCH_KEY = "q"; public static final String CHARSET = "GBK"; + public static final String SEARCH_CHARSET = "utf-8"; + @Override public String getSearchLink() { return NOVEL_SEARCH; @@ -44,6 +46,11 @@ public class TianLaiReadCrawler implements ReadCrawler{ return SEARCH_KEY; } + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + /** * 从html中获取章节正文 * diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/find/ABC.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/find/ABC.java new file mode 100644 index 0000000..faa8f4d --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/find/ABC.java @@ -0,0 +1,117 @@ +package xyz.fycz.myreader.webapi.crawler.find; + +import android.content.Context; +import android.graphics.Bitmap; +import android.util.Log; +import android.webkit.*; +import okhttp3.*; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import xyz.fycz.myreader.application.MyApplication; +import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.entity.bookstore.BookType; +import xyz.fycz.myreader.entity.bookstore.QDBook; +import xyz.fycz.myreader.entity.bookstore.RankBook; +import xyz.fycz.myreader.entity.bookstore.SortBook; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.util.IOUtils; +import xyz.fycz.myreader.util.SharedPreUtils; +import xyz.fycz.myreader.util.StringHelper; +import xyz.fycz.myreader.webapi.CommonApi; +import xyz.fycz.myreader.webapi.crawler.FindCrawler; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * @author fengyue + * @date 2020/9/16 22:01 + */ +public class ABC extends FindCrawler { + private String rankUrl = ""; + private String sortUrl = ""; + private String[] sex = {"male", "female"}; + private String aParam = ""; + private String imgUrl = ""; + private String defaultCookie = ""; + private String yearmonthFormat = ""; + private LinkedHashMap rankName = new LinkedHashMap<>(); + private LinkedHashMap sortName = new LinkedHashMap<>(); + private boolean isFemale; + private boolean isSort; + + public ABC(boolean isFemale) { + this.isFemale = isFemale; + } + + public ABC(boolean isFemale, boolean isSort) { + this.isFemale = isFemale; + this.isSort = isSort; + } + + private void initMaleRankName() { + + } + + private void initSortNames() { + } + + + public List getRankTypes() { + return null; + } + + public void getRankBooks(BookType bookType, ResultCallback rc) { + + } + + private List getBooksFromJson(String json) { + return null; + } + + @Override + public String getCharset() { + return null; + } + + @Override + public String getFindName() { + return null; + } + + @Override + public String getFindUrl() { + return null; + } + + @Override + public boolean getTypePage(BookType curType, int page) { + return false; + } + + @Override + public boolean hasImg() { + return true; + } + + @Override + public List getBookTypeList(String html) { + return null; + } + + @Override + public List getRankBookList(String html) { + return null; + } + + + public void initCookie(Context mContext, ResultCallback rc) { + + } + +} diff --git a/app/src/main/res/anim/fade_in.xml b/app/src/main/res/anim/fade_in.xml new file mode 100644 index 0000000..95a9075 --- /dev/null +++ b/app/src/main/res/anim/fade_in.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/fade_out.xml b/app/src/main/res/anim/fade_out.xml new file mode 100644 index 0000000..3dfb4a7 --- /dev/null +++ b/app/src/main/res/anim/fade_out.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/color/selector_bn.xml b/app/src/main/res/color/selector_bn.xml new file mode 100644 index 0000000..acd07e1 --- /dev/null +++ b/app/src/main/res/color/selector_bn.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/selector_btn_file_add.xml b/app/src/main/res/color/selector_btn_file_add.xml index ba3485d..aac85c1 100644 --- a/app/src/main/res/color/selector_btn_file_add.xml +++ b/app/src/main/res/color/selector_btn_file_add.xml @@ -1,6 +1,6 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xhdpi/setting_style_blue_deep_circle.xml b/app/src/main/res/drawable-xhdpi/setting_style_blue_deep_circle.xml index 2825928..3e3ce4e 100644 --- a/app/src/main/res/drawable-xhdpi/setting_style_blue_deep_circle.xml +++ b/app/src/main/res/drawable-xhdpi/setting_style_blue_deep_circle.xml @@ -1,7 +1,11 @@ - + + + + + diff --git a/app/src/main/res/drawable-xhdpi/setting_style_breen_circle.xml b/app/src/main/res/drawable-xhdpi/setting_style_breen_circle.xml index 6c0b696..15e63b1 100644 --- a/app/src/main/res/drawable-xhdpi/setting_style_breen_circle.xml +++ b/app/src/main/res/drawable-xhdpi/setting_style_breen_circle.xml @@ -1,6 +1,10 @@ - + + + + + diff --git a/app/src/main/res/drawable-xhdpi/setting_style_common_circle.xml b/app/src/main/res/drawable-xhdpi/setting_style_common_circle.xml index e23c3f0..9b923d3 100644 --- a/app/src/main/res/drawable-xhdpi/setting_style_common_circle.xml +++ b/app/src/main/res/drawable-xhdpi/setting_style_common_circle.xml @@ -1,9 +1,13 @@ - + + + + + - + \ No newline at end of file diff --git a/app/src/main/res/drawable-xhdpi/setting_style_common_circle_selected.xml b/app/src/main/res/drawable-xhdpi/setting_style_common_circle_selected.xml index b6a6165..2bdba8a 100644 --- a/app/src/main/res/drawable-xhdpi/setting_style_common_circle_selected.xml +++ b/app/src/main/res/drawable-xhdpi/setting_style_common_circle_selected.xml @@ -7,7 +7,7 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable-xhdpi/setting_style_leather_circle.xml b/app/src/main/res/drawable-xhdpi/setting_style_leather_circle.xml index f300a09..e8d9154 100644 --- a/app/src/main/res/drawable-xhdpi/setting_style_leather_circle.xml +++ b/app/src/main/res/drawable-xhdpi/setting_style_leather_circle.xml @@ -1,6 +1,10 @@ - + + + + + diff --git a/app/src/main/res/drawable-xhdpi/setting_style_protect_eye_circle.xml b/app/src/main/res/drawable-xhdpi/setting_style_protect_eye_circle.xml index 607998f..395ee27 100644 --- a/app/src/main/res/drawable-xhdpi/setting_style_protect_eye_circle.xml +++ b/app/src/main/res/drawable-xhdpi/setting_style_protect_eye_circle.xml @@ -1,7 +1,11 @@ - + + + + + diff --git a/app/src/main/res/drawable-xxxhdpi/setting_btn_bg2.xml b/app/src/main/res/drawable-xxxhdpi/setting_btn_bg2.xml index 2d2ea5c..c8fd06a 100644 --- a/app/src/main/res/drawable-xxxhdpi/setting_btn_bg2.xml +++ b/app/src/main/res/drawable-xxxhdpi/setting_btn_bg2.xml @@ -4,7 +4,7 @@ + android:color="@color/textSecondary" /> - + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_skip.xml b/app/src/main/res/drawable/bg_skip.xml deleted file mode 100644 index a4ffc4d..0000000 --- a/app/src/main/res/drawable/bg_skip.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_aa.xml b/app/src/main/res/drawable/ic_aa.xml new file mode 100644 index 0000000..d204794 --- /dev/null +++ b/app/src/main/res/drawable/ic_aa.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_back.xml b/app/src/main/res/drawable/ic_back.xml new file mode 100644 index 0000000..591470a --- /dev/null +++ b/app/src/main/res/drawable/ic_back.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_book_last.xml b/app/src/main/res/drawable/ic_book_last.xml new file mode 100644 index 0000000..dbadfd8 --- /dev/null +++ b/app/src/main/res/drawable/ic_book_last.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_bookshelf.xml b/app/src/main/res/drawable/ic_bookshelf.xml new file mode 100644 index 0000000..e4f4b27 --- /dev/null +++ b/app/src/main/res/drawable/ic_bookshelf.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_bookstore.xml b/app/src/main/res/drawable/ic_bookstore.xml new file mode 100644 index 0000000..06a903a --- /dev/null +++ b/app/src/main/res/drawable/ic_bookstore.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_catalog.xml b/app/src/main/res/drawable/ic_catalog.xml new file mode 100644 index 0000000..e372f4b --- /dev/null +++ b/app/src/main/res/drawable/ic_catalog.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_cathe.xml b/app/src/main/res/drawable/ic_cathe.xml new file mode 100644 index 0000000..51aa3b1 --- /dev/null +++ b/app/src/main/res/drawable/ic_cathe.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_clear.xml b/app/src/main/res/drawable/ic_clear.xml new file mode 100644 index 0000000..2b9906d --- /dev/null +++ b/app/src/main/res/drawable/ic_clear.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_day_mode.xml b/app/src/main/res/drawable/ic_day_mode.xml new file mode 100644 index 0000000..f2cb8a9 --- /dev/null +++ b/app/src/main/res/drawable/ic_day_mode.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_dicovery.xml b/app/src/main/res/drawable/ic_dicovery.xml new file mode 100644 index 0000000..b2ec491 --- /dev/null +++ b/app/src/main/res/drawable/ic_dicovery.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_feedback.xml b/app/src/main/res/drawable/ic_feedback.xml new file mode 100644 index 0000000..0a55ce5 --- /dev/null +++ b/app/src/main/res/drawable/ic_feedback.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_group.xml b/app/src/main/res/drawable/ic_group.xml new file mode 100644 index 0000000..0ebcd45 --- /dev/null +++ b/app/src/main/res/drawable/ic_group.xml @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_history.xml b/app/src/main/res/drawable/ic_history.xml new file mode 100644 index 0000000..7b1dd93 --- /dev/null +++ b/app/src/main/res/drawable/ic_history.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_mine.xml b/app/src/main/res/drawable/ic_mine.xml new file mode 100644 index 0000000..803b08d --- /dev/null +++ b/app/src/main/res/drawable/ic_mine.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_night_mode.xml b/app/src/main/res/drawable/ic_night_mode.xml new file mode 100644 index 0000000..bddd4c1 --- /dev/null +++ b/app/src/main/res/drawable/ic_night_mode.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_qq_group.xml b/app/src/main/res/drawable/ic_qq_group.xml new file mode 100644 index 0000000..81d4c85 --- /dev/null +++ b/app/src/main/res/drawable/ic_qq_group.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_question.xml b/app/src/main/res/drawable/ic_question.xml index f51e466..60ba837 100644 --- a/app/src/main/res/drawable/ic_question.xml +++ b/app/src/main/res/drawable/ic_question.xml @@ -4,6 +4,6 @@ android:viewportWidth="1024" android:viewportHeight="1024"> diff --git a/app/src/main/res/drawable/ic_read_book.xml b/app/src/main/res/drawable/ic_read_book.xml new file mode 100644 index 0000000..3a92aed --- /dev/null +++ b/app/src/main/res/drawable/ic_read_book.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search.xml b/app/src/main/res/drawable/ic_search.xml new file mode 100644 index 0000000..81fbb11 --- /dev/null +++ b/app/src/main/res/drawable/ic_search.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_sort.xml b/app/src/main/res/drawable/ic_sort.xml new file mode 100644 index 0000000..ed0a932 --- /dev/null +++ b/app/src/main/res/drawable/ic_sort.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_theme.xml b/app/src/main/res/drawable/ic_theme.xml new file mode 100644 index 0000000..90da164 --- /dev/null +++ b/app/src/main/res/drawable/ic_theme.xml @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_top.xml b/app/src/main/res/drawable/ic_top.xml new file mode 100644 index 0000000..0574938 --- /dev/null +++ b/app/src/main/res/drawable/ic_top.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..03356fc --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_vector_add_bookcase.xml b/app/src/main/res/drawable/ic_vector_add_bookcase.xml index 7b44c5b..fd15736 100644 --- a/app/src/main/res/drawable/ic_vector_add_bookcase.xml +++ b/app/src/main/res/drawable/ic_vector_add_bookcase.xml @@ -5,8 +5,8 @@ android:viewportHeight="1024.0"> + android:fillColor="@color/textPrimary"/> + android:fillColor="@color/textPrimary"/> diff --git a/app/src/main/res/drawable/search_btn_backcolor.xml b/app/src/main/res/drawable/search_btn_backcolor.xml index 9e64f57..a2f848a 100644 --- a/app/src/main/res/drawable/search_btn_backcolor.xml +++ b/app/src/main/res/drawable/search_btn_backcolor.xml @@ -1,6 +1,6 @@ - + - + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_unclick.xml b/app/src/main/res/drawable/shape_unclick.xml index 3cca521..6b20751 100644 --- a/app/src/main/res/drawable/shape_unclick.xml +++ b/app/src/main/res/drawable/shape_unclick.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/theme_mode_bak.xml b/app/src/main/res/drawable/theme_mode_bak.xml new file mode 100644 index 0000000..0dc704d --- /dev/null +++ b/app/src/main/res/drawable/theme_mode_bak.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/actiity_bookstore.xml b/app/src/main/res/layout/actiity_bookstore.xml new file mode 100644 index 0000000..38d89eb --- /dev/null +++ b/app/src/main/res/layout/actiity_bookstore.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml index c8b892e..89cc520 100644 --- a/app/src/main/res/layout/activity_about.xml +++ b/app/src/main/res/layout/activity_about.xml @@ -7,7 +7,7 @@ android:orientation="vertical" tools:context=".ui.activity.AboutActivity"> - + + android:background="@color/colorBackground"> + + + + app:popupTheme="@style/AppTheme.PopupOverlay"/> + - - - - - - - - - + + + + + + + android:layout_weight="9" + app:tabIndicatorColor="@color/colorAccent" + app:tabIndicatorHeight="2dp" + app:tabIndicatorFullWidth="true" + app:tabSelectedTextColor="@color/textPrimaryInverted" + app:tabTextColor="@color/translucent_text" + app:tabTextAppearance="@style/TabLayoutTextStyle"/> + - - - - - - + - - + android:id="@+id/catalog_vp" + android:layout_width="match_parent" + android:layout_height="match_parent"/> diff --git a/app/src/main/res/layout/activity_file_system.xml b/app/src/main/res/layout/activity_file_system.xml index 46f0b49..b75daf4 100644 --- a/app/src/main/res/layout/activity_file_system.xml +++ b/app/src/main/res/layout/activity_file_system.xml @@ -32,7 +32,7 @@ android:layout_marginStart="15dp" android:text="全选" android:textSize="15dp" - android:textColor="@color/selector_cb_file" + android:textColor="@color/textSecondary" android:theme="@style/MyCheckBox" />