From dde79d15d760a3d51efa4a46c2c1c2e91669c92e Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 22 Jan 2020 19:17:50 +0800 Subject: [PATCH 001/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 4 +- .../kunfei/bookshelf/base/BaseModelImpl.java | 2 +- .../com/kunfei/bookshelf/help/DataBackup.java | 237 ----------- .../kunfei/bookshelf/help/DataRestore.java | 161 ------- .../com/kunfei/bookshelf/help/WebDavHelp.java | 36 -- .../kunfei/bookshelf/help/storage/Backup.kt | 123 ++++++ .../bookshelf/help/storage/Preferences.kt | 48 +++ .../kunfei/bookshelf/help/storage/Restore.kt | 99 +++++ .../bookshelf/help/storage/WebDavHelp.kt | 94 +++++ .../bookshelf/presenter/MainPresenter.java | 44 -- .../presenter/contract/MainContract.java | 4 - .../kunfei/bookshelf/utils/GsonExtensions.kt | 43 ++ .../bookshelf/utils/web_dav/WebDavFile.java | 394 ------------------ .../bookshelf/utils/web_dav/http/Handler.java | 23 - .../utils/web_dav/http/HttpAuth.java | 36 -- .../bookshelf/utils/web_dav/http/OkHttp.java | 27 -- .../kunfei/bookshelf/utils/webdav/README.md | 1 + .../kunfei/bookshelf/utils/webdav/WebDav.kt | 249 +++++++++++ .../bookshelf/utils/webdav/http/Handler.kt | 16 + .../bookshelf/utils/webdav/http/HttpAuth.kt | 9 + .../bookshelf/view/activity/MainActivity.java | 117 +++++- .../view/activity/ReadBookActivity.java | 74 ++-- .../view/fragment/WebDavSettingsFragment.java | 107 +---- basemvplib/build.gradle | 1 + 24 files changed, 829 insertions(+), 1120 deletions(-) delete mode 100644 app/src/main/java/com/kunfei/bookshelf/help/DataBackup.java delete mode 100644 app/src/main/java/com/kunfei/bookshelf/help/DataRestore.java delete mode 100644 app/src/main/java/com/kunfei/bookshelf/help/WebDavHelp.java create mode 100644 app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt create mode 100644 app/src/main/java/com/kunfei/bookshelf/help/storage/Preferences.kt create mode 100644 app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt create mode 100644 app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt create mode 100644 app/src/main/java/com/kunfei/bookshelf/utils/GsonExtensions.kt delete mode 100644 app/src/main/java/com/kunfei/bookshelf/utils/web_dav/WebDavFile.java delete mode 100644 app/src/main/java/com/kunfei/bookshelf/utils/web_dav/http/Handler.java delete mode 100644 app/src/main/java/com/kunfei/bookshelf/utils/web_dav/http/HttpAuth.java delete mode 100644 app/src/main/java/com/kunfei/bookshelf/utils/web_dav/http/OkHttp.java create mode 100644 app/src/main/java/com/kunfei/bookshelf/utils/webdav/README.md create mode 100644 app/src/main/java/com/kunfei/bookshelf/utils/webdav/WebDav.kt create mode 100644 app/src/main/java/com/kunfei/bookshelf/utils/webdav/http/Handler.kt create mode 100644 app/src/main/java/com/kunfei/bookshelf/utils/webdav/http/HttpAuth.kt diff --git a/app/build.gradle b/app/build.gradle index 75314c28a6..f4865d5936 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -83,7 +83,7 @@ dependencies { implementation "org.jetbrains.anko:anko-sdk27-listeners:$anko_version" //fireBase - implementation 'com.google.firebase:firebase-core:17.2.1' + implementation 'com.google.firebase:firebase-core:17.2.2' implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1' //androidX @@ -94,7 +94,7 @@ dependencies { implementation 'androidx.legacy:legacy-support-v4:1.0.0' //google - implementation 'com.google.android.material:material:1.2.0-alpha03' + implementation 'com.google.android.material:material:1.2.0-alpha04' implementation 'com.google.code.gson:gson:2.8.5' implementation 'com.google.android:flexbox:1.1.0' diff --git a/app/src/main/java/com/kunfei/bookshelf/base/BaseModelImpl.java b/app/src/main/java/com/kunfei/bookshelf/base/BaseModelImpl.java index 1377b0cd54..a9bc0302ed 100644 --- a/app/src/main/java/com/kunfei/bookshelf/base/BaseModelImpl.java +++ b/app/src/main/java/com/kunfei/bookshelf/base/BaseModelImpl.java @@ -80,7 +80,7 @@ public Retrofit getRetrofitString(String url, String encode) { .build(); } - private static OkHttpClient.Builder getClientBuilder() { + public static OkHttpClient.Builder getClientBuilder() { if (clientBuilder == null) { clientBuilder = new OkHttpClient.Builder() .connectTimeout(15, TimeUnit.SECONDS) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/DataBackup.java b/app/src/main/java/com/kunfei/bookshelf/help/DataBackup.java deleted file mode 100644 index 15482e5f1c..0000000000 --- a/app/src/main/java/com/kunfei/bookshelf/help/DataBackup.java +++ /dev/null @@ -1,237 +0,0 @@ -package com.kunfei.bookshelf.help; - -import android.content.SharedPreferences; -import android.os.Handler; -import android.os.Looper; -import android.widget.Toast; - -import androidx.documentfile.provider.DocumentFile; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.kunfei.bookshelf.BuildConfig; -import com.kunfei.bookshelf.DbHelper; -import com.kunfei.bookshelf.MApplication; -import com.kunfei.bookshelf.R; -import com.kunfei.bookshelf.bean.BookShelfBean; -import com.kunfei.bookshelf.bean.BookSourceBean; -import com.kunfei.bookshelf.bean.ReplaceRuleBean; -import com.kunfei.bookshelf.bean.SearchHistoryBean; -import com.kunfei.bookshelf.bean.TxtChapterRuleBean; -import com.kunfei.bookshelf.model.BookSourceManager; -import com.kunfei.bookshelf.model.ReplaceRuleManager; -import com.kunfei.bookshelf.model.TxtChapterRuleManager; -import com.kunfei.bookshelf.utils.FileUtils; -import com.kunfei.bookshelf.utils.RxUtils; -import com.kunfei.bookshelf.utils.TimeUtils; -import com.kunfei.bookshelf.utils.XmlUtils; -import com.kunfei.bookshelf.utils.ZipUtils; -import com.kunfei.bookshelf.utils.web_dav.WebDavFile; - -import java.io.File; -import java.io.FileOutputStream; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.concurrent.TimeUnit; - -import io.reactivex.Single; -import io.reactivex.SingleObserver; -import io.reactivex.SingleOnSubscribe; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.Disposable; -import io.reactivex.schedulers.Schedulers; - - -/** - * Created by GKF on 2018/1/30. - * 数据备份 - */ - -public class DataBackup { - - public static DataBackup getInstance() { - return new DataBackup(); - } - - public void autoSave() { - Single.create((SingleOnSubscribe) e -> { - long currentTime = System.currentTimeMillis(); - if (!BuildConfig.DEBUG) { - File file = new File(FileUtils.getSdCardPath() + File.separator + "YueDu" + File.separator + "autoSave" + File.separator + "myBookShelf.json"); - if (file.exists()) { - if (currentTime - file.lastModified() < TimeUnit.DAYS.toMillis(1)) { - e.onSuccess(false); - return; - } - } - DocumentHelper.createDirIfNotExist(FileUtils.getSdCardPath(), "YueDu"); - String dirPath = FileUtils.getSdCardPath() + File.separator + "YueDu"; - DocumentHelper.createDirIfNotExist(dirPath, "autoSave"); - dirPath += File.separator + "autoSave"; - backupConfig(dirPath); - backupBookShelf(dirPath); - backupBookSource(dirPath); - backupSearchHistory(dirPath); - backupReplaceRule(dirPath); - backupTxtChapterRule(dirPath); - upload(dirPath); - e.onSuccess(true); - } - e.onSuccess(false); - }).compose(RxUtils::toSimpleSingle) - .subscribe(); - } - - public void run() { - Single.create((SingleOnSubscribe) e -> { - DocumentHelper.createDirIfNotExist(FileUtils.getSdCardPath(), "YueDu"); - String dirPath = FileUtils.getSdCardPath() + File.separator + "YueDu"; - backupConfig(dirPath); - backupBookShelf(dirPath); - backupBookSource(dirPath); - backupSearchHistory(dirPath); - backupReplaceRule(dirPath); - backupTxtChapterRule(dirPath); - upload(dirPath); - e.onSuccess(true); - }) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new SingleObserver() { - @Override - public void onSubscribe(Disposable d) { - - } - - @Override - public void onSuccess(Boolean value) { - if (value) { - Toast.makeText(MApplication.getInstance(), R.string.backup_success, Toast.LENGTH_LONG).show(); - } else { - Toast.makeText(MApplication.getInstance(), R.string.backup_fail, Toast.LENGTH_LONG).show(); - } - } - - @Override - public void onError(Throwable e) { - e.printStackTrace(); - Toast.makeText(MApplication.getInstance(), R.string.backup_fail, Toast.LENGTH_LONG).show(); - } - }); - } - - private void upload(String dirPath) { - List filePaths = new ArrayList<>(); - filePaths.add(dirPath + File.separator + "config.xml"); - filePaths.add(dirPath + File.separator + "myBookShelf.json"); - filePaths.add(dirPath + File.separator + "myBookSource.json"); - filePaths.add(dirPath + File.separator + "myBookSearchHistory.json"); - filePaths.add(dirPath + File.separator + "myBookReplaceRule.json"); - filePaths.add(dirPath + File.separator + "myTxtChapterRule.json"); - String zipFilePath = FileHelp.getCachePath() + File.separator + "backup" + ".zip"; - try { - FileHelp.deleteFile(zipFilePath); - if (ZipUtils.zipFiles(filePaths, zipFilePath)) { - if (WebDavHelp.initWebDav()) { - new WebDavFile(WebDavHelp.getWebDavUrl() + "YueDu").makeAsDir(); - String putUrl = WebDavHelp.getWebDavUrl() + "YueDu/backup" + TimeUtils.date2String(TimeUtils.getNowDate(), new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())) + ".zip"; - WebDavFile webDavFile = new WebDavFile(putUrl); - webDavFile.upload(zipFilePath); - } - } - } catch (Exception e) { - e.printStackTrace(); - new Handler(Looper.getMainLooper()) - .post(() -> Toast - .makeText(MApplication.getInstance(), e.getLocalizedMessage(), Toast.LENGTH_SHORT) - .show()); - } - } - - private void backupBookShelf(String file) { - List bookShelfList = BookshelfHelp.getAllBook(); - if (bookShelfList != null && bookShelfList.size() > 0) { - Gson gson = new GsonBuilder() - .disableHtmlEscaping() - .setPrettyPrinting() - .create(); - String bookshelf = gson.toJson(bookShelfList); - DocumentFile docFile = DocumentHelper.createFileIfNotExist("myBookShelf.json", file); - if (docFile != null) { - DocumentHelper.writeString(bookshelf, docFile); - } - } - } - - private void backupBookSource(String file) { - List bookSourceList = BookSourceManager.getAllBookSource(); - if (bookSourceList != null && bookSourceList.size() > 0) { - Gson gson = new GsonBuilder() - .disableHtmlEscaping() - .setPrettyPrinting() - .create(); - String str = gson.toJson(bookSourceList); - DocumentFile docFile = DocumentHelper.createFileIfNotExist("myBookSource.json", file); - if (docFile != null) { - DocumentHelper.writeString(str, docFile); - } - } - } - - private void backupSearchHistory(String file) { - List searchHistoryBeans = DbHelper.getDaoSession().getSearchHistoryBeanDao() - .queryBuilder().list(); - if (searchHistoryBeans != null && searchHistoryBeans.size() > 0) { - Gson gson = new GsonBuilder() - .disableHtmlEscaping() - .setPrettyPrinting() - .create(); - String str = gson.toJson(searchHistoryBeans); - DocumentFile docFile = DocumentHelper.createFileIfNotExist("myBookSearchHistory.json", file); - if (docFile != null) { - DocumentHelper.writeString(str, docFile); - } - } - } - - private void backupReplaceRule(String file) { - List replaceRuleBeans = ReplaceRuleManager.getAll().blockingGet(); - if (replaceRuleBeans != null && replaceRuleBeans.size() > 0) { - Gson gson = new GsonBuilder() - .disableHtmlEscaping() - .setPrettyPrinting() - .create(); - String str = gson.toJson(replaceRuleBeans); - DocumentFile docFile = DocumentHelper.createFileIfNotExist("myBookReplaceRule.json", file); - if (docFile != null) { - DocumentHelper.writeString(str, docFile); - } - } - } - - private void backupTxtChapterRule(String file) { - List ruleBeans = TxtChapterRuleManager.getAll(); - if (ruleBeans != null && ruleBeans.size() > 0) { - Gson gson = new GsonBuilder() - .disableHtmlEscaping() - .setPrettyPrinting() - .create(); - String str = gson.toJson(ruleBeans); - DocumentFile docFile = DocumentHelper.createFileIfNotExist("myTxtChapterRule.json", file); - if (docFile != null) { - DocumentHelper.writeString(str, docFile); - } - } - } - - private void backupConfig(String file) { - SharedPreferences pref = MApplication.getConfigPreferences(); - try (FileOutputStream out = new FileOutputStream(file + File.separator + "config.xml")) { - XmlUtils.writeMapXml(pref.getAll(), out); - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/app/src/main/java/com/kunfei/bookshelf/help/DataRestore.java b/app/src/main/java/com/kunfei/bookshelf/help/DataRestore.java deleted file mode 100644 index 0bea6ae59a..0000000000 --- a/app/src/main/java/com/kunfei/bookshelf/help/DataRestore.java +++ /dev/null @@ -1,161 +0,0 @@ -package com.kunfei.bookshelf.help; - -import android.content.SharedPreferences; - -import com.kunfei.bookshelf.DbHelper; -import com.kunfei.bookshelf.MApplication; -import com.kunfei.bookshelf.R; -import com.kunfei.bookshelf.bean.BookShelfBean; -import com.kunfei.bookshelf.bean.BookSourceBean; -import com.kunfei.bookshelf.bean.ReplaceRuleBean; -import com.kunfei.bookshelf.bean.SearchHistoryBean; -import com.kunfei.bookshelf.bean.TxtChapterRuleBean; -import com.kunfei.bookshelf.model.BookSourceManager; -import com.kunfei.bookshelf.model.ReplaceRuleManager; -import com.kunfei.bookshelf.model.TxtChapterRuleManager; -import com.kunfei.bookshelf.utils.FileUtils; -import com.kunfei.bookshelf.utils.GsonUtils; -import com.kunfei.bookshelf.utils.XmlUtils; - -import java.io.File; -import java.io.FileInputStream; -import java.util.List; -import java.util.Map; - -/** - * Created by GKF on 2018/1/30. - * 数据恢复 - */ - -public class DataRestore { - - public static DataRestore getInstance() { - return new DataRestore(); - } - - public Boolean run() { - String dirPath = FileUtils.getSdCardPath() + File.separator + "YueDu"; - restoreBookSource(dirPath); - restoreBookShelf(dirPath); - restoreSearchHistory(dirPath); - restoreReplaceRule(dirPath); - restoreTxtChapterRule(dirPath); - restoreConfig(dirPath); - return true; - } - - private void restoreBookShelf(String file) { - try { - String json = DocumentHelper.readString("myBookShelf.json", file); - if (json == null) return; - List bookShelfList = GsonUtils.parseJArray(json, BookShelfBean.class); - if (bookShelfList == null) return; - for (BookShelfBean bookshelf : bookShelfList) { - if (bookshelf.getNoteUrl() != null) { - DbHelper.getDaoSession().getBookShelfBeanDao().insertOrReplace(bookshelf); - } - if (bookshelf.getBookInfoBean().getNoteUrl() != null) { - DbHelper.getDaoSession().getBookInfoBeanDao().insertOrReplace(bookshelf.getBookInfoBean()); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void restoreBookSource(String file) { - try { - String json = DocumentHelper.readString("myBookSource.json", file); - if (json == null) return; - List bookSourceBeans = GsonUtils.parseJArray(json, BookSourceBean.class); - if (bookSourceBeans == null) return; - BookSourceManager.addBookSource(bookSourceBeans); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void restoreSearchHistory(String file) { - try { - String json = DocumentHelper.readString("myBookSearchHistory.json", file); - if (json == null) return; - List searchHistoryBeans = GsonUtils.parseJArray(json, SearchHistoryBean.class); - if (searchHistoryBeans == null) return; - DbHelper.getDaoSession().getSearchHistoryBeanDao().insertOrReplaceInTx(searchHistoryBeans); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void restoreReplaceRule(String file) { - try { - String json = DocumentHelper.readString("myBookReplaceRule.json", file); - if (json == null) return; - List replaceRuleBeans = GsonUtils.parseJArray(json, ReplaceRuleBean.class); - if (replaceRuleBeans == null) return; - ReplaceRuleManager.addDataS(replaceRuleBeans); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void restoreTxtChapterRule(String file) { - try { - String json = DocumentHelper.readString("myTxtChapterRule.json", file); - if (json == null) return; - List ruleBeanList = GsonUtils.parseJArray(json, TxtChapterRuleBean.class); - if (ruleBeanList == null) return; - TxtChapterRuleManager.save(ruleBeanList); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void restoreConfig(String dirPath) { - try { - Map entries = null; - try (FileInputStream ins = new FileInputStream(dirPath + File.separator + "config.xml")) { - entries = XmlUtils.readMapXml(ins); - } catch (Exception ignored) { - } - if (entries == null || entries.isEmpty()) return; - long donateHb = MApplication.getConfigPreferences().getLong("DonateHb", 0); - donateHb = donateHb > System.currentTimeMillis() ? 0 : donateHb; - SharedPreferences.Editor editor = MApplication.getConfigPreferences().edit(); - editor.clear(); - for (Map.Entry entry : entries.entrySet()) { - Object v = entry.getValue(); - String key = entry.getKey(); - String type = v.getClass().getSimpleName(); - - switch (type) { - case "Integer": - editor.putInt(key, (Integer) v); - break; - case "Boolean": - editor.putBoolean(key, (Boolean) v); - break; - case "String": - editor.putString(key, (String) v); - break; - case "Float": - editor.putFloat(key, (Float) v); - break; - case "Long": - editor.putLong(key, (Long) v); - break; - } - } - editor.putLong("DonateHb", donateHb); - editor.putInt("versionCode", MApplication.getVersionCode()); - editor.apply(); - LauncherIcon.ChangeIcon(MApplication.getConfigPreferences().getString("launcher_icon", MApplication.getInstance().getString(R.string.icon_main))); - ReadBookControl.getInstance().updateReaderSettings(); - MApplication.getInstance().upThemeStore(); - MApplication.getInstance().initNightTheme(); - } catch (Exception e) { - e.printStackTrace(); - } - } - -} diff --git a/app/src/main/java/com/kunfei/bookshelf/help/WebDavHelp.java b/app/src/main/java/com/kunfei/bookshelf/help/WebDavHelp.java deleted file mode 100644 index fd1f204da9..0000000000 --- a/app/src/main/java/com/kunfei/bookshelf/help/WebDavHelp.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.kunfei.bookshelf.help; - -import android.text.TextUtils; - -import com.kunfei.bookshelf.MApplication; -import com.kunfei.bookshelf.utils.StringUtils; -import com.kunfei.bookshelf.utils.web_dav.http.HttpAuth; - -import static com.kunfei.bookshelf.constant.AppConstant.DEFAULT_WEB_DAV_URL; - -public class WebDavHelp { - - public static String getWebDavUrl() { - String url = MApplication.getConfigPreferences().getString("web_dav_url", DEFAULT_WEB_DAV_URL); - if (TextUtils.isEmpty(url)) url = DEFAULT_WEB_DAV_URL; - assert url != null; - if (!url.endsWith("/")) { - url = url + "/"; - } - return url; - } - - public static boolean initWebDav() { - String account = MApplication.getConfigPreferences().getString("web_dav_account", ""); - String password = MApplication.getConfigPreferences().getString("web_dav_password", ""); - if (!StringUtils.isTrimEmpty(account) && !StringUtils.isTrimEmpty(password)) { - HttpAuth.setAuth(account, password); - return true; - } - return false; - } - - private WebDavHelp() { - - } -} diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt new file mode 100644 index 0000000000..808b8039d8 --- /dev/null +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt @@ -0,0 +1,123 @@ +package com.kunfei.bookshelf.help.storage + +import android.content.Context +import android.net.Uri +import androidx.documentfile.provider.DocumentFile +import com.kunfei.bookshelf.DbHelper +import com.kunfei.bookshelf.MApplication +import com.kunfei.bookshelf.help.BookshelfHelp +import com.kunfei.bookshelf.help.FileHelp +import com.kunfei.bookshelf.model.BookSourceManager +import com.kunfei.bookshelf.model.ReplaceRuleManager +import com.kunfei.bookshelf.model.TxtChapterRuleManager +import com.kunfei.bookshelf.utils.DocumentUtil +import com.kunfei.bookshelf.utils.FileUtils +import com.kunfei.bookshelf.utils.GSON +import io.reactivex.Single +import io.reactivex.SingleOnSubscribe +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.schedulers.Schedulers +import java.io.File + + +object Backup { + + val backupPath = MApplication.getInstance().filesDir.absolutePath + File.separator + "backup" + + val defaultPath by lazy { + FileUtils.getSdCardPath() + File.separator + "YueDu" + } + + val backupFileNames by lazy { + arrayOf( + "myBookShelf.json", + "myBookSource.json", + "myBookSearchHistory.json", + "myBookReplaceRule.json", + "myTxtChapterRule.json", + "config.xml" + ) + } + + fun backup(context: Context, uri: Uri?) { + Single.create(SingleOnSubscribe { e -> + BookshelfHelp.getAllBook().let { + if (it.isNotEmpty()) { + val json = GSON.toJson(it) + FileHelp.getFile(backupPath + File.separator + "myBookShelf.json").writeText(json) + } + } + BookSourceManager.getAllBookSource().let { + if (it.isNotEmpty()) { + val json = GSON.toJson(it) + FileHelp.getFile(backupPath + File.separator + "myBookSource.json").writeText(json) + } + } + DbHelper.getDaoSession().searchHistoryBeanDao.queryBuilder().list().let { + if (it.isNotEmpty()) { + val json = GSON.toJson(it) + FileHelp.getFile(backupPath + File.separator + "myBookSearchHistory.json") + .writeText(json) + } + } + ReplaceRuleManager.getAll().blockingGet().let { + if (it.isNotEmpty()) { + val json = GSON.toJson(it) + FileHelp.getFile(backupPath + File.separator + "myBookReplaceRule.json").writeText(json) + } + } + TxtChapterRuleManager.getAll().let { + if (it.isNotEmpty()) { + val json = GSON.toJson(it) + FileHelp.getFile(backupPath + File.separator + "myTxtChapterRule.json") + .writeText(json) + } + } + Preferences.getSharedPreferences(context, backupPath, "config")?.let { sp -> + val edit = sp.edit() + MApplication.getConfigPreferences().all.map { + when (val value = it.value) { + is Int -> edit.putInt(it.key, value) + is Boolean -> edit.putBoolean(it.key, value) + is Long -> edit.putLong(it.key, value) + is Float -> edit.putFloat(it.key, value) + is String -> edit.putString(it.key, value) + else -> Unit + } + } + edit.commit() + } + WebDavHelp.backUpWebDav(backupPath) + if (uri != null) { + copyBackup(context, uri) + } else { + copyBackup() + } + e.onSuccess(true) + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe() + } + + private fun copyBackup(context: Context, uri: Uri) { + DocumentFile.fromTreeUri(context, uri)?.let { treeDoc -> + for (fileName in backupFileNames) { + val doc = treeDoc.findFile(fileName) ?: treeDoc.createFile("", fileName) + doc?.let { + DocumentUtil.writeBytes(context, FileHelp.getFile(backupPath + File.separator + fileName).readBytes(), doc) + } + } + } + } + + private fun copyBackup() { + try { + for (fileName in backupFileNames) { + FileHelp.getFile(backupPath + File.separator + "bookshelf.json") + .copyTo(FileHelp.getFile(defaultPath + File.separator + "bookshelf.json"), true) + } + } catch (e: Exception) { + e.printStackTrace() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/Preferences.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/Preferences.kt new file mode 100644 index 0000000000..2918d711fb --- /dev/null +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/Preferences.kt @@ -0,0 +1,48 @@ +package com.kunfei.bookshelf.help.storage + +import android.app.Activity +import android.content.Context +import android.content.ContextWrapper +import android.content.SharedPreferences +import java.io.File + +object Preferences { + + /** + * 用反射生成 SharedPreferences + * @param context + * @param dir + * @param fileName 文件名,不需要 '.xml' 后缀 + * @return + */ + fun getSharedPreferences( + context: Context, + dir: String, + fileName: String + ): SharedPreferences? { + try { + // 获取 ContextWrapper对象中的mBase变量。该变量保存了 ContextImpl 对象 + val fieldMBase = ContextWrapper::class.java.getDeclaredField("mBase") + fieldMBase.isAccessible = true + // 获取 mBase变量 + val objMBase = fieldMBase.get(context) + // 获取 ContextImpl。mPreferencesDir变量,该变量保存了数据文件的保存路径 + val fieldMPreferencesDir = objMBase.javaClass.getDeclaredField("mPreferencesDir") + fieldMPreferencesDir.isAccessible = true + // 创建自定义路径 + // String FILE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()+"/Android"; + val file = File(dir) + // 修改mPreferencesDir变量的值 + fieldMPreferencesDir.set(objMBase, file) + // 返回修改路径以后的 SharedPreferences :%FILE_PATH%/%fileName%.xml + return context.getSharedPreferences(fileName, Activity.MODE_PRIVATE) + } catch (e: NoSuchFieldException) { + e.printStackTrace() + } catch (e: IllegalArgumentException) { + e.printStackTrace() + } catch (e: IllegalAccessException) { + e.printStackTrace() + } + return null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt new file mode 100644 index 0000000000..751ead8118 --- /dev/null +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt @@ -0,0 +1,99 @@ +package com.kunfei.bookshelf.help.storage + +import android.content.Context +import android.net.Uri +import androidx.documentfile.provider.DocumentFile +import com.kunfei.bookshelf.DbHelper +import com.kunfei.bookshelf.MApplication +import com.kunfei.bookshelf.bean.* +import com.kunfei.bookshelf.help.FileHelp +import com.kunfei.bookshelf.model.BookSourceManager +import com.kunfei.bookshelf.model.ReplaceRuleManager +import com.kunfei.bookshelf.model.TxtChapterRuleManager +import com.kunfei.bookshelf.utils.DocumentUtil +import com.kunfei.bookshelf.utils.GSON +import com.kunfei.bookshelf.utils.fromJsonArray +import java.io.File + +object Restore { + + fun restore(context: Context, uri: Uri) { + DocumentFile.fromTreeUri(context, uri)?.listFiles()?.forEach { doc -> + for (fileName in Backup.backupFileNames) { + if (doc.name == fileName) { + DocumentUtil.readBytes(context, doc.uri)?.let { + FileHelp.getFile(Backup.backupPath + File.separator + fileName) + .writeBytes(it) + } + } + } + } + restore(Backup.backupPath) + } + + fun restore(path: String) { + try { + val file = FileHelp.getFile(path + File.separator + "myBookShelf.json") + val json = file.readText() + GSON.fromJsonArray(json)?.forEach { bookshelf -> + if (bookshelf.noteUrl != null) { + DbHelper.getDaoSession().bookShelfBeanDao.insertOrReplace(bookshelf) + } + if (bookshelf.bookInfoBean.noteUrl != null) { + DbHelper.getDaoSession().bookInfoBeanDao.insertOrReplace(bookshelf.bookInfoBean) + } + } + } catch (e: Exception) { + e.printStackTrace() + } + try { + val file = FileHelp.getFile(path + File.separator + "myBookSource.json") + val json = file.readText() + GSON.fromJsonArray(json)?.let { + BookSourceManager.addBookSource(it) + } + } catch (e: Exception) { + e.printStackTrace() + } + try { + val file = FileHelp.getFile(path + File.separator + "myBookSearchHistory.json") + val json = file.readText() + GSON.fromJsonArray(json)?.let { + DbHelper.getDaoSession().searchHistoryBeanDao.insertOrReplaceInTx(it) + } + } catch (e: Exception) { + e.printStackTrace() + } + try { + val file = FileHelp.getFile(path + File.separator + "myBookReplaceRule.json") + val json = file.readText() + GSON.fromJsonArray(json)?.let { + ReplaceRuleManager.addDataS(it) + } + } catch (e: Exception) { + e.printStackTrace() + } + try { + val file = FileHelp.getFile(path + File.separator + "myTxtChapterRule.json") + val json = file.readText() + GSON.fromJsonArray(json)?.let { + TxtChapterRuleManager.save(it) + } + } catch (e: Exception) { + e.printStackTrace() + } + Preferences.getSharedPreferences(MApplication.getInstance(), path, "config")?.all?.map { + val edit = MApplication.getConfigPreferences().edit() + when (val value = it.value) { + is Int -> edit.putInt(it.key, value) + is Boolean -> edit.putBoolean(it.key, value) + is Long -> edit.putLong(it.key, value) + is Float -> edit.putFloat(it.key, value) + is String -> edit.putString(it.key, value) + else -> Unit + } + edit.commit() + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt new file mode 100644 index 0000000000..01dc842b22 --- /dev/null +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt @@ -0,0 +1,94 @@ +package com.kunfei.bookshelf.help.storage + +import android.content.Context +import com.kunfei.bookshelf.MApplication +import com.kunfei.bookshelf.constant.AppConstant +import com.kunfei.bookshelf.help.FileHelp +import com.kunfei.bookshelf.utils.ZipUtils +import com.kunfei.bookshelf.utils.webdav.WebDav +import com.kunfei.bookshelf.utils.webdav.http.HttpAuth +import org.jetbrains.anko.selector +import java.io.File +import java.text.SimpleDateFormat +import java.util.* +import kotlin.math.min + +object WebDavHelp { + private val zipFilePath = FileHelp.getCachePath() + "/backup" + ".zip" + private val unzipFilesPath by lazy { + FileHelp.getCachePath() + } + + private fun getWebDavUrl(): String? { + var url = MApplication.getConfigPreferences().getString("web_dav_url", AppConstant.DEFAULT_WEB_DAV_URL) + if (url.isNullOrBlank()) return null + if (!url.endsWith("/")) url += "/" + return url + } + + private fun initWebDav(): Boolean { + val account = MApplication.getConfigPreferences().getString("web_dav_account", "") + val password = MApplication.getConfigPreferences().getString("web_dav_password", "") + if (!account.isNullOrBlank() && !password.isNullOrBlank()) { + HttpAuth.auth = HttpAuth.Auth(account, password) + return true + } + return false + } + + private fun getWebDavFileNames(): ArrayList { + val url = getWebDavUrl() + val names = arrayListOf() + if (!url.isNullOrBlank() && initWebDav()) { + var files = WebDav(url + "YueDu/").listFiles() + files = files.reversed() + for (index: Int in 0 until min(10, files.size)) { + files[index].displayName?.let { + names.add(it) + } + } + } + return names + } + + fun showRestoreDialog(context: Context): Boolean { + val names = getWebDavFileNames() + return if (names.isNotEmpty()) { + context.selector(title = "选择恢复文件", items = names) { _, index -> + if (index in 0 until names.size) { + restoreWebDav(names[index]) + } + } + true + } else { + false + } + } + + private fun restoreWebDav(name: String) { + getWebDavUrl()?.let { + val file = WebDav(it + "YueDu/" + name) + file.downloadTo(zipFilePath, true) + @Suppress("BlockingMethodInNonBlockingContext") + ZipUtils.unzipFile(zipFilePath, unzipFilesPath) + Restore.restore(unzipFilesPath) + } + } + + fun backUpWebDav(path: String) { + if (initWebDav()) { + val paths = arrayListOf(*Backup.backupFileNames) + for (i in 0 until paths.size) { + paths[i] = path + File.separator + paths[i] + } + FileHelp.deleteFile(zipFilePath) + if (ZipUtils.zipFiles(paths, zipFilePath)) { + WebDav(getWebDavUrl() + "YueDu").makeAsDir() + val putUrl = getWebDavUrl() + "YueDu/backup" + + SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) + .format(Date(System.currentTimeMillis())) + ".zip" + WebDav(putUrl).upload(zipFilePath) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kunfei/bookshelf/presenter/MainPresenter.java b/app/src/main/java/com/kunfei/bookshelf/presenter/MainPresenter.java index 948a628e41..a968c5581e 100644 --- a/app/src/main/java/com/kunfei/bookshelf/presenter/MainPresenter.java +++ b/app/src/main/java/com/kunfei/bookshelf/presenter/MainPresenter.java @@ -12,7 +12,6 @@ import com.kunfei.basemvplib.BasePresenterImpl; import com.kunfei.basemvplib.impl.IView; import com.kunfei.bookshelf.DbHelper; -import com.kunfei.bookshelf.R; import com.kunfei.bookshelf.base.observer.MyObserver; import com.kunfei.bookshelf.bean.BookChapterBean; import com.kunfei.bookshelf.bean.BookInfoBean; @@ -21,8 +20,6 @@ import com.kunfei.bookshelf.constant.RxBusTag; import com.kunfei.bookshelf.dao.BookSourceBeanDao; import com.kunfei.bookshelf.help.BookshelfHelp; -import com.kunfei.bookshelf.help.DataBackup; -import com.kunfei.bookshelf.help.DataRestore; import com.kunfei.bookshelf.model.WebBookModel; import com.kunfei.bookshelf.presenter.contract.MainContract; import com.kunfei.bookshelf.utils.RxUtils; @@ -31,48 +28,11 @@ import java.util.List; import io.reactivex.Observable; -import io.reactivex.ObservableOnSubscribe; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; public class MainPresenter extends BasePresenterImpl implements MainContract.Presenter { - @Override - public void backupData() { - DataBackup.getInstance().run(); - } - - @Override - public void restoreData() { - mView.onRestore(mView.getContext().getString(R.string.on_restore)); - Observable.create((ObservableOnSubscribe) e -> { - if (DataRestore.getInstance().run()) { - e.onNext(true); - } else { - e.onNext(false); - } - e.onComplete(); - }) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new MyObserver() { - @Override - public void onNext(Boolean value) { - mView.dismissHUD(); - mView.toast(R.string.restore_success); - //更新书架并刷新 - mView.recreate(); - } - - @Override - public void onError(Throwable e) { - e.printStackTrace(); - mView.dismissHUD(); - mView.toast(R.string.restore_fail); - } - }); - } - @Override public void addBookUrl(String bookUrls) { bookUrls = bookUrls.trim(); @@ -198,8 +158,4 @@ public void recreate(Boolean recreate) { mView.recreate(); } - @Subscribe(thread = EventThread.MAIN_THREAD, tags = {@Tag(RxBusTag.AUTO_BACKUP)}) - public void autoBackup(Boolean backup) { - DataBackup.getInstance().autoSave(); - } } \ No newline at end of file diff --git a/app/src/main/java/com/kunfei/bookshelf/presenter/contract/MainContract.java b/app/src/main/java/com/kunfei/bookshelf/presenter/contract/MainContract.java index 45a6b15bac..33af9c6ec5 100644 --- a/app/src/main/java/com/kunfei/bookshelf/presenter/contract/MainContract.java +++ b/app/src/main/java/com/kunfei/bookshelf/presenter/contract/MainContract.java @@ -30,10 +30,6 @@ interface View extends IView { interface Presenter extends IPresenter { - void backupData(); - - void restoreData(); - void addBookUrl(String bookUrl); } diff --git a/app/src/main/java/com/kunfei/bookshelf/utils/GsonExtensions.kt b/app/src/main/java/com/kunfei/bookshelf/utils/GsonExtensions.kt new file mode 100644 index 0000000000..0424801b56 --- /dev/null +++ b/app/src/main/java/com/kunfei/bookshelf/utils/GsonExtensions.kt @@ -0,0 +1,43 @@ +package com.kunfei.bookshelf.utils + +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import com.google.gson.JsonSyntaxException +import com.google.gson.reflect.TypeToken +import org.jetbrains.anko.attempt +import java.lang.reflect.ParameterizedType +import java.lang.reflect.Type + +val GSON: Gson by lazy { + GsonBuilder() + .disableHtmlEscaping() + .setPrettyPrinting() + .create() +} + +inline fun genericType() = object : TypeToken() {}.type + + +@Throws(JsonSyntaxException::class) +inline fun Gson.fromJsonObject(json: String?): T? {//可转成任意类型 + return attempt { + val result: T? = fromJson(json, genericType()) + result + }.value +} + +@Throws(JsonSyntaxException::class) +inline fun Gson.fromJsonArray(json: String?): List? { + return attempt { + val result: List? = fromJson(json, ParameterizedTypeImpl(T::class.java)) + result + }.value +} + +class ParameterizedTypeImpl(private val clazz: Class<*>) : ParameterizedType { + override fun getRawType(): Type = List::class.java + + override fun getOwnerType(): Type? = null + + override fun getActualTypeArguments(): Array = arrayOf(clazz) +} diff --git a/app/src/main/java/com/kunfei/bookshelf/utils/web_dav/WebDavFile.java b/app/src/main/java/com/kunfei/bookshelf/utils/web_dav/WebDavFile.java deleted file mode 100644 index 2dc2e617fd..0000000000 --- a/app/src/main/java/com/kunfei/bookshelf/utils/web_dav/WebDavFile.java +++ /dev/null @@ -1,394 +0,0 @@ -package com.kunfei.bookshelf.utils.web_dav; - -import com.kunfei.bookshelf.utils.web_dav.http.Handler; -import com.kunfei.bookshelf.utils.web_dav.http.HttpAuth; -import com.kunfei.bookshelf.utils.web_dav.http.OkHttp; - -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import org.jsoup.select.Elements; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Field; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.List; - -import okhttp3.Credentials; -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; - -@SuppressWarnings("ResultOfMethodCallIgnored") -public class WebDavFile { - public final static String TAG = WebDavFile.class.getSimpleName(); - public final static String OBJECT_NOT_EXISTS_TAG = "ObjectNotFound"; - // 指定返回哪些属性 - private final static String DIR = "\n" + - "\n" + - "\n" + - "\n\n\n\n\n%s" + - "\n" + - ""; - - private URL url; - private String httpUrl; - - private String displayName; - private long createTime; - private long lastModified; - private long size; - private boolean isDirectory = true; - private boolean exists = false; - private String parent = ""; - private String urlName = ""; - - private OkHttpClient okHttpClient; - - public WebDavFile(String url) throws MalformedURLException { - this.url = new URL(null, url, Handler.HANDLER); - okHttpClient = OkHttp.getInstance().client(); - } - - public String getUrl() { - if (httpUrl == null) { - String raw = url.toString().replace("davs://", "https://").replace("dav://", "http://"); - try { - httpUrl = URLEncoder.encode(raw, "UTF-8") - .replaceAll("\\+", "%20") - .replaceAll("%3A", ":") - .replaceAll("%2F", "/"); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - } - return httpUrl; - } - - public String getPath() { - return url.toString(); - } - - /** - * 填充文件信息。实例化WebDAVFile对象时,并没有将远程文件的信息填充到实例中。需要手动填充! - * - * @return 远程文件是否存在 - */ - public boolean indexFileInfo() throws IOException { - Response response = propFindResponse(new ArrayList<>()); - String s = ""; - try { - if (response == null || !response.isSuccessful()) { - this.exists = false; - return false; - } - s = response.body().string(); - } catch (Exception e) { - e.printStackTrace(); - } - - - return false; - } - - /** - * 列出当前路径下的文件。默认列出文件的如下属性:displayname、resourcetype、getcontentlength、creationdate、getlastmodified - * - * @return 文件列表 - */ - public List listFiles() throws IOException { - return listFiles(new ArrayList<>()); - } - - /** - * 列出当前路径下的文件 - * - * @param propsList 指定列出文件的哪些属性 - * @return 文件列表 - */ - public List listFiles(ArrayList propsList) throws IOException { - Response response = propFindResponse(propsList); - try { - assert response != null; - if (response.isSuccessful()) { - return parseDir(response.body().string()); - } - } catch (Exception e) { - e.printStackTrace(); - } - return new ArrayList<>(); - } - - private Response propFindResponse(ArrayList propsList) throws IOException { - return propFindResponse(propsList, 1); - } - - private Response propFindResponse(ArrayList propsList, int depth) throws IOException { - StringBuilder requestProps = new StringBuilder(); - for (String p : propsList) { - requestProps.append("\n"); - } - String requestPropsStr; - if (requestProps.toString().isEmpty()) { - requestPropsStr = DIR.replace("%s", ""); - } else { - requestPropsStr = String.format(DIR, requestProps.toString() + "\n"); - } - Request.Builder request = new Request.Builder() - .url(getUrl()) - // 添加RequestBody对象,可以只返回的属性。如果设为null,则会返回全部属性 - // 注意:尽量手动指定需要返回的属性。若返回全部属性,可能后由于Prop.java里没有该属性名,而崩溃。 - .method("PROPFIND", RequestBody.create(MediaType.parse("text/plain"), requestPropsStr)); - - HttpAuth.Auth auth = HttpAuth.getAuth(); - if (auth != null) { - request.header("Authorization", Credentials.basic(auth.getUser(), auth.getPass())); - } - request.header("Depth", depth < 0 ? "infinity" : Integer.toString(depth)); - - return okHttpClient.newCall(request.build()).execute(); - } - - private List parseDir(String s) { - List list = new ArrayList<>(); - Document document = Jsoup.parse(s); - Elements elements = document.getElementsByTag("d:response"); - String baseUrl = getUrl().endsWith("/") ? getUrl() : getUrl() + "/"; - for (Element element : elements) { - String href = element.getElementsByTag("d:href").get(0).text(); - if (!href.endsWith("/")) { - String fileName = href.substring(href.lastIndexOf("/") + 1); - WebDavFile webDavFile; - try { - webDavFile = new WebDavFile(baseUrl + fileName); - webDavFile.setDisplayName(fileName); - webDavFile.setUrlName(href); - list.add(webDavFile); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - } - } - return list; - } - - public InputStream getInputStream() { - Request.Builder request = new Request.Builder() - .url(getUrl()); - - HttpAuth.Auth auth = HttpAuth.getAuth(); - - if (auth != null) { - request.header("Authorization", Credentials.basic(auth.getUser(), auth.getPass())); - } - - try { - Response response = okHttpClient.newCall(request.build()).execute(); - return response.body().byteStream(); - } catch (IOException | IllegalArgumentException e) { - e.printStackTrace(); - } - return null; - } - - /** - * 根据自己的URL,在远程处创建对应的文件夹 - * - * @return 是否创建成功 - */ - public boolean makeAsDir() throws IOException { - Request.Builder request = new Request.Builder() - .url(getUrl()) - .method("MKCOL", null); - return execRequest(request); - } - - /** - * 下载到本地 - * - * @param savedPath 本地的完整路径,包括最后的文件名 - * @param replaceExisting 是否替换本地的同名文件 - * @return 下载是否成功 - */ - public boolean download(String savedPath, boolean replaceExisting) { - File file = new File(savedPath); - if (file.exists()) { - if (replaceExisting) { - file.delete(); - } else { - return false; - } - } - InputStream in = getInputStream(); - FileOutputStream out = null; - try { - file.createNewFile(); - out = new FileOutputStream(file); - byte[] buffer = new byte[1024 * 8]; - int byteRead; - while ((byteRead = in.read(buffer)) != -1) { - out.write(buffer, 0, byteRead); - } - out.flush(); - return true; - } catch (Exception e) { - e.printStackTrace(); - } finally { - try { - if (out != null) out.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - return false; - } - - /** - * 上传文件 - * - * @param localPath 本地文件路径 - * @return 是否成功成功 - */ - public boolean upload(String localPath) throws IOException { - return upload(localPath, null); - } - - public boolean upload(String localPath, String contentType) throws IOException { - File file = new File((localPath)); - if (!file.exists()) return false; - MediaType mediaType = contentType == null ? null : MediaType.parse(contentType); - // 务必注意RequestBody不要嵌套,不然上传时内容可能会被追加多余的文件信息 - RequestBody fileBody = RequestBody.create(mediaType, file); - Request.Builder request = new Request.Builder() - .url(getUrl()) - .put(fileBody); - - return execRequest(request); - } - - /** - * 执行请求,获取响应结果 - * - * @param requestBuilder 因为还需要追加验证信息,所以此处传递Request.Builder的对象,而不是Request的对象 - * @return 请求执行的结果 - */ - private boolean execRequest(Request.Builder requestBuilder) throws IOException { - HttpAuth.Auth auth = HttpAuth.getAuth(); - if (auth != null) { - requestBuilder.header("Authorization", Credentials.basic(auth.getUser(), auth.getPass())); - } - - Response response = okHttpClient.newCall(requestBuilder.build()).execute(); - return response.isSuccessful(); - } - - /** - * 打印对象内的所有属性 - */ - public static T printAllAttrs(String className, Object o) { - try { - Class c = Class.forName(className); - Field[] fields = c.getDeclaredFields(); - for (Field f : fields) { - f.setAccessible(true); - } - System.out.println("=============" + className + "==============="); - for (Field f : fields) { - String field = f.toString().substring(f.toString().lastIndexOf(".") + 1); //取出属性名称 - System.out.println(field + " --> " + f.get(o)); - } - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public String getDisplayName() { - return displayName; - } - - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - - public long getCreateTime() { - return createTime; - } - - public void setCreateTime(long createTime) { - this.createTime = createTime; - } - - public long getLastModified() { - return lastModified; - } - - public void setLastModified(long lastModified) { - this.lastModified = lastModified; - } - - public long getSize() { - return size; - } - - public void setSize(long size) { - this.size = size; - } - - public void setUrlName(String urlName) { - this.urlName = urlName; - } - - public boolean isDirectory() { - return isDirectory; - } - - public String getURLName() { - if (urlName.isEmpty()) { - urlName = (parent.isEmpty() ? url.getFile() : url.toString().replace(parent, "")). - replace("/", ""); - } - return urlName; - } - - public String getHost() { - return url.getHost(); - } - - public boolean canRead() { - return true; - } - - public boolean canWrite() { - return false; - } - - public boolean exists() { - return exists; - } - - public void exists(boolean exists) { - this.exists = exists; - } - - public String getParent() { - return parent; - } - - public void setParent(String path) { - parent = path; - } - - public void setIsDirectory(boolean isDirectory) { - this.isDirectory = isDirectory; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/kunfei/bookshelf/utils/web_dav/http/Handler.java b/app/src/main/java/com/kunfei/bookshelf/utils/web_dav/http/Handler.java deleted file mode 100644 index ad67541062..0000000000 --- a/app/src/main/java/com/kunfei/bookshelf/utils/web_dav/http/Handler.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.kunfei.bookshelf.utils.web_dav.http; - -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; - -public class Handler extends URLStreamHandler { - - public static final URLStreamHandler HANDLER = new Handler(); - - protected int getDefaultPort() { - return 80; - } - - public URLConnection openConnection(URL u) { - return null; - } - - @Override - protected void parseURL(URL url, String spec, int start, int end) { - super.parseURL(url, spec, start, end); - } -} diff --git a/app/src/main/java/com/kunfei/bookshelf/utils/web_dav/http/HttpAuth.java b/app/src/main/java/com/kunfei/bookshelf/utils/web_dav/http/HttpAuth.java deleted file mode 100644 index 4fd731358c..0000000000 --- a/app/src/main/java/com/kunfei/bookshelf/utils/web_dav/http/HttpAuth.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.kunfei.bookshelf.utils.web_dav.http; - -public class HttpAuth { - - private static Auth auth; - - private HttpAuth() { - } - - public static void setAuth(String user, String password) { - auth = new Auth(user, password); - } - - public static Auth getAuth() { - return auth; - } - - public static class Auth { - private String user; - private String pass; - - Auth(String user, String pass) { - this.user = user; - this.pass = pass; - } - - public String getUser() { - return user; - } - - public String getPass() { - return pass; - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/kunfei/bookshelf/utils/web_dav/http/OkHttp.java b/app/src/main/java/com/kunfei/bookshelf/utils/web_dav/http/OkHttp.java deleted file mode 100644 index dae2ed7f22..0000000000 --- a/app/src/main/java/com/kunfei/bookshelf/utils/web_dav/http/OkHttp.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.kunfei.bookshelf.utils.web_dav.http; - -import okhttp3.OkHttpClient; - -public class OkHttp { - - private OkHttpClient okHttpClient; - - private OkHttp() { - } - - public static OkHttp getInstance() { - return SingletonHelper.INSTANCE; - } - - public OkHttpClient client() { - if (okHttpClient == null) { - okHttpClient = new OkHttpClient.Builder().build(); - } - return okHttpClient; - } - - private static class SingletonHelper { - private final static OkHttp INSTANCE = new OkHttp(); - } - -} diff --git a/app/src/main/java/com/kunfei/bookshelf/utils/webdav/README.md b/app/src/main/java/com/kunfei/bookshelf/utils/webdav/README.md new file mode 100644 index 0000000000..f6ac57a9db --- /dev/null +++ b/app/src/main/java/com/kunfei/bookshelf/utils/webdav/README.md @@ -0,0 +1 @@ +## 用于网络备份的WebDav \ No newline at end of file diff --git a/app/src/main/java/com/kunfei/bookshelf/utils/webdav/WebDav.kt b/app/src/main/java/com/kunfei/bookshelf/utils/webdav/WebDav.kt new file mode 100644 index 0000000000..368c76efb4 --- /dev/null +++ b/app/src/main/java/com/kunfei/bookshelf/utils/webdav/WebDav.kt @@ -0,0 +1,249 @@ +package com.kunfei.bookshelf.utils.webdav + +import com.kunfei.bookshelf.base.BaseModelImpl +import com.kunfei.bookshelf.utils.webdav.http.Handler +import com.kunfei.bookshelf.utils.webdav.http.HttpAuth +import okhttp3.Credentials +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.Request +import okhttp3.RequestBody.Companion.asRequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.Response +import org.jsoup.Jsoup +import java.io.File +import java.io.IOException +import java.io.InputStream +import java.io.UnsupportedEncodingException +import java.net.MalformedURLException +import java.net.URL +import java.net.URLEncoder +import java.util.* + +class WebDav @Throws(MalformedURLException::class) +constructor(urlStr: String) { + companion object { + // 指定返回哪些属性 + private const val DIR = "\n" + + "\n" + + "\n" + + "\n\n\n\n\n%s" + + "\n" + + "" + } + + private val url: URL = URL(null, urlStr, Handler) + private val httpUrl: String? by lazy { + val raw = url.toString().replace("davs://", "https://").replace("dav://", "http://") + try { + return@lazy URLEncoder.encode(raw, "UTF-8") + .replace("\\+".toRegex(), "%20") + .replace("%3A".toRegex(), ":") + .replace("%2F".toRegex(), "/") + } catch (e: UnsupportedEncodingException) { + e.printStackTrace() + return@lazy null + } + } + + var displayName: String? = null + var size: Long = 0 + var exists = false + var parent = "" + var urlName = "" + get() { + if (field.isEmpty()) { + this.urlName = ( + if (parent.isEmpty()) url.file + else url.toString().replace(parent, "") + ).replace("/", "") + } + return field + } + + fun getPath() = url.toString() + + fun getHost() = url.host + + /** + * 填充文件信息。实例化WebDAVFile对象时,并没有将远程文件的信息填充到实例中。需要手动填充! + * + * @return 远程文件是否存在 + */ + @Throws(IOException::class) + fun indexFileInfo(): Boolean { + propFindResponse(ArrayList())?.let { response -> + if (!response.isSuccessful) { + this.exists = false + return false + } + response.body?.let { + if (it.string().isNotEmpty()) { + return true + } + } + } + return false + } + + /** + * 列出当前路径下的文件 + * + * @param propsList 指定列出文件的哪些属性 + * @return 文件列表 + */ + @Throws(IOException::class) + @JvmOverloads + fun listFiles(propsList: ArrayList = ArrayList()): List { + propFindResponse(propsList)?.let { response -> + if (response.isSuccessful) { + response.body?.let { body -> + return parseDir(body.string()) + } + } + } + return ArrayList() + } + + @Throws(IOException::class) + private fun propFindResponse(propsList: ArrayList, depth: Int = 1): Response? { + val requestProps = StringBuilder() + for (p in propsList) { + requestProps.append("\n") + } + val requestPropsStr: String + requestPropsStr = if (requestProps.toString().isEmpty()) { + DIR.replace("%s", "") + } else { + String.format(DIR, requestProps.toString() + "\n") + } + httpUrl?.let { url -> + val request = Request.Builder() + .url(url) + // 添加RequestBody对象,可以只返回的属性。如果设为null,则会返回全部属性 + // 注意:尽量手动指定需要返回的属性。若返回全部属性,可能后由于Prop.java里没有该属性名,而崩溃。 + .method("PROPFIND", requestPropsStr.toRequestBody("text/plain".toMediaTypeOrNull())) + + HttpAuth.auth?.let { + request.header( + "Authorization", + Credentials.basic(it.user, it.pass) + ) + } + request.header("Depth", if (depth < 0) "infinity" else depth.toString()) + return BaseModelImpl.getClientBuilder().build().newCall(request.build()).execute() + } + return null + } + + private fun parseDir(s: String): List { + val list = ArrayList() + val document = Jsoup.parse(s) + val elements = document.getElementsByTag("d:response") + httpUrl?.let { url -> + val baseUrl = if (url.endsWith("/")) url else "$url/" + for (element in elements) { + val href = element.getElementsByTag("d:href")[0].text() + if (!href.endsWith("/")) { + val fileName = href.substring(href.lastIndexOf("/") + 1) + val webDavFile: WebDav + try { + webDavFile = WebDav(baseUrl + fileName) + webDavFile.displayName = fileName + webDavFile.urlName = href + list.add(webDavFile) + } catch (e: MalformedURLException) { + e.printStackTrace() + } + } + } + } + return list + } + + /** + * 根据自己的URL,在远程处创建对应的文件夹 + * + * @return 是否创建成功 + */ + @Throws(IOException::class) + fun makeAsDir(): Boolean { + httpUrl?.let { url -> + val request = Request.Builder() + .url(url) + .method("MKCOL", null) + return execRequest(request) + } + return false + } + + /** + * 下载到本地 + * + * @param savedPath 本地的完整路径,包括最后的文件名 + * @param replaceExisting 是否替换本地的同名文件 + * @return 下载是否成功 + */ + fun downloadTo(savedPath: String, replaceExisting: Boolean): Boolean { + if (File(savedPath).exists()) { + if (!replaceExisting) return false + } + val inputS = getInputStream() ?: return false + File(savedPath).writeBytes(inputS.readBytes()) + return true + } + + /** + * 上传文件 + */ + @Throws(IOException::class) + @JvmOverloads + fun upload(localPath: String, contentType: String? = null): Boolean { + val file = File(localPath) + if (!file.exists()) return false + val mediaType = contentType?.toMediaTypeOrNull() + // 务必注意RequestBody不要嵌套,不然上传时内容可能会被追加多余的文件信息 + val fileBody = file.asRequestBody(mediaType) + httpUrl?.let { + val request = Request.Builder() + .url(it) + .put(fileBody) + return execRequest(request) + } + return false + } + + /** + * 执行请求,获取响应结果 + * @param requestBuilder 因为还需要追加验证信息,所以此处传递Request.Builder的对象,而不是Request的对象 + * @return 请求执行的结果 + */ + @Throws(IOException::class) + private fun execRequest(requestBuilder: Request.Builder): Boolean { + HttpAuth.auth?.let { + requestBuilder.header( + "Authorization", + Credentials.basic(it.user, it.pass) + ) + } + val response = BaseModelImpl.getClientBuilder().build().newCall(requestBuilder.build()).execute() + return response.isSuccessful + } + + private fun getInputStream(): InputStream? { + httpUrl?.let { url -> + val request = Request.Builder().url(url) + HttpAuth.auth?.let { + request.header("Authorization", Credentials.basic(it.user, it.pass)) + } + try { + return BaseModelImpl.getClientBuilder().build().newCall(request.build()).execute().body?.byteStream() + } catch (e: IOException) { + e.printStackTrace() + } catch (e: IllegalArgumentException) { + e.printStackTrace() + } + } + return null + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/kunfei/bookshelf/utils/webdav/http/Handler.kt b/app/src/main/java/com/kunfei/bookshelf/utils/webdav/http/Handler.kt new file mode 100644 index 0000000000..2600b9a842 --- /dev/null +++ b/app/src/main/java/com/kunfei/bookshelf/utils/webdav/http/Handler.kt @@ -0,0 +1,16 @@ +package com.kunfei.bookshelf.utils.webdav.http + +import java.net.URL +import java.net.URLConnection +import java.net.URLStreamHandler + +object Handler : URLStreamHandler() { + + override fun getDefaultPort(): Int { + return 80 + } + + public override fun openConnection(u: URL): URLConnection? { + return null + } +} diff --git a/app/src/main/java/com/kunfei/bookshelf/utils/webdav/http/HttpAuth.kt b/app/src/main/java/com/kunfei/bookshelf/utils/webdav/http/HttpAuth.kt new file mode 100644 index 0000000000..9102fbc4a1 --- /dev/null +++ b/app/src/main/java/com/kunfei/bookshelf/utils/webdav/http/HttpAuth.kt @@ -0,0 +1,9 @@ +package com.kunfei.bookshelf.utils.webdav.http + +object HttpAuth { + + var auth: Auth? = null + + class Auth internal constructor(val user: String, val pass: String) + +} \ No newline at end of file diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java index 99ba33141c..406f61e5a5 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java @@ -6,8 +6,11 @@ import android.content.SharedPreferences; import android.content.res.Configuration; import android.graphics.PorterDuff; +import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.text.TextUtils; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; @@ -19,6 +22,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.AlertDialog; @@ -45,6 +49,9 @@ import com.kunfei.bookshelf.help.ProcessTextHelp; import com.kunfei.bookshelf.help.permission.Permissions; import com.kunfei.bookshelf.help.permission.PermissionsCompat; +import com.kunfei.bookshelf.help.storage.Backup; +import com.kunfei.bookshelf.help.storage.Restore; +import com.kunfei.bookshelf.help.storage.WebDavHelp; import com.kunfei.bookshelf.model.UpLastChapterModel; import com.kunfei.bookshelf.presenter.MainPresenter; import com.kunfei.bookshelf.presenter.contract.MainContract; @@ -71,6 +78,8 @@ public class MainActivity extends BaseTabActivity implements MainContract.View, BookListFragment.CallbackValue { private final int requestSource = 14; + private final int backupSelectRequestCode = 23; + private final int restoreSelectRequestCode = 33; private String[] mTitles; @BindView(R.id.drawer) @@ -86,7 +95,6 @@ public class MainActivity extends BaseTabActivity implem private AppCompatImageView vwNightTheme; private int group; - private boolean viewIsList; private ActionBarDrawerToggle mDrawerToggle; private MoDialogHUD moDialogHUD; private long exitTime = 0; @@ -159,7 +167,6 @@ public void initImmersionBar() { @Override protected void initData() { - viewIsList = preferences.getBoolean("bookshelfIsList", true); mTitles = new String[]{getString(R.string.bookshelf), getString(R.string.find)}; } @@ -585,10 +592,27 @@ private void selectBookshelfLayout() { }).show(); } + private String getBackupPath() { + return preferences.getString("backupPath", ""); + } + /** * 备份 */ private void backup() { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + String path = getBackupPath(); + if (TextUtils.isEmpty(path)) { + selectBackupFolder(); + } else { + Backup.INSTANCE.backup(this, Uri.parse(path)); + } + } else { + backupOld(); + } + } + + private void backupOld() { new PermissionsCompat.Builder(this) .addPermissions(Permissions.READ_EXTERNAL_STORAGE, Permissions.WRITE_EXTERNAL_STORAGE) .rationale(R.string.backup_permission) @@ -596,7 +620,9 @@ private void backup() { AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this) .setTitle(R.string.backup_confirmation) .setMessage(R.string.backup_message) - .setPositiveButton(R.string.ok, (dialog, which) -> mPresenter.backupData()) + .setPositiveButton(R.string.ok, (dialog, which) -> + Backup.INSTANCE.backup(MainActivity.this, null) + ) .setNegativeButton(R.string.cancel, null) .show(); ATH.setAlertDialogTint(alertDialog); @@ -604,23 +630,50 @@ private void backup() { }).request(); } + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private void selectBackupFolder() { + try { + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + startActivityForResult(intent, backupSelectRequestCode); + } catch (Exception e) { + backupOld(); + } + } + /** * 恢复 */ private void restore() { - new PermissionsCompat.Builder(this) - .addPermissions(Permissions.READ_EXTERNAL_STORAGE, Permissions.WRITE_EXTERNAL_STORAGE) - .rationale(R.string.restore_permission) - .onGranted((requestCode) -> { - AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this) - .setTitle(R.string.restore_confirmation) - .setMessage(R.string.restore_message) - .setPositiveButton(R.string.ok, (dialog, which) -> mPresenter.restoreData()) - .setNegativeButton(R.string.cancel, null) - .show(); - ATH.setAlertDialogTint(alertDialog); - return Unit.INSTANCE; - }).request(); + if (!WebDavHelp.INSTANCE.showRestoreDialog(this)) { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + String path = getBackupPath(); + if (TextUtils.isEmpty(path)) { + selectRestoreFolder(); + } else { + Restore.INSTANCE.restore(this, Uri.parse(path)); + } + } else { + new PermissionsCompat.Builder(this) + .addPermissions(Permissions.READ_EXTERNAL_STORAGE, Permissions.WRITE_EXTERNAL_STORAGE) + .rationale(R.string.restore_permission) + .onGranted((requestCode) -> { + Restore.INSTANCE.restore(Backup.INSTANCE.getDefaultPath()); + return Unit.INSTANCE; + }).request(); + } + } + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private void selectRestoreFolder() { + try { + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + startActivityForResult(intent, restoreSelectRequestCode); + } catch (Exception e) { + Restore.INSTANCE.restore(Backup.INSTANCE.getDefaultPath()); + } } /** @@ -714,13 +767,33 @@ protected void onDestroy() { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - if (resultCode == RESULT_OK) { - if (requestCode == requestSource) { - FindBookFragment findBookFragment = getFindFragment(); - if (findBookFragment != null) { - findBookFragment.refreshData(); + switch (requestCode) { + case requestSource: + if (resultCode == RESULT_OK) { + FindBookFragment findBookFragment = getFindFragment(); + if (findBookFragment != null) { + findBookFragment.refreshData(); + } } - } + break; + case backupSelectRequestCode: + if (resultCode == RESULT_OK && data != null) { + Uri uri = data.getData(); + if (uri == null) return; + getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + preferences.edit().putString("backupPath", uri.toString()).apply(); + backup(); + } + break; + case restoreSelectRequestCode: + if (resultCode == RESULT_OK && data != null) { + Uri uri = data.getData(); + if (uri == null) return; + getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + preferences.edit().putString("backupPath", uri.toString()).apply(); + restore(); + } + break; } } diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadBookActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadBookActivity.java index c0dc3d004c..8ce9c479dd 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadBookActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadBookActivity.java @@ -37,7 +37,6 @@ import androidx.appcompat.widget.Toolbar; import com.google.android.material.appbar.AppBarLayout; -import com.hwangjr.rxbus.RxBus; import com.kunfei.basemvplib.AppActivityManager; import com.kunfei.basemvplib.BitIntentDataManager; import com.kunfei.bookshelf.DbHelper; @@ -50,7 +49,6 @@ import com.kunfei.bookshelf.bean.BookmarkBean; import com.kunfei.bookshelf.bean.ReplaceRuleBean; import com.kunfei.bookshelf.bean.TxtChapterRuleBean; -import com.kunfei.bookshelf.constant.RxBusTag; import com.kunfei.bookshelf.dao.TxtChapterRuleBeanDao; import com.kunfei.bookshelf.help.ChapterContentHelp; import com.kunfei.bookshelf.help.ReadBookControl; @@ -1824,37 +1822,45 @@ public void onMediaButton(String cmd) { } switch (aloudStatus) { case PAUSE: - if (cmd.equals(ReadAloudService.ActionMediaPlay)) { - ReadAloudService.resume(this); - readBottomMenu.setFabReadAloudText(getString(R.string.read_aloud)); - } else if (cmd.equals(ReadAloudService.ActionMediaPrev)) { - //停止倒计时 - ReadAloudService.setTimer(getContext(), ReadAloudService.maxTimeMinute + 1); - //语音提示倒计时结束 - ReadAloudService.tts_ui_timer_stop(this); - } else if (cmd.equals(ReadAloudService.ActionMediaNext)) { - //翻到上一章并开始朗读 - if (mPageLoader != null) { - mPageLoader.skipPreChapter(); - } - ReadAloudService.resume(this); - readBottomMenu.setFabReadAloudText(getString(R.string.read_aloud)); + switch (cmd) { + case ReadAloudService.ActionMediaPlay: + ReadAloudService.resume(this); + readBottomMenu.setFabReadAloudText(getString(R.string.read_aloud)); + break; + case ReadAloudService.ActionMediaPrev: + //停止倒计时 + ReadAloudService.setTimer(getContext(), ReadAloudService.maxTimeMinute + 1); + //语音提示倒计时结束 + ReadAloudService.tts_ui_timer_stop(this); + break; + case ReadAloudService.ActionMediaNext: + //翻到上一章并开始朗读 + if (mPageLoader != null) { + mPageLoader.skipPreChapter(); + } + ReadAloudService.resume(this); + readBottomMenu.setFabReadAloudText(getString(R.string.read_aloud)); + break; } break; case PLAY: - if (cmd.equals(ReadAloudService.ActionMediaPlay)) { - ReadAloudService.pause(this); - readBottomMenu.setFabReadAloudText(getString(R.string.read_aloud_pause)); - } else if (cmd.equals(ReadAloudService.ActionMediaPrev)) { - //倒计时增加 - ReadAloudService.setTimer(getContext(), 10); - //语音提示剩余时间 - ReadAloudService.tts_ui_timer_remaining(this); - } else if (cmd.equals(ReadAloudService.ActionMediaNext)) { - //翻到下一章 - if (mPageLoader != null) { - mPageLoader.skipNextChapter(); - } + switch (cmd) { + case ReadAloudService.ActionMediaPlay: + ReadAloudService.pause(this); + readBottomMenu.setFabReadAloudText(getString(R.string.read_aloud_pause)); + break; + case ReadAloudService.ActionMediaPrev: + //倒计时增加 + ReadAloudService.setTimer(getContext(), 10); + //语音提示剩余时间 + ReadAloudService.tts_ui_timer_remaining(this); + break; + case ReadAloudService.ActionMediaNext: + //翻到下一章 + if (mPageLoader != null) { + mPageLoader.skipNextChapter(); + } + break; } break; default: @@ -1919,15 +1925,19 @@ public void finish() { Intent intent = new Intent(this, MainActivity.class); startActivity(intent); } + backup(); + super.finish(); + } + + private void backup() { new PermissionsCompat.Builder(this) .addPermissions(Permissions.READ_EXTERNAL_STORAGE, Permissions.WRITE_EXTERNAL_STORAGE) .rationale("自动备份需要存储权限") .onGranted((requestCode) -> { - RxBus.get().post(RxBusTag.AUTO_BACKUP, true); + return Unit.INSTANCE; }) .request(); - super.finish(); } @Override diff --git a/app/src/main/java/com/kunfei/bookshelf/view/fragment/WebDavSettingsFragment.java b/app/src/main/java/com/kunfei/bookshelf/view/fragment/WebDavSettingsFragment.java index 7f0aab7791..560eb48c98 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/fragment/WebDavSettingsFragment.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/fragment/WebDavSettingsFragment.java @@ -9,38 +9,16 @@ import android.preference.PreferenceFragment; import android.preference.PreferenceScreen; import android.text.TextUtils; -import android.widget.Toast; -import androidx.appcompat.app.AlertDialog; - -import com.hwangjr.rxbus.RxBus; -import com.kunfei.bookshelf.MApplication; import com.kunfei.bookshelf.R; -import com.kunfei.bookshelf.constant.RxBusTag; -import com.kunfei.bookshelf.help.DataRestore; import com.kunfei.bookshelf.help.FileHelp; import com.kunfei.bookshelf.help.ProcessTextHelp; -import com.kunfei.bookshelf.help.WebDavHelp; -import com.kunfei.bookshelf.help.permission.Permissions; -import com.kunfei.bookshelf.help.permission.PermissionsCompat; -import com.kunfei.bookshelf.utils.FileUtils; -import com.kunfei.bookshelf.utils.RxUtils; -import com.kunfei.bookshelf.utils.ZipUtils; -import com.kunfei.bookshelf.utils.theme.ATH; -import com.kunfei.bookshelf.utils.web_dav.WebDavFile; +import com.kunfei.bookshelf.help.storage.WebDavHelp; import com.kunfei.bookshelf.view.activity.SettingActivity; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; import java.util.Objects; -import io.reactivex.Single; -import io.reactivex.SingleObserver; -import io.reactivex.SingleOnSubscribe; import io.reactivex.disposables.CompositeDisposable; -import io.reactivex.disposables.Disposable; -import kotlin.Unit; import static com.kunfei.bookshelf.constant.AppConstant.DEFAULT_WEB_DAV_URL; @@ -132,20 +110,15 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin @Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { if (preference.getKey().equals("web_dav_restore")) { - if (!WebDavHelp.initWebDav()) - return super.onPreferenceTreeClick(preferenceScreen, preference); - new PermissionsCompat.Builder(settingActivity) - .addPermissions(Permissions.READ_EXTERNAL_STORAGE, Permissions.WRITE_EXTERNAL_STORAGE) - .rationale(R.string.backup_permission) - .onGranted((requestCode) -> { - showRestoreFiles(); - return Unit.INSTANCE; - }) - .request(); + restore(); } return super.onPreferenceTreeClick(preferenceScreen, preference); } + private void restore() { + WebDavHelp.INSTANCE.showRestoreDialog(getActivity()); + } + @Override public void onDestroy() { compositeDisposable.dispose(); @@ -157,72 +130,4 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); } - public void showRestoreFiles() { - Single.create((SingleOnSubscribe) emitter -> { - List webDavFiles = new WebDavFile(WebDavHelp.getWebDavUrl() + "YueDu/").listFiles(); - Collections.reverse(webDavFiles); - List fileNames = new ArrayList<>(); - for (int i = 0; i < Math.min(webDavFiles.size(), 10); i++) { - fileNames.add(webDavFiles.get(i).getDisplayName()); - } - String[] strings = fileNames.toArray(new String[0]); - emitter.onSuccess(strings); - }).compose(RxUtils::toSimpleSingle) - .subscribe(new SingleObserver() { - @Override - public void onSubscribe(Disposable d) { - compositeDisposable.add(d); - } - - @Override - public void onSuccess(String[] strings) { - if (strings.length > 0) { - AlertDialog dialog = new AlertDialog.Builder(settingActivity) - .setTitle("选择恢复文件") - .setSingleChoiceItems(strings, 0, (dialogInterface, i) -> { - restore(WebDavHelp.getWebDavUrl() + "YueDu/" + strings[i]); - dialogInterface.dismiss(); - }) - .create(); - dialog.show(); - ATH.setAlertDialogTint(dialog); - } else { - Toast.makeText(MApplication.getInstance(), "没有找到备份", Toast.LENGTH_SHORT).show(); - } - } - - @Override - public void onError(Throwable e) { - Toast.makeText(MApplication.getInstance(), e.getLocalizedMessage(), Toast.LENGTH_SHORT).show(); - } - }); - } - - public void restore(String url) { - Single.create(emitter -> { - WebDavFile webDavFile = new WebDavFile(url); - String zipFilePath = FileHelp.getCachePath() + "/backup" + ".zip"; - webDavFile.download(zipFilePath, true); - ZipUtils.unzipFile(zipFilePath, FileUtils.getSdCardPath() + "/YueDu"); - DataRestore.getInstance().run(); - emitter.onSuccess(new Object()); - }).compose(RxUtils::toSimpleSingle) - .subscribe(new SingleObserver() { - @Override - public void onSubscribe(Disposable d) { - compositeDisposable.add(d); - } - - @Override - public void onSuccess(Object o) { - Toast.makeText(MApplication.getInstance(), "恢复完成", Toast.LENGTH_SHORT).show(); - RxBus.get().post(RxBusTag.RECREATE, true); - } - - @Override - public void onError(Throwable e) { - Toast.makeText(MApplication.getInstance(), e.getLocalizedMessage(), Toast.LENGTH_SHORT).show(); - } - }); - } } diff --git a/basemvplib/build.gradle b/basemvplib/build.gradle index 38a60ae30c..b4757af48a 100644 --- a/basemvplib/build.gradle +++ b/basemvplib/build.gradle @@ -41,6 +41,7 @@ dependencies { api 'com.hwangjr.rxbus:rxbus:2.0.1' //Retrofit + implementation 'com.squareup.okhttp3:logging-interceptor:4.1.0' api 'com.squareup.retrofit2:retrofit:2.6.1' api 'com.squareup.retrofit2:adapter-rxjava2:2.6.1' api 'com.squareup.retrofit2:converter-scalars:2.6.1' From 871a1a7adeeb1681c541b41dc834304cbad3be0b Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 22 Jan 2020 19:21:32 +0800 Subject: [PATCH 002/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../view/activity/ReadBookActivity.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadBookActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadBookActivity.java index 8ce9c479dd..51bf2edea7 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadBookActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadBookActivity.java @@ -54,6 +54,7 @@ import com.kunfei.bookshelf.help.ReadBookControl; import com.kunfei.bookshelf.help.permission.Permissions; import com.kunfei.bookshelf.help.permission.PermissionsCompat; +import com.kunfei.bookshelf.help.storage.Backup; import com.kunfei.bookshelf.model.ReplaceRuleManager; import com.kunfei.bookshelf.model.TxtChapterRuleManager; import com.kunfei.bookshelf.presenter.ReadBookPresenter; @@ -1930,14 +1931,19 @@ public void finish() { } private void backup() { - new PermissionsCompat.Builder(this) - .addPermissions(Permissions.READ_EXTERNAL_STORAGE, Permissions.WRITE_EXTERNAL_STORAGE) - .rationale("自动备份需要存储权限") - .onGranted((requestCode) -> { - - return Unit.INSTANCE; - }) - .request(); + String path = preferences.getString("backupPath", ""); + if (TextUtils.isEmpty(path)) { + new PermissionsCompat.Builder(this) + .addPermissions(Permissions.READ_EXTERNAL_STORAGE, Permissions.WRITE_EXTERNAL_STORAGE) + .rationale("自动备份需要存储权限") + .onGranted((requestCode) -> { + Backup.INSTANCE.backup(ReadBookActivity.this, null); + return Unit.INSTANCE; + }) + .request(); + } else { + Backup.INSTANCE.backup(this, Uri.parse(path)); + } } @Override From 5c8888d1ceb3fc71d78932fbd9753279f75489b0 Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 22 Jan 2020 19:27:55 +0800 Subject: [PATCH 003/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/values-zh-rTW/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/pref_settings.xml | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index fe46121246..4002b01650 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -267,6 +267,7 @@ 自動跳轉最近閱讀 替換範圍,選填書名或者源名 分組 + 备份路徑 內容緩存路徑 系統檔案選擇器 新版本 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 240e9f69cc..020687ae0e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -267,6 +267,7 @@ 自动跳转最近阅读 替换范围,选填书名或者源名 分组 + 备份路径 内容缓存路径 系统文件选择器 新版本 diff --git a/app/src/main/res/xml/pref_settings.xml b/app/src/main/res/xml/pref_settings.xml index a66e66c0c5..8d8bc41bc4 100644 --- a/app/src/main/res/xml/pref_settings.xml +++ b/app/src/main/res/xml/pref_settings.xml @@ -53,6 +53,10 @@ android:key="replaceEnableDefault" android:title="默认启用替换净化" /> + + From 02632044c7cde1d4b844bccb88a84b6a013c36a1 Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 22 Jan 2020 19:42:45 +0800 Subject: [PATCH 004/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../view/fragment/SettingsFragment.java | 19 +++++++++++++++++++ app/src/main/res/xml/pref_settings.xml | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java b/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java index db5d367ad0..1f34eae020 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java @@ -3,6 +3,7 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.net.Uri; import android.os.Bundle; import android.preference.ListPreference; import android.preference.Preference; @@ -30,12 +31,15 @@ import kotlin.Unit; +import static android.app.Activity.RESULT_OK; + /** * Created by GKF on 2017/12/16. * 设置 */ public class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener { private SettingActivity settingActivity; + private final int backupSelectRequestCode = 23; @Override public void onCreate(Bundle savedInstanceState) { @@ -105,6 +109,16 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { if (preference.getKey().equals(getString(R.string.pk_download_path))) { selectDownloadPath(preference); + } else if (preference.getKey().equals("backupPath")) { + try { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + startActivityForResult(intent, backupSelectRequestCode); + } + } catch (Exception ignored) { + + } } else if (preference.getKey().equals("webDavSetting")) { WebDavSettingsFragment webDavSettingsFragment = new WebDavSettingsFragment(); getFragmentManager().beginTransaction().replace(R.id.settingsFrameLayout, webDavSettingsFragment, "webDavSettings").commit(); @@ -153,5 +167,10 @@ private void selectDownloadPath(Preference preference) { @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); + if (requestCode == backupSelectRequestCode && resultCode == RESULT_OK && data != null) { + Uri uri = data.getData(); + if (uri == null) return; + getPreferenceManager().getSharedPreferences().edit().putString("backupPath", uri.toString()).apply(); + } } } diff --git a/app/src/main/res/xml/pref_settings.xml b/app/src/main/res/xml/pref_settings.xml index 8d8bc41bc4..342fc93e04 100644 --- a/app/src/main/res/xml/pref_settings.xml +++ b/app/src/main/res/xml/pref_settings.xml @@ -54,7 +54,7 @@ android:title="默认启用替换净化" /> Date: Wed, 22 Jan 2020 20:16:42 +0800 Subject: [PATCH 005/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bookshelf/help/storage/WebDavHelp.kt | 5 +- .../bookshelf/view/activity/MainActivity.java | 52 ++++++++++++------- .../view/fragment/WebDavSettingsFragment.java | 20 ++++++- 3 files changed, 55 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt index 01dc842b22..48f6230674 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt @@ -36,7 +36,7 @@ object WebDavHelp { return false } - private fun getWebDavFileNames(): ArrayList { + fun getWebDavFileNames(): ArrayList { val url = getWebDavUrl() val names = arrayListOf() if (!url.isNullOrBlank() && initWebDav()) { @@ -51,8 +51,7 @@ object WebDavHelp { return names } - fun showRestoreDialog(context: Context): Boolean { - val names = getWebDavFileNames() + fun showRestoreDialog(context: Context, names: ArrayList): Boolean { return if (names.isNotEmpty()) { context.selector(title = "选择恢复文件", items = names) { _, index -> if (index in 0 until names.size) { diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java index 406f61e5a5..5e5bb298eb 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java @@ -44,6 +44,7 @@ import com.kunfei.bookshelf.MApplication; import com.kunfei.bookshelf.R; import com.kunfei.bookshelf.base.BaseTabActivity; +import com.kunfei.bookshelf.base.observer.MySingleObserver; import com.kunfei.bookshelf.constant.RxBusTag; import com.kunfei.bookshelf.help.FileHelp; import com.kunfei.bookshelf.help.ProcessTextHelp; @@ -66,12 +67,17 @@ import com.kunfei.bookshelf.widget.modialog.InputDialog; import com.kunfei.bookshelf.widget.modialog.MoDialogHUD; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import butterknife.BindView; import butterknife.ButterKnife; +import io.reactivex.Single; +import io.reactivex.SingleOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; import kotlin.Unit; import static com.kunfei.bookshelf.utils.NetworkUtils.isNetWorkAvailable; @@ -645,24 +651,34 @@ private void selectBackupFolder() { * 恢复 */ private void restore() { - if (!WebDavHelp.INSTANCE.showRestoreDialog(this)) { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { - String path = getBackupPath(); - if (TextUtils.isEmpty(path)) { - selectRestoreFolder(); - } else { - Restore.INSTANCE.restore(this, Uri.parse(path)); - } - } else { - new PermissionsCompat.Builder(this) - .addPermissions(Permissions.READ_EXTERNAL_STORAGE, Permissions.WRITE_EXTERNAL_STORAGE) - .rationale(R.string.restore_permission) - .onGranted((requestCode) -> { - Restore.INSTANCE.restore(Backup.INSTANCE.getDefaultPath()); - return Unit.INSTANCE; - }).request(); - } - } + Single.create((SingleOnSubscribe>) emitter -> { + emitter.onSuccess(WebDavHelp.INSTANCE.getWebDavFileNames()); + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new MySingleObserver>() { + @Override + public void onSuccess(ArrayList strings) { + if (WebDavHelp.INSTANCE.showRestoreDialog(MainActivity.this, strings)) { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + String path = getBackupPath(); + if (TextUtils.isEmpty(path)) { + selectRestoreFolder(); + } else { + Restore.INSTANCE.restore(MainActivity.this, Uri.parse(path)); + } + } else { + new PermissionsCompat.Builder(MainActivity.this) + .addPermissions(Permissions.READ_EXTERNAL_STORAGE, Permissions.WRITE_EXTERNAL_STORAGE) + .rationale(R.string.restore_permission) + .onGranted((requestCode) -> { + Restore.INSTANCE.restore(Backup.INSTANCE.getDefaultPath()); + return Unit.INSTANCE; + }).request(); + } + } + } + }); + } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) diff --git a/app/src/main/java/com/kunfei/bookshelf/view/fragment/WebDavSettingsFragment.java b/app/src/main/java/com/kunfei/bookshelf/view/fragment/WebDavSettingsFragment.java index 560eb48c98..d461f070d9 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/fragment/WebDavSettingsFragment.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/fragment/WebDavSettingsFragment.java @@ -9,16 +9,23 @@ import android.preference.PreferenceFragment; import android.preference.PreferenceScreen; import android.text.TextUtils; +import android.widget.Toast; import com.kunfei.bookshelf.R; +import com.kunfei.bookshelf.base.observer.MySingleObserver; import com.kunfei.bookshelf.help.FileHelp; import com.kunfei.bookshelf.help.ProcessTextHelp; import com.kunfei.bookshelf.help.storage.WebDavHelp; import com.kunfei.bookshelf.view.activity.SettingActivity; +import java.util.ArrayList; import java.util.Objects; +import io.reactivex.Single; +import io.reactivex.SingleOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; import static com.kunfei.bookshelf.constant.AppConstant.DEFAULT_WEB_DAV_URL; @@ -116,7 +123,18 @@ public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preferen } private void restore() { - WebDavHelp.INSTANCE.showRestoreDialog(getActivity()); + Single.create((SingleOnSubscribe>) emitter -> { + emitter.onSuccess(WebDavHelp.INSTANCE.getWebDavFileNames()); + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new MySingleObserver>() { + @Override + public void onSuccess(ArrayList strings) { + if (!WebDavHelp.INSTANCE.showRestoreDialog(getActivity(), strings)) { + Toast.makeText(getActivity(), "没有备份", Toast.LENGTH_SHORT).show(); + } + } + }); } @Override From 51340b77655cb9a1b7e851ef62c3b98c8e79f626 Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 22 Jan 2020 20:18:39 +0800 Subject: [PATCH 006/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index f69e40c34a..2c18434b85 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -5,6 +5,7 @@ **2020/01/21** * 将规则解析后得到的字符串反转义(unescape) * 在正文规则使用all可查看源码,例:`tag.body@all` +* 添加备份时选择备份文件夹--适配安卓10 **2020/01/09** * 修复按键码为0时翻页的bug From 94eff8dc403ceb9351622c9daf6c9cd49e233c9e Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 22 Jan 2020 20:24:05 +0800 Subject: [PATCH 007/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kunfei/bookshelf/base/BaseModelImpl.java | 17 +++++++++-------- .../com/kunfei/bookshelf/utils/webdav/WebDav.kt | 6 +++--- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/base/BaseModelImpl.java b/app/src/main/java/com/kunfei/bookshelf/base/BaseModelImpl.java index a9bc0302ed..0236998f5a 100644 --- a/app/src/main/java/com/kunfei/bookshelf/base/BaseModelImpl.java +++ b/app/src/main/java/com/kunfei/bookshelf/base/BaseModelImpl.java @@ -32,7 +32,7 @@ import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; public class BaseModelImpl { - private static OkHttpClient.Builder clientBuilder; + private static OkHttpClient httpClient; public static BaseModelImpl getInstance() { return new BaseModelImpl(); @@ -66,7 +66,7 @@ public Retrofit getRetrofitString(String url) { .addConverterFactory(EncodeConverter.create()) //增加返回值为Observable的支持 .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) - .client(getClientBuilder().build()) + .client(getClient()) .build(); } @@ -76,13 +76,13 @@ public Retrofit getRetrofitString(String url, String encode) { .addConverterFactory(EncodeConverter.create(encode)) //增加返回值为Observable的支持 .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) - .client(getClientBuilder().build()) + .client(getClient()) .build(); } - public static OkHttpClient.Builder getClientBuilder() { - if (clientBuilder == null) { - clientBuilder = new OkHttpClient.Builder() + synchronized public static OkHttpClient getClient() { + if (httpClient == null) { + httpClient = new OkHttpClient.Builder() .connectTimeout(15, TimeUnit.SECONDS) .writeTimeout(15, TimeUnit.SECONDS) .readTimeout(15, TimeUnit.SECONDS) @@ -90,9 +90,10 @@ public static OkHttpClient.Builder getClientBuilder() { .sslSocketFactory(SSLSocketClient.getSSLSocketFactory(), SSLSocketClient.createTrustAllManager()) .hostnameVerifier(SSLSocketClient.getHostnameVerifier()) .protocols(Collections.singletonList(Protocol.HTTP_1_1)) - .addInterceptor(getHeaderInterceptor()); + .addInterceptor(getHeaderInterceptor()) + .build(); } - return clientBuilder; + return httpClient; } private static Interceptor getHeaderInterceptor() { diff --git a/app/src/main/java/com/kunfei/bookshelf/utils/webdav/WebDav.kt b/app/src/main/java/com/kunfei/bookshelf/utils/webdav/WebDav.kt index 368c76efb4..284ee67b2a 100644 --- a/app/src/main/java/com/kunfei/bookshelf/utils/webdav/WebDav.kt +++ b/app/src/main/java/com/kunfei/bookshelf/utils/webdav/WebDav.kt @@ -130,7 +130,7 @@ constructor(urlStr: String) { ) } request.header("Depth", if (depth < 0) "infinity" else depth.toString()) - return BaseModelImpl.getClientBuilder().build().newCall(request.build()).execute() + return BaseModelImpl.getClient().newCall(request.build()).execute() } return null } @@ -225,7 +225,7 @@ constructor(urlStr: String) { Credentials.basic(it.user, it.pass) ) } - val response = BaseModelImpl.getClientBuilder().build().newCall(requestBuilder.build()).execute() + val response = BaseModelImpl.getClient().newCall(requestBuilder.build()).execute() return response.isSuccessful } @@ -236,7 +236,7 @@ constructor(urlStr: String) { request.header("Authorization", Credentials.basic(it.user, it.pass)) } try { - return BaseModelImpl.getClientBuilder().build().newCall(request.build()).execute().body?.byteStream() + return BaseModelImpl.getClient().newCall(request.build()).execute().body?.byteStream() } catch (e: IOException) { e.printStackTrace() } catch (e: IllegalArgumentException) { From 44e17b5cba47cdcd68a5edde3b063c65531c4626 Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 22 Jan 2020 20:38:45 +0800 Subject: [PATCH 008/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/kunfei/bookshelf/help/storage/Backup.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt index 808b8039d8..1c603898d4 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt @@ -2,9 +2,12 @@ package com.kunfei.bookshelf.help.storage import android.content.Context import android.net.Uri +import android.widget.Toast import androidx.documentfile.provider.DocumentFile import com.kunfei.bookshelf.DbHelper import com.kunfei.bookshelf.MApplication +import com.kunfei.bookshelf.R +import com.kunfei.bookshelf.base.observer.MySingleObserver import com.kunfei.bookshelf.help.BookshelfHelp import com.kunfei.bookshelf.help.FileHelp import com.kunfei.bookshelf.model.BookSourceManager @@ -96,7 +99,11 @@ object Backup { e.onSuccess(true) }).subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe() + .subscribe(object : MySingleObserver() { + override fun onSuccess(t: Boolean) { + Toast.makeText(context, R.string.backup_success, Toast.LENGTH_SHORT).show() + } + }) } private fun copyBackup(context: Context, uri: Uri) { From 61f3eececfcd96b63338ad006bc8e68d6b152feb Mon Sep 17 00:00:00 2001 From: kunfei Date: Thu, 23 Jan 2020 07:32:28 +0800 Subject: [PATCH 009/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bookshelf/help/storage/WebDavHelp.kt | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt index 48f6230674..e5a7fa6221 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt @@ -1,12 +1,19 @@ package com.kunfei.bookshelf.help.storage import android.content.Context +import android.widget.Toast import com.kunfei.bookshelf.MApplication +import com.kunfei.bookshelf.R +import com.kunfei.bookshelf.base.observer.MySingleObserver import com.kunfei.bookshelf.constant.AppConstant import com.kunfei.bookshelf.help.FileHelp import com.kunfei.bookshelf.utils.ZipUtils import com.kunfei.bookshelf.utils.webdav.WebDav import com.kunfei.bookshelf.utils.webdav.http.HttpAuth +import io.reactivex.Single +import io.reactivex.SingleOnSubscribe +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.schedulers.Schedulers import org.jetbrains.anko.selector import java.io.File import java.text.SimpleDateFormat @@ -65,13 +72,22 @@ object WebDavHelp { } private fun restoreWebDav(name: String) { - getWebDavUrl()?.let { - val file = WebDav(it + "YueDu/" + name) - file.downloadTo(zipFilePath, true) - @Suppress("BlockingMethodInNonBlockingContext") - ZipUtils.unzipFile(zipFilePath, unzipFilesPath) - Restore.restore(unzipFilesPath) - } + Single.create(SingleOnSubscribe { e -> + getWebDavUrl()?.let { + val file = WebDav(it + "YueDu/" + name) + file.downloadTo(zipFilePath, true) + @Suppress("BlockingMethodInNonBlockingContext") + ZipUtils.unzipFile(zipFilePath, unzipFilesPath) + Restore.restore(unzipFilesPath) + } + e.onSuccess(true) + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : MySingleObserver() { + override fun onSuccess(t: Boolean) { + Toast.makeText(MApplication.getInstance(), R.string.restore_success, Toast.LENGTH_SHORT).show() + } + }) } fun backUpWebDav(path: String) { From be3b8845a51f5e2f7dac044509e4f37490d6e12a Mon Sep 17 00:00:00 2001 From: kunfei Date: Thu, 23 Jan 2020 07:39:05 +0800 Subject: [PATCH 010/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kunfei/bookshelf/help/ReadBookControl.java | 2 +- .../com/kunfei/bookshelf/help/storage/Restore.kt | 12 ++++++++++++ .../com/kunfei/bookshelf/help/storage/WebDavHelp.kt | 3 +++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/ReadBookControl.java b/app/src/main/java/com/kunfei/bookshelf/help/ReadBookControl.java index 3ba5d4315b..1d03558fbf 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/ReadBookControl.java +++ b/app/src/main/java/com/kunfei/bookshelf/help/ReadBookControl.java @@ -91,7 +91,7 @@ private ReadBookControl() { updateReaderSettings(); } - void updateReaderSettings() { + public void updateReaderSettings() { this.hideStatusBar = preferences.getBoolean("hide_status_bar", false); this.hideNavigationBar = preferences.getBoolean("hide_navigation_bar", false); this.indent = preferences.getInt("indent", 2); diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt index 751ead8118..fa1a5d074c 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt @@ -5,8 +5,11 @@ import android.net.Uri import androidx.documentfile.provider.DocumentFile import com.kunfei.bookshelf.DbHelper import com.kunfei.bookshelf.MApplication +import com.kunfei.bookshelf.R import com.kunfei.bookshelf.bean.* import com.kunfei.bookshelf.help.FileHelp +import com.kunfei.bookshelf.help.LauncherIcon +import com.kunfei.bookshelf.help.ReadBookControl import com.kunfei.bookshelf.model.BookSourceManager import com.kunfei.bookshelf.model.ReplaceRuleManager import com.kunfei.bookshelf.model.TxtChapterRuleManager @@ -82,6 +85,8 @@ object Restore { } catch (e: Exception) { e.printStackTrace() } + var donateHb = MApplication.getConfigPreferences().getLong("DonateHb", 0) + donateHb = if (donateHb > System.currentTimeMillis()) 0 else donateHb Preferences.getSharedPreferences(MApplication.getInstance(), path, "config")?.all?.map { val edit = MApplication.getConfigPreferences().edit() when (val value = it.value) { @@ -92,6 +97,13 @@ object Restore { is String -> edit.putString(it.key, value) else -> Unit } + edit.putLong("DonateHb", donateHb) + edit.putInt("versionCode", MApplication.getVersionCode()) + edit.apply() + LauncherIcon.ChangeIcon(MApplication.getConfigPreferences().getString("launcher_icon", MApplication.getInstance().getString(R.string.icon_main))) + ReadBookControl.getInstance().updateReaderSettings() + MApplication.getInstance().upThemeStore() + MApplication.getInstance().initNightTheme() edit.commit() } } diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt index e5a7fa6221..993c58c752 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt @@ -2,10 +2,12 @@ package com.kunfei.bookshelf.help.storage import android.content.Context import android.widget.Toast +import com.hwangjr.rxbus.RxBus import com.kunfei.bookshelf.MApplication import com.kunfei.bookshelf.R import com.kunfei.bookshelf.base.observer.MySingleObserver import com.kunfei.bookshelf.constant.AppConstant +import com.kunfei.bookshelf.constant.RxBusTag import com.kunfei.bookshelf.help.FileHelp import com.kunfei.bookshelf.utils.ZipUtils import com.kunfei.bookshelf.utils.webdav.WebDav @@ -85,6 +87,7 @@ object WebDavHelp { .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : MySingleObserver() { override fun onSuccess(t: Boolean) { + RxBus.get().post(RxBusTag.RECREATE, true) Toast.makeText(MApplication.getInstance(), R.string.restore_success, Toast.LENGTH_SHORT).show() } }) From 8b7e6dffcdf9c7dcfe06400d950b9686485a077e Mon Sep 17 00:00:00 2001 From: kunfei Date: Thu, 23 Jan 2020 11:44:34 +0800 Subject: [PATCH 011/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kunfei/bookshelf/help/storage/Backup.kt | 10 ++++++---- .../bookshelf/view/activity/MainActivity.java | 13 ++++++++++--- .../bookshelf/view/activity/ReadBookActivity.java | 4 ++-- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt index 1c603898d4..21ba47b93b 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt @@ -2,11 +2,9 @@ package com.kunfei.bookshelf.help.storage import android.content.Context import android.net.Uri -import android.widget.Toast import androidx.documentfile.provider.DocumentFile import com.kunfei.bookshelf.DbHelper import com.kunfei.bookshelf.MApplication -import com.kunfei.bookshelf.R import com.kunfei.bookshelf.base.observer.MySingleObserver import com.kunfei.bookshelf.help.BookshelfHelp import com.kunfei.bookshelf.help.FileHelp @@ -42,7 +40,7 @@ object Backup { ) } - fun backup(context: Context, uri: Uri?) { + fun backup(context: Context, uri: Uri?, callBack: CallBack?) { Single.create(SingleOnSubscribe { e -> BookshelfHelp.getAllBook().let { if (it.isNotEmpty()) { @@ -101,7 +99,7 @@ object Backup { .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : MySingleObserver() { override fun onSuccess(t: Boolean) { - Toast.makeText(context, R.string.backup_success, Toast.LENGTH_SHORT).show() + callBack?.backupSuccess() } }) } @@ -127,4 +125,8 @@ object Backup { e.printStackTrace() } } + + interface CallBack { + fun backupSuccess() + } } \ No newline at end of file diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java index 5e5bb298eb..ac25b35724 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java @@ -82,7 +82,9 @@ import static com.kunfei.bookshelf.utils.NetworkUtils.isNetWorkAvailable; -public class MainActivity extends BaseTabActivity implements MainContract.View, BookListFragment.CallbackValue { +public class MainActivity extends BaseTabActivity implements MainContract.View, + BookListFragment.CallbackValue, + Backup.CallBack { private final int requestSource = 14; private final int backupSelectRequestCode = 23; private final int restoreSelectRequestCode = 33; @@ -611,7 +613,7 @@ private void backup() { if (TextUtils.isEmpty(path)) { selectBackupFolder(); } else { - Backup.INSTANCE.backup(this, Uri.parse(path)); + Backup.INSTANCE.backup(this, Uri.parse(path), MainActivity.this); } } else { backupOld(); @@ -627,7 +629,7 @@ private void backupOld() { .setTitle(R.string.backup_confirmation) .setMessage(R.string.backup_message) .setPositiveButton(R.string.ok, (dialog, which) -> - Backup.INSTANCE.backup(MainActivity.this, null) + Backup.INSTANCE.backup(MainActivity.this, null, MainActivity.this) ) .setNegativeButton(R.string.cancel, null) .show(); @@ -756,6 +758,11 @@ public boolean onKeyDown(int keyCode, KeyEvent event) { } } + @Override + public void backupSuccess() { + toast(R.string.backup_success); + } + /** * 退出 */ diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadBookActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadBookActivity.java index 51bf2edea7..ea7060d3a4 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadBookActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadBookActivity.java @@ -1937,12 +1937,12 @@ private void backup() { .addPermissions(Permissions.READ_EXTERNAL_STORAGE, Permissions.WRITE_EXTERNAL_STORAGE) .rationale("自动备份需要存储权限") .onGranted((requestCode) -> { - Backup.INSTANCE.backup(ReadBookActivity.this, null); + Backup.INSTANCE.backup(ReadBookActivity.this, null, null); return Unit.INSTANCE; }) .request(); } else { - Backup.INSTANCE.backup(this, Uri.parse(path)); + Backup.INSTANCE.backup(this, Uri.parse(path), null); } } From c72c27d60bdb6675c8e3cd84fe95032410068904 Mon Sep 17 00:00:00 2001 From: kunfei Date: Thu, 23 Jan 2020 12:24:35 +0800 Subject: [PATCH 012/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bookshelf/view/fragment/SettingsFragment.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java b/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java index 1f34eae020..88b361b3c8 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java @@ -1,6 +1,5 @@ package com.kunfei.bookshelf.view.fragment; -import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; @@ -58,6 +57,7 @@ public void onCreate(Bundle savedInstanceState) { addPreferencesFromResource(R.xml.pref_settings); bindPreferenceSummaryToValue(findPreference(getString(R.string.pk_bookshelf_px))); bindPreferenceSummaryToValue(findPreference(getString(R.string.pk_download_path))); + bindPreferenceSummaryToValue(findPreference("backupPath")); } private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = (Preference preference, Object value) -> { @@ -75,11 +75,14 @@ public void onCreate(Bundle savedInstanceState) { return true; }; - private static void bindPreferenceSummaryToValue(Preference preference) { + private void bindPreferenceSummaryToValue(Preference preference) { // Set the listener to watch for value changes. preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener); - sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, - preference.getContext().getSharedPreferences("CONFIG", Context.MODE_PRIVATE).getString(preference.getKey(), "")); + sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, getPrefValue(preference.getKey())); + } + + private String getPrefValue(String key) { + return MApplication.getConfigPreferences().getString(key, ""); } @Override From 8888c949ae0ef50f76450eedfa5f289d4653e4a5 Mon Sep 17 00:00:00 2001 From: kunfei Date: Thu, 23 Jan 2020 12:43:34 +0800 Subject: [PATCH 013/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kunfei/bookshelf/utils/webdav/WebDav.kt | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/utils/webdav/WebDav.kt b/app/src/main/java/com/kunfei/bookshelf/utils/webdav/WebDav.kt index 284ee67b2a..30078c049c 100644 --- a/app/src/main/java/com/kunfei/bookshelf/utils/webdav/WebDav.kt +++ b/app/src/main/java/com/kunfei/bookshelf/utils/webdav/WebDav.kt @@ -23,12 +23,18 @@ class WebDav @Throws(MalformedURLException::class) constructor(urlStr: String) { companion object { // 指定返回哪些属性 - private const val DIR = "\n" + - "\n" + - "\n" + - "\n\n\n\n\n%s" + - "\n" + - "" + private const val DIR = + """ + + + + + + + + %s + + """ } private val url: URL = URL(null, urlStr, Handler) From ce4dc566d07d221ce2a7eca85738f5e01ca909b7 Mon Sep 17 00:00:00 2001 From: kunfei Date: Thu, 23 Jan 2020 13:00:21 +0800 Subject: [PATCH 014/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kunfei/bookshelf/view/activity/MainActivity.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java index ac25b35724..d184414ea1 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java @@ -660,13 +660,14 @@ private void restore() { .subscribe(new MySingleObserver>() { @Override public void onSuccess(ArrayList strings) { - if (WebDavHelp.INSTANCE.showRestoreDialog(MainActivity.this, strings)) { + if (!WebDavHelp.INSTANCE.showRestoreDialog(MainActivity.this, strings)) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { String path = getBackupPath(); if (TextUtils.isEmpty(path)) { selectRestoreFolder(); } else { Restore.INSTANCE.restore(MainActivity.this, Uri.parse(path)); + recreate(); } } else { new PermissionsCompat.Builder(MainActivity.this) @@ -674,6 +675,7 @@ public void onSuccess(ArrayList strings) { .rationale(R.string.restore_permission) .onGranted((requestCode) -> { Restore.INSTANCE.restore(Backup.INSTANCE.getDefaultPath()); + recreate(); return Unit.INSTANCE; }).request(); } @@ -814,7 +816,8 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (uri == null) return; getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); preferences.edit().putString("backupPath", uri.toString()).apply(); - restore(); + Restore.INSTANCE.restore(this, uri); + recreate(); } break; } From dc2c2d12b284fe3bde87cd43b430ccfad8ce1e01 Mon Sep 17 00:00:00 2001 From: kunfei Date: Thu, 23 Jan 2020 13:09:56 +0800 Subject: [PATCH 015/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bookshelf/view/activity/MainActivity.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java index d184414ea1..e2ad76f805 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java @@ -666,7 +666,7 @@ public void onSuccess(ArrayList strings) { if (TextUtils.isEmpty(path)) { selectRestoreFolder(); } else { - Restore.INSTANCE.restore(MainActivity.this, Uri.parse(path)); + restore(Uri.parse(path)); recreate(); } } else { @@ -685,6 +685,20 @@ public void onSuccess(ArrayList strings) { } + private void restore(Uri uri) { + Single.create((SingleOnSubscribe) e -> { + Restore.INSTANCE.restore(this, uri); + e.onSuccess(true); + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new MySingleObserver() { + @Override + public void onSuccess(Boolean t) { + recreate(); + } + }); + } + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private void selectRestoreFolder() { try { @@ -816,8 +830,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (uri == null) return; getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); preferences.edit().putString("backupPath", uri.toString()).apply(); - Restore.INSTANCE.restore(this, uri); - recreate(); + restore(uri); } break; } From 775118daa2e9393d7a21dfcf9e1d5d7cbc20ae3f Mon Sep 17 00:00:00 2001 From: kunfei Date: Thu, 23 Jan 2020 13:13:00 +0800 Subject: [PATCH 016/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 2c18434b85..8a8cadbfee 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -2,6 +2,9 @@ ### 关注公众号[开源阅读软件]点击广告可支持作者! ### 捐赠里点击红包搜索码可开启高级功能! +**2020/01/23** +* 修复备份bug + **2020/01/21** * 将规则解析后得到的字符串反转义(unescape) * 在正文规则使用all可查看源码,例:`tag.body@all` From 2bd50b324de395c694f5df7d40ff431b77be32ee Mon Sep 17 00:00:00 2001 From: kunfei Date: Thu, 23 Jan 2020 18:12:05 +0800 Subject: [PATCH 017/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 5 +- .../view/activity/WelcomeBookActivity.java | 88 +++++++++++++++++++ 2 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 430b53a888..0d58955cda 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,9 +41,8 @@ android:name="android.app.shortcuts" android:resource="@xml/shortcuts" /> - - + diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java new file mode 100644 index 0000000000..46c6181a9e --- /dev/null +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java @@ -0,0 +1,88 @@ +//Copyright (c) 2017. 章钦豪. All rights reserved. +package com.kunfei.bookshelf.view.activity; + +import android.animation.Animator; +import android.animation.ValueAnimator; +import android.content.Intent; +import android.widget.ImageView; + +import com.kunfei.basemvplib.impl.IPresenter; +import com.kunfei.bookshelf.R; +import com.kunfei.bookshelf.base.MBaseActivity; +import com.kunfei.bookshelf.presenter.ReadBookPresenter; +import com.kunfei.bookshelf.utils.theme.ThemeStore; + +import butterknife.BindView; +import butterknife.ButterKnife; + +public class WelcomeBookActivity extends MBaseActivity { + + @BindView(R.id.iv_bg) + ImageView ivBg; + + @Override + protected IPresenter initInjector() { + return null; + } + + @Override + protected void onCreateActivity() { + // 避免从桌面启动程序后,会重新实例化入口类的activity + if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { + finish(); + return; + } + setContentView(R.layout.activity_welcome); + ButterKnife.bind(this); + ivBg.setColorFilter(ThemeStore.accentColor(this)); + ValueAnimator welAnimator = ValueAnimator.ofFloat(1f, 0f).setDuration(800); + welAnimator.setStartDelay(500); + welAnimator.addUpdateListener(animation -> { + float alpha = (Float) animation.getAnimatedValue(); + ivBg.setAlpha(alpha); + }); + welAnimator.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + if (preferences.getBoolean(getString(R.string.pk_default_read), false)) { + startReadActivity(); + } else { + startBookshelfActivity(); + } + finish(); + } + + @Override + public void onAnimationEnd(Animator animation) { + + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); + welAnimator.start(); + } + + private void startBookshelfActivity() { + startActivityByAnim(new Intent(this, MainActivity.class), android.R.anim.fade_in, android.R.anim.fade_out); + } + + private void startReadActivity() { + Intent intent = new Intent(this, ReadBookActivity.class); + intent.putExtra("openFrom", ReadBookPresenter.OPEN_FROM_APP); + startActivity(intent); + } + + @Override + protected void initData() { + + } + +} From ca19c5507cb34db56e2edadfc5a15e2c51fde862 Mon Sep 17 00:00:00 2001 From: kunfei Date: Thu, 23 Jan 2020 18:13:37 +0800 Subject: [PATCH 018/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../view/activity/WelcomeBookActivity.java | 84 +------------------ 1 file changed, 1 insertion(+), 83 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java index 46c6181a9e..005f6c44ff 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java @@ -1,88 +1,6 @@ //Copyright (c) 2017. 章钦豪. All rights reserved. package com.kunfei.bookshelf.view.activity; -import android.animation.Animator; -import android.animation.ValueAnimator; -import android.content.Intent; -import android.widget.ImageView; - -import com.kunfei.basemvplib.impl.IPresenter; -import com.kunfei.bookshelf.R; -import com.kunfei.bookshelf.base.MBaseActivity; -import com.kunfei.bookshelf.presenter.ReadBookPresenter; -import com.kunfei.bookshelf.utils.theme.ThemeStore; - -import butterknife.BindView; -import butterknife.ButterKnife; - -public class WelcomeBookActivity extends MBaseActivity { - - @BindView(R.id.iv_bg) - ImageView ivBg; - - @Override - protected IPresenter initInjector() { - return null; - } - - @Override - protected void onCreateActivity() { - // 避免从桌面启动程序后,会重新实例化入口类的activity - if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { - finish(); - return; - } - setContentView(R.layout.activity_welcome); - ButterKnife.bind(this); - ivBg.setColorFilter(ThemeStore.accentColor(this)); - ValueAnimator welAnimator = ValueAnimator.ofFloat(1f, 0f).setDuration(800); - welAnimator.setStartDelay(500); - welAnimator.addUpdateListener(animation -> { - float alpha = (Float) animation.getAnimatedValue(); - ivBg.setAlpha(alpha); - }); - welAnimator.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - if (preferences.getBoolean(getString(R.string.pk_default_read), false)) { - startReadActivity(); - } else { - startBookshelfActivity(); - } - finish(); - } - - @Override - public void onAnimationEnd(Animator animation) { - - } - - @Override - public void onAnimationCancel(Animator animation) { - - } - - @Override - public void onAnimationRepeat(Animator animation) { - - } - }); - welAnimator.start(); - } - - private void startBookshelfActivity() { - startActivityByAnim(new Intent(this, MainActivity.class), android.R.anim.fade_in, android.R.anim.fade_out); - } - - private void startReadActivity() { - Intent intent = new Intent(this, ReadBookActivity.class); - intent.putExtra("openFrom", ReadBookPresenter.OPEN_FROM_APP); - startActivity(intent); - } - - @Override - protected void initData() { - - } +public class WelcomeBookActivity extends WelcomeActivity { } From 588ba8d10dd00285fb35f795adc01a22ab20dbc4 Mon Sep 17 00:00:00 2001 From: kunfei Date: Thu, 23 Jan 2020 21:27:52 +0800 Subject: [PATCH 019/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/kunfei/bookshelf/view/activity/MainActivity.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java index e2ad76f805..7dc8c8157e 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java @@ -667,7 +667,6 @@ public void onSuccess(ArrayList strings) { selectRestoreFolder(); } else { restore(Uri.parse(path)); - recreate(); } } else { new PermissionsCompat.Builder(MainActivity.this) From 5b1d4f0df27dbc2e163a9a97d03e1972160b9a69 Mon Sep 17 00:00:00 2001 From: kunfei Date: Fri, 24 Jan 2020 08:07:51 +0800 Subject: [PATCH 020/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bookshelf/view/activity/MainActivity.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java index 7dc8c8157e..cee8b1185b 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java @@ -673,8 +673,7 @@ public void onSuccess(ArrayList strings) { .addPermissions(Permissions.READ_EXTERNAL_STORAGE, Permissions.WRITE_EXTERNAL_STORAGE) .rationale(R.string.restore_permission) .onGranted((requestCode) -> { - Restore.INSTANCE.restore(Backup.INSTANCE.getDefaultPath()); - recreate(); + restoreOld(); return Unit.INSTANCE; }).request(); } @@ -698,6 +697,20 @@ public void onSuccess(Boolean t) { }); } + private void restoreOld() { + Single.create((SingleOnSubscribe) e -> { + Restore.INSTANCE.restore(Backup.INSTANCE.getDefaultPath()); + e.onSuccess(true); + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new MySingleObserver() { + @Override + public void onSuccess(Boolean t) { + recreate(); + } + }); + } + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private void selectRestoreFolder() { try { @@ -705,7 +718,7 @@ private void selectRestoreFolder() { intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivityForResult(intent, restoreSelectRequestCode); } catch (Exception e) { - Restore.INSTANCE.restore(Backup.INSTANCE.getDefaultPath()); + restoreOld(); } } From 48fcef3003352c0fc86f4b6affec25f82341a4ae Mon Sep 17 00:00:00 2001 From: kunfei Date: Fri, 24 Jan 2020 08:08:55 +0800 Subject: [PATCH 021/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 8a8cadbfee..f95c08f5f7 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -2,8 +2,9 @@ ### 关注公众号[开源阅读软件]点击广告可支持作者! ### 捐赠里点击红包搜索码可开启高级功能! -**2020/01/23** +**2020/01/24** * 修复备份bug +* 修复切换图标后不在后台显示的bug **2020/01/21** * 将规则解析后得到的字符串反转义(unescape) From dcdde8425a2595443f7784e45e5a4692912c42c1 Mon Sep 17 00:00:00 2001 From: Mupceet Date: Tue, 28 Jan 2020 11:29:28 +0800 Subject: [PATCH 022/105] fix(notification): fix invalid format of WebService URL in traditonal --- app/src/main/res/values-zh-rTW/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 4002b01650..194cd6bef1 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -43,7 +43,7 @@ 重試 web服務 web編輯書源 - HTTP://%S:%d + http://%s:%d 離線下載 離線下載 下載選擇的章節到本地 From 83e7ed64ef3eea33a15692f712f484139caaeed7 Mon Sep 17 00:00:00 2001 From: Mupceet Date: Tue, 28 Jan 2020 13:22:21 +0800 Subject: [PATCH 023/105] feat(web-service): improve the user experience of enabling web service Prompt the service is started when the user repeatedly starts the service --- .../kunfei/bookshelf/service/WebService.java | 32 +++++++++++++------ .../bookshelf/view/activity/MainActivity.java | 10 ++++-- app/src/main/res/values/strings.xml | 3 ++ 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/service/WebService.java b/app/src/main/java/com/kunfei/bookshelf/service/WebService.java index 032d010e8e..00a199ab11 100644 --- a/app/src/main/java/com/kunfei/bookshelf/service/WebService.java +++ b/app/src/main/java/com/kunfei/bookshelf/service/WebService.java @@ -4,6 +4,7 @@ import android.app.Notification; import android.app.PendingIntent; import android.app.Service; +import android.content.Context; import android.content.Intent; import android.os.Handler; import android.os.IBinder; @@ -26,18 +27,29 @@ import static com.kunfei.bookshelf.constant.AppConstant.ActionStartService; public class WebService extends Service { - private static boolean isRunning = false; + private static boolean sIsRunning = false; private HttpServer httpServer; private WebSocketServer webSocketServer; - public static void startThis(Activity activity) { - Intent intent = new Intent(activity, WebService.class); - intent.setAction(ActionStartService); - activity.startService(intent); + /** + * Start the web service, return true if the service can be started normally, false if it is started. + * + * @param context Indicates component context. + * @return true if the service can be started normally, false if it is started. + */ + public static boolean startThis(Context context) { + if (sIsRunning) { + return false; + } else { + Intent intent = new Intent(context, WebService.class); + intent.setAction(ActionStartService); + context.startService(intent); + return true; + } } public static void upHttpServer(Activity activity) { - if (isRunning) { + if (sIsRunning) { Intent intent = new Intent(activity, WebService.class); intent.setAction(ActionStartService); activity.startService(intent); @@ -47,9 +59,9 @@ public static void upHttpServer(Activity activity) { @Override public void onCreate() { super.onCreate(); - updateNotification("正在启动服务"); + updateNotification(getString(R.string.web_service_starting_hint_short)); new Handler(Looper.getMainLooper()) - .post(() -> Toast.makeText(this, "正在启动服务\n具体信息查看通知栏", Toast.LENGTH_SHORT).show()); + .post(() -> Toast.makeText(this, R.string.web_service_starting_hint_long, Toast.LENGTH_SHORT).show()); } @Override @@ -85,7 +97,7 @@ private void upServer() { try { httpServer.start(); webSocketServer.start(1000 * 30); // 通信超时设置 - isRunning = true; + sIsRunning = true; updateNotification(getString(R.string.http_ip, inetAddress.getHostAddress(), port)); } catch (IOException e) { stopSelf(); @@ -98,7 +110,7 @@ private void upServer() { @Override public void onDestroy() { super.onDestroy(); - isRunning = false; + sIsRunning = false; if (httpServer != null && httpServer.isAlive()) { httpServer.stop(); } diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java index cee8b1185b..490da845ba 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java @@ -462,10 +462,11 @@ public void delete(String value) { }).show(); break; case R.id.action_download_all: - if (!isNetWorkAvailable()) + if (!isNetWorkAvailable()) { toast(R.string.network_connection_unavailable); - else + } else { RxBus.get().post(RxBusTag.DOWNLOAD_ALL, 10000); + } break; case R.id.menu_bookshelf_layout: selectBookshelfLayout(); @@ -476,7 +477,10 @@ public void delete(String value) { } break; case R.id.action_web_start: - WebService.startThis(this); + boolean startedThisTime = WebService.startThis(this); + if (!startedThisTime) { + toast(getString(R.string.web_service_already_started_hint)); + } break; case android.R.id.home: if (drawer.isDrawerOpen(GravityCompat.START)) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 020687ae0e..c438fbbcd1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -44,6 +44,9 @@ web服务 web编辑书源 http://%s:%d + 正在启动服务 + 正在启动服务\n具体信息查看通知栏 + 服务已启动 离线下载 离线下载 下载选择的章节到本地 From 813809575a2b107fd5cb7b8bb8a8d6a1ae16cd71 Mon Sep 17 00:00:00 2001 From: kunfei Date: Fri, 31 Jan 2020 23:16:08 +0800 Subject: [PATCH 024/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kunfei/bookshelf/model/analyzeRule/AnalyzeRule.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/model/analyzeRule/AnalyzeRule.java b/app/src/main/java/com/kunfei/bookshelf/model/analyzeRule/AnalyzeRule.java index 26cc621f36..ca2ec56ded 100644 --- a/app/src/main/java/com/kunfei/bookshelf/model/analyzeRule/AnalyzeRule.java +++ b/app/src/main/java/com/kunfei/bookshelf/model/analyzeRule/AnalyzeRule.java @@ -9,6 +9,7 @@ import com.kunfei.bookshelf.bean.BaseBookBean; import com.kunfei.bookshelf.utils.NetworkUtils; import com.kunfei.bookshelf.utils.StringUtils; + import org.jsoup.nodes.Entities; import java.util.ArrayList; @@ -251,7 +252,11 @@ public String getString(List ruleList, boolean isUrl) throws Excepti if (isUrl && !StringUtils.isTrimEmpty(baseUrl)) { return NetworkUtils.getAbsoluteURL(baseUrl, Entities.unescape(String.valueOf(result))); } - return Entities.unescape(String.valueOf(result)); + try { + return Entities.unescape(String.valueOf(result)); + } catch (Exception e) { + return String.valueOf(result); + } } /** From f29cb0f37fdf1087adf13921f7d1bc3f75845259 Mon Sep 17 00:00:00 2001 From: kunfei Date: Mon, 3 Feb 2020 14:10:27 +0800 Subject: [PATCH 025/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kunfei/bookshelf/view/fragment/SettingsFragment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java b/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java index 88b361b3c8..ed1ec5ae0e 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java @@ -174,6 +174,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { Uri uri = data.getData(); if (uri == null) return; getPreferenceManager().getSharedPreferences().edit().putString("backupPath", uri.toString()).apply(); + MApplication.getInstance().setDownloadPath(uri.toString()); } } } From 323d5bdd824e1bfa33a3230faf5d6ab4dd890f6a Mon Sep 17 00:00:00 2001 From: kunfei Date: Mon, 3 Feb 2020 22:08:10 +0800 Subject: [PATCH 026/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/kunfei/bookshelf/widget/page/PageView.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/page/PageView.java b/app/src/main/java/com/kunfei/bookshelf/widget/page/PageView.java index de5c322523..9ba539afbb 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/page/PageView.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/page/PageView.java @@ -146,9 +146,6 @@ void setPageMode(PageAnimation.Mode pageMode, int marginTop, int marginBottom) { marginTop = marginTop + statusBarHeight; } switch (pageMode) { - case SIMULATION: - mPageAnim = new SimulationPageAnim(mViewWidth, mViewHeight, this, this); - break; case COVER: mPageAnim = new CoverPageAnim(mViewWidth, mViewHeight, this, this); break; From a8e8617027110a9c71e2adb89cc0d0f0d7ba575c Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 4 Feb 2020 16:54:39 +0800 Subject: [PATCH 027/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kunfei/bookshelf/bean/BookShelfBean.java | 16 ++ .../com/kunfei/bookshelf/help/ImageLoader.kt | 50 ++++++ .../view/activity/BookCoverEditActivity.java | 2 +- .../view/activity/BookDetailActivity.java | 61 +++---- .../view/activity/BookInfoEditActivity.java | 28 +--- .../view/activity/ReadStyleActivity.java | 2 +- .../view/adapter/BookShelfGridAdapter.java | 31 +--- .../view/adapter/BookShelfListAdapter.java | 49 +----- .../view/adapter/ChoiceBookAdapter.java | 31 ++-- .../view/adapter/DownloadAdapter.java | 14 +- .../view/adapter/SearchBookAdapter.java | 30 ++-- .../view/popupwindow/MediaPlayerPop.java | 44 ++--- .../bookshelf/widget/CoverImageView.java | 64 ------- .../bookshelf/widget/image/CoverImageView.kt | 158 ++++++++++++++++++ .../widget/{ => image}/FilletImageView.java | 2 +- .../main/res/drawable/image_cover_default.jpg | Bin 0 -> 11323 bytes .../main/res/drawable/img_cover_default.jpg | Bin 6927 -> 0 bytes app/src/main/res/drawable/img_cover_gs.jpg | Bin 3753 -> 0 bytes .../main/res/layout/activity_book_detail.xml | 7 +- .../res/layout/activity_book_info_edit.xml | 4 +- .../main/res/layout/item_bookshelf_grid.xml | 4 +- .../main/res/layout/item_bookshelf_list.xml | 4 +- app/src/main/res/layout/item_change_cover.xml | 2 +- app/src/main/res/layout/item_download.xml | 4 +- app/src/main/res/layout/item_read_bg.xml | 3 +- app/src/main/res/layout/item_search_book.xml | 4 +- app/src/main/res/layout/pop_media_player.xml | 5 +- 27 files changed, 319 insertions(+), 300 deletions(-) create mode 100644 app/src/main/java/com/kunfei/bookshelf/help/ImageLoader.kt delete mode 100644 app/src/main/java/com/kunfei/bookshelf/widget/CoverImageView.java create mode 100644 app/src/main/java/com/kunfei/bookshelf/widget/image/CoverImageView.kt rename app/src/main/java/com/kunfei/bookshelf/widget/{ => image}/FilletImageView.java (98%) create mode 100644 app/src/main/res/drawable/image_cover_default.jpg delete mode 100644 app/src/main/res/drawable/img_cover_default.jpg delete mode 100644 app/src/main/res/drawable/img_cover_gs.jpg diff --git a/app/src/main/java/com/kunfei/bookshelf/bean/BookShelfBean.java b/app/src/main/java/com/kunfei/bookshelf/bean/BookShelfBean.java index 8c094b4b71..2e916b9c81 100644 --- a/app/src/main/java/com/kunfei/bookshelf/bean/BookShelfBean.java +++ b/app/src/main/java/com/kunfei/bookshelf/bean/BookShelfBean.java @@ -278,6 +278,14 @@ public String getCustomCoverPath() { return this.customCoverPath; } + public String getCoverPath() { + if (TextUtils.isEmpty(customCoverPath)) { + return bookInfoBean.getCoverUrl(); + } else { + return this.customCoverPath; + } + } + public void setCustomCoverPath(String customCoverPath) { this.customCoverPath = customCoverPath; } @@ -306,6 +314,14 @@ public Boolean getReplaceEnable() { return replaceEnable == null ? MApplication.getConfigPreferences().getBoolean("replaceEnableDefault", true) : replaceEnable; } + public String getName() { + return bookInfoBean.getName(); + } + + public String getAuthor() { + return bookInfoBean.getAuthor(); + } + public void setReplaceEnable(Boolean replaceEnable) { this.replaceEnable = replaceEnable; } diff --git a/app/src/main/java/com/kunfei/bookshelf/help/ImageLoader.kt b/app/src/main/java/com/kunfei/bookshelf/help/ImageLoader.kt new file mode 100644 index 0000000000..cd074808cb --- /dev/null +++ b/app/src/main/java/com/kunfei/bookshelf/help/ImageLoader.kt @@ -0,0 +1,50 @@ +package com.kunfei.bookshelf.help + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.drawable.Drawable +import android.net.Uri +import androidx.annotation.DrawableRes +import com.bumptech.glide.Glide +import com.bumptech.glide.RequestBuilder +import java.io.File + +object ImageLoader { + + fun load(context: Context, path: String?): RequestBuilder { + return when { + path.isNullOrEmpty() -> Glide.with(context).load(path) + path.startsWith("http", true) -> Glide.with(context).load(path) + else -> try { + Glide.with(context).load(File(path)) + } catch (e: Exception) { + Glide.with(context).load(path) + } + } + } + + fun load(context: Context, @DrawableRes resId: Int?): RequestBuilder { + return Glide.with(context).load(resId) + } + + fun load(context: Context, file: File?): RequestBuilder { + return Glide.with(context).load(file) + } + + fun load(context: Context, uri: Uri?): RequestBuilder { + return Glide.with(context).load(uri) + } + + fun load(context: Context, drawable: Drawable?): RequestBuilder { + return Glide.with(context).load(drawable) + } + + fun load(context: Context, bitmap: Bitmap?): RequestBuilder { + return Glide.with(context).load(bitmap) + } + + fun load(context: Context, bytes: ByteArray?): RequestBuilder { + return Glide.with(context).load(bytes) + } + +} diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/BookCoverEditActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/BookCoverEditActivity.java index c18e353e9a..8402a851e3 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/BookCoverEditActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/BookCoverEditActivity.java @@ -231,7 +231,7 @@ public void bind(String url, String origin, RecyclerView.ViewHolder holder) { tvSourceName.setText(origin); Glide.with(holder.itemView.getContext()) .load(url) - .error(R.drawable.img_cover_default) + .error(R.drawable.image_cover_default) .into(ivCover); ivCover.setOnClickListener(view -> { Intent intent = new Intent(); diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/BookDetailActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/BookDetailActivity.java index 84f5814944..222a227b3e 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/BookDetailActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/BookDetailActivity.java @@ -3,6 +3,7 @@ import android.annotation.SuppressLint; import android.content.Intent; +import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; import android.text.TextUtils; @@ -20,8 +21,8 @@ import androidx.annotation.NonNull; import androidx.appcompat.widget.AppCompatImageView; -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.RequestBuilder; +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; import com.bumptech.glide.request.RequestOptions; import com.hwangjr.rxbus.RxBus; import com.kunfei.basemvplib.AppActivityManager; @@ -36,18 +37,16 @@ import com.kunfei.bookshelf.constant.RxBusTag; import com.kunfei.bookshelf.help.BlurTransformation; import com.kunfei.bookshelf.help.BookshelfHelp; +import com.kunfei.bookshelf.help.ImageLoader; import com.kunfei.bookshelf.model.BookSourceManager; import com.kunfei.bookshelf.presenter.BookDetailPresenter; import com.kunfei.bookshelf.presenter.ReadBookPresenter; import com.kunfei.bookshelf.presenter.contract.BookDetailContract; import com.kunfei.bookshelf.utils.StringUtils; -import com.kunfei.bookshelf.widget.CoverImageView; +import com.kunfei.bookshelf.widget.image.CoverImageView; import com.kunfei.bookshelf.widget.modialog.ChangeSourceDialog; import com.kunfei.bookshelf.widget.modialog.MoDialogHUD; -import java.io.File; -import java.util.Objects; - import butterknife.BindView; import butterknife.ButterKnife; @@ -133,7 +132,7 @@ protected void bindView() { } else { if (mPresenter.getSearchBook() == null) return; SearchBookBean searchBookBean = mPresenter.getSearchBook(); - upImageView(searchBookBean.getCoverUrl()); + upImageView(searchBookBean.getCoverUrl(), searchBookBean.getName(), searchBookBean.getAuthor()); tvName.setText(searchBookBean.getName()); author = searchBookBean.getAuthor(); tvAuthor.setText(TextUtils.isEmpty(author) ? "未知" : author); @@ -200,9 +199,9 @@ public void updateView() { tvOrigin.setVisibility(View.INVISIBLE); } if (!TextUtils.isEmpty(bookShelfBean.getCustomCoverPath())) { - upImageView(bookShelfBean.getCustomCoverPath()); + upImageView(bookShelfBean.getCustomCoverPath(), bookInfoBean.getName(), bookInfoBean.getAuthor()); } else { - upImageView(bookInfoBean.getCoverUrl()); + upImageView(bookInfoBean.getCoverUrl(), bookInfoBean.getName(), bookInfoBean.getAuthor()); } if (bookShelfBean.getTag().equals(BookShelfBean.LOCAL_TAG)) { tvChangeOrigin.setVisibility(View.INVISIBLE); @@ -226,37 +225,19 @@ public void getBookShelfError() { }); } - private void upImageView(String path) { - if (TextUtils.isEmpty(path)) return; - if (Objects.equals(coverPath, path)) return; - if (this.isFinishing()) return; - coverPath = path; - if (coverPath.startsWith("http")) { - Glide.with(this).load(coverPath) - .dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop() - .placeholder(R.drawable.img_cover_default) - .into(ivCover); - Glide.with(this).load(coverPath) - .dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop() - .placeholder(R.drawable.img_cover_gs) - .apply(RequestOptions.bitmapTransform(new BlurTransformation(this, 25))) - .into(ivBlurCover); - } else { - File file = new File(coverPath); - Glide.with(this).load(file) - .dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop() - .placeholder(R.drawable.img_cover_default) - .into(ivCover); - Glide.with(this).load(file) - .diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop() - .placeholder(R.drawable.img_cover_gs) - .apply(RequestOptions.bitmapTransform(new BlurTransformation(this, 25))) - .into(ivBlurCover); - } + private void upImageView(String path, String name, String author) { + ivCover.load(path, name, author); + ImageLoader.INSTANCE.load(this, path) + .transition(DrawableTransitionOptions.withCrossFade(1500)) + .thumbnail(defaultCover()) + .centerCrop() + .apply(RequestOptions.bitmapTransform(new BlurTransformation(this, 25))) + .into(ivBlurCover); //模糊、渐变、缩小效果 + } + + private RequestBuilder defaultCover() { + return ImageLoader.INSTANCE.load(this, R.drawable.image_cover_default) + .apply(RequestOptions.bitmapTransform(new BlurTransformation(this, 25))); } private void refresh() { diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/BookInfoEditActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/BookInfoEditActivity.java index 039bc7a561..76704e97f1 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/BookInfoEditActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/BookInfoEditActivity.java @@ -8,15 +8,12 @@ import android.view.Menu; import android.view.MenuItem; import android.widget.EditText; -import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; import androidx.appcompat.widget.Toolbar; -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.google.android.material.textfield.TextInputLayout; import com.hwangjr.rxbus.RxBus; import com.kunfei.basemvplib.impl.IPresenter; @@ -30,10 +27,9 @@ import com.kunfei.bookshelf.utils.FileUtils; import com.kunfei.bookshelf.utils.SoftInputUtil; import com.kunfei.bookshelf.utils.theme.ThemeStore; +import com.kunfei.bookshelf.widget.image.CoverImageView; import com.kunfei.bookshelf.widget.modialog.MoDialogHUD; -import java.io.File; - import butterknife.BindView; import butterknife.ButterKnife; import kotlin.Unit; @@ -45,7 +41,7 @@ public class BookInfoEditActivity extends MBaseActivity { @BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.iv_cover) - ImageView ivCover; + CoverImageView ivCover; @BindView(R.id.tie_book_name) EditText tieBookName; @BindView(R.id.til_book_name) @@ -179,25 +175,7 @@ private void selectCover() { private void initCover() { if (!this.isFinishing() && book != null) { - if (TextUtils.isEmpty(book.getCustomCoverPath())) { - Glide.with(this).load(book.getBookInfoBean().getCoverUrl()) - .dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop() - .placeholder(R.drawable.img_cover_default) - .into(ivCover); - } else if (book.getCustomCoverPath().startsWith("http")) { - Glide.with(this).load(book.getCustomCoverPath()) - .dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop() - .placeholder(R.drawable.img_cover_default) - .into(ivCover); - } else { - Glide.with(this).load(new File(book.getCustomCoverPath())) - .dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop() - .placeholder(R.drawable.img_cover_default) - .into(ivCover); - } + ivCover.load(book.getCoverPath(), book.getName(), book.getAuthor()); } } diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadStyleActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadStyleActivity.java index b4f09031fd..b04c4fffe9 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadStyleActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadStyleActivity.java @@ -429,7 +429,7 @@ public View getView(int position, View convertView, ViewGroup parent) { if(convertView==null){ holder = new ViewHolder(); convertView = mInflater.inflate(R.layout.item_read_bg, null); - holder.mImage = convertView.findViewById(R.id.iv_cover); + holder.mImage = convertView.findViewById(R.id.iv_bg); holder.mTitle = convertView.findViewById(R.id.tv_desc); convertView.setTag(holder); } else { diff --git a/app/src/main/java/com/kunfei/bookshelf/view/adapter/BookShelfGridAdapter.java b/app/src/main/java/com/kunfei/bookshelf/view/adapter/BookShelfGridAdapter.java index d8432726b0..69a8106b44 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/adapter/BookShelfGridAdapter.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/adapter/BookShelfGridAdapter.java @@ -4,18 +4,14 @@ import android.annotation.SuppressLint; import android.app.Activity; import android.graphics.Color; -import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.kunfei.bookshelf.DbHelper; import com.kunfei.bookshelf.R; import com.kunfei.bookshelf.bean.BookInfoBean; @@ -26,8 +22,8 @@ import com.kunfei.bookshelf.view.adapter.base.OnItemClickListenerTwo; import com.kunfei.bookshelf.widget.BadgeView; import com.kunfei.bookshelf.widget.RotateLoading; +import com.kunfei.bookshelf.widget.image.CoverImageView; -import java.io.File; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -144,28 +140,7 @@ public void onBindViewHolder(@NonNull MyViewHolder holder, @SuppressLint("Recycl holder.tvName.setBackgroundColor(ThemeStore.backgroundColor(activity)); if (!activity.isFinishing()) { - if (TextUtils.isEmpty(bookShelfBean.getCustomCoverPath())) { - Glide.with(activity).load(bookShelfBean.getBookInfoBean().getCoverUrl()) - .dontAnimate() - .diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop() - .placeholder(R.drawable.img_cover_default) - .into(holder.ivCover); - } else if (bookShelfBean.getCustomCoverPath().startsWith("http")) { - Glide.with(activity).load(bookShelfBean.getCustomCoverPath()) - .dontAnimate() - .diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop() - .placeholder(R.drawable.img_cover_default) - .into(holder.ivCover); - } else { - Glide.with(activity).load(new File(bookShelfBean.getCustomCoverPath())) - .dontAnimate() - .diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop() - .placeholder(R.drawable.img_cover_default) - .into(holder.ivCover); - } + holder.ivCover.load(bookShelfBean.getCoverPath(), bookShelfBean.getName(), bookShelfBean.getAuthor()); } holder.ivCover.setOnClickListener(v -> { @@ -236,7 +211,7 @@ public HashSet getSelected() { } class MyViewHolder extends RecyclerView.ViewHolder { - ImageView ivCover; + CoverImageView ivCover; TextView tvName; BadgeView bvUnread; RotateLoading rotateLoading; diff --git a/app/src/main/java/com/kunfei/bookshelf/view/adapter/BookShelfListAdapter.java b/app/src/main/java/com/kunfei/bookshelf/view/adapter/BookShelfListAdapter.java index b5bf70b67a..1b05477f61 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/adapter/BookShelfListAdapter.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/adapter/BookShelfListAdapter.java @@ -4,26 +4,15 @@ import android.annotation.SuppressLint; import android.app.Activity; import android.graphics.Color; -import android.graphics.drawable.Drawable; import android.os.AsyncTask; -import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ImageView; 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.DataSource; -import com.bumptech.glide.load.engine.DiskCacheStrategy; -import com.bumptech.glide.load.engine.GlideException; -import com.bumptech.glide.request.RequestListener; -import com.bumptech.glide.request.RequestOptions; -import com.bumptech.glide.request.target.Target; import com.kunfei.bookshelf.DbHelper; import com.kunfei.bookshelf.R; import com.kunfei.bookshelf.bean.BookInfoBean; @@ -34,8 +23,8 @@ import com.kunfei.bookshelf.view.adapter.base.OnItemClickListenerTwo; import com.kunfei.bookshelf.widget.BadgeView; import com.kunfei.bookshelf.widget.RotateLoading; +import com.kunfei.bookshelf.widget.image.CoverImageView; -import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -145,39 +134,7 @@ public void onBindViewHolder(@NonNull MyViewHolder holder, @SuppressLint("Recycl } BookInfoBean bookInfoBean = bookShelfBean.getBookInfoBean(); if (!activity.isFinishing()) { - if (TextUtils.isEmpty(bookShelfBean.getCustomCoverPath())) { - Glide.with(activity).load(bookInfoBean.getCoverUrl()) - .dontAnimate() - .diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop() - .placeholder(R.drawable.img_cover_default) - .into(holder.ivCover); - } else if (bookShelfBean.getCustomCoverPath().startsWith("http")) { - Glide.with(activity).load(bookShelfBean.getCustomCoverPath()) - .listener(new RequestListener() { - @Override - public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { - bookShelfBean.setCustomCoverPath(""); - BookshelfHelp.saveBookToShelf(bookShelfBean); - return false; - } - - @Override - public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { - return false; - } - }) - .apply(new RequestOptions().dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop().placeholder(R.drawable.img_cover_default)) - .into(holder.ivCover); - } else { - Glide.with(activity).load(new File(bookShelfBean.getCustomCoverPath())) - .dontAnimate() - .diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop() - .placeholder(R.drawable.img_cover_default) - .into(holder.ivCover); - } + holder.ivCover.load(bookShelfBean.getCoverPath(), bookShelfBean.getName(), bookShelfBean.getAuthor()); } holder.tvName.setText(bookInfoBean.getName()); holder.tvAuthor.setText(bookInfoBean.getAuthor()); @@ -260,7 +217,7 @@ public HashSet getSelected() { class MyViewHolder extends RecyclerView.ViewHolder { ViewGroup flContent; - ImageView ivCover; + CoverImageView ivCover; BadgeView bvUnread; TextView tvName; TextView tvAuthor; diff --git a/app/src/main/java/com/kunfei/bookshelf/view/adapter/ChoiceBookAdapter.java b/app/src/main/java/com/kunfei/bookshelf/view/adapter/ChoiceBookAdapter.java index 12c57df1d5..8e0df44052 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/adapter/ChoiceBookAdapter.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/adapter/ChoiceBookAdapter.java @@ -9,13 +9,11 @@ import androidx.recyclerview.widget.RecyclerView; -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.kunfei.bookshelf.R; import com.kunfei.bookshelf.bean.BookKindBean; import com.kunfei.bookshelf.bean.SearchBookBean; import com.kunfei.bookshelf.utils.StringUtils; -import com.kunfei.bookshelf.widget.CoverImageView; +import com.kunfei.bookshelf.widget.image.CoverImageView; import com.kunfei.bookshelf.widget.recycler.refresh.RefreshRecyclerViewAdapter; import java.util.ArrayList; @@ -42,22 +40,17 @@ public RecyclerView.ViewHolder onCreateIViewHolder(ViewGroup parent, int viewTyp @Override public void onBindIViewHolder(final RecyclerView.ViewHolder holder, final int position) { MyViewHolder myViewHolder = (MyViewHolder) holder; - if (searchBooks.get(position) == null) return; + if (position >= searchBooks.size()) return; + SearchBookBean book = searchBooks.get(position); if (!activity.isFinishing()) { - Glide.with(activity) - .load(searchBooks.get(position).getCoverUrl()) - .dontAnimate() - .diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop() - .placeholder(R.drawable.img_cover_default) - .into(myViewHolder.ivCover); + myViewHolder.ivCover.load(book.getCoverUrl(), book.getName(), book.getCoverUrl()); } - String title = searchBooks.get(position).getName(); - String author = searchBooks.get(position).getAuthor(); + String title = book.getName(); + String author = book.getAuthor(); if (author != null && author.trim().length() > 0) title = String.format("%s (%s)", title, author); myViewHolder.tvName.setText(title); - BookKindBean bookKindBean = new BookKindBean(searchBooks.get(position).getKind()); + BookKindBean bookKindBean = new BookKindBean(book.getKind()); if (isTrimEmpty(bookKindBean.getKind())) { myViewHolder.tvKind.setVisibility(View.GONE); } else { @@ -77,21 +70,21 @@ public void onBindIViewHolder(final RecyclerView.ViewHolder holder, final int po myViewHolder.tvState.setText(bookKindBean.getState()); } //来源 - if (isTrimEmpty(searchBooks.get(position).getOrigin())) { + if (isTrimEmpty(book.getOrigin())) { myViewHolder.tvOrigin.setVisibility(View.GONE); } else { myViewHolder.tvOrigin.setVisibility(View.VISIBLE); myViewHolder.tvOrigin.setText(activity.getString(R.string.origin_format, searchBooks.get(position).getOrigin())); } //最新章节 - if (isTrimEmpty(searchBooks.get(position).getLastChapter())) { + if (isTrimEmpty(book.getLastChapter())) { myViewHolder.tvLasted.setVisibility(View.GONE); } else { - myViewHolder.tvLasted.setText(searchBooks.get(position).getLastChapter()); + myViewHolder.tvLasted.setText(book.getLastChapter()); myViewHolder.tvLasted.setVisibility(View.VISIBLE); } //简介 - if (isTrimEmpty(searchBooks.get(position).getIntroduce())) { + if (isTrimEmpty(book.getIntroduce())) { myViewHolder.tvIntroduce.setVisibility(View.GONE); } else { myViewHolder.tvIntroduce.setText(StringUtils.formatHtml(searchBooks.get(position).getIntroduce())); @@ -100,7 +93,7 @@ public void onBindIViewHolder(final RecyclerView.ViewHolder holder, final int po myViewHolder.flContent.setOnClickListener(v -> { if (callback != null) - callback.clickItem(myViewHolder.ivCover, position, searchBooks.get(position)); + callback.clickItem(myViewHolder.ivCover, position, book); }); } diff --git a/app/src/main/java/com/kunfei/bookshelf/view/adapter/DownloadAdapter.java b/app/src/main/java/com/kunfei/bookshelf/view/adapter/DownloadAdapter.java index e3ccb49f14..07f1537518 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/adapter/DownloadAdapter.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/adapter/DownloadAdapter.java @@ -10,13 +10,11 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.engine.DiskCacheStrategy; -import com.bumptech.glide.request.RequestOptions; import com.kunfei.bookshelf.R; import com.kunfei.bookshelf.bean.DownloadBookBean; import com.kunfei.bookshelf.service.DownloadService; import com.kunfei.bookshelf.view.activity.DownloadActivity; +import com.kunfei.bookshelf.widget.image.CoverImageView; import java.util.ArrayList; import java.util.Collections; @@ -110,13 +108,7 @@ public void onBindViewHolder(@NonNull MyViewHolder holder, int position, @NonNul } else { holder.ivDel.getDrawable().mutate(); holder.ivDel.getDrawable().setColorFilter(activity.getResources().getColor(R.color.tv_text_default), PorterDuff.Mode.SRC_ATOP); - Glide.with(activity) - .load(item.getCoverUrl()) - .apply(new RequestOptions() - .diskCacheStrategy(DiskCacheStrategy.RESOURCE).centerCrop() - .dontAnimate().placeholder(R.drawable.img_cover_default) - .error(R.drawable.img_cover_default)) - .into(holder.ivCover); + holder.ivCover.load(item.getCoverUrl(), item.getName(), null); if (item.getSuccessCount() > 0) { holder.tvName.setText(String.format(Locale.getDefault(), "%s(正在下载)", item.getName())); } else { @@ -134,7 +126,7 @@ public int getItemCount() { } class MyViewHolder extends RecyclerView.ViewHolder { - ImageView ivCover; + CoverImageView ivCover; TextView tvName; TextView tvDownload; ImageView ivDel; diff --git a/app/src/main/java/com/kunfei/bookshelf/view/adapter/SearchBookAdapter.java b/app/src/main/java/com/kunfei/bookshelf/view/adapter/SearchBookAdapter.java index 61b8d94fc5..c6fe245651 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/adapter/SearchBookAdapter.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/adapter/SearchBookAdapter.java @@ -13,7 +13,6 @@ import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; -import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.kunfei.bookshelf.DbHelper; import com.kunfei.bookshelf.R; import com.kunfei.bookshelf.bean.BookKindBean; @@ -21,7 +20,7 @@ import com.kunfei.bookshelf.utils.StringUtils; import com.kunfei.bookshelf.utils.theme.ThemeStore; import com.kunfei.bookshelf.view.adapter.base.BaseListAdapter; -import com.kunfei.bookshelf.widget.CoverImageView; +import com.kunfei.bookshelf.widget.image.CoverImageView; import com.kunfei.bookshelf.widget.recycler.refresh.RefreshRecyclerViewAdapter; import java.lang.ref.WeakReference; @@ -57,17 +56,12 @@ public void onBindIViewHolder(final RecyclerView.ViewHolder holder, final int po if (itemClickListener != null) itemClickListener.onItemClick(v, position); }); + SearchBookBean book = searchBooks.get(position); if (!activity.isFinishing()) { - Glide.with(activity) - .load(searchBooks.get(position).getCoverUrl()) - .dontAnimate() - .diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop() - .placeholder(R.drawable.img_cover_default) - .into(myViewHolder.ivCover); + myViewHolder.ivCover.load(book.getCoverUrl(), book.getName(), book.getAuthor()); } - myViewHolder.tvName.setText(String.format("%s (%s)", searchBooks.get(position).getName(), searchBooks.get(position).getAuthor())); - BookKindBean bookKindBean = new BookKindBean(searchBooks.get(position).getKind()); + myViewHolder.tvName.setText(String.format("%s (%s)", book.getName(), book.getAuthor())); + BookKindBean bookKindBean = new BookKindBean(book.getKind()); if (isTrimEmpty(bookKindBean.getKind())) { myViewHolder.tvKind.setVisibility(View.GONE); } else { @@ -87,27 +81,27 @@ public void onBindIViewHolder(final RecyclerView.ViewHolder holder, final int po myViewHolder.tvState.setText(bookKindBean.getState()); } //来源 - if (isTrimEmpty(searchBooks.get(position).getOrigin())) { + if (isTrimEmpty(book.getOrigin())) { myViewHolder.tvOrigin.setVisibility(View.GONE); } else { myViewHolder.tvOrigin.setVisibility(View.VISIBLE); - myViewHolder.tvOrigin.setText(activity.getString(R.string.origin_format, searchBooks.get(position).getOrigin())); + myViewHolder.tvOrigin.setText(activity.getString(R.string.origin_format, book.getOrigin())); } //最新章节 - if (isTrimEmpty(searchBooks.get(position).getLastChapter())) { + if (isTrimEmpty(book.getLastChapter())) { myViewHolder.tvLasted.setVisibility(View.GONE); } else { - myViewHolder.tvLasted.setText(searchBooks.get(position).getLastChapter()); + myViewHolder.tvLasted.setText(book.getLastChapter()); myViewHolder.tvLasted.setVisibility(View.VISIBLE); } //简介 - if (isTrimEmpty(searchBooks.get(position).getIntroduce())) { + if (isTrimEmpty(book.getIntroduce())) { myViewHolder.tvIntroduce.setVisibility(View.GONE); } else { - myViewHolder.tvIntroduce.setText(StringUtils.formatHtml(searchBooks.get(position).getIntroduce())); + myViewHolder.tvIntroduce.setText(StringUtils.formatHtml(book.getIntroduce())); myViewHolder.tvIntroduce.setVisibility(View.VISIBLE); } - myViewHolder.tvOriginNum.setText(String.format("共%d个源", searchBooks.get(position).getOriginNum())); + myViewHolder.tvOriginNum.setText(String.format("共%d个源", book.getOriginNum())); } @Override diff --git a/app/src/main/java/com/kunfei/bookshelf/view/popupwindow/MediaPlayerPop.java b/app/src/main/java/com/kunfei/bookshelf/view/popupwindow/MediaPlayerPop.java index 908acf2be2..3e5c8e6280 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/popupwindow/MediaPlayerPop.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/popupwindow/MediaPlayerPop.java @@ -6,7 +6,6 @@ import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.Build; -import android.text.TextUtils; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; @@ -18,19 +17,20 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestBuilder; import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; import com.bumptech.glide.request.RequestOptions; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.kunfei.bookshelf.R; import com.kunfei.bookshelf.help.BlurTransformation; +import com.kunfei.bookshelf.help.ImageLoader; import com.kunfei.bookshelf.utils.ColorUtil; import com.kunfei.bookshelf.utils.TimeUtils; import com.kunfei.bookshelf.utils.theme.MaterialValueHelper; import com.kunfei.bookshelf.utils.theme.ThemeStore; import com.kunfei.bookshelf.widget.views.ATESeekBar; -import java.io.File; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Locale; @@ -172,29 +172,21 @@ public void setFabReadAloudImage(int id) { } public void setCover(String coverPath) { - if (TextUtils.isEmpty(coverPath)) return; - if (coverPath.startsWith("http")) { - Glide.with(this).load(coverPath) - .apply(new RequestOptions().dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESOURCE).centerCrop() - .placeholder(R.drawable.img_cover_default)) - .into(ivCover); - Glide.with(this).load(coverPath) - .apply(new RequestOptions().dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESOURCE).centerCrop() - .placeholder(R.drawable.img_cover_gs)) - .apply(RequestOptions.bitmapTransform(new BlurTransformation(getContext(), 25))) - .into(ivCoverBg); - } else { - File file = new File(coverPath); - Glide.with(this).load(file) - .apply(new RequestOptions().dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESOURCE).centerCrop() - .placeholder(R.drawable.img_cover_default)) - .into(ivCover); - Glide.with(this).load(file) - .apply(new RequestOptions().dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESOURCE).centerCrop() - .placeholder(R.drawable.img_cover_gs)) - .apply(RequestOptions.bitmapTransform(new BlurTransformation(getContext(), 25))) - .into(ivCoverBg); - } + ImageLoader.INSTANCE.load(getContext(), coverPath) + .apply(new RequestOptions().dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESOURCE).centerCrop() + .placeholder(R.drawable.image_cover_default)) + .into(ivCover); + ImageLoader.INSTANCE.load(getContext(), coverPath) + .transition(DrawableTransitionOptions.withCrossFade(1500)) + .thumbnail(defaultCover()) + .centerCrop() + .apply(RequestOptions.bitmapTransform(new BlurTransformation(getContext(), 25))) + .into(ivCoverBg); + } + + private RequestBuilder defaultCover() { + return ImageLoader.INSTANCE.load(getContext(), R.drawable.image_cover_default) + .apply(RequestOptions.bitmapTransform(new BlurTransformation(getContext(), 25))); } public interface Callback { diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/CoverImageView.java b/app/src/main/java/com/kunfei/bookshelf/widget/CoverImageView.java deleted file mode 100644 index 63a512f6e8..0000000000 --- a/app/src/main/java/com/kunfei/bookshelf/widget/CoverImageView.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.kunfei.bookshelf.widget; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Path; -import android.util.AttributeSet; - - -public class CoverImageView extends androidx.appcompat.widget.AppCompatImageView { - float width, height; - - public CoverImageView(Context context) { - super(context); - } - - public CoverImageView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public CoverImageView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - width = getWidth(); - height = getHeight(); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int measuredWidth = MeasureSpec.getSize(widthMeasureSpec); - int measuredHeight = measuredWidth * 7 / 5; - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(measuredHeight, MeasureSpec.EXACTLY)); - } - - @Override - protected void onDraw(Canvas canvas) { - if (width >= 10 && height > 10) { - @SuppressLint("DrawAllocation") - Path path = new Path(); - //四个圆角 - path.moveTo(10, 0); - path.lineTo(width - 10, 0); - path.quadTo(width, 0, width, 10); - path.lineTo(width, height - 10); - path.quadTo(width, height, width - 10, height); - path.lineTo(10, height); - path.quadTo(0, height, 0, height - 10); - path.lineTo(0, 10); - path.quadTo(0, 0, 10, 0); - - canvas.clipPath(path); - } - super.onDraw(canvas); - } - - public void setHeight(int height) { - int width = height * 5 / 7; - setMinimumWidth(width); - } -} diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/image/CoverImageView.kt b/app/src/main/java/com/kunfei/bookshelf/widget/image/CoverImageView.kt new file mode 100644 index 0000000000..a86d9f8f04 --- /dev/null +++ b/app/src/main/java/com/kunfei/bookshelf/widget/image/CoverImageView.kt @@ -0,0 +1,158 @@ +package com.kunfei.bookshelf.widget.image + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.* +import android.graphics.drawable.Drawable +import android.text.TextPaint +import android.util.AttributeSet +import com.bumptech.glide.load.DataSource +import com.bumptech.glide.load.engine.GlideException +import com.bumptech.glide.request.RequestListener +import com.bumptech.glide.request.target.Target +import com.kunfei.bookshelf.R +import com.kunfei.bookshelf.help.ImageLoader + + +class CoverImageView : androidx.appcompat.widget.AppCompatImageView { + internal var width: Float = 0.toFloat() + internal var height: Float = 0.toFloat() + private var nameHeight = 0f + private var authorHeight = 0f + private val namePaint = TextPaint() + private val authorPaint = TextPaint() + private var name: String? = null + private var author: String? = null + private var loadFailed = false + + constructor(context: Context) : super(context) + + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) + + constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) + + init { + namePaint.typeface = Typeface.DEFAULT_BOLD + namePaint.isAntiAlias = true + namePaint.textAlign = Paint.Align.CENTER + namePaint.textSkewX = -0.2f + authorPaint.typeface = Typeface.DEFAULT + authorPaint.isAntiAlias = true + authorPaint.textAlign = Paint.Align.CENTER + authorPaint.textSkewX = -0.1f + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + val measuredWidth = MeasureSpec.getSize(widthMeasureSpec) + val measuredHeight = measuredWidth * 7 / 5 + super.onMeasure( + widthMeasureSpec, + MeasureSpec.makeMeasureSpec(measuredHeight, MeasureSpec.EXACTLY) + ) + } + + override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { + super.onLayout(changed, left, top, right, bottom) + width = getWidth().toFloat() + height = getHeight().toFloat() + namePaint.textSize = width / 6 + namePaint.strokeWidth = namePaint.textSize / 10 + authorPaint.textSize = width / 9 + authorPaint.strokeWidth = authorPaint.textSize / 10 + nameHeight = height / 2 + authorHeight = nameHeight + authorPaint.fontSpacing + } + + override fun onDraw(canvas: Canvas) { + if (width >= 10 && height > 10) { + @SuppressLint("DrawAllocation") + val path = Path() + //四个圆角 + path.moveTo(10f, 0f) + path.lineTo(width - 10, 0f) + path.quadTo(width, 0f, width, 10f) + path.lineTo(width, height - 10) + path.quadTo(width, height, width - 10, height) + path.lineTo(10f, height) + path.quadTo(0f, height, 0f, height - 10) + path.lineTo(0f, 10f) + path.quadTo(0f, 0f, 10f, 0f) + + canvas.clipPath(path) + } + super.onDraw(canvas) + if (!loadFailed) return + name?.let { + namePaint.color = Color.WHITE + namePaint.style = Paint.Style.STROKE + canvas.drawText(it, width / 2, nameHeight, namePaint) + namePaint.color = Color.RED + namePaint.style = Paint.Style.FILL + canvas.drawText(it, width / 2, nameHeight, namePaint) + } + author?.let { + authorPaint.color = Color.WHITE + authorPaint.style = Paint.Style.STROKE + canvas.drawText(it, width / 2, authorHeight, authorPaint) + authorPaint.color = Color.RED + authorPaint.style = Paint.Style.FILL + canvas.drawText(it, width / 2, authorHeight, authorPaint) + } + } + + fun setHeight(height: Int) { + val width = height * 5 / 7 + minimumWidth = width + } + + private fun setText(name: String?, author: String?) { + this.name = + when { + name == null -> null + name.length > 5 -> name.substring(0, 4) + "…" + else -> name + } + this.author = + when { + author == null -> null + author.length > 8 -> author.substring(0, 7) + "…" + else -> author + } + } + + fun load(path: String?, name: String?, author: String?) { + setText(name, author) + ImageLoader.load(context, path)//Glide自动识别http://和file:// + .placeholder(R.drawable.image_cover_default) + .error(R.drawable.image_cover_default) + .listener(object : RequestListener { + override fun onLoadFailed( + e: GlideException?, + model: Any?, + target: Target?, + isFirstResource: Boolean + ): Boolean { + loadFailed = true + return false + } + + override fun onResourceReady( + resource: Drawable?, + model: Any?, + target: Target?, + dataSource: DataSource?, + isFirstResource: Boolean + ): Boolean { + loadFailed = false + return false + } + + }) + .centerCrop() + .into(this) + } +} diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/FilletImageView.java b/app/src/main/java/com/kunfei/bookshelf/widget/image/FilletImageView.java similarity index 98% rename from app/src/main/java/com/kunfei/bookshelf/widget/FilletImageView.java rename to app/src/main/java/com/kunfei/bookshelf/widget/image/FilletImageView.java index 4db9573568..a2d8d9e2cd 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/FilletImageView.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/image/FilletImageView.java @@ -1,4 +1,4 @@ -package com.kunfei.bookshelf.widget; +package com.kunfei.bookshelf.widget.image; import android.annotation.SuppressLint; import android.content.Context; diff --git a/app/src/main/res/drawable/image_cover_default.jpg b/app/src/main/res/drawable/image_cover_default.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0b502033cdc6c48b811d9880eaadf55438cb965b GIT binary patch literal 11323 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_cover_default.jpg b/app/src/main/res/drawable/img_cover_default.jpg deleted file mode 100644 index 6504a4e7e8857ff417e2564aec97897265ef3289..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6927 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 - - + android:src="@drawable/image_cover_default" /> - + android:src="@drawable/image_cover_default" /> - diff --git a/app/src/main/res/layout/item_bookshelf_list.xml b/app/src/main/res/layout/item_bookshelf_list.xml index 4695fb739e..184534b023 100644 --- a/app/src/main/res/layout/item_bookshelf_list.xml +++ b/app/src/main/res/layout/item_bookshelf_list.xml @@ -10,14 +10,14 @@ android:background="?android:attr/selectableItemBackground" tools:ignore="UnusedAttribute"> - - - + android:src="@drawable/image_cover_default" /> - + android:src="@drawable/image_cover_default" /> + android:contentDescription="@string/img_cover" /> From 0f2533e8614dd1800879d5afb540d8215e5dca5c Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 4 Feb 2020 16:55:52 +0800 Subject: [PATCH 028/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index f95c08f5f7..c2a5fd7b9e 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -2,6 +2,10 @@ ### 关注公众号[开源阅读软件]点击广告可支持作者! ### 捐赠里点击红包搜索码可开启高级功能! +**2020/02/04** +* 修复bug +* 更换默认封面,默认封面绘制书名作者 + **2020/01/24** * 修复备份bug * 修复切换图标后不在后台显示的bug From 0139150a2b2e89ed995ebea8315da037756a6e2e Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 4 Feb 2020 17:33:01 +0800 Subject: [PATCH 029/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kunfei/bookshelf/help/storage/Backup.kt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt index 21ba47b93b..4ca1d79bcf 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt @@ -105,13 +105,17 @@ object Backup { } private fun copyBackup(context: Context, uri: Uri) { - DocumentFile.fromTreeUri(context, uri)?.let { treeDoc -> - for (fileName in backupFileNames) { - val doc = treeDoc.findFile(fileName) ?: treeDoc.createFile("", fileName) - doc?.let { - DocumentUtil.writeBytes(context, FileHelp.getFile(backupPath + File.separator + fileName).readBytes(), doc) + try { + DocumentFile.fromTreeUri(context, uri)?.let { treeDoc -> + for (fileName in backupFileNames) { + val doc = treeDoc.findFile(fileName) ?: treeDoc.createFile("", fileName) + doc?.let { + DocumentUtil.writeBytes(context, FileHelp.getFile(backupPath + File.separator + fileName).readBytes(), doc) + } } } + } catch (e: Exception) { + copyBackup() } } From 02a893ee05a6818f1a5b4e61b5a2c99cfe85573b Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 4 Feb 2020 18:53:46 +0800 Subject: [PATCH 030/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kunfei/bookshelf/view/fragment/SettingsFragment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java b/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java index ed1ec5ae0e..4b76014350 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java @@ -174,6 +174,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { Uri uri = data.getData(); if (uri == null) return; getPreferenceManager().getSharedPreferences().edit().putString("backupPath", uri.toString()).apply(); + findPreference("backupPath").setSummary(uri.toString()); MApplication.getInstance().setDownloadPath(uri.toString()); } } From 6ce44d02069faffd13783b1933ebf711c08046bf Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 5 Feb 2020 21:42:08 +0800 Subject: [PATCH 031/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kunfei/bookshelf/view/fragment/SettingsFragment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java b/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java index 4b76014350..8ca604547c 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java @@ -175,7 +175,6 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { if (uri == null) return; getPreferenceManager().getSharedPreferences().edit().putString("backupPath", uri.toString()).apply(); findPreference("backupPath").setSummary(uri.toString()); - MApplication.getInstance().setDownloadPath(uri.toString()); } } } From 83aaaa83cc89629605de07bc29804c7e2975365d Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 5 Feb 2020 21:42:59 +0800 Subject: [PATCH 032/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index c2a5fd7b9e..ce4f69b29d 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -2,6 +2,9 @@ ### 关注公众号[开源阅读软件]点击广告可支持作者! ### 捐赠里点击红包搜索码可开启高级功能! +**2020/02/05** +* 修复bug + **2020/02/04** * 修复bug * 更换默认封面,默认封面绘制书名作者 From 5ca901deb1283676ee08e296621a15a9a961d39b Mon Sep 17 00:00:00 2001 From: kunfei Date: Mon, 10 Feb 2020 07:55:21 +0800 Subject: [PATCH 033/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kunfei/bookshelf/help/storage/WebDavHelp.kt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt index 993c58c752..837162b082 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt @@ -48,14 +48,18 @@ object WebDavHelp { fun getWebDavFileNames(): ArrayList { val url = getWebDavUrl() val names = arrayListOf() - if (!url.isNullOrBlank() && initWebDav()) { - var files = WebDav(url + "YueDu/").listFiles() - files = files.reversed() - for (index: Int in 0 until min(10, files.size)) { - files[index].displayName?.let { - names.add(it) + try { + if (!url.isNullOrBlank() && initWebDav()) { + var files = WebDav(url + "YueDu/").listFiles() + files = files.reversed() + for (index: Int in 0 until min(10, files.size)) { + files[index].displayName?.let { + names.add(it) + } } } + } catch (e: Exception) { + e.printStackTrace() } return names } From 407e4cb81c70842a5e92d73a3043bf44cdb128c0 Mon Sep 17 00:00:00 2001 From: kunfei Date: Mon, 10 Feb 2020 12:37:40 +0800 Subject: [PATCH 034/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kunfei/bookshelf/help/storage/Backup.kt | 56 +++-- .../bookshelf/help/storage/BackupRestoreUi.kt | 234 ++++++++++++++++++ .../kunfei/bookshelf/help/storage/Restore.kt | 186 ++++++++------ .../bookshelf/help/storage/WebDavHelp.kt | 14 +- .../bookshelf/view/activity/MainActivity.java | 170 +------------ .../view/activity/ReadBookActivity.java | 18 +- .../view/fragment/WebDavSettingsFragment.java | 4 +- app/src/main/res/values/arrays.xml | 6 + app/src/main/res/values/strings.xml | 6 +- 9 files changed, 405 insertions(+), 289 deletions(-) create mode 100644 app/src/main/java/com/kunfei/bookshelf/help/storage/BackupRestoreUi.kt diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt index 4ca1d79bcf..161cdba59c 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt @@ -19,6 +19,7 @@ import io.reactivex.SingleOnSubscribe import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers import java.io.File +import java.util.concurrent.TimeUnit object Backup { @@ -40,7 +41,20 @@ object Backup { ) } - fun backup(context: Context, uri: Uri?, callBack: CallBack?) { + fun autoBack() { + val lastBackup = MApplication.getConfigPreferences().getLong("lastBackup", 0) + if (System.currentTimeMillis() - lastBackup < TimeUnit.DAYS.toMillis(1)) { + return + } + val path = MApplication.getConfigPreferences().getString("backupPath", defaultPath) + if (path == null) { + backup(MApplication.getInstance(), defaultPath, null) + } else { + backup(MApplication.getInstance(), path, null) + } + } + + fun backup(context: Context, path: String, callBack: CallBack?) { Single.create(SingleOnSubscribe { e -> BookshelfHelp.getAllBook().let { if (it.isNotEmpty()) { @@ -89,10 +103,10 @@ object Backup { edit.commit() } WebDavHelp.backUpWebDav(backupPath) - if (uri != null) { - copyBackup(context, uri) + if (path.isContentPath()) { + copyBackup(context, Uri.parse(path)) } else { - copyBackup() + copyBackup(path) } e.onSuccess(true) }).subscribeOn(Schedulers.io()) @@ -101,36 +115,36 @@ object Backup { override fun onSuccess(t: Boolean) { callBack?.backupSuccess() } + + override fun onError(e: Throwable) { + e.printStackTrace() + callBack?.backupError(e.localizedMessage ?: "ERROR") + } }) } + @Throws(Exception::class) private fun copyBackup(context: Context, uri: Uri) { - try { - DocumentFile.fromTreeUri(context, uri)?.let { treeDoc -> - for (fileName in backupFileNames) { - val doc = treeDoc.findFile(fileName) ?: treeDoc.createFile("", fileName) - doc?.let { - DocumentUtil.writeBytes(context, FileHelp.getFile(backupPath + File.separator + fileName).readBytes(), doc) - } + DocumentFile.fromTreeUri(context, uri)?.let { treeDoc -> + for (fileName in backupFileNames) { + val doc = treeDoc.findFile(fileName) ?: treeDoc.createFile("", fileName) + doc?.let { + DocumentUtil.writeBytes(context, FileHelp.getFile(backupPath + File.separator + fileName).readBytes(), doc) } } - } catch (e: Exception) { - copyBackup() } } - private fun copyBackup() { - try { - for (fileName in backupFileNames) { - FileHelp.getFile(backupPath + File.separator + "bookshelf.json") - .copyTo(FileHelp.getFile(defaultPath + File.separator + "bookshelf.json"), true) - } - } catch (e: Exception) { - e.printStackTrace() + @Throws(java.lang.Exception::class) + private fun copyBackup(path: String) { + for (fileName in backupFileNames) { + FileHelp.getFile(backupPath + File.separator + fileName) + .copyTo(FileHelp.getFile(path + File.separator + fileName), true) } } interface CallBack { fun backupSuccess() + fun backupError(msg: String) } } \ No newline at end of file diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/BackupRestoreUi.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/BackupRestoreUi.kt new file mode 100644 index 0000000000..1157b07961 --- /dev/null +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/BackupRestoreUi.kt @@ -0,0 +1,234 @@ +package com.kunfei.bookshelf.help.storage + +import android.app.Activity.RESULT_OK +import android.content.Intent +import android.net.Uri +import android.text.TextUtils +import androidx.appcompat.app.AppCompatActivity +import androidx.documentfile.provider.DocumentFile +import com.hwangjr.rxbus.RxBus +import com.kunfei.bookshelf.MApplication +import com.kunfei.bookshelf.R +import com.kunfei.bookshelf.base.observer.MySingleObserver +import com.kunfei.bookshelf.constant.RxBusTag +import com.kunfei.bookshelf.help.permission.Permissions +import com.kunfei.bookshelf.help.permission.PermissionsCompat +import com.kunfei.bookshelf.help.storage.WebDavHelp.getWebDavFileNames +import com.kunfei.bookshelf.help.storage.WebDavHelp.showRestoreDialog +import com.kunfei.bookshelf.widget.filepicker.picker.FilePicker +import io.reactivex.Single +import io.reactivex.SingleEmitter +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.schedulers.Schedulers +import org.jetbrains.anko.alert +import org.jetbrains.anko.toast +import java.util.* + +object BackupRestoreUi : Backup.CallBack, Restore.CallBack { + + private const val backupSelectRequestCode = 22 + private const val restoreSelectRequestCode = 33 + + private fun getBackupPath(): String? { + return MApplication.getConfigPreferences().getString("backupPath", null) + } + + private fun setBackupPath(path: String?) { + if (path.isNullOrEmpty()) { + MApplication.getConfigPreferences().edit().remove("backupPath").apply() + } else { + MApplication.getConfigPreferences().edit().putString("backupPath", path).apply() + } + } + + override fun backupSuccess() { + MApplication.getInstance().toast(R.string.backup_success) + } + + override fun backupError(msg: String) { + MApplication.getInstance().toast(msg) + } + + override fun restoreSuccess() { + MApplication.getInstance().toast(R.string.restore_success) + RxBus.get().post(RxBusTag.RECREATE, true) + } + + override fun restoreError(msg: String) { + MApplication.getInstance().toast(msg) + } + + fun backup(activity: AppCompatActivity) { + val backupPath = getBackupPath() + if (backupPath.isNullOrEmpty()) { + selectBackupFolder(activity) + } else { + if (backupPath.isContentPath()) { + val uri = Uri.parse(backupPath) + val doc = DocumentFile.fromTreeUri(activity, uri) + if (doc?.canWrite() == true) { + Backup.backup(activity, backupPath, this) + } else { + selectBackupFolder(activity) + } + } else { + backupUsePermission(activity) + } + } + } + + private fun backupUsePermission(activity: AppCompatActivity, path: String = Backup.defaultPath) { + PermissionsCompat.Builder(activity) + .addPermissions(*Permissions.Group.STORAGE) + .rationale(R.string.get_storage_per) + .onGranted { + setBackupPath(path) + Backup.backup(activity, path, this) + } + .request() + } + + private fun selectBackupFolder(activity: AppCompatActivity) { + activity.alert { + titleResource = R.string.select_folder + items(activity.resources.getStringArray(R.array.select_folder).toList()) { _, index -> + when (index) { + 0 -> backupUsePermission(activity) + 1 -> { + try { + val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + activity.startActivityForResult(intent, backupSelectRequestCode) + } catch (e: java.lang.Exception) { + e.printStackTrace() + activity.toast(e.localizedMessage ?: "ERROR") + } + } + 2 -> { + PermissionsCompat.Builder(activity) + .addPermissions(*Permissions.Group.STORAGE) + .rationale(R.string.get_storage_per) + .onGranted { + selectBackupFolderApp(activity, false) + } + .request() + } + } + } + }.show() + } + + private fun selectBackupFolderApp(activity: AppCompatActivity, isRestore: Boolean) { + val picker = FilePicker(activity, FilePicker.DIRECTORY) + picker.setBackgroundColor(activity.resources.getColor(R.color.background)) + picker.setTopBackgroundColor(activity.resources.getColor(R.color.background)) + picker.setItemHeight(30) + picker.setOnFilePickListener { currentPath: String -> + setBackupPath(currentPath) + if (isRestore) { + Restore.restore(currentPath, this) + } else { + Backup.backup(activity, currentPath, this) + } + } + picker.show() + } + + fun restore(activity: AppCompatActivity) { + Single.create { emitter: SingleEmitter?> -> + emitter.onSuccess(getWebDavFileNames()) + }.subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : MySingleObserver?>() { + override fun onSuccess(strings: ArrayList) { + if (!showRestoreDialog(activity, strings, this@BackupRestoreUi)) { + val path = getBackupPath() + if (TextUtils.isEmpty(path)) { + selectRestoreFolder(activity) + } else { + if (path.isContentPath()) { + val uri = Uri.parse(path) + val doc = DocumentFile.fromTreeUri(activity, uri) + if (doc?.canWrite() == true) { + Restore.restore(activity, Uri.parse(path), this@BackupRestoreUi) + } else { + selectRestoreFolder(activity) + } + } else { + restoreUsePermission(activity) + } + } + } + } + }) + } + + private fun restoreUsePermission(activity: AppCompatActivity, path: String = Backup.defaultPath) { + PermissionsCompat.Builder(activity) + .addPermissions(*Permissions.Group.STORAGE) + .rationale(R.string.get_storage_per) + .onGranted { + setBackupPath(path) + Restore.restore(path, this) + } + .request() + } + + private fun selectRestoreFolder(activity: AppCompatActivity) { + activity.alert { + titleResource = R.string.select_folder + items(activity.resources.getStringArray(R.array.select_folder).toList()) { _, index -> + when (index) { + 0 -> restoreUsePermission(activity) + 1 -> { + try { + val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + activity.startActivityForResult(intent, restoreSelectRequestCode) + } catch (e: java.lang.Exception) { + e.printStackTrace() + activity.toast(e.localizedMessage ?: "ERROR") + } + } + 2 -> { + PermissionsCompat.Builder(activity) + .addPermissions(*Permissions.Group.STORAGE) + .rationale(R.string.get_storage_per) + .onGranted { + selectBackupFolderApp(activity, true) + } + .request() + } + } + } + }.show() + } + + fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + when (requestCode) { + backupSelectRequestCode -> if (resultCode == RESULT_OK) { + data?.data?.let { uri -> + MApplication.getInstance().contentResolver.takePersistableUriPermission( + uri, + Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION + ) + setBackupPath(uri.toString()) + Backup.backup(MApplication.getInstance(), uri.toString(), this) + } + } + restoreSelectRequestCode -> if (resultCode == RESULT_OK) { + data?.data?.let { uri -> + MApplication.getInstance().contentResolver.takePersistableUriPermission( + uri, + Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION + ) + setBackupPath(uri.toString()) + Restore.restore(MApplication.getInstance(), uri, this) + } + } + } + } + +} + +fun String?.isContentPath(): Boolean = this?.startsWith("content://") == true \ No newline at end of file diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt index fa1a5d074c..fb87bc78c6 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt @@ -6,6 +6,7 @@ import androidx.documentfile.provider.DocumentFile import com.kunfei.bookshelf.DbHelper import com.kunfei.bookshelf.MApplication import com.kunfei.bookshelf.R +import com.kunfei.bookshelf.base.observer.MySingleObserver import com.kunfei.bookshelf.bean.* import com.kunfei.bookshelf.help.FileHelp import com.kunfei.bookshelf.help.LauncherIcon @@ -16,96 +17,133 @@ import com.kunfei.bookshelf.model.TxtChapterRuleManager import com.kunfei.bookshelf.utils.DocumentUtil import com.kunfei.bookshelf.utils.GSON import com.kunfei.bookshelf.utils.fromJsonArray +import io.reactivex.Single +import io.reactivex.SingleOnSubscribe +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.schedulers.Schedulers import java.io.File object Restore { - fun restore(context: Context, uri: Uri) { - DocumentFile.fromTreeUri(context, uri)?.listFiles()?.forEach { doc -> - for (fileName in Backup.backupFileNames) { - if (doc.name == fileName) { - DocumentUtil.readBytes(context, doc.uri)?.let { - FileHelp.getFile(Backup.backupPath + File.separator + fileName) - .writeBytes(it) + fun restore(context: Context, uri: Uri, callBack: CallBack?) { + Single.create(SingleOnSubscribe { e -> + DocumentFile.fromTreeUri(context, uri)?.listFiles()?.forEach { doc -> + for (fileName in Backup.backupFileNames) { + if (doc.name == fileName) { + DocumentUtil.readBytes(context, doc.uri)?.let { + FileHelp.getFile(Backup.backupPath + File.separator + fileName) + .writeBytes(it) + } } } } - } - restore(Backup.backupPath) + e.onSuccess(true) + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : MySingleObserver() { + override fun onSuccess(t: Boolean) { + restore(Backup.backupPath, callBack) + } + + override fun onError(e: Throwable) { + e.printStackTrace() + callBack?.restoreError(e.localizedMessage ?: "ERROR") + } + }) } - fun restore(path: String) { - try { - val file = FileHelp.getFile(path + File.separator + "myBookShelf.json") - val json = file.readText() - GSON.fromJsonArray(json)?.forEach { bookshelf -> - if (bookshelf.noteUrl != null) { - DbHelper.getDaoSession().bookShelfBeanDao.insertOrReplace(bookshelf) - } - if (bookshelf.bookInfoBean.noteUrl != null) { - DbHelper.getDaoSession().bookInfoBeanDao.insertOrReplace(bookshelf.bookInfoBean) + fun restore(path: String, callBack: CallBack?) { + Single.create(SingleOnSubscribe { e -> + try { + val file = FileHelp.getFile(path + File.separator + "myBookShelf.json") + val json = file.readText() + GSON.fromJsonArray(json)?.forEach { bookshelf -> + if (bookshelf.noteUrl != null) { + DbHelper.getDaoSession().bookShelfBeanDao.insertOrReplace(bookshelf) + } + if (bookshelf.bookInfoBean.noteUrl != null) { + DbHelper.getDaoSession().bookInfoBeanDao.insertOrReplace(bookshelf.bookInfoBean) + } } + } catch (e: Exception) { + e.printStackTrace() } - } catch (e: Exception) { - e.printStackTrace() - } - try { - val file = FileHelp.getFile(path + File.separator + "myBookSource.json") - val json = file.readText() - GSON.fromJsonArray(json)?.let { - BookSourceManager.addBookSource(it) + try { + val file = FileHelp.getFile(path + File.separator + "myBookSource.json") + val json = file.readText() + GSON.fromJsonArray(json)?.let { + BookSourceManager.addBookSource(it) + } + } catch (e: Exception) { + e.printStackTrace() } - } catch (e: Exception) { - e.printStackTrace() - } - try { - val file = FileHelp.getFile(path + File.separator + "myBookSearchHistory.json") - val json = file.readText() - GSON.fromJsonArray(json)?.let { - DbHelper.getDaoSession().searchHistoryBeanDao.insertOrReplaceInTx(it) + try { + val file = FileHelp.getFile(path + File.separator + "myBookSearchHistory.json") + val json = file.readText() + GSON.fromJsonArray(json)?.let { + DbHelper.getDaoSession().searchHistoryBeanDao.insertOrReplaceInTx(it) + } + } catch (e: Exception) { + e.printStackTrace() } - } catch (e: Exception) { - e.printStackTrace() - } - try { - val file = FileHelp.getFile(path + File.separator + "myBookReplaceRule.json") - val json = file.readText() - GSON.fromJsonArray(json)?.let { - ReplaceRuleManager.addDataS(it) + try { + val file = FileHelp.getFile(path + File.separator + "myBookReplaceRule.json") + val json = file.readText() + GSON.fromJsonArray(json)?.let { + ReplaceRuleManager.addDataS(it) + } + } catch (e: Exception) { + e.printStackTrace() } - } catch (e: Exception) { - e.printStackTrace() - } - try { - val file = FileHelp.getFile(path + File.separator + "myTxtChapterRule.json") - val json = file.readText() - GSON.fromJsonArray(json)?.let { - TxtChapterRuleManager.save(it) + try { + val file = FileHelp.getFile(path + File.separator + "myTxtChapterRule.json") + val json = file.readText() + GSON.fromJsonArray(json)?.let { + TxtChapterRuleManager.save(it) + } + } catch (e: Exception) { + e.printStackTrace() } - } catch (e: Exception) { - e.printStackTrace() - } - var donateHb = MApplication.getConfigPreferences().getLong("DonateHb", 0) - donateHb = if (donateHb > System.currentTimeMillis()) 0 else donateHb - Preferences.getSharedPreferences(MApplication.getInstance(), path, "config")?.all?.map { - val edit = MApplication.getConfigPreferences().edit() - when (val value = it.value) { - is Int -> edit.putInt(it.key, value) - is Boolean -> edit.putBoolean(it.key, value) - is Long -> edit.putLong(it.key, value) - is Float -> edit.putFloat(it.key, value) - is String -> edit.putString(it.key, value) - else -> Unit + var donateHb = MApplication.getConfigPreferences().getLong("DonateHb", 0) + donateHb = if (donateHb > System.currentTimeMillis()) 0 else donateHb + Preferences.getSharedPreferences(MApplication.getInstance(), path, "config")?.all?.map { + val edit = MApplication.getConfigPreferences().edit() + when (val value = it.value) { + is Int -> edit.putInt(it.key, value) + is Boolean -> edit.putBoolean(it.key, value) + is Long -> edit.putLong(it.key, value) + is Float -> edit.putFloat(it.key, value) + is String -> edit.putString(it.key, value) + else -> Unit + } + edit.putLong("DonateHb", donateHb) + edit.putInt("versionCode", MApplication.getVersionCode()) + edit.apply() + LauncherIcon.ChangeIcon(MApplication.getConfigPreferences().getString("launcher_icon", MApplication.getInstance().getString(R.string.icon_main))) + ReadBookControl.getInstance().updateReaderSettings() + MApplication.getInstance().upThemeStore() + MApplication.getInstance().initNightTheme() + edit.commit() } - edit.putLong("DonateHb", donateHb) - edit.putInt("versionCode", MApplication.getVersionCode()) - edit.apply() - LauncherIcon.ChangeIcon(MApplication.getConfigPreferences().getString("launcher_icon", MApplication.getInstance().getString(R.string.icon_main))) - ReadBookControl.getInstance().updateReaderSettings() - MApplication.getInstance().upThemeStore() - MApplication.getInstance().initNightTheme() - edit.commit() - } + e.onSuccess(true) + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : MySingleObserver() { + override fun onSuccess(t: Boolean) { + callBack?.restoreSuccess() + } + + override fun onError(e: Throwable) { + e.printStackTrace() + callBack?.restoreError(e.localizedMessage ?: "ERROR") + } + }) + } + + + interface CallBack { + fun restoreSuccess() + fun restoreError(msg: String) } } \ No newline at end of file diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt index 837162b082..7cfe32314c 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt @@ -1,13 +1,9 @@ package com.kunfei.bookshelf.help.storage import android.content.Context -import android.widget.Toast -import com.hwangjr.rxbus.RxBus import com.kunfei.bookshelf.MApplication -import com.kunfei.bookshelf.R import com.kunfei.bookshelf.base.observer.MySingleObserver import com.kunfei.bookshelf.constant.AppConstant -import com.kunfei.bookshelf.constant.RxBusTag import com.kunfei.bookshelf.help.FileHelp import com.kunfei.bookshelf.utils.ZipUtils import com.kunfei.bookshelf.utils.webdav.WebDav @@ -64,11 +60,11 @@ object WebDavHelp { return names } - fun showRestoreDialog(context: Context, names: ArrayList): Boolean { + fun showRestoreDialog(context: Context, names: ArrayList, callBack: Restore.CallBack?): Boolean { return if (names.isNotEmpty()) { context.selector(title = "选择恢复文件", items = names) { _, index -> if (index in 0 until names.size) { - restoreWebDav(names[index]) + restoreWebDav(names[index], callBack) } } true @@ -77,22 +73,20 @@ object WebDavHelp { } } - private fun restoreWebDav(name: String) { + private fun restoreWebDav(name: String, callBack: Restore.CallBack?) { Single.create(SingleOnSubscribe { e -> getWebDavUrl()?.let { val file = WebDav(it + "YueDu/" + name) file.downloadTo(zipFilePath, true) @Suppress("BlockingMethodInNonBlockingContext") ZipUtils.unzipFile(zipFilePath, unzipFilesPath) - Restore.restore(unzipFilesPath) } e.onSuccess(true) }).subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : MySingleObserver() { override fun onSuccess(t: Boolean) { - RxBus.get().post(RxBusTag.RECREATE, true) - Toast.makeText(MApplication.getInstance(), R.string.restore_success, Toast.LENGTH_SHORT).show() + Restore.restore(unzipFilesPath, callBack) } }) } diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java index 490da845ba..60a1d2548e 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/MainActivity.java @@ -6,11 +6,8 @@ import android.content.SharedPreferences; import android.content.res.Configuration; import android.graphics.PorterDuff; -import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.os.Handler; -import android.text.TextUtils; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; @@ -22,7 +19,6 @@ import android.widget.TextView; import androidx.annotation.NonNull; -import androidx.annotation.RequiresApi; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.AlertDialog; @@ -44,22 +40,18 @@ import com.kunfei.bookshelf.MApplication; import com.kunfei.bookshelf.R; import com.kunfei.bookshelf.base.BaseTabActivity; -import com.kunfei.bookshelf.base.observer.MySingleObserver; import com.kunfei.bookshelf.constant.RxBusTag; import com.kunfei.bookshelf.help.FileHelp; import com.kunfei.bookshelf.help.ProcessTextHelp; import com.kunfei.bookshelf.help.permission.Permissions; import com.kunfei.bookshelf.help.permission.PermissionsCompat; -import com.kunfei.bookshelf.help.storage.Backup; -import com.kunfei.bookshelf.help.storage.Restore; -import com.kunfei.bookshelf.help.storage.WebDavHelp; +import com.kunfei.bookshelf.help.storage.BackupRestoreUi; import com.kunfei.bookshelf.model.UpLastChapterModel; import com.kunfei.bookshelf.presenter.MainPresenter; import com.kunfei.bookshelf.presenter.contract.MainContract; import com.kunfei.bookshelf.service.WebService; import com.kunfei.bookshelf.utils.ACache; import com.kunfei.bookshelf.utils.StringUtils; -import com.kunfei.bookshelf.utils.theme.ATH; import com.kunfei.bookshelf.utils.theme.NavigationViewUtil; import com.kunfei.bookshelf.utils.theme.ThemeStore; import com.kunfei.bookshelf.view.fragment.BookListFragment; @@ -67,27 +59,19 @@ import com.kunfei.bookshelf.widget.modialog.InputDialog; import com.kunfei.bookshelf.widget.modialog.MoDialogHUD; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import butterknife.BindView; import butterknife.ButterKnife; -import io.reactivex.Single; -import io.reactivex.SingleOnSubscribe; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.schedulers.Schedulers; import kotlin.Unit; import static com.kunfei.bookshelf.utils.NetworkUtils.isNetWorkAvailable; public class MainActivity extends BaseTabActivity implements MainContract.View, - BookListFragment.CallbackValue, - Backup.CallBack { + BookListFragment.CallbackValue { private final int requestSource = 14; - private final int backupSelectRequestCode = 23; - private final int restoreSelectRequestCode = 33; private String[] mTitles; @BindView(R.id.drawer) @@ -568,10 +552,10 @@ private void setUpNavigationView() { handler.postDelayed(() -> DonateActivity.startThis(this), 200); break; case R.id.action_backup: - handler.postDelayed(this::backup, 200); + handler.postDelayed(() -> BackupRestoreUi.INSTANCE.backup(this), 200); break; case R.id.action_restore: - handler.postDelayed(this::restore, 200); + handler.postDelayed(() -> BackupRestoreUi.INSTANCE.restore(this), 200); break; case R.id.action_theme: handler.postDelayed(() -> ThemeSettingActivity.startThis(this), 200); @@ -604,128 +588,6 @@ private void selectBookshelfLayout() { }).show(); } - private String getBackupPath() { - return preferences.getString("backupPath", ""); - } - - /** - * 备份 - */ - private void backup() { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { - String path = getBackupPath(); - if (TextUtils.isEmpty(path)) { - selectBackupFolder(); - } else { - Backup.INSTANCE.backup(this, Uri.parse(path), MainActivity.this); - } - } else { - backupOld(); - } - } - - private void backupOld() { - new PermissionsCompat.Builder(this) - .addPermissions(Permissions.READ_EXTERNAL_STORAGE, Permissions.WRITE_EXTERNAL_STORAGE) - .rationale(R.string.backup_permission) - .onGranted((requestCode) -> { - AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this) - .setTitle(R.string.backup_confirmation) - .setMessage(R.string.backup_message) - .setPositiveButton(R.string.ok, (dialog, which) -> - Backup.INSTANCE.backup(MainActivity.this, null, MainActivity.this) - ) - .setNegativeButton(R.string.cancel, null) - .show(); - ATH.setAlertDialogTint(alertDialog); - return Unit.INSTANCE; - }).request(); - } - - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - private void selectBackupFolder() { - try { - Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - startActivityForResult(intent, backupSelectRequestCode); - } catch (Exception e) { - backupOld(); - } - } - - /** - * 恢复 - */ - private void restore() { - Single.create((SingleOnSubscribe>) emitter -> { - emitter.onSuccess(WebDavHelp.INSTANCE.getWebDavFileNames()); - }).subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new MySingleObserver>() { - @Override - public void onSuccess(ArrayList strings) { - if (!WebDavHelp.INSTANCE.showRestoreDialog(MainActivity.this, strings)) { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { - String path = getBackupPath(); - if (TextUtils.isEmpty(path)) { - selectRestoreFolder(); - } else { - restore(Uri.parse(path)); - } - } else { - new PermissionsCompat.Builder(MainActivity.this) - .addPermissions(Permissions.READ_EXTERNAL_STORAGE, Permissions.WRITE_EXTERNAL_STORAGE) - .rationale(R.string.restore_permission) - .onGranted((requestCode) -> { - restoreOld(); - return Unit.INSTANCE; - }).request(); - } - } - } - }); - - } - - private void restore(Uri uri) { - Single.create((SingleOnSubscribe) e -> { - Restore.INSTANCE.restore(this, uri); - e.onSuccess(true); - }).subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new MySingleObserver() { - @Override - public void onSuccess(Boolean t) { - recreate(); - } - }); - } - - private void restoreOld() { - Single.create((SingleOnSubscribe) e -> { - Restore.INSTANCE.restore(Backup.INSTANCE.getDefaultPath()); - e.onSuccess(true); - }).subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new MySingleObserver() { - @Override - public void onSuccess(Boolean t) { - recreate(); - } - }); - } - - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - private void selectRestoreFolder() { - try { - Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - startActivityForResult(intent, restoreSelectRequestCode); - } catch (Exception e) { - restoreOld(); - } - } - /** * 新版本运行 */ @@ -790,11 +652,6 @@ public boolean onKeyDown(int keyCode, KeyEvent event) { } } - @Override - public void backupSuccess() { - toast(R.string.backup_success); - } - /** * 退出 */ @@ -822,6 +679,7 @@ protected void onDestroy() { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); + BackupRestoreUi.INSTANCE.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case requestSource: if (resultCode == RESULT_OK) { @@ -831,24 +689,6 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { } } break; - case backupSelectRequestCode: - if (resultCode == RESULT_OK && data != null) { - Uri uri = data.getData(); - if (uri == null) return; - getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - preferences.edit().putString("backupPath", uri.toString()).apply(); - backup(); - } - break; - case restoreSelectRequestCode: - if (resultCode == RESULT_OK && data != null) { - Uri uri = data.getData(); - if (uri == null) return; - getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - preferences.edit().putString("backupPath", uri.toString()).apply(); - restore(uri); - } - break; } } diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadBookActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadBookActivity.java index ea7060d3a4..92e4465b80 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadBookActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/ReadBookActivity.java @@ -1926,26 +1926,10 @@ public void finish() { Intent intent = new Intent(this, MainActivity.class); startActivity(intent); } - backup(); + Backup.INSTANCE.autoBack(); super.finish(); } - private void backup() { - String path = preferences.getString("backupPath", ""); - if (TextUtils.isEmpty(path)) { - new PermissionsCompat.Builder(this) - .addPermissions(Permissions.READ_EXTERNAL_STORAGE, Permissions.WRITE_EXTERNAL_STORAGE) - .rationale("自动备份需要存储权限") - .onGranted((requestCode) -> { - Backup.INSTANCE.backup(ReadBookActivity.this, null, null); - return Unit.INSTANCE; - }) - .request(); - } else { - Backup.INSTANCE.backup(this, Uri.parse(path), null); - } - } - @Override public void changeSourceFinish(BookShelfBean book) { if (mPageLoader != null && mPageLoader instanceof PageLoaderNet) { diff --git a/app/src/main/java/com/kunfei/bookshelf/view/fragment/WebDavSettingsFragment.java b/app/src/main/java/com/kunfei/bookshelf/view/fragment/WebDavSettingsFragment.java index d461f070d9..5f1e4b66f7 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/fragment/WebDavSettingsFragment.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/fragment/WebDavSettingsFragment.java @@ -15,6 +15,7 @@ import com.kunfei.bookshelf.base.observer.MySingleObserver; import com.kunfei.bookshelf.help.FileHelp; import com.kunfei.bookshelf.help.ProcessTextHelp; +import com.kunfei.bookshelf.help.storage.BackupRestoreUi; import com.kunfei.bookshelf.help.storage.WebDavHelp; import com.kunfei.bookshelf.view.activity.SettingActivity; @@ -123,6 +124,7 @@ public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preferen } private void restore() { + Single.create((SingleOnSubscribe>) emitter -> { emitter.onSuccess(WebDavHelp.INSTANCE.getWebDavFileNames()); }).subscribeOn(Schedulers.io()) @@ -130,7 +132,7 @@ private void restore() { .subscribe(new MySingleObserver>() { @Override public void onSuccess(ArrayList strings) { - if (!WebDavHelp.INSTANCE.showRestoreDialog(getActivity(), strings)) { + if (!WebDavHelp.INSTANCE.showRestoreDialog(getActivity(), strings, BackupRestoreUi.INSTANCE)) { Toast.makeText(getActivity(), "没有备份", Toast.LENGTH_SHORT).show(); } } diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index e3664e9384..4b2c5e561b 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -76,6 +76,12 @@ 2 + + @string/default_path + @string/sys_folder_picker + @string/app_folder_picker + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c438fbbcd1..56c522e8cc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -419,6 +419,7 @@ 二字符缩进 三字符缩进 四字符缩进 + 选择文件夹 选择SD卡 没有发现,可以在书源里添加。 恢复默认 @@ -431,7 +432,10 @@ 正文边距 Tip边距 字距 - + 默认路径 + 系统文件夹选择器 + 自带选择器\n(Android10以上因权限限制可能无法使用) + Android10以上因权限限制可能无法读写文件 E-Ink 模式 去除动画,优化电纸书使用体验 Web服务 From 6247632dafda275a1ccb1925ba75f19867675e85 Mon Sep 17 00:00:00 2001 From: kunfei Date: Mon, 10 Feb 2020 12:39:08 +0800 Subject: [PATCH 035/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kunfei/bookshelf/help/storage/BackupRestoreUi.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/BackupRestoreUi.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/BackupRestoreUi.kt index 1157b07961..69e0ae0e1b 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/BackupRestoreUi.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/BackupRestoreUi.kt @@ -93,7 +93,10 @@ object BackupRestoreUi : Backup.CallBack, Restore.CallBack { titleResource = R.string.select_folder items(activity.resources.getStringArray(R.array.select_folder).toList()) { _, index -> when (index) { - 0 -> backupUsePermission(activity) + 0 -> { + setBackupPath(Backup.defaultPath) + backupUsePermission(activity) + } 1 -> { try { val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) From 2a3c7822c2ae8e461348d1656cce878a59f16f82 Mon Sep 17 00:00:00 2001 From: kunfei Date: Mon, 10 Feb 2020 12:40:32 +0800 Subject: [PATCH 036/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index ce4f69b29d..bf9fdc2a4a 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -1,7 +1,10 @@ ## 本软件为开源软件,请不要在任何地方购买! -### 关注公众号[开源阅读软件]点击广告可支持作者! +### 关注公众号 **开源阅读软件** 点击广告可支持作者! ### 捐赠里点击红包搜索码可开启高级功能! +**2020/02/10** +* 优化备份恢复 + **2020/02/05** * 修复bug From 3d6cc72d80019a301a3c8e46593ffab56b4c1f53 Mon Sep 17 00:00:00 2001 From: kunfei Date: Mon, 10 Feb 2020 12:43:01 +0800 Subject: [PATCH 037/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/kunfei/bookshelf/service/ReadAloudService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/service/ReadAloudService.java b/app/src/main/java/com/kunfei/bookshelf/service/ReadAloudService.java index 2c1c1d7a69..2d4c080af8 100644 --- a/app/src/main/java/com/kunfei/bookshelf/service/ReadAloudService.java +++ b/app/src/main/java/com/kunfei/bookshelf/service/ReadAloudService.java @@ -82,7 +82,7 @@ public class ReadAloudService extends Service { private Boolean pause = false; private List contentList = new ArrayList<>(); private int nowSpeak; - private int timeMinute = 0; + private static int timeMinute = 0; private boolean timerEnable = false; private AudioManager audioManager; private MediaSessionCompat mediaSessionCompat; From 61f5d2293299d3891ca9f93fe9737e5ca6b10179 Mon Sep 17 00:00:00 2001 From: kunfei Date: Mon, 10 Feb 2020 13:09:54 +0800 Subject: [PATCH 038/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bookshelf/help/permission/ActivitySource.kt | 7 +++---- .../help/permission/PermissionActivity.kt | 4 ++-- .../help/permission/PermissionsCompat.kt | 4 ++-- .../kunfei/bookshelf/help/permission/Request.kt | 4 ++-- .../bookshelf/help/storage/BackupRestoreUi.kt | 16 ++++++++-------- .../bookshelf/service/ReadAloudService.java | 9 +-------- .../view/fragment/SettingsFragment.java | 11 ++--------- 7 files changed, 20 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/permission/ActivitySource.kt b/app/src/main/java/com/kunfei/bookshelf/help/permission/ActivitySource.kt index 71a054a375..5f33da3291 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/permission/ActivitySource.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/permission/ActivitySource.kt @@ -1,14 +1,13 @@ package com.kunfei.bookshelf.help.permission +import android.app.Activity import android.content.Context import android.content.Intent -import androidx.appcompat.app.AppCompatActivity - import java.lang.ref.WeakReference -internal class ActivitySource(activity: AppCompatActivity) : RequestSource { +internal class ActivitySource(activity: Activity) : RequestSource { - private val actRef: WeakReference = WeakReference(activity) + private val actRef: WeakReference = WeakReference(activity) override val context: Context? get() = actRef.get() diff --git a/app/src/main/java/com/kunfei/bookshelf/help/permission/PermissionActivity.kt b/app/src/main/java/com/kunfei/bookshelf/help/permission/PermissionActivity.kt index 22a015bcbe..1f62adeb0e 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/permission/PermissionActivity.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/permission/PermissionActivity.kt @@ -1,16 +1,16 @@ package com.kunfei.bookshelf.help.permission +import android.app.Activity import android.content.Intent import android.net.Uri import android.os.Bundle import android.provider.Settings import android.view.KeyEvent import android.widget.Toast -import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import com.kunfei.bookshelf.R -class PermissionActivity : AppCompatActivity() { +class PermissionActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/permission/PermissionsCompat.kt b/app/src/main/java/com/kunfei/bookshelf/help/permission/PermissionsCompat.kt index 514dbf5363..61a51c3089 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/permission/PermissionsCompat.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/permission/PermissionsCompat.kt @@ -1,7 +1,7 @@ package com.kunfei.bookshelf.help.permission +import android.app.Activity import androidx.annotation.StringRes -import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment class PermissionsCompat private constructor() { @@ -15,7 +15,7 @@ class PermissionsCompat private constructor() { class Builder { private val request: Request - constructor(activity: AppCompatActivity) { + constructor(activity: Activity) { request = Request(activity) } diff --git a/app/src/main/java/com/kunfei/bookshelf/help/permission/Request.kt b/app/src/main/java/com/kunfei/bookshelf/help/permission/Request.kt index 9add285cdc..b06b422f1d 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/permission/Request.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/permission/Request.kt @@ -1,11 +1,11 @@ package com.kunfei.bookshelf.help.permission +import android.app.Activity import android.content.Intent import android.content.pm.PackageManager import android.os.Build import androidx.annotation.StringRes import androidx.appcompat.app.AlertDialog -import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import com.kunfei.bookshelf.R @@ -30,7 +30,7 @@ internal class Request : OnRequestPermissionsResultCallback { return getDeniedPermissions(this.permissions?.toTypedArray()) } - constructor(activity: AppCompatActivity) { + constructor(activity: Activity) { source = ActivitySource(activity) permissions = ArrayList() requestTime = System.currentTimeMillis() diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/BackupRestoreUi.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/BackupRestoreUi.kt index 69e0ae0e1b..a8cc619323 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/BackupRestoreUi.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/BackupRestoreUi.kt @@ -1,10 +1,10 @@ package com.kunfei.bookshelf.help.storage +import android.app.Activity import android.app.Activity.RESULT_OK import android.content.Intent import android.net.Uri import android.text.TextUtils -import androidx.appcompat.app.AppCompatActivity import androidx.documentfile.provider.DocumentFile import com.hwangjr.rxbus.RxBus import com.kunfei.bookshelf.MApplication @@ -58,7 +58,7 @@ object BackupRestoreUi : Backup.CallBack, Restore.CallBack { MApplication.getInstance().toast(msg) } - fun backup(activity: AppCompatActivity) { + fun backup(activity: Activity) { val backupPath = getBackupPath() if (backupPath.isNullOrEmpty()) { selectBackupFolder(activity) @@ -77,7 +77,7 @@ object BackupRestoreUi : Backup.CallBack, Restore.CallBack { } } - private fun backupUsePermission(activity: AppCompatActivity, path: String = Backup.defaultPath) { + private fun backupUsePermission(activity: Activity, path: String = Backup.defaultPath) { PermissionsCompat.Builder(activity) .addPermissions(*Permissions.Group.STORAGE) .rationale(R.string.get_storage_per) @@ -88,7 +88,7 @@ object BackupRestoreUi : Backup.CallBack, Restore.CallBack { .request() } - private fun selectBackupFolder(activity: AppCompatActivity) { + fun selectBackupFolder(activity: Activity) { activity.alert { titleResource = R.string.select_folder items(activity.resources.getStringArray(R.array.select_folder).toList()) { _, index -> @@ -121,7 +121,7 @@ object BackupRestoreUi : Backup.CallBack, Restore.CallBack { }.show() } - private fun selectBackupFolderApp(activity: AppCompatActivity, isRestore: Boolean) { + private fun selectBackupFolderApp(activity: Activity, isRestore: Boolean) { val picker = FilePicker(activity, FilePicker.DIRECTORY) picker.setBackgroundColor(activity.resources.getColor(R.color.background)) picker.setTopBackgroundColor(activity.resources.getColor(R.color.background)) @@ -137,7 +137,7 @@ object BackupRestoreUi : Backup.CallBack, Restore.CallBack { picker.show() } - fun restore(activity: AppCompatActivity) { + fun restore(activity: Activity) { Single.create { emitter: SingleEmitter?> -> emitter.onSuccess(getWebDavFileNames()) }.subscribeOn(Schedulers.io()) @@ -166,7 +166,7 @@ object BackupRestoreUi : Backup.CallBack, Restore.CallBack { }) } - private fun restoreUsePermission(activity: AppCompatActivity, path: String = Backup.defaultPath) { + private fun restoreUsePermission(activity: Activity, path: String = Backup.defaultPath) { PermissionsCompat.Builder(activity) .addPermissions(*Permissions.Group.STORAGE) .rationale(R.string.get_storage_per) @@ -177,7 +177,7 @@ object BackupRestoreUi : Backup.CallBack, Restore.CallBack { .request() } - private fun selectRestoreFolder(activity: AppCompatActivity) { + private fun selectRestoreFolder(activity: Activity) { activity.alert { titleResource = R.string.select_folder items(activity.resources.getStringArray(R.array.select_folder).toList()) { _, index -> diff --git a/app/src/main/java/com/kunfei/bookshelf/service/ReadAloudService.java b/app/src/main/java/com/kunfei/bookshelf/service/ReadAloudService.java index 2d4c080af8..b567b1b04e 100644 --- a/app/src/main/java/com/kunfei/bookshelf/service/ReadAloudService.java +++ b/app/src/main/java/com/kunfei/bookshelf/service/ReadAloudService.java @@ -15,7 +15,6 @@ import android.media.AudioManager; import android.media.MediaPlayer; import android.os.AsyncTask; -import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.IBinder; @@ -279,13 +278,7 @@ public int onStartCommand(Intent intent, int flags, int startId) { @Nullable @Override public IBinder onBind(Intent intent) { - return new MyBinder(); - } - - public class MyBinder extends Binder { - public ReadAloudService getService() { - return ReadAloudService.this; - } + return null; } private void initTTS() { diff --git a/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java b/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java index 8ca604547c..02db71310e 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java @@ -20,6 +20,7 @@ import com.kunfei.bookshelf.help.ProcessTextHelp; import com.kunfei.bookshelf.help.permission.Permissions; import com.kunfei.bookshelf.help.permission.PermissionsCompat; +import com.kunfei.bookshelf.help.storage.BackupRestoreUi; import com.kunfei.bookshelf.service.WebService; import com.kunfei.bookshelf.utils.FileUtils; import com.kunfei.bookshelf.utils.theme.ATH; @@ -113,15 +114,7 @@ public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preferen if (preference.getKey().equals(getString(R.string.pk_download_path))) { selectDownloadPath(preference); } else if (preference.getKey().equals("backupPath")) { - try { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { - Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - startActivityForResult(intent, backupSelectRequestCode); - } - } catch (Exception ignored) { - - } + BackupRestoreUi.INSTANCE.selectBackupFolder(getActivity()); } else if (preference.getKey().equals("webDavSetting")) { WebDavSettingsFragment webDavSettingsFragment = new WebDavSettingsFragment(); getFragmentManager().beginTransaction().replace(R.id.settingsFrameLayout, webDavSettingsFragment, "webDavSettings").commit(); From 50c8a08e678033838d4009549d75d6b086f4735e Mon Sep 17 00:00:00 2001 From: kunfei Date: Mon, 10 Feb 2020 13:48:49 +0800 Subject: [PATCH 039/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../view/activity/SettingActivity.java | 7 + .../view/fragment/SettingsFragment.java | 173 ------------------ .../view/fragment/SettingsFragment.kt | 161 ++++++++++++++++ 3 files changed, 168 insertions(+), 173 deletions(-) delete mode 100644 app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java create mode 100644 app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.kt diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/SettingActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/SettingActivity.java index a13d3e6b9a..16c1e5c97d 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/SettingActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/SettingActivity.java @@ -5,12 +5,14 @@ import android.view.MenuItem; import android.widget.LinearLayout; +import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBar; import androidx.appcompat.widget.Toolbar; import com.kunfei.basemvplib.impl.IPresenter; import com.kunfei.bookshelf.R; import com.kunfei.bookshelf.base.MBaseActivity; +import com.kunfei.bookshelf.help.storage.BackupRestoreUi; import com.kunfei.bookshelf.utils.theme.ThemeStore; import com.kunfei.bookshelf.view.fragment.SettingsFragment; @@ -103,4 +105,9 @@ public void initImmersionBar() { super.initImmersionBar(); } + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + BackupRestoreUi.INSTANCE.onActivityResult(requestCode, resultCode, data); + } } diff --git a/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java b/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java deleted file mode 100644 index 02db71310e..0000000000 --- a/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.java +++ /dev/null @@ -1,173 +0,0 @@ -package com.kunfei.bookshelf.view.fragment; - -import android.content.Intent; -import android.content.SharedPreferences; -import android.net.Uri; -import android.os.Bundle; -import android.preference.ListPreference; -import android.preference.Preference; -import android.preference.PreferenceFragment; -import android.preference.PreferenceScreen; - -import androidx.appcompat.app.AlertDialog; - -import com.hwangjr.rxbus.RxBus; -import com.kunfei.bookshelf.MApplication; -import com.kunfei.bookshelf.R; -import com.kunfei.bookshelf.constant.RxBusTag; -import com.kunfei.bookshelf.help.BookshelfHelp; -import com.kunfei.bookshelf.help.FileHelp; -import com.kunfei.bookshelf.help.ProcessTextHelp; -import com.kunfei.bookshelf.help.permission.Permissions; -import com.kunfei.bookshelf.help.permission.PermissionsCompat; -import com.kunfei.bookshelf.help.storage.BackupRestoreUi; -import com.kunfei.bookshelf.service.WebService; -import com.kunfei.bookshelf.utils.FileUtils; -import com.kunfei.bookshelf.utils.theme.ATH; -import com.kunfei.bookshelf.view.activity.SettingActivity; -import com.kunfei.bookshelf.widget.filepicker.picker.FilePicker; - -import java.util.Objects; - -import kotlin.Unit; - -import static android.app.Activity.RESULT_OK; - -/** - * Created by GKF on 2017/12/16. - * 设置 - */ -public class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener { - private SettingActivity settingActivity; - private final int backupSelectRequestCode = 23; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getPreferenceManager().setSharedPreferencesName("CONFIG"); - settingActivity = (SettingActivity) this.getActivity(); - settingActivity.setupActionBar(getString(R.string.setting)); - SharedPreferences sharedPreferences = getPreferenceManager().getSharedPreferences(); - SharedPreferences.Editor editor = sharedPreferences.edit(); - boolean processTextEnabled = ProcessTextHelp.isProcessTextEnabled(); - editor.putBoolean("process_text", processTextEnabled); - if (Objects.equals(sharedPreferences.getString(getString(R.string.pk_download_path), ""), "")) { - editor.putString(getString(R.string.pk_download_path), FileHelp.getCachePath()); - } - editor.apply(); - addPreferencesFromResource(R.xml.pref_settings); - bindPreferenceSummaryToValue(findPreference(getString(R.string.pk_bookshelf_px))); - bindPreferenceSummaryToValue(findPreference(getString(R.string.pk_download_path))); - bindPreferenceSummaryToValue(findPreference("backupPath")); - } - - private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = (Preference preference, Object value) -> { - String stringValue = value.toString(); - - if (preference instanceof ListPreference) { - ListPreference listPreference = (ListPreference) preference; - int index = listPreference.findIndexOfValue(stringValue); - // Set the summary to reflect the new value. - preference.setSummary(index >= 0 ? listPreference.getEntries()[index] : null); - } else { - // For all other preferences, set the summary to the value's - preference.setSummary(stringValue); - } - return true; - }; - - private void bindPreferenceSummaryToValue(Preference preference) { - // Set the listener to watch for value changes. - preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener); - sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, getPrefValue(preference.getKey())); - } - - private String getPrefValue(String key) { - return MApplication.getConfigPreferences().getString(key, ""); - } - - @Override - public void onResume() { - super.onResume(); - getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); - } - - @Override - public void onPause() { - getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); - super.onPause(); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if (key.equals(getString(R.string.pk_bookshelf_px)) || key.equals("behaviorMain")) { - RxBus.get().post(RxBusTag.RECREATE, true); - } else if (key.equals("process_text")) { - ProcessTextHelp.setProcessTextEnable(sharedPreferences.getBoolean("process_text", true)); - } else if (key.equals("webPort")) { - WebService.upHttpServer(settingActivity); - } - } - - @Override - public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { - if (preference.getKey().equals(getString(R.string.pk_download_path))) { - selectDownloadPath(preference); - } else if (preference.getKey().equals("backupPath")) { - BackupRestoreUi.INSTANCE.selectBackupFolder(getActivity()); - } else if (preference.getKey().equals("webDavSetting")) { - WebDavSettingsFragment webDavSettingsFragment = new WebDavSettingsFragment(); - getFragmentManager().beginTransaction().replace(R.id.settingsFrameLayout, webDavSettingsFragment, "webDavSettings").commit(); - } else if (preference.getKey().equals("clearCache")) { - AlertDialog alertDialog = new AlertDialog.Builder(getActivity()) - .setTitle(R.string.clear_cache) - .setMessage(getString(R.string.sure_del_download_book)) - .setPositiveButton(R.string.yes, (dialog, which) -> BookshelfHelp.clearCaches(true)) - .setNegativeButton(R.string.no, (dialogInterface, i) -> BookshelfHelp.clearCaches(false)) - .show(); - ATH.setAlertDialogTint(alertDialog); - } - return super.onPreferenceTreeClick(preferenceScreen, preference); - } - - private void selectDownloadPath(Preference preference) { - new PermissionsCompat.Builder(settingActivity) - .addPermissions(Permissions.READ_EXTERNAL_STORAGE, Permissions.WRITE_EXTERNAL_STORAGE) - .rationale(R.string.set_download_per) - .onGranted((requestCode) -> { - FilePicker picker = new FilePicker(getActivity(), FilePicker.DIRECTORY); - picker.setBackgroundColor(getResources().getColor(R.color.background)); - picker.setTopBackgroundColor(getResources().getColor(R.color.background)); - picker.setRootPath(preference.getSummary().toString()); - picker.setItemHeight(30); - picker.setOnFilePickListener(currentPath -> { - if (!currentPath.contains(FileUtils.getSdCardPath())) { - MApplication.getInstance().setDownloadPath(null); - } else { - MApplication.getInstance().setDownloadPath(currentPath); - } - preference.setSummary(MApplication.downloadPath); - }); - picker.show(); - picker.getCancelButton().setText(R.string.restore_default); - picker.getCancelButton().setOnClickListener(view -> { - picker.dismiss(); - MApplication.getInstance().setDownloadPath(null); - preference.setSummary(MApplication.downloadPath); - }); - return Unit.INSTANCE; - }) - .request(); - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (requestCode == backupSelectRequestCode && resultCode == RESULT_OK && data != null) { - Uri uri = data.getData(); - if (uri == null) return; - getPreferenceManager().getSharedPreferences().edit().putString("backupPath", uri.toString()).apply(); - findPreference("backupPath").setSummary(uri.toString()); - } - } -} diff --git a/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.kt b/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.kt new file mode 100644 index 0000000000..f7101ed210 --- /dev/null +++ b/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.kt @@ -0,0 +1,161 @@ +package com.kunfei.bookshelf.view.fragment + +import android.content.Intent +import android.content.SharedPreferences +import android.content.SharedPreferences.OnSharedPreferenceChangeListener +import android.os.Bundle +import android.preference.ListPreference +import android.preference.Preference +import android.preference.PreferenceFragment +import android.preference.PreferenceScreen +import android.view.View +import com.hwangjr.rxbus.RxBus +import com.kunfei.bookshelf.MApplication +import com.kunfei.bookshelf.R +import com.kunfei.bookshelf.constant.RxBusTag +import com.kunfei.bookshelf.help.BookshelfHelp +import com.kunfei.bookshelf.help.FileHelp +import com.kunfei.bookshelf.help.ProcessTextHelp +import com.kunfei.bookshelf.help.permission.Permissions +import com.kunfei.bookshelf.help.permission.PermissionsCompat +import com.kunfei.bookshelf.help.storage.BackupRestoreUi.selectBackupFolder +import com.kunfei.bookshelf.service.WebService +import com.kunfei.bookshelf.utils.FileUtils +import com.kunfei.bookshelf.view.activity.SettingActivity +import com.kunfei.bookshelf.widget.filepicker.picker.FilePicker +import org.jetbrains.anko.alert +import org.jetbrains.anko.noButton +import org.jetbrains.anko.okButton + +/** + * Created by GKF on 2017/12/16. + * 设置 + */ +@Suppress("DEPRECATION") +class SettingsFragment : PreferenceFragment(), OnSharedPreferenceChangeListener { + private var settingActivity: SettingActivity? = null + private lateinit var bookshelfPxKey: String + private lateinit var downloadPathKey: String + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + preferenceManager.sharedPreferencesName = "CONFIG" + settingActivity = activity as? SettingActivity + settingActivity?.setupActionBar(getString(R.string.setting)) + addPreferencesFromResource(R.xml.pref_settings) + val sharedPreferences = preferenceManager.sharedPreferences + val editor = sharedPreferences.edit() + val processTextEnabled = ProcessTextHelp.isProcessTextEnabled() + editor.putBoolean("process_text", processTextEnabled) + if (sharedPreferences.getString(getString(R.string.pk_download_path), "") == "") { + editor.putString(getString(R.string.pk_download_path), FileHelp.getCachePath()) + } + editor.apply() + bookshelfPxKey = getString(R.string.pk_bookshelf_px) + downloadPathKey = getString(R.string.pk_download_path) + upPreferenceSummary(bookshelfPxKey, sharedPreferences.getString(bookshelfPxKey, "0")) + upPreferenceSummary(downloadPathKey, MApplication.downloadPath) + upPreferenceSummary("backupPath", sharedPreferences.getString("backupPath", null)) + preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(this) + } + + override fun onDestroy() { + super.onDestroy() + preferenceManager.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this) + } + + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { + when (key) { + bookshelfPxKey -> { + upPreferenceSummary(key, sharedPreferences.getString(key, "0")) + RxBus.get().post(RxBusTag.RECREATE, true) + } + "behaviorMain" -> RxBus.get().post(RxBusTag.RECREATE, true) + "process_text" -> ProcessTextHelp.setProcessTextEnable(sharedPreferences.getBoolean("process_text", true)) + "webPort" -> WebService.upHttpServer(activity) + "backupPath" -> upPreferenceSummary(key, sharedPreferences.getString(key, null)) + downloadPathKey -> upPreferenceSummary(downloadPathKey, MApplication.downloadPath) + } + + if (key == bookshelfPxKey || key == "behaviorMain") { + RxBus.get().post(RxBusTag.RECREATE, true) + } else if (key == "process_text") { + ProcessTextHelp.setProcessTextEnable(sharedPreferences.getBoolean("process_text", true)) + } else if (key == "webPort") { + WebService.upHttpServer(activity) + } + } + + private fun upPreferenceSummary(preferenceKey: String, value: String?) { + val preference = findPreference(preferenceKey) ?: return + if (preference is ListPreference) { + val index = preference.findIndexOfValue(value) + // Set the summary to reflect the new value. + preference.summary = if (index >= 0) preference.entries[index] else null + } else { + preference.summary = value + } + } + + override fun onPreferenceTreeClick(preferenceScreen: PreferenceScreen, preference: Preference): Boolean { + when (preference.key) { + getString(R.string.pk_download_path) -> { + selectDownloadPath(preference) + } + "backupPath" -> { + selectBackupFolder(activity) + } + "webDavSetting" -> { + val webDavSettingsFragment = WebDavSettingsFragment() + fragmentManager.beginTransaction().replace(R.id.settingsFrameLayout, webDavSettingsFragment, "webDavSettings").commit() + } + "clearCache" -> { + alert { + titleResource = R.string.clear_cache + messageResource = R.string.sure_del_download_book + okButton { + BookshelfHelp.clearCaches(true) + } + noButton { + BookshelfHelp.clearCaches(false) + } + }.show() + } + } + return super.onPreferenceTreeClick(preferenceScreen, preference) + } + + private fun selectDownloadPath(preference: Preference) { + PermissionsCompat.Builder(activity) + .addPermissions(Permissions.READ_EXTERNAL_STORAGE, Permissions.WRITE_EXTERNAL_STORAGE) + .rationale(R.string.set_download_per) + .onGranted { + val picker = FilePicker(activity, FilePicker.DIRECTORY) + picker.setBackgroundColor(resources.getColor(R.color.background)) + picker.setTopBackgroundColor(resources.getColor(R.color.background)) + picker.setRootPath(preference.summary.toString()) + picker.setItemHeight(30) + picker.setOnFilePickListener { currentPath: String -> + if (!currentPath.contains(FileUtils.getSdCardPath())) { + MApplication.getInstance().setDownloadPath(null) + } else { + MApplication.getInstance().setDownloadPath(currentPath) + } + preference.summary = MApplication.downloadPath + } + picker.show() + picker.cancelButton.setText(R.string.restore_default) + picker.cancelButton.setOnClickListener { view: View? -> + picker.dismiss() + MApplication.getInstance().setDownloadPath(null) + preference.summary = MApplication.downloadPath + } + } + .request() + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { + super.onActivityResult(requestCode, resultCode, data) + } + +} \ No newline at end of file From 61c35c195d0f5b05207eb40e605468f363767197 Mon Sep 17 00:00:00 2001 From: kunfei Date: Mon, 10 Feb 2020 13:50:03 +0800 Subject: [PATCH 040/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index bf9fdc2a4a..9f2d146157 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -1,9 +1,10 @@ ## 本软件为开源软件,请不要在任何地方购买! -### 关注公众号 **开源阅读软件** 点击广告可支持作者! +### 关注公众号"开源阅读软件"点击广告可支持作者! ### 捐赠里点击红包搜索码可开启高级功能! **2020/02/10** * 优化备份恢复 +* 朗读定时会记住 **2020/02/05** * 修复bug From 4e9e4c154d1e8a2bfa11d91610e3b53f9db3629d Mon Sep 17 00:00:00 2001 From: kunfei Date: Mon, 10 Feb 2020 14:15:30 +0800 Subject: [PATCH 041/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bookshelf/help/storage/WebDavHelp.kt | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt index 7cfe32314c..7a21edafbd 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/WebDavHelp.kt @@ -1,6 +1,8 @@ package com.kunfei.bookshelf.help.storage import android.content.Context +import android.os.Handler +import android.os.Looper import com.kunfei.bookshelf.MApplication import com.kunfei.bookshelf.base.observer.MySingleObserver import com.kunfei.bookshelf.constant.AppConstant @@ -13,6 +15,7 @@ import io.reactivex.SingleOnSubscribe import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers import org.jetbrains.anko.selector +import org.jetbrains.anko.toast import java.io.File import java.text.SimpleDateFormat import java.util.* @@ -24,9 +27,11 @@ object WebDavHelp { FileHelp.getCachePath() } - private fun getWebDavUrl(): String? { + private fun getWebDavUrl(): String { var url = MApplication.getConfigPreferences().getString("web_dav_url", AppConstant.DEFAULT_WEB_DAV_URL) - if (url.isNullOrBlank()) return null + if (url.isNullOrEmpty()) { + url = AppConstant.DEFAULT_WEB_DAV_URL + } if (!url.endsWith("/")) url += "/" return url } @@ -45,7 +50,7 @@ object WebDavHelp { val url = getWebDavUrl() val names = arrayListOf() try { - if (!url.isNullOrBlank() && initWebDav()) { + if (initWebDav()) { var files = WebDav(url + "YueDu/").listFiles() files = files.reversed() for (index: Int in 0 until min(10, files.size)) { @@ -75,7 +80,7 @@ object WebDavHelp { private fun restoreWebDav(name: String, callBack: Restore.CallBack?) { Single.create(SingleOnSubscribe { e -> - getWebDavUrl()?.let { + getWebDavUrl().let { val file = WebDav(it + "YueDu/" + name) file.downloadTo(zipFilePath, true) @Suppress("BlockingMethodInNonBlockingContext") @@ -92,18 +97,24 @@ object WebDavHelp { } fun backUpWebDav(path: String) { - if (initWebDav()) { - val paths = arrayListOf(*Backup.backupFileNames) - for (i in 0 until paths.size) { - paths[i] = path + File.separator + paths[i] + try { + if (initWebDav()) { + val paths = arrayListOf(*Backup.backupFileNames) + for (i in 0 until paths.size) { + paths[i] = path + File.separator + paths[i] + } + FileHelp.deleteFile(zipFilePath) + if (ZipUtils.zipFiles(paths, zipFilePath)) { + WebDav(getWebDavUrl() + "YueDu").makeAsDir() + val putUrl = getWebDavUrl() + "YueDu/backup" + + SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) + .format(Date(System.currentTimeMillis())) + ".zip" + WebDav(putUrl).upload(zipFilePath) + } } - FileHelp.deleteFile(zipFilePath) - if (ZipUtils.zipFiles(paths, zipFilePath)) { - WebDav(getWebDavUrl() + "YueDu").makeAsDir() - val putUrl = getWebDavUrl() + "YueDu/backup" + - SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) - .format(Date(System.currentTimeMillis())) + ".zip" - WebDav(putUrl).upload(zipFilePath) + } catch (e: Exception) { + Handler(Looper.getMainLooper()).post { + MApplication.getInstance().toast("WebDav\n${e.localizedMessage}") } } } From 5dc1d43470f9c03cd550314f9d0d87d923245fde Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 11 Feb 2020 08:43:27 +0800 Subject: [PATCH 042/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt index 161cdba59c..bdfda57d4e 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt @@ -52,6 +52,7 @@ object Backup { } else { backup(MApplication.getInstance(), path, null) } + MApplication.getConfigPreferences().edit().putLong("lastBackup", System.currentTimeMillis()).apply() } fun backup(context: Context, path: String, callBack: CallBack?) { From 95ad5aabe125a94d603dd3a969c3667d40261095 Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 11 Feb 2020 15:42:06 +0800 Subject: [PATCH 043/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/kunfei/bookshelf/base/BaseModelImpl.java | 6 +++--- .../java/com/kunfei/bookshelf/help/EncodeConverter.java | 7 ++++++- .../com/kunfei/bookshelf/model/analyzeRule/AnalyzeUrl.java | 4 ++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/base/BaseModelImpl.java b/app/src/main/java/com/kunfei/bookshelf/base/BaseModelImpl.java index 0236998f5a..b7e0439ac2 100644 --- a/app/src/main/java/com/kunfei/bookshelf/base/BaseModelImpl.java +++ b/app/src/main/java/com/kunfei/bookshelf/base/BaseModelImpl.java @@ -41,19 +41,19 @@ public static BaseModelImpl getInstance() { public Observable> getResponseO(AnalyzeUrl analyzeUrl) { switch (analyzeUrl.getUrlMode()) { case POST: - return getRetrofitString(analyzeUrl.getHost()) + return getRetrofitString(analyzeUrl.getHost(), analyzeUrl.getCharCode()) .create(IHttpPostApi.class) .postMap(analyzeUrl.getPath(), analyzeUrl.getQueryMap(), analyzeUrl.getHeaderMap()); case GET: - return getRetrofitString(analyzeUrl.getHost()) + return getRetrofitString(analyzeUrl.getHost(), analyzeUrl.getCharCode()) .create(IHttpGetApi.class) .getMap(analyzeUrl.getPath(), analyzeUrl.getQueryMap(), analyzeUrl.getHeaderMap()); default: - return getRetrofitString(analyzeUrl.getHost()) + return getRetrofitString(analyzeUrl.getHost(), analyzeUrl.getCharCode()) .create(IHttpGetApi.class) .get(analyzeUrl.getPath(), analyzeUrl.getHeaderMap()); diff --git a/app/src/main/java/com/kunfei/bookshelf/help/EncodeConverter.java b/app/src/main/java/com/kunfei/bookshelf/help/EncodeConverter.java index 98faeaad77..9d43ced792 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/EncodeConverter.java +++ b/app/src/main/java/com/kunfei/bookshelf/help/EncodeConverter.java @@ -23,7 +23,12 @@ private EncodeConverter() { } private EncodeConverter(String encode) { - this.encode = encode; + try { + Charset charset = Charset.forName(encode); + this.encode = charset.name(); + } catch (Exception ignored) { + + } } public static EncodeConverter create() { diff --git a/app/src/main/java/com/kunfei/bookshelf/model/analyzeRule/AnalyzeUrl.java b/app/src/main/java/com/kunfei/bookshelf/model/analyzeRule/AnalyzeUrl.java index 1ba68538bf..bbc2e46622 100644 --- a/app/src/main/java/com/kunfei/bookshelf/model/analyzeRule/AnalyzeUrl.java +++ b/app/src/main/java/com/kunfei/bookshelf/model/analyzeRule/AnalyzeUrl.java @@ -260,6 +260,10 @@ private Object evalJS(String jsStr, Object result) throws Exception { return SCRIPT_ENGINE.eval(jsStr, bindings); } + public String getCharCode() { + return charCode; + } + public String getHost() { return host; } From d9bfbf4c6be3a1f47c278a1441fd6fbc8a5c55aa Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 11 Feb 2020 16:00:38 +0800 Subject: [PATCH 044/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kunfei/bookshelf/help/EncodeConverter.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/EncodeConverter.java b/app/src/main/java/com/kunfei/bookshelf/help/EncodeConverter.java index 9d43ced792..adf28c7eba 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/EncodeConverter.java +++ b/app/src/main/java/com/kunfei/bookshelf/help/EncodeConverter.java @@ -23,12 +23,7 @@ private EncodeConverter() { } private EncodeConverter(String encode) { - try { - Charset charset = Charset.forName(encode); - this.encode = charset.name(); - } catch (Exception ignored) { - - } + this.encode = encode; } public static EncodeConverter create() { @@ -44,7 +39,10 @@ public Converter responseBodyConverter(Type type, Annotati return value -> { byte[] responseBytes = UTF8BOMFighter.removeUTF8BOM(value.bytes()); if (!TextUtils.isEmpty(encode)) { - return new String((responseBytes), encode); + try { + return new String((responseBytes), Charset.forName(encode)); + } catch (Exception ignored) { + } } String charsetStr; MediaType mediaType = value.contentType(); @@ -54,7 +52,10 @@ public Converter responseBodyConverter(Type type, Annotati if (charset != null) { charsetStr = charset.displayName(); if (!isEmpty(charsetStr)) { - return new String(responseBytes, Charset.forName(charsetStr)); + try { + return new String((responseBytes), Charset.forName(charsetStr)); + } catch (Exception ignored) { + } } } } @@ -63,4 +64,5 @@ public Converter responseBodyConverter(Type type, Annotati return new String(responseBytes, Charset.forName(charsetStr)); }; } + } From 7fa6b1211d2f2e5e917736291a862d50a7c4bda3 Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 11 Feb 2020 16:09:28 +0800 Subject: [PATCH 045/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kunfei/bookshelf/help/EncodeConverter.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/EncodeConverter.java b/app/src/main/java/com/kunfei/bookshelf/help/EncodeConverter.java index adf28c7eba..0b4b333dc1 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/EncodeConverter.java +++ b/app/src/main/java/com/kunfei/bookshelf/help/EncodeConverter.java @@ -13,8 +13,6 @@ import retrofit2.Converter; import retrofit2.Retrofit; -import static android.text.TextUtils.isEmpty; - public class EncodeConverter extends Converter.Factory { private String encode; @@ -50,13 +48,7 @@ public Converter responseBodyConverter(Type type, Annotati if (mediaType != null) { Charset charset = mediaType.charset(); if (charset != null) { - charsetStr = charset.displayName(); - if (!isEmpty(charsetStr)) { - try { - return new String((responseBytes), Charset.forName(charsetStr)); - } catch (Exception ignored) { - } - } + return new String((responseBytes), charset); } } //根据内容判断 From 376fa29c6c04d0737f460574975f81eee1254f21 Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 12 Feb 2020 12:06:33 +0800 Subject: [PATCH 046/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index f4865d5936..12229a591f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -74,7 +74,7 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(':basemvplib') - api 'androidx.core:core-ktx:1.2.0-rc01' + api 'androidx.core:core-ktx:1.1.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" //anko From b01fff89e09da0ab12a9327c529b36568c27064e Mon Sep 17 00:00:00 2001 From: kunfei Date: Thu, 13 Feb 2020 14:19:04 +0800 Subject: [PATCH 047/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kunfei/bookshelf/widget/prefs/IconListPreference.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/prefs/IconListPreference.java b/app/src/main/java/com/kunfei/bookshelf/widget/prefs/IconListPreference.java index 78b8325242..85ea2cc4a0 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/prefs/IconListPreference.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/prefs/IconListPreference.java @@ -91,11 +91,11 @@ public AppArrayAdapter(Context context, int textViewResourceId, public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = ((Activity) getContext()).getLayoutInflater(); View view = inflater.inflate(R.layout.item_icon_preference, parent, false); - CheckedTextView textView = (CheckedTextView) view.findViewById(R.id.label); + CheckedTextView textView = view.findViewById(R.id.label); textView.setText(getItem(position)); textView.setChecked(position == mSelectedIndex); - ImageView imageView = (ImageView) view.findViewById(R.id.icon); + ImageView imageView = view.findViewById(R.id.icon); imageView.setImageDrawable(mImageDrawables.get(position)); return view; } From e3a59dab25d626ad96acb4cc1e7f09aa0bf46b2f Mon Sep 17 00:00:00 2001 From: kunfei Date: Fri, 14 Feb 2020 08:30:10 +0800 Subject: [PATCH 048/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 12229a591f..98fe1909a5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -74,7 +74,7 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(':basemvplib') - api 'androidx.core:core-ktx:1.1.0' + api 'androidx.core:core-ktx:1.2.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" //anko From 572e897e2816ccb7ee52f1db3b0acb704b7ee979 Mon Sep 17 00:00:00 2001 From: kunfei Date: Fri, 14 Feb 2020 10:48:44 +0800 Subject: [PATCH 049/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 7 -- .../view/activity/WelcomeActivity.java | 4 + .../view/activity/WelcomeBookActivity.java | 6 -- .../view/activity/WelcomeToReadActivity.java | 75 ------------------- app/src/main/res/xml/shortcuts.xml | 8 +- 5 files changed, 11 insertions(+), 89 deletions(-) delete mode 100644 app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java delete mode 100644 app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeToReadActivity.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0d58955cda..6a294a690a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -57,13 +57,6 @@ android:name="android.app.shortcuts" android:resource="@xml/shortcuts" /> - - - - - { - float alpha = (Float) animation.getAnimatedValue(); - ivBg.setAlpha(alpha); - }); - welAnimator.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - startReadActivity(); - finish(); - } - - @Override - public void onAnimationEnd(Animator animation) { - - } - - @Override - public void onAnimationCancel(Animator animation) { - - } - - @Override - public void onAnimationRepeat(Animator animation) { - - } - }); - welAnimator.start(); - } - - private void startReadActivity() { - Intent intent = new Intent(this, ReadBookActivity.class); - intent.putExtra("openFrom", ReadBookPresenter.OPEN_FROM_APP); - startActivity(intent); - } - - @Override - protected void initData() { - - } - -} diff --git a/app/src/main/res/xml/shortcuts.xml b/app/src/main/res/xml/shortcuts.xml index 0a1e858190..124e9766ea 100644 --- a/app/src/main/res/xml/shortcuts.xml +++ b/app/src/main/res/xml/shortcuts.xml @@ -13,7 +13,13 @@ + android:targetClass="com.kunfei.bookshelf.view.activity.MainActivity" /> + + + From 10800c2a92e5695690fc3f29f6e0fd54dc32b0d6 Mon Sep 17 00:00:00 2001 From: kunfei Date: Fri, 14 Feb 2020 11:14:31 +0800 Subject: [PATCH 050/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kunfei/bookshelf/view/activity/WelcomeActivity.java | 4 ---- .../kunfei/bookshelf/view/activity/WelcomeBookActivity.java | 5 +++++ 2 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeActivity.java index 24980b3c0e..a98517b1a0 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeActivity.java @@ -88,8 +88,4 @@ protected void initData() { } -} - -class WelcomeBookActivity extends WelcomeActivity { - } \ No newline at end of file diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java new file mode 100644 index 0000000000..4136dfee48 --- /dev/null +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java @@ -0,0 +1,5 @@ +package com.kunfei.bookshelf.view.activity; + +class WelcomeBookActivity extends WelcomeActivity { + +} From 3b34be35b8259030e9b339785f0dd05b7098db79 Mon Sep 17 00:00:00 2001 From: kunfei Date: Fri, 14 Feb 2020 14:12:05 +0800 Subject: [PATCH 051/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java b/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java index 4136dfee48..95dc6b5f8d 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/view/activity/WelcomeBookActivity.java @@ -1,5 +1,5 @@ package com.kunfei.bookshelf.view.activity; -class WelcomeBookActivity extends WelcomeActivity { +public class WelcomeBookActivity extends WelcomeActivity { } From 21a9f9c4da34c70163a4a45b9a63728b6932efe2 Mon Sep 17 00:00:00 2001 From: kunfei Date: Fri, 14 Feb 2020 16:44:17 +0800 Subject: [PATCH 052/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/kunfei/bookshelf/help/BookshelfHelp.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/BookshelfHelp.java b/app/src/main/java/com/kunfei/bookshelf/help/BookshelfHelp.java index c8c8c7f4ff..bb35ce8c5e 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/BookshelfHelp.java +++ b/app/src/main/java/com/kunfei/bookshelf/help/BookshelfHelp.java @@ -254,6 +254,7 @@ public static BookShelfBean getBook(String bookUrl) { public static List searchBookInfo(String key) { return DbHelper.getDaoSession().getBookInfoBeanDao().queryBuilder() .where(BookInfoBeanDao.Properties.Name.like("%" + key + "%")) + .orderAsc(BookInfoBeanDao.Properties.Name) .list(); } From 7c91a96c3d6bc94b3621b72ebf1a6fa71ca3e867 Mon Sep 17 00:00:00 2001 From: kunfei Date: Sat, 15 Feb 2020 13:24:55 +0800 Subject: [PATCH 053/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 3 +++ .../kunfei/bookshelf/utils/webdav/WebDav.kt | 19 +++++++------------ basemvplib/build.gradle | 3 +-- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 9f2d146157..e1bc31bf75 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -2,6 +2,9 @@ ### 关注公众号"开源阅读软件"点击广告可支持作者! ### 捐赠里点击红包搜索码可开启高级功能! +**2020/02/15** +* 修复低版本无法联网的问题 + **2020/02/10** * 优化备份恢复 * 朗读定时会记住 diff --git a/app/src/main/java/com/kunfei/bookshelf/utils/webdav/WebDav.kt b/app/src/main/java/com/kunfei/bookshelf/utils/webdav/WebDav.kt index 30078c049c..a7e84c3aa3 100644 --- a/app/src/main/java/com/kunfei/bookshelf/utils/webdav/WebDav.kt +++ b/app/src/main/java/com/kunfei/bookshelf/utils/webdav/WebDav.kt @@ -3,12 +3,7 @@ package com.kunfei.bookshelf.utils.webdav import com.kunfei.bookshelf.base.BaseModelImpl import com.kunfei.bookshelf.utils.webdav.http.Handler import com.kunfei.bookshelf.utils.webdav.http.HttpAuth -import okhttp3.Credentials -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.Request -import okhttp3.RequestBody.Companion.asRequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import okhttp3.Response +import okhttp3.* import org.jsoup.Jsoup import java.io.File import java.io.IOException @@ -82,7 +77,7 @@ constructor(urlStr: String) { this.exists = false return false } - response.body?.let { + response.body()?.let { if (it.string().isNotEmpty()) { return true } @@ -102,7 +97,7 @@ constructor(urlStr: String) { fun listFiles(propsList: ArrayList = ArrayList()): List { propFindResponse(propsList)?.let { response -> if (response.isSuccessful) { - response.body?.let { body -> + response.body()?.let { body -> return parseDir(body.string()) } } @@ -127,7 +122,7 @@ constructor(urlStr: String) { .url(url) // 添加RequestBody对象,可以只返回的属性。如果设为null,则会返回全部属性 // 注意:尽量手动指定需要返回的属性。若返回全部属性,可能后由于Prop.java里没有该属性名,而崩溃。 - .method("PROPFIND", requestPropsStr.toRequestBody("text/plain".toMediaTypeOrNull())) + .method("PROPFIND", RequestBody.create(MediaType.parse("text/plain"), requestPropsStr)) HttpAuth.auth?.let { request.header( @@ -206,9 +201,9 @@ constructor(urlStr: String) { fun upload(localPath: String, contentType: String? = null): Boolean { val file = File(localPath) if (!file.exists()) return false - val mediaType = contentType?.toMediaTypeOrNull() + val mediaType = if (contentType == null) null else MediaType.parse(contentType) // 务必注意RequestBody不要嵌套,不然上传时内容可能会被追加多余的文件信息 - val fileBody = file.asRequestBody(mediaType) + val fileBody = RequestBody.create(mediaType, file) httpUrl?.let { val request = Request.Builder() .url(it) @@ -242,7 +237,7 @@ constructor(urlStr: String) { request.header("Authorization", Credentials.basic(it.user, it.pass)) } try { - return BaseModelImpl.getClient().newCall(request.build()).execute().body?.byteStream() + return BaseModelImpl.getClient().newCall(request.build()).execute().body()?.byteStream() } catch (e: IOException) { e.printStackTrace() } catch (e: IllegalArgumentException) { diff --git a/basemvplib/build.gradle b/basemvplib/build.gradle index b4757af48a..455e9a60b4 100644 --- a/basemvplib/build.gradle +++ b/basemvplib/build.gradle @@ -30,7 +30,7 @@ dependencies { api fileTree(dir: 'libs', include: ['*.jar']) //support - api 'androidx.core:core:1.2.0-rc01' + api 'androidx.core:core:1.2.0' api 'androidx.appcompat:appcompat:1.1.0' //RxAndroid @@ -41,7 +41,6 @@ dependencies { api 'com.hwangjr.rxbus:rxbus:2.0.1' //Retrofit - implementation 'com.squareup.okhttp3:logging-interceptor:4.1.0' api 'com.squareup.retrofit2:retrofit:2.6.1' api 'com.squareup.retrofit2:adapter-rxjava2:2.6.1' api 'com.squareup.retrofit2:converter-scalars:2.6.1' From eaea66474e1bb015b345f1050b9cd150552dd570 Mon Sep 17 00:00:00 2001 From: kunfei Date: Sat, 15 Feb 2020 13:25:10 +0800 Subject: [PATCH 054/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index e1bc31bf75..90310ee960 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -3,7 +3,7 @@ ### 捐赠里点击红包搜索码可开启高级功能! **2020/02/15** -* 修复低版本无法联网的问题 +* 修复低版本手机无法联网的问题 **2020/02/10** * 优化备份恢复 From cd69baa3548c2e945afdb207ce41a5584b5cd51e Mon Sep 17 00:00:00 2001 From: kunfei Date: Sat, 15 Feb 2020 15:18:50 +0800 Subject: [PATCH 055/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kunfei/bookshelf/help/BookshelfHelp.java | 2 +- .../com/kunfei/bookshelf/help/FileHelp.java | 2 +- .../kunfei/bookshelf/help/storage/Backup.kt | 25 +++++++++++-------- .../kunfei/bookshelf/help/storage/Restore.kt | 12 ++++----- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/BookshelfHelp.java b/app/src/main/java/com/kunfei/bookshelf/help/BookshelfHelp.java index bb35ce8c5e..7c7f37060d 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/BookshelfHelp.java +++ b/app/src/main/java/com/kunfei/bookshelf/help/BookshelfHelp.java @@ -125,7 +125,7 @@ public static synchronized boolean saveChapterInfo(String folderName, int index, * 创建或获取存储文件 */ public static File getBookFile(String folderName, int index, String fileName) { - return FileHelp.getFile(AppConstant.BOOK_CACHE_PATH + formatFolderName(folderName) + return FileHelp.createFileIfNotExist(AppConstant.BOOK_CACHE_PATH + formatFolderName(folderName) + File.separator + getCacheFileName(index, fileName) + FileHelp.SUFFIX_NB); } diff --git a/app/src/main/java/com/kunfei/bookshelf/help/FileHelp.java b/app/src/main/java/com/kunfei/bookshelf/help/FileHelp.java index 3237697c6d..43efdd9290 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/FileHelp.java +++ b/app/src/main/java/com/kunfei/bookshelf/help/FileHelp.java @@ -41,7 +41,7 @@ public static File getFolder(String filePath) { } //获取文件 - public static synchronized File getFile(String filePath) { + public static synchronized File createFileIfNotExist(String filePath) { File file = new File(filePath); try { if (!file.exists()) { diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt index bdfda57d4e..2daa47085e 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt @@ -60,32 +60,32 @@ object Backup { BookshelfHelp.getAllBook().let { if (it.isNotEmpty()) { val json = GSON.toJson(it) - FileHelp.getFile(backupPath + File.separator + "myBookShelf.json").writeText(json) + FileHelp.createFileIfNotExist(backupPath + File.separator + "myBookShelf.json").writeText(json) } } BookSourceManager.getAllBookSource().let { if (it.isNotEmpty()) { val json = GSON.toJson(it) - FileHelp.getFile(backupPath + File.separator + "myBookSource.json").writeText(json) + FileHelp.createFileIfNotExist(backupPath + File.separator + "myBookSource.json").writeText(json) } } DbHelper.getDaoSession().searchHistoryBeanDao.queryBuilder().list().let { if (it.isNotEmpty()) { val json = GSON.toJson(it) - FileHelp.getFile(backupPath + File.separator + "myBookSearchHistory.json") + FileHelp.createFileIfNotExist(backupPath + File.separator + "myBookSearchHistory.json") .writeText(json) } } ReplaceRuleManager.getAll().blockingGet().let { if (it.isNotEmpty()) { val json = GSON.toJson(it) - FileHelp.getFile(backupPath + File.separator + "myBookReplaceRule.json").writeText(json) + FileHelp.createFileIfNotExist(backupPath + File.separator + "myBookReplaceRule.json").writeText(json) } } TxtChapterRuleManager.getAll().let { if (it.isNotEmpty()) { val json = GSON.toJson(it) - FileHelp.getFile(backupPath + File.separator + "myTxtChapterRule.json") + FileHelp.createFileIfNotExist(backupPath + File.separator + "myTxtChapterRule.json") .writeText(json) } } @@ -128,9 +128,12 @@ object Backup { private fun copyBackup(context: Context, uri: Uri) { DocumentFile.fromTreeUri(context, uri)?.let { treeDoc -> for (fileName in backupFileNames) { - val doc = treeDoc.findFile(fileName) ?: treeDoc.createFile("", fileName) - doc?.let { - DocumentUtil.writeBytes(context, FileHelp.getFile(backupPath + File.separator + fileName).readBytes(), doc) + val file = File(backupPath + File.separator + fileName) + if (file.exists()) { + val doc = treeDoc.findFile(fileName) ?: treeDoc.createFile("", fileName) + doc?.let { + DocumentUtil.writeBytes(context, file.readBytes(), doc) + } } } } @@ -139,8 +142,10 @@ object Backup { @Throws(java.lang.Exception::class) private fun copyBackup(path: String) { for (fileName in backupFileNames) { - FileHelp.getFile(backupPath + File.separator + fileName) - .copyTo(FileHelp.getFile(path + File.separator + fileName), true) + val file = File(backupPath + File.separator + fileName) + if (file.exists()) { + file.copyTo(FileHelp.createFileIfNotExist(path + File.separator + fileName), true) + } } } diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt index fb87bc78c6..3a8e57935b 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt @@ -31,7 +31,7 @@ object Restore { for (fileName in Backup.backupFileNames) { if (doc.name == fileName) { DocumentUtil.readBytes(context, doc.uri)?.let { - FileHelp.getFile(Backup.backupPath + File.separator + fileName) + FileHelp.createFileIfNotExist(Backup.backupPath + File.separator + fileName) .writeBytes(it) } } @@ -55,7 +55,7 @@ object Restore { fun restore(path: String, callBack: CallBack?) { Single.create(SingleOnSubscribe { e -> try { - val file = FileHelp.getFile(path + File.separator + "myBookShelf.json") + val file = FileHelp.createFileIfNotExist(path + File.separator + "myBookShelf.json") val json = file.readText() GSON.fromJsonArray(json)?.forEach { bookshelf -> if (bookshelf.noteUrl != null) { @@ -69,7 +69,7 @@ object Restore { e.printStackTrace() } try { - val file = FileHelp.getFile(path + File.separator + "myBookSource.json") + val file = FileHelp.createFileIfNotExist(path + File.separator + "myBookSource.json") val json = file.readText() GSON.fromJsonArray(json)?.let { BookSourceManager.addBookSource(it) @@ -78,7 +78,7 @@ object Restore { e.printStackTrace() } try { - val file = FileHelp.getFile(path + File.separator + "myBookSearchHistory.json") + val file = FileHelp.createFileIfNotExist(path + File.separator + "myBookSearchHistory.json") val json = file.readText() GSON.fromJsonArray(json)?.let { DbHelper.getDaoSession().searchHistoryBeanDao.insertOrReplaceInTx(it) @@ -87,7 +87,7 @@ object Restore { e.printStackTrace() } try { - val file = FileHelp.getFile(path + File.separator + "myBookReplaceRule.json") + val file = FileHelp.createFileIfNotExist(path + File.separator + "myBookReplaceRule.json") val json = file.readText() GSON.fromJsonArray(json)?.let { ReplaceRuleManager.addDataS(it) @@ -96,7 +96,7 @@ object Restore { e.printStackTrace() } try { - val file = FileHelp.getFile(path + File.separator + "myTxtChapterRule.json") + val file = FileHelp.createFileIfNotExist(path + File.separator + "myTxtChapterRule.json") val json = file.readText() GSON.fromJsonArray(json)?.let { TxtChapterRuleManager.save(it) From a459bfa18249d1eb53ef09764f1f8278b576a8fa Mon Sep 17 00:00:00 2001 From: kunfei Date: Sat, 15 Feb 2020 15:19:52 +0800 Subject: [PATCH 056/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 90310ee960..6e0d739495 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -4,6 +4,7 @@ **2020/02/15** * 修复低版本手机无法联网的问题 +* 优化备份恢复 **2020/02/10** * 优化备份恢复 From 495407d71c9283fc05d030e6050a32094cac2348 Mon Sep 17 00:00:00 2001 From: kunfei Date: Sat, 15 Feb 2020 15:31:36 +0800 Subject: [PATCH 057/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt index 2daa47085e..f54f07157b 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt @@ -52,10 +52,10 @@ object Backup { } else { backup(MApplication.getInstance(), path, null) } - MApplication.getConfigPreferences().edit().putLong("lastBackup", System.currentTimeMillis()).apply() } fun backup(context: Context, path: String, callBack: CallBack?) { + MApplication.getConfigPreferences().edit().putLong("lastBackup", System.currentTimeMillis()).apply() Single.create(SingleOnSubscribe { e -> BookshelfHelp.getAllBook().let { if (it.isNotEmpty()) { From 45946f0280699d52017a1eeb825e97e996b8fe85 Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 18 Feb 2020 21:05:14 +0800 Subject: [PATCH 058/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widget/page/animation/SimulationPageAnim.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java index d15d117a51..469fca498e 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java @@ -516,8 +516,7 @@ private void calcPoints() { mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / (mCornerY - mMiddleY); } - mBezierStart1.x = mBezierControl1.x - (mCornerX - mBezierControl1.x) - / 2; + mBezierStart1.x = mBezierControl1.x - (mCornerX - mBezierControl1.x) / 2; mBezierStart1.y = mCornerY; // 当mBezierStart1.x < 0或者mBezierStart1.x > 480时 @@ -558,16 +557,15 @@ private void calcPoints() { } } mBezierStart2.x = mCornerX; - mBezierStart2.y = mBezierControl2.y - (mCornerY - mBezierControl2.y) - / 2; + mBezierStart2.y = mBezierControl2.y - (mCornerY - mBezierControl2.y) / 2; mTouchToCornerDis = (float) Math.hypot((mTouchX - mCornerX), (mTouchY - mCornerY)); - mBezierEnd1 = getCross(new PointF(mTouchX, mTouchY), mBezierControl1, mBezierStart1, - mBezierStart2); - mBezierEnd2 = getCross(new PointF(mTouchX, mTouchY), mBezierControl2, mBezierStart1, - mBezierStart2); + mBezierEnd1 = + getCross(new PointF(mTouchX, mTouchY), mBezierControl1, mBezierStart1, mBezierStart2); + mBezierEnd2 = + getCross(new PointF(mTouchX, mTouchY), mBezierControl2, mBezierStart1, mBezierStart2); mBezierVertex1.x = (mBezierStart1.x + 2 * mBezierControl1.x + mBezierEnd1.x) / 4; mBezierVertex1.y = (2 * mBezierControl1.y + mBezierStart1.y + mBezierEnd1.y) / 4; From 7f76d7f09b45a6226a0bf38dbb27a40e2b94fb5b Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 18 Feb 2020 21:57:11 +0800 Subject: [PATCH 059/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bookshelf/widget/page/animation/SimulationPageAnim.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java index 469fca498e..9285f8685f 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java @@ -223,10 +223,6 @@ private void createDrawable() { .setGradientType(GradientDrawable.LINEAR_GRADIENT); } - public boolean right() { - return mCornerX <= -4; - } - /** * 绘制翻起页背面 */ From 8b3f8c80201b2834eae4562406c4566e89de87b1 Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 18 Feb 2020 22:08:57 +0800 Subject: [PATCH 060/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widget/page/animation/SimulationPageAnim.java | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java index 9285f8685f..77f5f7188c 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java @@ -293,15 +293,11 @@ private void drawCurrentBackArea(Canvas canvas, Bitmap bitmap) { private void drawCurrentPageShadow(Canvas canvas) { double degree; if (mIsRT_LB) { - degree = Math.PI - / 4 - - Math.atan2(mBezierControl1.y - mTouchY, mTouchX - - mBezierControl1.x); + degree = Math.PI / 4 + - Math.atan2(mBezierControl1.y - mTouchY, mTouchX - mBezierControl1.x); } else { - degree = Math.PI - / 4 - - Math.atan2(mTouchY - mBezierControl1.y, mTouchX - - mBezierControl1.x); + degree = Math.PI / 4 + - Math.atan2(mTouchY - mBezierControl1.y, mTouchX - mBezierControl1.x); } // 翻起页阴影顶点与touch点的距离 double d1 = (float) 25 * 1.414 * Math.cos(degree); From b6cf12976eb6b0cea799e87f76295a5c5573dd0d Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 18 Feb 2020 22:20:38 +0800 Subject: [PATCH 061/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../page/animation/SimulationPageAnim.java | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java index 77f5f7188c..c93da3858b 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java @@ -341,12 +341,10 @@ private void drawCurrentPageShadow(Canvas canvas) { mCurrentPageShadow = mFrontShadowDrawableVRL; } - rotateDegrees = (float) Math.toDegrees(Math.atan2(mTouchX - - mBezierControl1.x, mBezierControl1.y - mTouchY)); + rotateDegrees = (float) Math.toDegrees(Math.atan2(mTouchX - mBezierControl1.x, mBezierControl1.y - mTouchY)); canvas.rotate(rotateDegrees, mBezierControl1.x, mBezierControl1.y); - mCurrentPageShadow.setBounds(leftx, - (int) (mBezierControl1.y - mMaxLength), rightx, - (int) (mBezierControl1.y)); + mCurrentPageShadow.setBounds(leftx, (int) (mBezierControl1.y - mMaxLength), + rightx, (int) (mBezierControl1.y)); mCurrentPageShadow.draw(canvas); canvas.restore(); @@ -377,14 +375,11 @@ private void drawCurrentPageShadow(Canvas canvas) { rightx = (int) (mBezierControl2.y + 1); mCurrentPageShadow = mFrontShadowDrawableHBT; } - rotateDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl2.y - - mTouchY, mBezierControl2.x - mTouchX)); + rotateDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl2.y - mTouchY, mBezierControl2.x - mTouchX)); canvas.rotate(rotateDegrees, mBezierControl2.x, mBezierControl2.y); float temp; - if (mBezierControl2.y < 0) - temp = mBezierControl2.y - mScreenHeight; - else - temp = mBezierControl2.y; + if (mBezierControl2.y < 0) temp = mBezierControl2.y - mScreenHeight; + else temp = mBezierControl2.y; int hmg = (int) Math.hypot(mBezierControl2.x, temp); if (hmg > mMaxLength) From b1b6d2e42ae0790bccfc0041138aff3040c3e4af Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 18 Feb 2020 22:32:38 +0800 Subject: [PATCH 062/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bookshelf/widget/page/animation/SimulationPageAnim.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java index c93da3858b..c833abc6af 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java @@ -405,8 +405,8 @@ private void drawNextPageAreaAndShadow(Canvas canvas, Bitmap bitmap) { mPath1.lineTo(mCornerX, mCornerY); mPath1.close(); - mDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl1.x - - mCornerX, mBezierControl2.y - mCornerY)); + mDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl1.x - mCornerX, + mBezierControl2.y - mCornerY)); int leftx; int rightx; GradientDrawable mBackShadowDrawable; From 1ef8396400535d60bb84244d6f085deb61b3fd59 Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 18 Feb 2020 22:36:00 +0800 Subject: [PATCH 063/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bookshelf/widget/page/animation/SimulationPageAnim.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java index c833abc6af..3ac5ef5393 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java @@ -443,12 +443,10 @@ private void drawNextPageAreaAndShadow(Canvas canvas, Bitmap bitmap) { private void drawCurrentPageArea(Canvas canvas, Bitmap bitmap, Path path) { mPath0.reset(); mPath0.moveTo(mBezierStart1.x, mBezierStart1.y); - mPath0.quadTo(mBezierControl1.x, mBezierControl1.y, mBezierEnd1.x, - mBezierEnd1.y); + mPath0.quadTo(mBezierControl1.x, mBezierControl1.y, mBezierEnd1.x, mBezierEnd1.y); mPath0.lineTo(mTouchX, mTouchY); mPath0.lineTo(mBezierEnd2.x, mBezierEnd2.y); - mPath0.quadTo(mBezierControl2.x, mBezierControl2.y, mBezierStart2.x, - mBezierStart2.y); + mPath0.quadTo(mBezierControl2.x, mBezierControl2.y, mBezierStart2.x, mBezierStart2.y); mPath0.lineTo(mCornerX, mCornerY); mPath0.close(); From 8bc5bfa818d4e6444cc83f2b890600d685713b18 Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 19 Feb 2020 17:25:04 +0800 Subject: [PATCH 064/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bookshelf/widget/page/animation/SimulationPageAnim.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java index 3ac5ef5393..a3e0981ea6 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java @@ -490,10 +490,9 @@ private void calcPoints() { mBezierControl1.x = mMiddleX - (mCornerY - mMiddleY) * (mCornerY - mMiddleY) / (mCornerX - mMiddleX); mBezierControl1.y = mCornerY; - mBezierControl2.x = mCornerX; - float f4 = mCornerY - mMiddleY; - if (f4 == 0) { + mBezierControl2.x = mCornerX; + if (mCornerY - mMiddleY == 0) { mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / 0.1f; From cd4340c8111ee0318d329ae5e737065ff0c5c356 Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 19 Feb 2020 19:17:02 +0800 Subject: [PATCH 065/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bookshelf/widget/page/animation/SimulationPageAnim.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java index a3e0981ea6..06d01f7e5d 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java @@ -514,8 +514,7 @@ private void calcPoints() { float f2 = mScreenWidth * f1 / mBezierStart1.x; mTouchX = Math.abs(mCornerX - f2); - float f3 = Math.abs(mCornerX - mTouchX) - * Math.abs(mCornerY - mTouchY) / f1; + float f3 = Math.abs(mCornerX - mTouchX) * Math.abs(mCornerY - mTouchY) / f1; mTouchY = Math.abs(mCornerY - f3); mMiddleX = (mTouchX + mCornerX) / 2; From c30f039b7f0342c9af161035e382cf9d71a656e6 Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 19 Feb 2020 19:30:20 +0800 Subject: [PATCH 066/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bookshelf/widget/page/animation/SimulationPageAnim.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java index 06d01f7e5d..98f7c84841 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java @@ -487,8 +487,8 @@ private void calcCornerXY(float x, float y) { private void calcPoints() { mMiddleX = (mTouchX + mCornerX) / 2; mMiddleY = (mTouchY + mCornerY) / 2; - mBezierControl1.x = mMiddleX - (mCornerY - mMiddleY) - * (mCornerY - mMiddleY) / (mCornerX - mMiddleX); + mBezierControl1.x = + mMiddleX - (mCornerY - mMiddleY) * (mCornerY - mMiddleY) / (mCornerX - mMiddleX); mBezierControl1.y = mCornerY; mBezierControl2.x = mCornerX; From cf2759b240961eb6a9a5792ee9de41203cf14ede Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 19 Feb 2020 19:42:23 +0800 Subject: [PATCH 067/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bookshelf/widget/page/animation/SimulationPageAnim.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java index 98f7c84841..b217c1326b 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java @@ -503,8 +503,7 @@ private void calcPoints() { mBezierStart1.x = mBezierControl1.x - (mCornerX - mBezierControl1.x) / 2; mBezierStart1.y = mCornerY; - // 当mBezierStart1.x < 0或者mBezierStart1.x > 480时 - // 如果继续翻页,会出现BUG故在此限制 + // 固定左边上下两个点 if (mTouchX > 0 && mTouchX < mScreenWidth) { if (mBezierStart1.x < 0 || mBezierStart1.x > mScreenWidth) { if (mBezierStart1.x < 0) From 7f1597b715626f7dbfec43c0317c99e1c5e28b84 Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 19 Feb 2020 19:54:54 +0800 Subject: [PATCH 068/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../page/animation/SimulationPageAnim.java | 105 +++++++++--------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java index b217c1326b..5596e967be 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java @@ -84,19 +84,42 @@ public SimulationPageAnim(int w, int h, View view, OnPageChangeListener listener } @Override - public void drawMove(Canvas canvas) { - if (mDirection == Direction.NEXT) { - calcPoints(); - drawCurrentPageArea(canvas, bitmapList.get(1), mPath0);//绘制翻页时的正面页 - drawNextPageAreaAndShadow(canvas, bitmapList.get(2)); - drawCurrentPageShadow(canvas); - drawCurrentBackArea(canvas, bitmapList.get(1)); - } else { - calcPoints(); - drawCurrentPageArea(canvas, bitmapList.get(0), mPath0); - drawNextPageAreaAndShadow(canvas, bitmapList.get(1)); - drawCurrentPageShadow(canvas); - drawCurrentBackArea(canvas, bitmapList.get(0)); + public void setStartPoint(float x, float y) { + super.setStartPoint(x, y); + calcCornerXY(x, y); + } + + @Override + public void setTouchPoint(float x, float y) { + super.setTouchPoint(x, y); + //触摸y中间位置吧y变成屏幕高度 + if ((mStartY > mScreenHeight / 3.0 && mStartY < mScreenHeight * 2 / 3.0) || mDirection.equals(Direction.PREV)) { + mTouchY = mScreenHeight; + } + + if (mStartY > mScreenHeight / 3.0 && mStartY < mScreenHeight / 2.0 && mDirection.equals(Direction.NEXT)) { + mTouchY = 1; + } + } + + @Override + public void setDirection(Direction direction) { + super.setDirection(direction); + + switch (direction) { + case PREV: + //上一页滑动不出现对角 + if (mStartX > mScreenWidth / 2.0) { + calcCornerXY(mStartX, mScreenHeight); + } else { + calcCornerXY(mScreenWidth - mStartX, mScreenHeight); + } + break; + case NEXT: + if (mScreenWidth / 2.0 > mStartX) { + calcCornerXY(mScreenWidth - mStartX, mStartY); + } + break; } } @@ -139,42 +162,19 @@ public void startAnim() { } @Override - public void setDirection(Direction direction) { - super.setDirection(direction); - - switch (direction) { - case PREV: - //上一页滑动不出现对角 - if (mStartX > mScreenWidth / 2.0) { - calcCornerXY(mStartX, mScreenHeight); - } else { - calcCornerXY(mScreenWidth - mStartX, mScreenHeight); - } - break; - case NEXT: - if (mScreenWidth / 2.0 > mStartX) { - calcCornerXY(mScreenWidth - mStartX, mStartY); - } - break; - } - } - - @Override - public void setStartPoint(float x, float y) { - super.setStartPoint(x, y); - calcCornerXY(x, y); - } - - @Override - public void setTouchPoint(float x, float y) { - super.setTouchPoint(x, y); - //触摸y中间位置吧y变成屏幕高度 - if ((mStartY > mScreenHeight / 3.0 && mStartY < mScreenHeight * 2 / 3.0) || mDirection.equals(Direction.PREV)) { - mTouchY = mScreenHeight; - } - - if (mStartY > mScreenHeight / 3.0 && mStartY < mScreenHeight / 2.0 && mDirection.equals(Direction.NEXT)) { - mTouchY = 1; + public void drawMove(Canvas canvas) { + if (mDirection == Direction.NEXT) { + calcPoints(); + drawCurrentPageArea(canvas, bitmapList.get(1), mPath0);//绘制翻页时的正面页 + drawNextPageAreaAndShadow(canvas, bitmapList.get(2)); + drawCurrentPageShadow(canvas); + drawCurrentBackArea(canvas, bitmapList.get(1)); + } else { + calcPoints(); + drawCurrentPageArea(canvas, bitmapList.get(0), mPath0); + drawNextPageAreaAndShadow(canvas, bitmapList.get(1)); + drawCurrentPageShadow(canvas); + drawCurrentBackArea(canvas, bitmapList.get(0)); } } @@ -519,8 +519,8 @@ private void calcPoints() { mMiddleX = (mTouchX + mCornerX) / 2; mMiddleY = (mTouchY + mCornerY) / 2; - mBezierControl1.x = mMiddleX - (mCornerY - mMiddleY) - * (mCornerY - mMiddleY) / (mCornerX - mMiddleX); + mBezierControl1.x = + mMiddleX - (mCornerY - mMiddleY) * (mCornerY - mMiddleY) / (mCornerX - mMiddleX); mBezierControl1.y = mCornerY; mBezierControl2.x = mCornerX; @@ -541,8 +541,7 @@ private void calcPoints() { mBezierStart2.x = mCornerX; mBezierStart2.y = mBezierControl2.y - (mCornerY - mBezierControl2.y) / 2; - mTouchToCornerDis = (float) Math.hypot((mTouchX - mCornerX), - (mTouchY - mCornerY)); + mTouchToCornerDis = (float) Math.hypot((mTouchX - mCornerX), (mTouchY - mCornerY)); mBezierEnd1 = getCross(new PointF(mTouchX, mTouchY), mBezierControl1, mBezierStart1, mBezierStart2); From f8ab9aac6a132d8ad1a77ddaa88dd73679f27c34 Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 19 Feb 2020 20:42:26 +0800 Subject: [PATCH 069/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bookshelf/widget/page/animation/SimulationPageAnim.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java index 5596e967be..6fbf2d66ff 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java @@ -385,8 +385,7 @@ private void drawCurrentPageShadow(Canvas canvas) { if (hmg > mMaxLength) mCurrentPageShadow .setBounds((int) (mBezierControl2.x - 25) - hmg, leftx, - (int) (mBezierControl2.x + mMaxLength) - hmg, - rightx); + (int) (mBezierControl2.x + mMaxLength) - hmg, rightx); else mCurrentPageShadow.setBounds( (int) (mBezierControl2.x - mMaxLength), leftx, From 2f7d4a7a0fc0bdc359a923c49a11bfd96d5537b7 Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 19 Feb 2020 20:46:25 +0800 Subject: [PATCH 070/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bookshelf/widget/page/animation/SimulationPageAnim.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java index 6fbf2d66ff..823b2eb379 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java @@ -430,7 +430,6 @@ private void drawNextPageAreaAndShadow(Canvas canvas, Bitmap bitmap) { } catch (Exception ignored) { } - canvas.drawBitmap(bitmap, 0, 0, null); canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y); mBackShadowDrawable.setBounds(leftx, (int) mBezierStart1.y, rightx, From 1f0c14521e0d592160d0155f0dee467fb6306c71 Mon Sep 17 00:00:00 2001 From: 52fisher <32198215+52fisher@users.noreply.github.com> Date: Thu, 20 Feb 2020 21:18:32 +0800 Subject: [PATCH 071/105] Update txtChapterRule.json --- app/src/main/assets/txtChapterRule.json | 92 +++++++++++++++---------- 1 file changed, 55 insertions(+), 37 deletions(-) diff --git a/app/src/main/assets/txtChapterRule.json b/app/src/main/assets/txtChapterRule.json index b035fccb53..7cfa049bbf 100644 --- a/app/src/main/assets/txtChapterRule.json +++ b/app/src/main/assets/txtChapterRule.json @@ -1,38 +1,56 @@ [ - { - "enable": true, - "name": "默认正则1", - "rule": "^(.{0,8})(第)([0-9零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,10})([章节卷集部篇回场])(.{0,30})$", - "serialNumber": 0 - }, - { - "enable": true, - "name": "默认正则2", - "rule": "^([0-9]{1,5})([\\,\\.,-])(.{1,20})$", - "serialNumber": 1 - }, - { - "enable": true, - "name": "默认正则3", - "rule": "^(\\s{0,4})([\\(【《]?(卷)?)([0-9零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,10})([\\.:: \f\t])(.{0,30})$", - "serialNumber": 2 - }, - { - "enable": true, - "name": "默认正则4", - "rule": "^(\\s{0,4})([\\((【《])(.{0,30})([\\))】》])(\\s{0,2})$", - "serialNumber": 3 - }, - { - "enable": true, - "name": "默认正则5", - "rule": "^(\\s{0,4})(正文)(.{0,20})$", - "serialNumber": 4 - }, - { - "enable": true, - "name": "默认正则6", - "rule": "^(.{0,4})(Chapter|chapter)(\\s{0,4})([0-9]{1,4})(.{0,30})$", - "serialNumber": 5 - } -] \ No newline at end of file + { + "enable": true, + "name": "数字 分隔符 标题名称", + "rule": "^[ \\t]{0,4}\\d{1,5}[\\,\\., 、\\-].{1,30}$", + "serialNumber": 0 + }, + { + "enable": true, + "name": "特殊符号 序号 标题", + "rule": "^[ \\t]{0,4}[\\[〈「『〖〔《(【\\(]?[第卷][\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,10}[\\.:: \f\t].{0,30}$", + "serialNumber": 1 + }, + { + "enable": true, + "name": "特殊符号 标题", + "rule": "^[ \\t]{0,4}[\\[〈「『〖〔《(【\\(☆★].{1,30}[\\)】)》〕〗』」〉\\]]?\\s{0,4}$", + "serialNumber": 2 + }, + { + "enable": true, + "name": "特殊符号 标题(不匹配空白字符)", + "rule": "(?<=\\s)[\\[〈「『〖〔《(【\\(☆★].{1,30}[\\)】)》〕〗』」〉\\]]?\\s{0,4}$", + "serialNumber": 3 + }, + { + "enable": true, + "name": "Chapter/Section/Part 序号 标题", + "rule": "^[ \\t]{0,4}(?:[Cc]hapter|[Ss]ection|[Pp]art)\\s{0,4}\\d{1,4}.{0,30}$", + "serialNumber": 4 + }, + { + "enable": true, + "name": "正文 标题/序号", + "rule": "^[ \\t]{0,4}正文\\s{1,4}.{0,20}$", + "serialNumber": 5 + }, + { + "enable": true, + "name": "目录", + "rule": "^[ \\t]{0,4}(?:(?:内容|文章)?简介|前言|序章|楔子|正文(?!完)|[Cc]hapter|[Ss]ection|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", + "serialNumber": 6 + }, + { + "enable": true, + "name": "目录(不匹配行前空白,正文不出现双标题)", + "rule": "^(?<=\\s)(?:(?:内容|文章)?简介|前言|序章|楔子|正文(?!完)|[Cc]hapter|[Ss]ection|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", + "serialNumber": 7 + }, + { + "enable": true, + "name": "目录(古典小说备用)", + "rule": "^[ \\t]{0,4}(?:(?:内容|文章)?简介|前言|序章|楔子|正文(?!完)|[Cc]hapter|[Ss]ection|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|场(?![和合比电是])|篇(?!张))).{0,30}$", + "serialNumber": 8 + } +] From 9d6dae1c04c45ad8dafeb5f964c045d5e64e8aa1 Mon Sep 17 00:00:00 2001 From: 52fisher <32198215+52fisher@users.noreply.github.com> Date: Thu, 20 Feb 2020 21:19:35 +0800 Subject: [PATCH 072/105] Update txtChapterRule.json --- app/src/main/assets/txtChapterRule.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/assets/txtChapterRule.json b/app/src/main/assets/txtChapterRule.json index 7cfa049bbf..783dd41d8a 100644 --- a/app/src/main/assets/txtChapterRule.json +++ b/app/src/main/assets/txtChapterRule.json @@ -18,7 +18,7 @@ "serialNumber": 2 }, { - "enable": true, + "enable":false, "name": "特殊符号 标题(不匹配空白字符)", "rule": "(?<=\\s)[\\[〈「『〖〔《(【\\(☆★].{1,30}[\\)】)》〕〗』」〉\\]]?\\s{0,4}$", "serialNumber": 3 @@ -42,13 +42,13 @@ "serialNumber": 6 }, { - "enable": true, + "enable": false, "name": "目录(不匹配行前空白,正文不出现双标题)", "rule": "^(?<=\\s)(?:(?:内容|文章)?简介|前言|序章|楔子|正文(?!完)|[Cc]hapter|[Ss]ection|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", "serialNumber": 7 }, { - "enable": true, + "enable": false, "name": "目录(古典小说备用)", "rule": "^[ \\t]{0,4}(?:(?:内容|文章)?简介|前言|序章|楔子|正文(?!完)|[Cc]hapter|[Ss]ection|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|场(?![和合比电是])|篇(?!张))).{0,30}$", "serialNumber": 8 From 358433b281c79544a5d5c9755e2e78ff5d62d083 Mon Sep 17 00:00:00 2001 From: fisher Date: Sat, 22 Feb 2020 22:13:12 +0800 Subject: [PATCH 073/105] fixed some rule --- app/src/main/assets/txtChapterRule.json | 48 ++++++++++++++----------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/app/src/main/assets/txtChapterRule.json b/app/src/main/assets/txtChapterRule.json index 783dd41d8a..224d99f39b 100644 --- a/app/src/main/assets/txtChapterRule.json +++ b/app/src/main/assets/txtChapterRule.json @@ -7,50 +7,56 @@ }, { "enable": true, - "name": "特殊符号 序号 标题", - "rule": "^[ \\t]{0,4}[\\[〈「『〖〔《(【\\(]?[第卷][\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,10}[\\.:: \f\t].{0,30}$", + "name": "目录", + "rule": "^[ \\t]{0,4}(?:(?:内容|文章)?简介|前言|序章|楔子|正文(?!完)|[Cc]hapter|[Ss]ection|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", "serialNumber": 1 }, { - "enable": true, - "name": "特殊符号 标题", - "rule": "^[ \\t]{0,4}[\\[〈「『〖〔《(【\\(☆★].{1,30}[\\)】)》〕〗』」〉\\]]?\\s{0,4}$", + "enable": false, + "name": "目录(不匹配行前空白)", + "rule": "^(?<=\\s)(?:(?:内容|文章)?简介|前言|序章|楔子|正文(?!完)|[Cc]hapter|[Ss]ection|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", "serialNumber": 2 }, { - "enable":false, - "name": "特殊符号 标题(不匹配空白字符)", - "rule": "(?<=\\s)[\\[〈「『〖〔《(【\\(☆★].{1,30}[\\)】)》〕〗』」〉\\]]?\\s{0,4}$", + "enable": false, + "name": "目录(去简介)", + "rule": "^(?<=\\s)(?:前言|序章|楔子|正文(?!完)|[Cc]hapter|[Ss]ection|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", "serialNumber": 3 }, { - "enable": true, - "name": "Chapter/Section/Part 序号 标题", - "rule": "^[ \\t]{0,4}(?:[Cc]hapter|[Ss]ection|[Pp]art)\\s{0,4}\\d{1,4}.{0,30}$", + "enable": false, + "name": "目录(古典小说备用)", + "rule": "^[ \\t]{0,4}(?:前言|序章|楔子|正文(?!完)|[Cc]hapter|[Ss]ection|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|场(?![和合比电是])|篇(?!张))).{0,30}$", "serialNumber": 4 }, { "enable": true, - "name": "正文 标题/序号", - "rule": "^[ \\t]{0,4}正文\\s{1,4}.{0,20}$", + "name": "Chapter/Section/Part 序号 标题", + "rule": "^[ \\t]{0,4}(?:[Cc]hapter|[Ss]ection|[Pp]art)\\s{0,4}\\d{1,4}.{0,30}$", "serialNumber": 5 }, { "enable": true, - "name": "目录", - "rule": "^[ \\t]{0,4}(?:(?:内容|文章)?简介|前言|序章|楔子|正文(?!完)|[Cc]hapter|[Ss]ection|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", + "name": "正文 标题/序号", + "rule": "^[ \\t]{0,4}正文\\s{1,4}.{0,20}$", "serialNumber": 6 }, { - "enable": false, - "name": "目录(不匹配行前空白,正文不出现双标题)", - "rule": "^(?<=\\s)(?:(?:内容|文章)?简介|前言|序章|楔子|正文(?!完)|[Cc]hapter|[Ss]ection|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", + "enable": true, + "name": "特殊符号 序号 标题", + "rule": "^[ \\t]{0,4}[〈〖〔【][第卷][\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,10}[章节][\\.:: \f\t].{0,30}$", "serialNumber": 7 }, { - "enable": false, - "name": "目录(古典小说备用)", - "rule": "^[ \\t]{0,4}(?:(?:内容|文章)?简介|前言|序章|楔子|正文(?!完)|[Cc]hapter|[Ss]ection|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|场(?![和合比电是])|篇(?!张))).{0,30}$", + "enable": true, + "name": "特殊符号 标题", + "rule": "^[ \\t]{0,4}[〈〖〔【☆★].{1,30}[】〕〗〉]?\\s{0,4}$", "serialNumber": 8 + }, + { + "enable":false, + "name": "特殊符号 标题(不匹配空白字符)", + "rule": "(?<=\\s)[〈〖〔【☆★].{1,30}[】〕〗〉]?\\s{0,4}$", + "serialNumber": 9 } ] From ad129aa76106c22ac14e859d410980fddd07169c Mon Sep 17 00:00:00 2001 From: kunfei Date: Sun, 23 Feb 2020 10:46:34 +0800 Subject: [PATCH 074/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/layout/pop_read_adjust.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/layout/pop_read_adjust.xml b/app/src/main/res/layout/pop_read_adjust.xml index 0753aaff8b..0d27c4c0d6 100644 --- a/app/src/main/res/layout/pop_read_adjust.xml +++ b/app/src/main/res/layout/pop_read_adjust.xml @@ -134,7 +134,7 @@ android:layout_height="30dp" android:layout_marginStart="15dp" android:layout_marginEnd="15dp" - android:max="45" /> + android:max="95" /> From f743bb5b43d2a870bf2d9bdce8b1b1a08b934129 Mon Sep 17 00:00:00 2001 From: fisher Date: Sun, 23 Feb 2020 16:23:55 +0800 Subject: [PATCH 075/105] added hanging indention --- app/src/main/assets/txtChapterRule.json | 44 ++++++++++++++++--------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/app/src/main/assets/txtChapterRule.json b/app/src/main/assets/txtChapterRule.json index 224d99f39b..68c5977cc1 100644 --- a/app/src/main/assets/txtChapterRule.json +++ b/app/src/main/assets/txtChapterRule.json @@ -1,38 +1,38 @@ [ { "enable": true, - "name": "数字 分隔符 标题名称", - "rule": "^[ \\t]{0,4}\\d{1,5}[\\,\\., 、\\-].{1,30}$", + "name": "目录", + "rule": "^[ \\t]{0,4}(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", "serialNumber": 0 }, { - "enable": true, - "name": "目录", - "rule": "^[ \\t]{0,4}(?:(?:内容|文章)?简介|前言|序章|楔子|正文(?!完)|[Cc]hapter|[Ss]ection|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", + "enable": false, + "name": "目录(多级标题)", + "rule": "^[ \\t]{0,4}(第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?卷|卷[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?)\\s{0,4}第?[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?章.{0,30}$", "serialNumber": 1 }, { "enable": false, "name": "目录(不匹配行前空白)", - "rule": "^(?<=\\s)(?:(?:内容|文章)?简介|前言|序章|楔子|正文(?!完)|[Cc]hapter|[Ss]ection|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", + "rule": "^(?<=\\s)(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", "serialNumber": 2 }, { "enable": false, "name": "目录(去简介)", - "rule": "^(?<=\\s)(?:前言|序章|楔子|正文(?!完)|[Cc]hapter|[Ss]ection|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", + "rule": "^(?<=\\s)(?:前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", "serialNumber": 3 }, { "enable": false, - "name": "目录(古典小说备用)", - "rule": "^[ \\t]{0,4}(?:前言|序章|楔子|正文(?!完)|[Cc]hapter|[Ss]ection|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|场(?![和合比电是])|篇(?!张))).{0,30}$", + "name": "目录(古典、轻小说备用)", + "rule": "^[ \\t]{0,4}(?:前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|场(?![和合比电是])|篇(?!张))).{0,30}$", "serialNumber": 4 }, { "enable": true, - "name": "Chapter/Section/Part 序号 标题", - "rule": "^[ \\t]{0,4}(?:[Cc]hapter|[Ss]ection|[Pp]art)\\s{0,4}\\d{1,4}.{0,30}$", + "name": "数字 分隔符 标题名称", + "rule": "^[ \\t]{0,4}\\d{1,5}[\\,\\., 、\\-].{1,30}$", "serialNumber": 5 }, { @@ -41,22 +41,34 @@ "rule": "^[ \\t]{0,4}正文\\s{1,4}.{0,20}$", "serialNumber": 6 }, + { + "enable": true, + "name": "Chapter/Section/Part 序号 标题", + "rule": "^[ \\t]{0,4}(?:[Cc]hapter|[Ss]ection|[Pp]art)\\s{0,4}\\d{1,4}.{0,30}$", + "serialNumber": 7 + }, { "enable": true, "name": "特殊符号 序号 标题", "rule": "^[ \\t]{0,4}[〈〖〔【][第卷][\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,10}[章节][\\.:: \f\t].{0,30}$", - "serialNumber": 7 + "serialNumber": 8 }, { "enable": true, "name": "特殊符号 标题", - "rule": "^[ \\t]{0,4}[〈〖〔【☆★].{1,30}[】〕〗〉]?\\s{0,4}$", - "serialNumber": 8 + "rule": "^[ \\t]{0,4}[\\[〈「『〖〔《(【\\(☆★].{1,30}[\\)】)》〕〗』」〉\\]]?\\s{0,4}$", + "serialNumber": 9 }, { "enable":false, "name": "特殊符号 标题(不匹配空白字符)", - "rule": "(?<=\\s)[〈〖〔【☆★].{1,30}[】〕〗〉]?\\s{0,4}$", - "serialNumber": 9 + "rule": "^(?<=\\s)[\\[〈「『〖〔《(【\\(☆★].{1,30}[\\)】)》〕〗』」〉\\]]?\\s{0,4}$", + "serialNumber": 10 + }, + { + "enable":false, + "name": "顶格标题", + "rule": "^\\S.{1,20}$", + "serialNumber": 11 } ] From 70758996b5680fac79ac5eaa3d5a19c822177b6f Mon Sep 17 00:00:00 2001 From: fisher Date: Sun, 23 Feb 2020 16:31:33 +0800 Subject: [PATCH 076/105] deleted multistage catalog --- app/src/main/assets/txtChapterRule.json | 26 ++++++++++--------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/app/src/main/assets/txtChapterRule.json b/app/src/main/assets/txtChapterRule.json index 68c5977cc1..acca0ffccc 100644 --- a/app/src/main/assets/txtChapterRule.json +++ b/app/src/main/assets/txtChapterRule.json @@ -5,70 +5,64 @@ "rule": "^[ \\t]{0,4}(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", "serialNumber": 0 }, - { - "enable": false, - "name": "目录(多级标题)", - "rule": "^[ \\t]{0,4}(第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?卷|卷[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?)\\s{0,4}第?[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?章.{0,30}$", - "serialNumber": 1 - }, { "enable": false, "name": "目录(不匹配行前空白)", "rule": "^(?<=\\s)(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", - "serialNumber": 2 + "serialNumber": 1 }, { "enable": false, "name": "目录(去简介)", "rule": "^(?<=\\s)(?:前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", - "serialNumber": 3 + "serialNumber": 2 }, { "enable": false, "name": "目录(古典、轻小说备用)", "rule": "^[ \\t]{0,4}(?:前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|场(?![和合比电是])|篇(?!张))).{0,30}$", - "serialNumber": 4 + "serialNumber": 3 }, { "enable": true, "name": "数字 分隔符 标题名称", "rule": "^[ \\t]{0,4}\\d{1,5}[\\,\\., 、\\-].{1,30}$", - "serialNumber": 5 + "serialNumber": 4 }, { "enable": true, "name": "正文 标题/序号", "rule": "^[ \\t]{0,4}正文\\s{1,4}.{0,20}$", - "serialNumber": 6 + "serialNumber": 5 }, { "enable": true, "name": "Chapter/Section/Part 序号 标题", "rule": "^[ \\t]{0,4}(?:[Cc]hapter|[Ss]ection|[Pp]art)\\s{0,4}\\d{1,4}.{0,30}$", - "serialNumber": 7 + "serialNumber": 6 }, { "enable": true, "name": "特殊符号 序号 标题", "rule": "^[ \\t]{0,4}[〈〖〔【][第卷][\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,10}[章节][\\.:: \f\t].{0,30}$", - "serialNumber": 8 + "serialNumber": 7 }, { "enable": true, "name": "特殊符号 标题", "rule": "^[ \\t]{0,4}[\\[〈「『〖〔《(【\\(☆★].{1,30}[\\)】)》〕〗』」〉\\]]?\\s{0,4}$", - "serialNumber": 9 + "serialNumber": 8 }, { "enable":false, "name": "特殊符号 标题(不匹配空白字符)", "rule": "^(?<=\\s)[\\[〈「『〖〔《(【\\(☆★].{1,30}[\\)】)》〕〗』」〉\\]]?\\s{0,4}$", - "serialNumber": 10 + "serialNumber": 9 }, { "enable":false, "name": "顶格标题", "rule": "^\\S.{1,20}$", - "serialNumber": 11 + "serialNumber": 10 } ] From 4e539a65f14b4da7a36ae3b9f3e5deea1a22f8c3 Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 25 Feb 2020 19:39:34 +0800 Subject: [PATCH 077/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 156843891c..316542227d 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ buildscript { maven { url 'https://plugins.gradle.org/m2/' } } dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' + classpath 'com.android.tools.build:gradle:3.6.0' classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' classpath 'com.google.gms:google-services:4.3.3' classpath 'io.fabric.tools:gradle:1.31.0' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fba40d216f..a21af7526c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Apr 28 22:21:17 CST 2019 +#Tue Feb 25 15:50:59 CST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip From 04df4c273302cc479d39b2d38fada5d741d549d1 Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 25 Feb 2020 20:34:56 +0800 Subject: [PATCH 078/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../page/animation/SimulationPageAnim.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java index 823b2eb379..d86ef90953 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java @@ -165,13 +165,13 @@ public void startAnim() { public void drawMove(Canvas canvas) { if (mDirection == Direction.NEXT) { calcPoints(); - drawCurrentPageArea(canvas, bitmapList.get(1), mPath0);//绘制翻页时的正面页 + drawCurrentPageArea(canvas, bitmapList.get(1));//绘制翻页时的正面页 drawNextPageAreaAndShadow(canvas, bitmapList.get(2)); drawCurrentPageShadow(canvas); drawCurrentBackArea(canvas, bitmapList.get(1)); } else { calcPoints(); - drawCurrentPageArea(canvas, bitmapList.get(0), mPath0); + drawCurrentPageArea(canvas, bitmapList.get(0)); drawNextPageAreaAndShadow(canvas, bitmapList.get(1)); drawCurrentPageShadow(canvas); drawCurrentBackArea(canvas, bitmapList.get(0)); @@ -438,7 +438,7 @@ private void drawNextPageAreaAndShadow(Canvas canvas, Bitmap bitmap) { canvas.restore(); } - private void drawCurrentPageArea(Canvas canvas, Bitmap bitmap, Path path) { + private void drawCurrentPageArea(Canvas canvas, Bitmap bitmap) { mPath0.reset(); mPath0.moveTo(mBezierStart1.x, mBezierStart1.y); mPath0.quadTo(mBezierControl1.x, mBezierControl1.y, mBezierEnd1.x, mBezierEnd1.y); @@ -450,9 +450,9 @@ private void drawCurrentPageArea(Canvas canvas, Bitmap bitmap, Path path) { canvas.save(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - canvas.clipOutPath(path); + canvas.clipOutPath(mPath0); } else { - canvas.clipPath(path, Region.Op.XOR); + canvas.clipPath(mPath0, Region.Op.XOR); } canvas.drawBitmap(bitmap, 0, 0, null); try { @@ -491,9 +491,7 @@ private void calcPoints() { mBezierControl2.x = mCornerX; if (mCornerY - mMiddleY == 0) { - mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX) - * (mCornerX - mMiddleX) / 0.1f; - + mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / 0.1f; } else { mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / (mCornerY - mMiddleY); @@ -522,7 +520,6 @@ private void calcPoints() { mBezierControl1.y = mCornerY; mBezierControl2.x = mCornerX; - float f5 = mCornerY - mMiddleY; if (f5 == 0) { mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX) @@ -532,8 +529,7 @@ private void calcPoints() { * (mCornerX - mMiddleX) / (mCornerY - mMiddleY); } - mBezierStart1.x = mBezierControl1.x - - (mCornerX - mBezierControl1.x) / 2; + mBezierStart1.x = mBezierControl1.x - (mCornerX - mBezierControl1.x) / 2; } } mBezierStart2.x = mCornerX; From 484d3f68b9a22cc4b8dab52aaba31c796f54fda8 Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 25 Feb 2020 21:28:16 +0800 Subject: [PATCH 079/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../page/animation/SimulationPageAnim.java | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java index d86ef90953..a5aaf8684c 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/page/animation/SimulationPageAnim.java @@ -281,8 +281,10 @@ private void drawCurrentBackArea(Canvas canvas, Bitmap bitmap) { mPaint.setColorFilter(null); canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y); - mFolderShadowDrawable.setBounds(left, (int) mBezierStart1.y, right, - (int) (mBezierStart1.y + mMaxLength)); + mFolderShadowDrawable.setBounds( + left, (int) mBezierStart1.y, + right, (int) (mBezierStart1.y + mMaxLength) + ); mFolderShadowDrawable.draw(canvas); canvas.restore(); } @@ -293,11 +295,9 @@ private void drawCurrentBackArea(Canvas canvas, Bitmap bitmap) { private void drawCurrentPageShadow(Canvas canvas) { double degree; if (mIsRT_LB) { - degree = Math.PI / 4 - - Math.atan2(mBezierControl1.y - mTouchY, mTouchX - mBezierControl1.x); + degree = Math.PI / 4 - Math.atan2(mBezierControl1.y - mTouchY, mTouchX - mBezierControl1.x); } else { - degree = Math.PI / 4 - - Math.atan2(mTouchY - mBezierControl1.y, mTouchX - mBezierControl1.x); + degree = Math.PI / 4 - Math.atan2(mTouchY - mBezierControl1.y, mTouchX - mBezierControl1.x); } // 翻起页阴影顶点与touch点的距离 double d1 = (float) 25 * 1.414 * Math.cos(degree); @@ -315,7 +315,6 @@ private void drawCurrentPageShadow(Canvas canvas) { mPath1.lineTo(mBezierControl1.x, mBezierControl1.y); mPath1.lineTo(mBezierStart1.x, mBezierStart1.y); mPath1.close(); - float rotateDegrees; canvas.save(); try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { @@ -341,9 +340,11 @@ private void drawCurrentPageShadow(Canvas canvas) { mCurrentPageShadow = mFrontShadowDrawableVRL; } + float rotateDegrees; rotateDegrees = (float) Math.toDegrees(Math.atan2(mTouchX - mBezierControl1.x, mBezierControl1.y - mTouchY)); canvas.rotate(rotateDegrees, mBezierControl1.x, mBezierControl1.y); - mCurrentPageShadow.setBounds(leftx, (int) (mBezierControl1.y - mMaxLength), + mCurrentPageShadow.setBounds( + leftx, (int) (mBezierControl1.y - mMaxLength), rightx, (int) (mBezierControl1.y)); mCurrentPageShadow.draw(canvas); canvas.restore(); @@ -383,9 +384,10 @@ private void drawCurrentPageShadow(Canvas canvas) { int hmg = (int) Math.hypot(mBezierControl2.x, temp); if (hmg > mMaxLength) - mCurrentPageShadow - .setBounds((int) (mBezierControl2.x - 25) - hmg, leftx, - (int) (mBezierControl2.x + mMaxLength) - hmg, rightx); + mCurrentPageShadow.setBounds( + (int) (mBezierControl2.x - 25) - hmg, leftx, + (int) (mBezierControl2.x + mMaxLength) - hmg, rightx + ); else mCurrentPageShadow.setBounds( (int) (mBezierControl2.x - mMaxLength), leftx, @@ -432,8 +434,9 @@ private void drawNextPageAreaAndShadow(Canvas canvas, Bitmap bitmap) { canvas.drawBitmap(bitmap, 0, 0, null); canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y); - mBackShadowDrawable.setBounds(leftx, (int) mBezierStart1.y, rightx, - (int) (mMaxLength + mBezierStart1.y));//左上及右下角的xy坐标值,构成一个矩形 + mBackShadowDrawable.setBounds( + leftx, (int) mBezierStart1.y, + rightx, (int) (mMaxLength + mBezierStart1.y));//左上及右下角的xy坐标值,构成一个矩形 mBackShadowDrawable.draw(canvas); canvas.restore(); } From b2238e70fc098739f659b52313598e808360025f Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 26 Feb 2020 08:27:25 +0800 Subject: [PATCH 080/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt index f54f07157b..96321c092f 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt @@ -130,7 +130,8 @@ object Backup { for (fileName in backupFileNames) { val file = File(backupPath + File.separator + fileName) if (file.exists()) { - val doc = treeDoc.findFile(fileName) ?: treeDoc.createFile("", fileName) + treeDoc.findFile(fileName)?.delete() + val doc = treeDoc.createFile("", fileName) doc?.let { DocumentUtil.writeBytes(context, file.readBytes(), doc) } From aaf452de5236496241a1eda37d89c738e7ad09ae Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 26 Feb 2020 08:31:11 +0800 Subject: [PATCH 081/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/kunfei/bookshelf/help/storage/Backup.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt index 96321c092f..5d47cc8149 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt @@ -131,9 +131,8 @@ object Backup { val file = File(backupPath + File.separator + fileName) if (file.exists()) { treeDoc.findFile(fileName)?.delete() - val doc = treeDoc.createFile("", fileName) - doc?.let { - DocumentUtil.writeBytes(context, file.readBytes(), doc) + treeDoc.createFile("", fileName)?.let { + DocumentUtil.writeBytes(context, file.readBytes(), it) } } } From 297f780ec45a6005cd52041e24ee67180fa4c521 Mon Sep 17 00:00:00 2001 From: kunfei Date: Wed, 26 Feb 2020 08:49:27 +0800 Subject: [PATCH 082/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 6e0d739495..273de73442 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -2,6 +2,11 @@ ### 关注公众号"开源阅读软件"点击广告可支持作者! ### 捐赠里点击红包搜索码可开启高级功能! +**2020/02/26** +* 更新默认txt目录规则,由https://github.com/52fisher提供 +* 新版本快上架了,基本功能以完成,上架后再慢慢优化 +* 别人说加广告一天能有几千收入,我不加广告大家给点力多看看公众号广告啊 + **2020/02/15** * 修复低版本手机无法联网的问题 * 优化备份恢复 From efdf70badc3ed9ab4000c17041e106fbd903f8bb Mon Sep 17 00:00:00 2001 From: fisher Date: Fri, 28 Feb 2020 20:32:17 +0800 Subject: [PATCH 083/105] =?UTF-8?q?=E6=81=A2=E5=A4=8D=E5=8F=A4=E5=85=B8?= =?UTF-8?q?=E5=B0=8F=E8=AF=B4=E8=AF=86=E5=88=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/txtChapterRule.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/assets/txtChapterRule.json b/app/src/main/assets/txtChapterRule.json index acca0ffccc..d8c59f9b5c 100644 --- a/app/src/main/assets/txtChapterRule.json +++ b/app/src/main/assets/txtChapterRule.json @@ -20,7 +20,7 @@ { "enable": false, "name": "目录(古典、轻小说备用)", - "rule": "^[ \\t]{0,4}(?:前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|场(?![和合比电是])|篇(?!张))).{0,30}$", + "rule": "^[ \\t]{0,4}(?:前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|回(?![合来事去])|(|场(?![和合比电是])|篇(?!张))).{0,30}$", "serialNumber": 3 }, { From 4be9f4fd7f3c378244bac2bab5c3aefd4aa13d36 Mon Sep 17 00:00:00 2001 From: fisher Date: Fri, 28 Feb 2020 20:33:45 +0800 Subject: [PATCH 084/105] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E5=8F=A4=E5=85=B8?= =?UTF-8?q?=E5=B0=8F=E8=AF=B4=E8=AF=86=E5=88=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/txtChapterRule.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/assets/txtChapterRule.json b/app/src/main/assets/txtChapterRule.json index d8c59f9b5c..1304059d01 100644 --- a/app/src/main/assets/txtChapterRule.json +++ b/app/src/main/assets/txtChapterRule.json @@ -20,7 +20,7 @@ { "enable": false, "name": "目录(古典、轻小说备用)", - "rule": "^[ \\t]{0,4}(?:前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|回(?![合来事去])|(|场(?![和合比电是])|篇(?!张))).{0,30}$", + "rule": "^[ \\t]{0,4}(?:前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|回(?![合来事去])|场(?![和合比电是])|篇(?!张))).{0,30}$", "serialNumber": 3 }, { From 8d1e0470b6374c480b435ca8d078963bd25467da Mon Sep 17 00:00:00 2001 From: kunfei Date: Sat, 29 Feb 2020 22:53:32 +0800 Subject: [PATCH 085/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widget/prefs/ATEPreferenceCategory.java | 3 +++ .../bookshelf/widget/prefs/ATESwitchPreference.java | 4 +++- .../bookshelf/widget/prefs/IconListPreference.java | 13 ++++++++----- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/prefs/ATEPreferenceCategory.java b/app/src/main/java/com/kunfei/bookshelf/widget/prefs/ATEPreferenceCategory.java index c183729803..c963646db5 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/prefs/ATEPreferenceCategory.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/prefs/ATEPreferenceCategory.java @@ -34,6 +34,9 @@ public ATEPreferenceCategory(Context context) { @Override protected void onBindView(View view) { super.onBindView(view); + if (view.isInEditMode()) { + return; + } if (view instanceof TextView) { TextView tv = (TextView) view; tv.setTextColor(ThemeStore.accentColor(view.getContext()));//设置title文本的颜色 diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/prefs/ATESwitchPreference.java b/app/src/main/java/com/kunfei/bookshelf/widget/prefs/ATESwitchPreference.java index 05d200617d..8001427b16 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/prefs/ATESwitchPreference.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/prefs/ATESwitchPreference.java @@ -38,7 +38,9 @@ public ATESwitchPreference(Context context) { @Override protected void onBindView(View view) { super.onBindView(view); - + if (view.isInEditMode()) { + return; + } if (view instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) view; LinkedList queue = new LinkedList<>(); diff --git a/app/src/main/java/com/kunfei/bookshelf/widget/prefs/IconListPreference.java b/app/src/main/java/com/kunfei/bookshelf/widget/prefs/IconListPreference.java index 85ea2cc4a0..11061c8896 100644 --- a/app/src/main/java/com/kunfei/bookshelf/widget/prefs/IconListPreference.java +++ b/app/src/main/java/com/kunfei/bookshelf/widget/prefs/IconListPreference.java @@ -18,6 +18,8 @@ import com.kunfei.bookshelf.R; +import org.jetbrains.annotations.NotNull; + import java.util.ArrayList; import java.util.List; @@ -50,7 +52,7 @@ public IconListPreference(Context context, AttributeSet attrs) { setWidgetLayoutResource(R.layout.view_icon); } - protected ListAdapter createListAdapter() { + private ListAdapter createListAdapter() { final String selectedValue = getValue(); int selectedIndex = findIndexOfValue(selectedValue); return new AppArrayAdapter(getContext(), R.layout.item_icon_preference, getEntries(), mEntryDrawables, selectedIndex); @@ -74,18 +76,19 @@ protected void onPrepareDialogBuilder(Builder builder) { super.onPrepareDialogBuilder(builder); } - public class AppArrayAdapter extends ArrayAdapter { + public static class AppArrayAdapter extends ArrayAdapter { private List mImageDrawables = null; private int mSelectedIndex = 0; - public AppArrayAdapter(Context context, int textViewResourceId, - CharSequence[] objects, List imageDrawables, - int selectedIndex) { + AppArrayAdapter(Context context, int textViewResourceId, + CharSequence[] objects, List imageDrawables, + int selectedIndex) { super(context, textViewResourceId, objects); mSelectedIndex = selectedIndex; mImageDrawables = imageDrawables; } + @NotNull @Override @SuppressLint("ViewHolder") public View getView(int position, View convertView, ViewGroup parent) { From a68a9377d9cb458eb3b8a86c4bb0e4aa9fdf22dd Mon Sep 17 00:00:00 2001 From: kunfei Date: Sun, 1 Mar 2020 12:43:36 +0800 Subject: [PATCH 086/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 273de73442..051017c6cb 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -1,6 +1,5 @@ -## 本软件为开源软件,请不要在任何地方购买! -### 关注公众号"开源阅读软件"点击广告可支持作者! -### 捐赠里点击红包搜索码可开启高级功能! +## 更新日志 +* 请关注[开源阅读软件]()支持我,同时关注合作公众号[小说拾遗](),阅读公众号小编。 **2020/02/26** * 更新默认txt目录规则,由https://github.com/52fisher提供 From 3e17fe7e373cef0309f156c2ca30974b9ac656b5 Mon Sep 17 00:00:00 2001 From: kunfei Date: Sun, 1 Mar 2020 14:51:48 +0800 Subject: [PATCH 087/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6a294a690a..ea87675e1b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -92,8 +92,7 @@ + android:launchMode="singleTask" /> Date: Sun, 1 Mar 2020 19:48:56 +0800 Subject: [PATCH 088/105] update full-width characters --- app/src/main/assets/txtChapterRule.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/src/main/assets/txtChapterRule.json b/app/src/main/assets/txtChapterRule.json index 1304059d01..775e6b1a31 100644 --- a/app/src/main/assets/txtChapterRule.json +++ b/app/src/main/assets/txtChapterRule.json @@ -2,31 +2,31 @@ { "enable": true, "name": "目录", - "rule": "^[ \\t]{0,4}(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", + "rule": "^[  \\t]{0,4}(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", "serialNumber": 0 }, { "enable": false, "name": "目录(不匹配行前空白)", - "rule": "^(?<=\\s)(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", + "rule": "^(?<= |\\s)(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", "serialNumber": 1 }, { "enable": false, "name": "目录(去简介)", - "rule": "^(?<=\\s)(?:前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", + "rule": "^(?<= |\\s)(?:前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|回(?![合来事去])|场(?![和合比电是])|篇(?!张))).{0,30}$", "serialNumber": 2 }, { "enable": false, "name": "目录(古典、轻小说备用)", - "rule": "^[ \\t]{0,4}(?:前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|回(?![合来事去])|场(?![和合比电是])|篇(?!张))).{0,30}$", + "rule": "^[  \\t]{0,4}(?:前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|回(?![合来事去])|场(?![和合比电是])|篇(?!张))).{0,30}$", "serialNumber": 3 }, { "enable": true, "name": "数字 分隔符 标题名称", - "rule": "^[ \\t]{0,4}\\d{1,5}[\\,\\., 、\\-].{1,30}$", + "rule": "^[  \\t]{0,4}\\d{1,5}[\\,\\., 、\\-].{1,30}$", "serialNumber": 4 }, { @@ -37,26 +37,26 @@ }, { "enable": true, - "name": "Chapter/Section/Part 序号 标题", - "rule": "^[ \\t]{0,4}(?:[Cc]hapter|[Ss]ection|[Pp]art)\\s{0,4}\\d{1,4}.{0,30}$", + "name": "Chapter/Section/Part/Episode 序号 标题", + "rule": "^[  \\t]{0,4}(?:[Cc]hapter|[Ss]ection|[Pp]art|PART|[Ee]pisode)\\s{0,4}\\d{1,4}.{0,30}$", "serialNumber": 6 }, { "enable": true, "name": "特殊符号 序号 标题", - "rule": "^[ \\t]{0,4}[〈〖〔【][第卷][\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,10}[章节][\\.:: \f\t].{0,30}$", + "rule": "^[  \\t]{0,4}[〈〖〔【][第卷][\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,10}[章节][\\.:: \f\t].{0,30}$", "serialNumber": 7 }, { "enable": true, "name": "特殊符号 标题", - "rule": "^[ \\t]{0,4}[\\[〈「『〖〔《(【\\(☆★].{1,30}[\\)】)》〕〗』」〉\\]]?\\s{0,4}$", + "rule": "^[  \\t]{0,4}[\\[〈「『〖〔《(【\\(☆★].{1,30}[\\)】)》〕〗』」〉\\]]?\\s{0,4}$", "serialNumber": 8 }, { "enable":false, "name": "特殊符号 标题(不匹配空白字符)", - "rule": "^(?<=\\s)[\\[〈「『〖〔《(【\\(☆★].{1,30}[\\)】)》〕〗』」〉\\]]?\\s{0,4}$", + "rule": "^(?<= |\\s)[\\[〈「『〖〔《(【\\(☆★].{1,30}[\\)】)》〕〗』」〉\\]]?\\s{0,4}$", "serialNumber": 9 }, { From 4875e83359b9d869959a6928ad8ed51ae65362ed Mon Sep 17 00:00:00 2001 From: fisher Date: Sun, 1 Mar 2020 19:59:28 +0800 Subject: [PATCH 089/105] update full-width characters --- app/src/main/assets/txtChapterRule.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/assets/txtChapterRule.json b/app/src/main/assets/txtChapterRule.json index 775e6b1a31..d99d765a20 100644 --- a/app/src/main/assets/txtChapterRule.json +++ b/app/src/main/assets/txtChapterRule.json @@ -32,7 +32,7 @@ { "enable": true, "name": "正文 标题/序号", - "rule": "^[ \\t]{0,4}正文\\s{1,4}.{0,20}$", + "rule": "^[  \\t]{0,4}正文\\s{1,4}.{0,20}$", "serialNumber": 5 }, { From 55a70d1ddecce4f92762366774bf6eee2ae8d423 Mon Sep 17 00:00:00 2001 From: kunfei Date: Sat, 7 Mar 2020 18:00:27 +0800 Subject: [PATCH 090/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kunfei/bookshelf/view/fragment/SettingsFragment.kt | 3 +-- build.gradle | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.kt b/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.kt index f7101ed210..c11315d829 100644 --- a/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.kt +++ b/app/src/main/java/com/kunfei/bookshelf/view/fragment/SettingsFragment.kt @@ -8,7 +8,6 @@ import android.preference.ListPreference import android.preference.Preference import android.preference.PreferenceFragment import android.preference.PreferenceScreen -import android.view.View import com.hwangjr.rxbus.RxBus import com.kunfei.bookshelf.MApplication import com.kunfei.bookshelf.R @@ -145,7 +144,7 @@ class SettingsFragment : PreferenceFragment(), OnSharedPreferenceChangeListener } picker.show() picker.cancelButton.setText(R.string.restore_default) - picker.cancelButton.setOnClickListener { view: View? -> + picker.cancelButton.setOnClickListener { picker.dismiss() MApplication.getInstance().setDownloadPath(null) preference.summary = MApplication.downloadPath diff --git a/build.gradle b/build.gradle index 316542227d..5ba1b33e21 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ buildscript { maven { url 'https://plugins.gradle.org/m2/' } } dependencies { - classpath 'com.android.tools.build:gradle:3.6.0' + classpath 'com.android.tools.build:gradle:3.6.1' classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' classpath 'com.google.gms:google-services:4.3.3' classpath 'io.fabric.tools:gradle:1.31.0' From f61cfae0a59da92f13aa483fee58e2f29df0f7e8 Mon Sep 17 00:00:00 2001 From: kunfei Date: Mon, 9 Mar 2020 19:52:32 +0800 Subject: [PATCH 091/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/kunfei/bookshelf/base/MBaseActivity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/kunfei/bookshelf/base/MBaseActivity.java b/app/src/main/java/com/kunfei/bookshelf/base/MBaseActivity.java index 0ef992b53f..bfd1d8b5a8 100644 --- a/app/src/main/java/com/kunfei/bookshelf/base/MBaseActivity.java +++ b/app/src/main/java/com/kunfei/bookshelf/base/MBaseActivity.java @@ -182,6 +182,7 @@ protected boolean isImmersionBarEnabled() { /** * 设置屏幕方向 */ + @SuppressLint("SourceLockedOrientationActivity") public void setOrientation(int screenDirection) { switch (screenDirection) { case 0: From 55e39431e04d3e931a22fd300130145aac973e6f Mon Sep 17 00:00:00 2001 From: fisher Date: Mon, 9 Mar 2020 20:24:16 +0800 Subject: [PATCH 092/105] update all rules --- app/src/main/assets/txtChapterRule.json | 56 ++++++++++++++++++------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/app/src/main/assets/txtChapterRule.json b/app/src/main/assets/txtChapterRule.json index d99d765a20..cce8711256 100644 --- a/app/src/main/assets/txtChapterRule.json +++ b/app/src/main/assets/txtChapterRule.json @@ -2,25 +2,25 @@ { "enable": true, "name": "目录", - "rule": "^[  \\t]{0,4}(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", + "rule": "^[  \\t]{0,4}(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", "serialNumber": 0 }, { "enable": false, - "name": "目录(不匹配行前空白)", - "rule": "^(?<= |\\s)(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", + "name": "目录(去空白)", + "rule": "(?<=[ \\s])(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|篇(?!张))).{0,30}$", "serialNumber": 1 }, { "enable": false, "name": "目录(去简介)", - "rule": "^(?<= |\\s)(?:前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|回(?![合来事去])|场(?![和合比电是])|篇(?!张))).{0,30}$", + "rule": "(?<=[ \\s])(?:前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|回(?![合来事去])|场(?![和合比电是])|篇(?!张))).{0,30}$", "serialNumber": 2 }, { "enable": false, "name": "目录(古典、轻小说备用)", - "rule": "^[  \\t]{0,4}(?:前言|序章|楔子|正文(?!完)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|回(?![合来事去])|场(?![和合比电是])|篇(?!张))).{0,30}$", + "rule": "^[  \\t]{0,4}(?:前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|回(?![合来事去])|场(?![和合比电是])|篇(?!张))).{0,30}$", "serialNumber": 3 }, { @@ -32,37 +32,61 @@ { "enable": true, "name": "正文 标题/序号", - "rule": "^[  \\t]{0,4}正文\\s{1,4}.{0,20}$", + "rule": "^[  \\t]{0,4}正文[  ]{1,4}.{0,20}$", "serialNumber": 5 }, { "enable": true, "name": "Chapter/Section/Part/Episode 序号 标题", - "rule": "^[  \\t]{0,4}(?:[Cc]hapter|[Ss]ection|[Pp]art|PART|[Ee]pisode)\\s{0,4}\\d{1,4}.{0,30}$", + "rule": "^[  \\t]{0,4}(?:[Cc]hapter|[Ss]ection|[Pp]art|PART|[Ee]pisode|(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外)\\s{0,4}\\d{1,4}.{0,30}$", "serialNumber": 6 }, { - "enable": true, - "name": "特殊符号 序号 标题", - "rule": "^[  \\t]{0,4}[〈〖〔【][第卷][\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,10}[章节][\\.:: \f\t].{0,30}$", + "enable": false, + "name": "Chapter(去简介)", + "rule": "^[  \\t]{0,4}(?:[Cc]hapter|[Ss]ection|[Pp]art|PART|[Ee]pisode)\\s{0,4}\\d{1,4}.{0,30}$", "serialNumber": 7 }, { "enable": true, - "name": "特殊符号 标题", - "rule": "^[  \\t]{0,4}[\\[〈「『〖〔《(【\\(☆★].{1,30}[\\)】)》〕〗』」〉\\]]?\\s{0,4}$", + "name": "特殊符号 序号 标题", + "rule": "(?<=[\\s ]{0,4}).{1,3}(?:第|卷|[Cc]hapter)[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,10}[章节]?[\\.:: \f\t].{0,20}$", "serialNumber": 8 }, { - "enable":false, - "name": "特殊符号 标题(不匹配空白字符)", - "rule": "^(?<= |\\s)[\\[〈「『〖〔《(【\\(☆★].{1,30}[\\)】)》〕〗』」〉\\]]?\\s{0,4}$", + "enable": false, + "name": "特殊符号 标题(成对)", + "rule": "(?<=[\\s ]{0,4})(?:[\\[〈「『〖〔《(【\\(].{1,30}[\\)】)》〕〗』」〉\\]]?|(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外)[  ]{0,4}$", "serialNumber": 9 }, + { + "enable":true, + "name": "特殊符号 标题(单个)", + "rule": "(?<=[\\s ]{0,4})(?:[☆★✦✧].{1,30}|(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外)[  ]{0,4}$", + "serialNumber": 10 + }, + { + "enable": true, + "name": "章/卷 序号 标题", + "rule": "^[ \\t ]{0,4}(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外|[卷章][\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8})[  ]{0,4}.{0,30}$", + "serialNumber": 11 + }, { "enable":false, "name": "顶格标题", "rule": "^\\S.{1,20}$", - "serialNumber": 10 + "serialNumber": 12 + }, + { + "enable":false, + "name": "双标题(前向)", + "rule": "(?m)(?<=[ \\t ]{0,4})第[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}章.{0,30}$(?=[\\s ]{0,8}第[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}章)", + "serialNumber": 13 + }, + { + "enable":false, + "name": "双标题(后向)", + "rule": "(?m)(?<=[ \\t ]{0,4}第[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}章.{0,30}$[\\s ]{0,8})第[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}章.{0,30}$", + "serialNumber": 14 } ] From 4b7ebd88d06242c81ad9787458082a5f903c6226 Mon Sep 17 00:00:00 2001 From: fisher Date: Mon, 9 Mar 2020 21:26:06 +0800 Subject: [PATCH 093/105] added numberical format --- app/src/main/assets/txtChapterRule.json | 28 +++++++++++++++---------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/app/src/main/assets/txtChapterRule.json b/app/src/main/assets/txtChapterRule.json index cce8711256..b4f6f5b28c 100644 --- a/app/src/main/assets/txtChapterRule.json +++ b/app/src/main/assets/txtChapterRule.json @@ -23,70 +23,76 @@ "rule": "^[  \\t]{0,4}(?:前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外|第?\\s{0,4}[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?!分)|回(?![合来事去])|场(?![和合比电是])|篇(?!张))).{0,30}$", "serialNumber": 3 }, + { + "enable": false, + "name": "数字(纯数字标题)", + "rule": "^\\d+$", + "serialNumber": 4 + }, { "enable": true, "name": "数字 分隔符 标题名称", "rule": "^[  \\t]{0,4}\\d{1,5}[\\,\\., 、\\-].{1,30}$", - "serialNumber": 4 + "serialNumber": 5 }, { "enable": true, "name": "正文 标题/序号", "rule": "^[  \\t]{0,4}正文[  ]{1,4}.{0,20}$", - "serialNumber": 5 + "serialNumber": 6 }, { "enable": true, "name": "Chapter/Section/Part/Episode 序号 标题", "rule": "^[  \\t]{0,4}(?:[Cc]hapter|[Ss]ection|[Pp]art|PART|[Ee]pisode|(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外)\\s{0,4}\\d{1,4}.{0,30}$", - "serialNumber": 6 + "serialNumber": 7 }, { "enable": false, "name": "Chapter(去简介)", "rule": "^[  \\t]{0,4}(?:[Cc]hapter|[Ss]ection|[Pp]art|PART|[Ee]pisode)\\s{0,4}\\d{1,4}.{0,30}$", - "serialNumber": 7 + "serialNumber": 8 }, { "enable": true, "name": "特殊符号 序号 标题", "rule": "(?<=[\\s ]{0,4}).{1,3}(?:第|卷|[Cc]hapter)[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,10}[章节]?[\\.:: \f\t].{0,20}$", - "serialNumber": 8 + "serialNumber": 9 }, { "enable": false, "name": "特殊符号 标题(成对)", "rule": "(?<=[\\s ]{0,4})(?:[\\[〈「『〖〔《(【\\(].{1,30}[\\)】)》〕〗』」〉\\]]?|(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外)[  ]{0,4}$", - "serialNumber": 9 + "serialNumber": 10 }, { "enable":true, "name": "特殊符号 标题(单个)", "rule": "(?<=[\\s ]{0,4})(?:[☆★✦✧].{1,30}|(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外)[  ]{0,4}$", - "serialNumber": 10 + "serialNumber": 11 }, { "enable": true, "name": "章/卷 序号 标题", "rule": "^[ \\t ]{0,4}(?:(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外|[卷章][\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8})[  ]{0,4}.{0,30}$", - "serialNumber": 11 + "serialNumber": 12 }, { "enable":false, "name": "顶格标题", "rule": "^\\S.{1,20}$", - "serialNumber": 12 + "serialNumber": 13 }, { "enable":false, "name": "双标题(前向)", "rule": "(?m)(?<=[ \\t ]{0,4})第[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}章.{0,30}$(?=[\\s ]{0,8}第[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}章)", - "serialNumber": 13 + "serialNumber": 14 }, { "enable":false, "name": "双标题(后向)", "rule": "(?m)(?<=[ \\t ]{0,4}第[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}章.{0,30}$[\\s ]{0,8})第[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}章.{0,30}$", - "serialNumber": 14 + "serialNumber": 15 } ] From 7499a1bde7b72a920f29cf3f2bec6eccf2b313ce Mon Sep 17 00:00:00 2001 From: fisher Date: Tue, 10 Mar 2020 00:35:56 +0800 Subject: [PATCH 094/105] update rules --- app/src/main/assets/txtChapterRule.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/assets/txtChapterRule.json b/app/src/main/assets/txtChapterRule.json index b4f6f5b28c..ececb68006 100644 --- a/app/src/main/assets/txtChapterRule.json +++ b/app/src/main/assets/txtChapterRule.json @@ -26,7 +26,7 @@ { "enable": false, "name": "数字(纯数字标题)", - "rule": "^\\d+$", + "rule": "(?<=[ \\s])\\d+[  \\t]{0,4}$", "serialNumber": 4 }, { From 7fc114d3bd3268a4aebff7435b10d46827913b2e Mon Sep 17 00:00:00 2001 From: kunfei Date: Thu, 12 Mar 2020 21:37:55 +0800 Subject: [PATCH 095/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 051017c6cb..82eaeb4c32 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -1,5 +1,10 @@ ## 更新日志 * 请关注[开源阅读软件]()支持我,同时关注合作公众号[小说拾遗](),阅读公众号小编。 +* 3.0版本以上线,虽然还有些小BUG,不过不太影响使用,可以用用了,公众号阅读量决定了我的更新速度 + +**2020/03/12** +* 更新txt解析目录 by 52fisher +* web看书加翻页 by Celeter **2020/02/26** * 更新默认txt目录规则,由https://github.com/52fisher提供 From 34ce8d3c6dbba5f0afb21260e97551f755a05622 Mon Sep 17 00:00:00 2001 From: kunfei Date: Fri, 20 Mar 2020 20:17:08 +0800 Subject: [PATCH 096/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kunfei/bookshelf/help/storage/Backup.kt | 58 +++++++++++++------ .../bookshelf/model/SearchBookModel.java | 2 +- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt index 5d47cc8149..903e6efa56 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/Backup.kt @@ -48,13 +48,13 @@ object Backup { } val path = MApplication.getConfigPreferences().getString("backupPath", defaultPath) if (path == null) { - backup(MApplication.getInstance(), defaultPath, null) + backup(MApplication.getInstance(), defaultPath, null, true) } else { - backup(MApplication.getInstance(), path, null) + backup(MApplication.getInstance(), path, null, true) } } - fun backup(context: Context, path: String, callBack: CallBack?) { + fun backup(context: Context, path: String, callBack: CallBack?, isAuto: Boolean = false) { MApplication.getConfigPreferences().edit().putLong("lastBackup", System.currentTimeMillis()).apply() Single.create(SingleOnSubscribe { e -> BookshelfHelp.getAllBook().let { @@ -105,9 +105,9 @@ object Backup { } WebDavHelp.backUpWebDav(backupPath) if (path.isContentPath()) { - copyBackup(context, Uri.parse(path)) + copyBackup(context, Uri.parse(path), isAuto) } else { - copyBackup(path) + copyBackup(path, isAuto) } e.onSuccess(true) }).subscribeOn(Schedulers.io()) @@ -125,14 +125,27 @@ object Backup { } @Throws(Exception::class) - private fun copyBackup(context: Context, uri: Uri) { - DocumentFile.fromTreeUri(context, uri)?.let { treeDoc -> - for (fileName in backupFileNames) { - val file = File(backupPath + File.separator + fileName) - if (file.exists()) { - treeDoc.findFile(fileName)?.delete() - treeDoc.createFile("", fileName)?.let { - DocumentUtil.writeBytes(context, file.readBytes(), it) + private fun copyBackup(context: Context, uri: Uri, isAuto: Boolean) { + synchronized(this) { + DocumentFile.fromTreeUri(context, uri)?.let { treeDoc -> + for (fileName in backupFileNames) { + val file = File(backupPath + File.separator + fileName) + if (file.exists()) { + if (isAuto) { + treeDoc.findFile("auto")?.findFile(fileName)?.delete() + var autoDoc = treeDoc.findFile("auto") + if (autoDoc == null) { + autoDoc = treeDoc.createDirectory("auto") + } + autoDoc?.createFile("", fileName)?.let { + DocumentUtil.writeBytes(context, file.readBytes(), it) + } + } else { + treeDoc.findFile(fileName)?.delete() + treeDoc.createFile("", fileName)?.let { + DocumentUtil.writeBytes(context, file.readBytes(), it) + } + } } } } @@ -140,11 +153,20 @@ object Backup { } @Throws(java.lang.Exception::class) - private fun copyBackup(path: String) { - for (fileName in backupFileNames) { - val file = File(backupPath + File.separator + fileName) - if (file.exists()) { - file.copyTo(FileHelp.createFileIfNotExist(path + File.separator + fileName), true) + private fun copyBackup(path: String, isAuto: Boolean) { + synchronized(this) { + for (fileName in backupFileNames) { + if (isAuto) { + val file = File(backupPath + File.separator + fileName) + if (file.exists()) { + file.copyTo(FileHelp.createFileIfNotExist(path + File.separator + "auto" + File.separator + fileName), true) + } + } else { + val file = File(backupPath + File.separator + fileName) + if (file.exists()) { + file.copyTo(FileHelp.createFileIfNotExist(path + File.separator + fileName), true) + } + } } } } diff --git a/app/src/main/java/com/kunfei/bookshelf/model/SearchBookModel.java b/app/src/main/java/com/kunfei/bookshelf/model/SearchBookModel.java index a09983709d..7a99fdbbd1 100644 --- a/app/src/main/java/com/kunfei/bookshelf/model/SearchBookModel.java +++ b/app/src/main/java/com/kunfei/bookshelf/model/SearchBookModel.java @@ -238,7 +238,7 @@ public interface OnSearchListener { int getItemCount(); } - private class SearchEngine { + private static class SearchEngine { private String tag; private Boolean hasMore; From 7b02545f943857072a3a0f7fc45c6c8f5e962437 Mon Sep 17 00:00:00 2001 From: kunfei Date: Fri, 20 Mar 2020 20:21:22 +0800 Subject: [PATCH 097/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 82eaeb4c32..8c8ad5781d 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -2,6 +2,9 @@ * 请关注[开源阅读软件]()支持我,同时关注合作公众号[小说拾遗](),阅读公众号小编。 * 3.0版本以上线,虽然还有些小BUG,不过不太影响使用,可以用用了,公众号阅读量决定了我的更新速度 +**2020/03/20** +* 自动备份文件和手动备份文件分开 + **2020/03/12** * 更新txt解析目录 by 52fisher * web看书加翻页 by Celeter From cc1249b1fd097be95f242752031e354096c40410 Mon Sep 17 00:00:00 2001 From: kunfei Date: Fri, 20 Mar 2020 20:27:06 +0800 Subject: [PATCH 098/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 8c8ad5781d..1d26669319 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -1,6 +1,7 @@ ## 更新日志 -* 请关注[开源阅读软件]()支持我,同时关注合作公众号[小说拾遗](),阅读公众号小编。 -* 3.0版本以上线,虽然还有些小BUG,不过不太影响使用,可以用用了,公众号阅读量决定了我的更新速度 +* 请关注[开源阅读]()支持我,同时关注合作公众号[小说拾遗](),阅读公众号小编。 +* 弄了个企业公众号[开源阅读](),后面弄好后会把原来的[开源阅读软件]()迁移过来 +* [3.0下载地址](https://www.coolapk.com/apk/256030) **2020/03/20** * 自动备份文件和手动备份文件分开 From 146206aadb1efa8304adcf214242cbe3019c5ade Mon Sep 17 00:00:00 2001 From: kunfei Date: Fri, 20 Mar 2020 20:37:02 +0800 Subject: [PATCH 099/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 9 +++++---- app/src/main/assets/updateLog.md | 1 + app/src/main/res/layout/mo_dialog_markdown.xml | 2 -- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 98fe1909a5..e03369fca9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,6 @@ apply plugin: 'com.android.application' -apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' apply plugin: 'org.greenrobot.greendao' apply plugin: 'io.fabric' apply plugin: "de.timfreiheit.resourceplaceholders" @@ -83,7 +83,7 @@ dependencies { implementation "org.jetbrains.anko:anko-sdk27-listeners:$anko_version" //fireBase - implementation 'com.google.firebase:firebase-core:17.2.2' + implementation 'com.google.firebase:firebase-core:17.2.3' implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1' //androidX @@ -94,7 +94,7 @@ dependencies { implementation 'androidx.legacy:legacy-support-v4:1.0.0' //google - implementation 'com.google.android.material:material:1.2.0-alpha04' + implementation 'com.google.android.material:material:1.2.0-alpha05' implementation 'com.google.code.gson:gson:2.8.5' implementation 'com.google.android:flexbox:1.1.0' @@ -118,6 +118,7 @@ dependencies { implementation 'de.hdodenhof:circleimageview:3.0.0' //bind view + //noinspection AnnotationProcessorOnCompilePath implementation 'com.jakewharton:butterknife:10.1.0' annotationProcessor 'com.jakewharton:butterknife-compiler:10.1.0' @@ -126,7 +127,7 @@ dependencies { implementation 'org.nanohttpd:nanohttpd-websocket:2.3.1' //二维码 - implementation 'cn.bingoogolapple:bga-qrcode-zxing:1.3.6' + implementation 'cn.bingoogolapple:bga-qrcode-zxing:1.3.7' //颜色选择 implementation 'com.jaredrummler:colorpicker:1.1.0' diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 1d26669319..8be888fd9e 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -5,6 +5,7 @@ **2020/03/20** * 自动备份文件和手动备份文件分开 +* 更新一些库文件 **2020/03/12** * 更新txt解析目录 by 52fisher diff --git a/app/src/main/res/layout/mo_dialog_markdown.xml b/app/src/main/res/layout/mo_dialog_markdown.xml index a8c5113fa5..0cd758c7a9 100644 --- a/app/src/main/res/layout/mo_dialog_markdown.xml +++ b/app/src/main/res/layout/mo_dialog_markdown.xml @@ -17,8 +17,6 @@ android:id="@+id/tv_markdown" android:layout_width="match_parent" android:layout_height="match_parent" - android:linksClickable="true" - android:autoLink="web" android:lineSpacingMultiplier="1.2" android:padding="10dp"/> From 651649383b78d0b6414d6cf19ad0e57ade2dd56b Mon Sep 17 00:00:00 2001 From: kunfei Date: Mon, 23 Mar 2020 19:09:55 +0800 Subject: [PATCH 100/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 1 + build.gradle | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index e03369fca9..d2e39702d7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -104,6 +104,7 @@ dependencies { implementation 'com.jayway.jsonpath:json-path:2.4.0' //JS + //noinspection GradleDependency implementation 'com.github.gedoor:rhino-android:1.3' //GreenDao diff --git a/build.gradle b/build.gradle index 5ba1b33e21..48e06a45be 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ ext { support_library_version = '28.0.0' } buildscript { - ext.kotlin_version = '1.3.61' + ext.kotlin_version = '1.3.70' repositories { google() jcenter() @@ -14,7 +14,7 @@ buildscript { classpath 'com.android.tools.build:gradle:3.6.1' classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' classpath 'com.google.gms:google-services:4.3.3' - classpath 'io.fabric.tools:gradle:1.31.0' + classpath 'io.fabric.tools:gradle:1.31.2' classpath 'net.ricecode:string-similarity:1.0.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'de.timfreiheit.resourceplaceholders:placeholders:0.3' From f06f6696dcc2b2d7869d67ce2c3259e0cd058301 Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 31 Mar 2020 19:16:23 +0800 Subject: [PATCH 101/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/kunfei/bookshelf/help/storage/Restore.kt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt b/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt index 3a8e57935b..1c63176cc3 100644 --- a/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt +++ b/app/src/main/java/com/kunfei/bookshelf/help/storage/Restore.kt @@ -119,17 +119,16 @@ object Restore { edit.putLong("DonateHb", donateHb) edit.putInt("versionCode", MApplication.getVersionCode()) edit.apply() - LauncherIcon.ChangeIcon(MApplication.getConfigPreferences().getString("launcher_icon", MApplication.getInstance().getString(R.string.icon_main))) - ReadBookControl.getInstance().updateReaderSettings() - MApplication.getInstance().upThemeStore() - MApplication.getInstance().initNightTheme() - edit.commit() } e.onSuccess(true) }).subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : MySingleObserver() { override fun onSuccess(t: Boolean) { + LauncherIcon.ChangeIcon(MApplication.getConfigPreferences().getString("launcher_icon", MApplication.getInstance().getString(R.string.icon_main))) + ReadBookControl.getInstance().updateReaderSettings() + MApplication.getInstance().upThemeStore() + MApplication.getInstance().initNightTheme() callBack?.restoreSuccess() } From 560157b1a9e40bdea075ee73b35583d126907dd2 Mon Sep 17 00:00:00 2001 From: kunfei Date: Sat, 11 Apr 2020 19:57:36 +0800 Subject: [PATCH 102/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 12 ++++++------ build.gradle | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d2e39702d7..67c2ce8088 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -70,7 +70,7 @@ resourcePlaceholders { } dependencies { - testImplementation 'junit:junit:4.13-beta-3' + testImplementation 'junit:junit:4.13' implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(':basemvplib') @@ -83,7 +83,7 @@ dependencies { implementation "org.jetbrains.anko:anko-sdk27-listeners:$anko_version" //fireBase - implementation 'com.google.firebase:firebase-core:17.2.3' + implementation 'com.google.firebase:firebase-core:17.3.0' implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1' //androidX @@ -95,11 +95,11 @@ dependencies { //google implementation 'com.google.android.material:material:1.2.0-alpha05' - implementation 'com.google.code.gson:gson:2.8.5' + implementation 'com.google.code.gson:gson:2.8.6' implementation 'com.google.android:flexbox:1.1.0' //J_SOUP - implementation 'org.jsoup:jsoup:1.12.1' + implementation 'org.jsoup:jsoup:1.13.1' implementation 'cn.wanghaomiao:JsoupXpath:2.3.2' implementation 'com.jayway.jsonpath:json-path:2.4.0' @@ -112,7 +112,7 @@ dependencies { implementation 'com.github.yuweiguocn:GreenDaoUpgradeHelper:v2.1.0' //Glide - implementation 'com.github.bumptech.glide:glide:4.9.0' + implementation 'com.github.bumptech.glide:glide:4.11.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0' //CircleImageView @@ -140,7 +140,7 @@ dependencies { implementation 'net.ricecode:string-similarity:1.0.0' //MarkDown - implementation 'ru.noties.markwon:core:3.0.2' + implementation 'ru.noties.markwon:core:3.1.0' //epub implementation('nl.siegmann.epublib:epublib-core:3.1') { diff --git a/build.gradle b/build.gradle index 48e06a45be..45c0b80a03 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ ext { support_library_version = '28.0.0' } buildscript { - ext.kotlin_version = '1.3.70' + ext.kotlin_version = '1.3.71' repositories { google() jcenter() @@ -11,7 +11,7 @@ buildscript { maven { url 'https://plugins.gradle.org/m2/' } } dependencies { - classpath 'com.android.tools.build:gradle:3.6.1' + classpath 'com.android.tools.build:gradle:3.6.2' classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' classpath 'com.google.gms:google-services:4.3.3' classpath 'io.fabric.tools:gradle:1.31.2' From ae30cc339eb51f2b6daf08395bf672a5db25cc6c Mon Sep 17 00:00:00 2001 From: kunfei Date: Sat, 11 Apr 2020 20:45:25 +0800 Subject: [PATCH 103/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 8 ++++---- basemvplib/build.gradle | 11 ++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 67c2ce8088..898f921aee 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -113,15 +113,15 @@ dependencies { //Glide implementation 'com.github.bumptech.glide:glide:4.11.0' - annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0' + annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' //CircleImageView - implementation 'de.hdodenhof:circleimageview:3.0.0' + implementation 'de.hdodenhof:circleimageview:3.1.0' //bind view //noinspection AnnotationProcessorOnCompilePath - implementation 'com.jakewharton:butterknife:10.1.0' - annotationProcessor 'com.jakewharton:butterknife-compiler:10.1.0' + implementation 'com.jakewharton:butterknife:10.2.1' + annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.1' //webServer implementation 'org.nanohttpd:nanohttpd:2.3.1' diff --git a/basemvplib/build.gradle b/basemvplib/build.gradle index 455e9a60b4..b94743aaa8 100644 --- a/basemvplib/build.gradle +++ b/basemvplib/build.gradle @@ -26,7 +26,7 @@ android { } dependencies { - testImplementation 'junit:junit:4.13-beta-3' + testImplementation 'junit:junit:4.13' api fileTree(dir: 'libs', include: ['*.jar']) //support @@ -34,15 +34,16 @@ dependencies { api 'androidx.appcompat:appcompat:1.1.0' //RxAndroid - api 'io.reactivex.rxjava2:rxjava:2.2.10' + api 'io.reactivex.rxjava2:rxjava:2.2.19' api 'io.reactivex.rxjava2:rxandroid:2.1.1' //RxBus api 'com.hwangjr.rxbus:rxbus:2.0.1' //Retrofit - api 'com.squareup.retrofit2:retrofit:2.6.1' - api 'com.squareup.retrofit2:adapter-rxjava2:2.6.1' - api 'com.squareup.retrofit2:converter-scalars:2.6.1' + //noinspection GradleDependency + api 'com.squareup.retrofit2:retrofit:2.7.2' + api 'com.squareup.retrofit2:adapter-rxjava2:2.8.1' + api 'com.squareup.retrofit2:converter-scalars:2.8.1' } \ No newline at end of file From 39f75583bec21c38948afd01685a4b21b71a8bac Mon Sep 17 00:00:00 2001 From: kunfei Date: Sat, 11 Apr 2020 21:07:00 +0800 Subject: [PATCH 104/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bookshelf/model/analyzeRule/AnalyzeByRegex.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/kunfei/bookshelf/model/analyzeRule/AnalyzeByRegex.java b/app/src/main/java/com/kunfei/bookshelf/model/analyzeRule/AnalyzeByRegex.java index 20a2597cd4..fe7e435e82 100644 --- a/app/src/main/java/com/kunfei/bookshelf/model/analyzeRule/AnalyzeByRegex.java +++ b/app/src/main/java/com/kunfei/bookshelf/model/analyzeRule/AnalyzeByRegex.java @@ -8,6 +8,7 @@ import com.kunfei.bookshelf.bean.BookSourceBean; import com.kunfei.bookshelf.model.content.Debug; import com.kunfei.bookshelf.utils.NetworkUtils; +import com.kunfei.bookshelf.utils.StringUtils; import java.util.ArrayList; import java.util.HashMap; @@ -82,10 +83,13 @@ public static void getInfoOfRegex(String res, String[] regs, int index, ruleVal.put(ruleName.get(i), hasVarParams.get(i) ? AnalyzeByRegex.checkKeys(infoVal.toString(), analyzer) : infoVal.toString()); } // 保存详情信息 - if (!isEmpty(ruleVal.get("BookName"))) bookInfoBean.setName(ruleVal.get("BookName")); - if (!isEmpty(ruleVal.get("BookAuthor"))) bookInfoBean.setAuthor(ruleVal.get("BookAuthor")); + if (!isEmpty(ruleVal.get("BookName"))) + bookInfoBean.setName(StringUtils.formatHtml(ruleVal.get("BookName"))); + if (!isEmpty(ruleVal.get("BookAuthor"))) + bookInfoBean.setAuthor(StringUtils.formatHtml(ruleVal.get("BookAuthor"))); if (!isEmpty(ruleVal.get("LastChapter"))) bookShelfBean.setLastChapterName(ruleVal.get("LastChapter")); - if (!isEmpty(ruleVal.get("Introduce"))) bookInfoBean.setIntroduce(ruleVal.get("Introduce")); + if (!isEmpty(ruleVal.get("Introduce"))) + bookInfoBean.setIntroduce(StringUtils.formatHtml(ruleVal.get("Introduce"))); if (!isEmpty(ruleVal.get("CoverUrl"))) bookInfoBean.setCoverUrl(ruleVal.get("CoverUrl")); if (!isEmpty(ruleVal.get("ChapterUrl"))) bookInfoBean.setChapterUrl(NetworkUtils.getAbsoluteURL(baseUrl, ruleVal.get("ChapterUrl"))); else bookInfoBean.setChapterUrl(baseUrl); From fbc1f61a79fbf6003691577345adeb3665f6a64b Mon Sep 17 00:00:00 2001 From: kunfei Date: Sat, 11 Apr 2020 21:08:09 +0800 Subject: [PATCH 105/105] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 8be888fd9e..ce0eb71fc6 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -3,6 +3,10 @@ * 弄了个企业公众号[开源阅读](),后面弄好后会把原来的[开源阅读软件]()迁移过来 * [3.0下载地址](https://www.coolapk.com/apk/256030) +**2020/04/11** +* 修复一些bug +* 更新一些库 + **2020/03/20** * 自动备份文件和手动备份文件分开 * 更新一些库文件