master
fengyuecanzhu 3 years ago
parent 299f4bc366
commit 974d522dd5
  1. 5
      .github/workflows/reader.yml
  2. 6
      .idea/misc.xml
  3. 4
      DialogX/build.gradle
  4. 6
      app/src/main/AndroidManifest.xml
  5. 5
      app/src/main/assets/updatelog.fy
  6. 9
      app/src/main/java/xyz/fycz/myreader/entity/thirdsource/BookSource3Bean.java
  7. 39
      app/src/main/java/xyz/fycz/myreader/entity/thirdsource/ExploreKind.kt
  8. 4
      app/src/main/java/xyz/fycz/myreader/model/SearchEngine.java
  9. 5
      app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/BookSourceManager.java
  10. 3
      app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java
  11. 8
      app/src/main/java/xyz/fycz/myreader/ui/activity/BookstoreActivity.java
  12. 3
      app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java
  13. 8
      app/src/main/java/xyz/fycz/myreader/ui/activity/ReadRecordActivity.java
  14. 2
      app/src/main/java/xyz/fycz/myreader/ui/adapter/FileSystemAdapter.java
  15. 8
      app/src/main/java/xyz/fycz/myreader/ui/adapter/FontsAdapter.java
  16. 9
      app/src/main/java/xyz/fycz/myreader/ui/dialog/SourceExchangeDialog.java
  17. 54
      app/src/main/java/xyz/fycz/myreader/ui/fragment/DIYSourceFragment.java
  18. 14
      app/src/main/java/xyz/fycz/myreader/util/UriFileUtil.java
  19. 1
      app/src/main/java/xyz/fycz/myreader/util/help/JsExtensions.java
  20. 2
      app/src/main/java/xyz/fycz/myreader/util/utils/FileUtils.java
  21. 2
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/base/BaseReadCrawler.java
  22. 1
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/base/ReadCrawler.java
  23. 14
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/source/find/ThirdFindCrawler.java

@ -83,11 +83,6 @@ jobs:
echo "上传APP至蓝奏云"
python3 $GITHUB_WORKSPACE/keystore/scripts/lzy.py "${{ steps.get_path.outputs.file_path }}" "${{ steps.config.outputs.lanzou_folder_id }}"
echo "[$(date -u -d '+8 hour' '+%Y.%m.%d %H:%M:%S')] 分享链接: ${{ steps.config.outputs.lanzou_share_url }}"
- name: Upload App To Team
run: |
echo "上传APP至官网"
python3 $GITHUB_WORKSPACE/keystore/scripts/team.py "$GITHUB_WORKSPACE" "${{ steps.get_path.outputs.file_path }}" "${{ steps.config.outputs.need_create_release }}"
echo "[$(date -u -d '+8 hour' '+%Y.%m.%d %H:%M:%S')] 官网链接:https://reader.fycz.tk/"
- name: Create Release
id: create_release
if: ${{ steps.config.outputs.need_create_release == 'true' }}

@ -6,10 +6,13 @@
<entry key="..\:/android/FYReader/app/src/main/res/drawable/ic_re_seg.xml" value="0.1962962962962963" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_about.xml" value="0.12132725430597771" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_donate.xml" value="0.536" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_feedback.xml" value="0.12132725430597771" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_file_picker.xml" value="0.2318840579710145" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_group_manager.xml" value="0.12132725430597771" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_manage_group.xml" value="0.21195652173913043" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_more_setting.xml" value="0.264" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/fingerprint_dialog.xml" value="0.20425724637681159" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/fragment_file_category.xml" value="0.2318840579710145" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/fragment_find_book_2.xml" value="0.12132725430597771" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/fragment_private_bookcase.xml" value="0.21195652173913043" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/fragment_webdav_setting.xml" value="0.4" />
@ -26,6 +29,9 @@
</map>
</option>
</component>
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>

@ -7,11 +7,11 @@ def gitUrl = 'https://github.com/kongzue/DialogX.git' //Git仓库的地址
group = "com.kongzue.dialogx"
android {
compileSdkVersion 30
compileSdkVersion 29
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
targetSdkVersion 29
versionCode 10
versionName "1.0"

@ -61,7 +61,6 @@
android:resource="@xml/shortcuts" />
</activity>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
@ -88,6 +87,7 @@
<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
<data android:mimeType="application/epub+zip" />
</intent-filter>
@ -110,7 +110,9 @@
<activity android:name=".ui.activity.MoreSettingActivity" />
<activity android:name=".ui.activity.BookstoreActivity" />
<activity android:name=".ui.activity.QRCodeScanActivity" />
<activity android:name=".ui.activity.BookSourceActivity" />
<activity
android:name=".ui.activity.BookSourceActivity"
android:exported="true" />
<activity android:name=".ui.activity.SourceEditActivity" />
<activity android:name=".ui.activity.SourceDebugActivity" />
<activity android:name=".ui.activity.AdSettingActivity" />

@ -1,3 +1,8 @@
风月读书v2.2.1
更新内容:
1、修复切换书源对话框内存泄漏的问题
2、优化导入书源选择
风月读书v2.2.0
更新内容:
1、修复从书籍详情页进入阅读后切换日夜模式闪退的bug

@ -1,11 +1,15 @@
package xyz.fycz.myreader.entity.thirdsource;
import android.text.TextUtils;
import com.google.gson.Gson;
import java.util.ArrayList;
import java.util.List;
import kotlin.jvm.Transient;
import xyz.fycz.myreader.util.utils.GsonUtils;
import xyz.fycz.myreader.util.utils.StringUtils;
// 解析阅读3.0的书源规则,toBookSourceBean()方法转换为阅读2.0书源规则
// https://raw.githubusercontent.com/gedoor/legado/master/app/src/main/java/io/legado/app/data/entities/BookSource.kt
@ -215,6 +219,9 @@ public class BookSource3Bean {
header="@Header:"+this.header.replaceAll("\\n"," ");
}
if (!TextUtils.isEmpty(ruleFindUrl)){
ruleFindUrl += header;
}
return new BookSourceBean(
bookSourceUrl,
@ -226,7 +233,7 @@ public class BookSource3Bean {
0, //u serialNumber,
weight,
true, //u enable,
ruleFindUrl+header,//发现规则 ruleFindUrl,
ruleFindUrl,//发现规则 ruleFindUrl,
ruleExplore.bookList, // 列表 ruleFindList,
ruleExplore.name,// ruleFindName,
ruleExplore.author,// ruleFindAuthor,

@ -0,0 +1,39 @@
package xyz.fycz.myreader.entity.thirdsource
data class ExploreKind(
val title: String,
val url: String? = null,
val style: Style? = null
) {
companion object {
val defaultStyle = Style()
}
fun style(): Style {
return style ?: defaultStyle
}
data class Style(
val layout_flexGrow: Float = 0F,
val layout_flexShrink: Float = 1F,
val layout_alignSelf: String = "auto",
val layout_flexBasisPercent: Float = -1F,
val layout_wrapBefore: Boolean = false,
) {
fun alignSelf(): Int {
return when (layout_alignSelf) {
"auto" -> -1
"flex_start" -> 0
"flex_end" -> 1
"center" -> 2
"baseline" -> 3
"stretch" -> 4
else -> -1
}
}
}
}

@ -258,6 +258,10 @@ public class SearchEngine {
});
}
public boolean isSearching(){
return compositeDisposable != null && compositeDisposable.size() > 0;
}
/************************************************************************/
public interface OnSearchListener {

@ -4,6 +4,7 @@ import android.database.Cursor;
import android.text.TextUtils;
import android.util.Log;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -309,6 +310,8 @@ public class BookSourceManager {
} else if (StringUtils.isCompressJsonType(string)) {
return importBookSourceFromJson(StringUtils.unCompressJson(string))
.compose(RxUtils::toSimpleSingle);
} else if (new File(string).isFile()) {
return importSource(FileUtils.readText(string));
}
if (NetworkUtils.isUrl(string)) {
String finalString = string;
@ -316,7 +319,7 @@ public class BookSourceManager {
.flatMap(BookSourceManager::importBookSourceFromJson)
.compose(RxUtils::toSimpleSingle);
}
return Observable.error(new Exception("不是Json或Url格式"));
return Observable.error(new Exception("不是Json或Url格式或文件路径"));
}
private static Observable<List<BookSource>> importBookSourceFromJson(String json) {

@ -138,6 +138,9 @@ public class BookDetailedActivity extends BaseActivity {
@Override
protected void onDestroy() {
if (chaptersDis != null) chaptersDis.dispose();
if (mSourceDialog != null) {
mSourceDialog.stopSearch();
}
super.onDestroy();
}

@ -116,6 +116,14 @@ public class BookstoreActivity extends BaseActivity {
getSupportActionBar().setSubtitle(subTitle);
}
@Override
protected void onDestroy() {
if (mSourceDia != null) {
mSourceDia.stopSearch();
}
super.onDestroy();
}
@Override
protected void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);

@ -696,6 +696,9 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
mPageLoader.closeBook();
mPageLoader = null;
}
if (mSourceDialog != null) {
mSourceDialog.stopSearch();
}
}
@Override

@ -62,6 +62,14 @@ public class ReadRecordActivity extends BaseActivity {
getSupportActionBar().setTitle(getString(R.string.read_record));
}
@Override
protected void onDestroy() {
if (mSourceDia != null) {
mSourceDia.stopSearch();
}
super.onDestroy();
}
@Override
protected void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);

@ -86,7 +86,7 @@ public class FileSystemAdapter extends BaseListAdapter<File> {
mCheckMap.put(file, true);
++mCheckedCount;
}
notifyDataSetChanged();
notifyItemChanged(pos);
}
public void setCheckedAll(boolean isChecked){

@ -10,6 +10,7 @@ import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.MimeTypeMap;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
@ -168,9 +169,10 @@ public class FontsAdapter extends ArrayAdapter<Font> {
dialog.show();*/
StoragePermissionUtils.request(mFontsActivity, (permissions, all) -> {
ToastUtils.showInfo("请选择一个ttf格式的字体文件");
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension("ttf");
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT)
.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{mime})
.setType("*/*");
mFontsActivity.startActivityForResult(intent, APPCONST.SELECT_FILE_CODE);
});
});

@ -2,6 +2,7 @@ package xyz.fycz.myreader.ui.dialog;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Gravity;
@ -108,14 +109,13 @@ public class SourceExchangeDialog extends Dialog {
super.onStart();
if (aBooks.size() == 0) {
searchEngine.search(mShelfBook.getName(), mShelfBook.getAuthor());
binding.ivStopSearch.setVisibility(View.VISIBLE);
binding.rpb.setIsAutoLoading(true);
}else {
if (mAdapter.getItemCount() == 0) {
mAdapter.addItems(aBooks);
}
binding.ivStopSearch.setVisibility(View.GONE);
}
binding.ivStopSearch.setVisibility(searchEngine.isSearching() ? View.VISIBLE : View.GONE);
}
/**
@ -239,6 +239,11 @@ public class SourceExchangeDialog extends Dialog {
});
}
public void stopSearch(){
if (searchEngine != null) {
searchEngine.stopSearch();
}
}
/**************************Interface**********************************/
public interface OnSourceChangeListener {

@ -3,7 +3,9 @@ package xyz.fycz.myreader.ui.fragment;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MenuInflater;
@ -23,6 +25,8 @@ import com.kongzue.dialogx.dialogs.BottomMenu;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import io.reactivex.Observable;
@ -50,6 +54,7 @@ import xyz.fycz.myreader.ui.dialog.LoadingDialog;
import xyz.fycz.myreader.ui.dialog.MyAlertDialog;
import xyz.fycz.myreader.util.ShareUtils;
import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.util.UriFileUtil;
import xyz.fycz.myreader.util.utils.ClipBoardUtil;
import xyz.fycz.myreader.util.utils.FileUtils;
import xyz.fycz.myreader.util.utils.GsonExtensionsKt;
@ -67,6 +72,7 @@ import static xyz.fycz.myreader.util.UriFileUtil.getPath;
* @date 2021/2/10 12:05
*/
public class DIYSourceFragment extends BaseFragment {
private static final String TAG = DIYSourceFragment.class.getSimpleName();
private FragmentImportSourceBinding binding;
private final BookSourceActivity sourceActivity;
@ -182,11 +188,13 @@ public class DIYSourceFragment extends BaseFragment {
ToastUtils.showError("剪切板内容为空,导入失败");
}
} else if (which == 1) {
ToastUtils.showInfo("请选择书源JSON文件");
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("application/json");
StoragePermissionUtils.request(this, (permissions, all) -> {
ToastUtils.showInfo("请选择书源文件");
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT)
.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{"text/*", "application/json"})
.setType("*/*");
startActivityForResult(intent, APPCONST.REQUEST_IMPORT_BOOK_SOURCE);
});
} else {
String[] url = new String[1];
MyAlertDialog.createInputDia(getContext(), "网络导入",
@ -236,19 +244,19 @@ public class DIYSourceFragment extends BaseFragment {
refreshSources();
ToastUtils.showSuccess(String.format("成功导入%s个书源", size));
} else {
ToastUtils.showError("格式不对");
ToastUtils.showError("书源格式错误,请导入正确的书源");
}
dialog.dismiss();
}
@Override
public void onError(Throwable e) {
ToastUtils.showError("格式不对");
ToastUtils.showError("书源格式错误,请导入正确的书源");
dialog.dismiss();
}
});
} else {
ToastUtils.showError("导入失败");
ToastUtils.showError("书源格式错误,请导入正确的书源");
}
}
@ -303,13 +311,35 @@ public class DIYSourceFragment extends BaseFragment {
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == APPCONST.REQUEST_IMPORT_BOOK_SOURCE) {
String path = getPath(getContext(), data.getData());
String json = FileUtils.readText(path);
if (!isEmpty(json)) {
importDataS(json);
} else {
LoadingDialog dialog = new LoadingDialog(getContext(), "读取文件", () -> {
if (importSourceDis != null) {
importSourceDis.dispose();
}
});
dialog.show();
Single.create((SingleOnSubscribe<String>) emitter -> {
String path = UriFileUtil.getChooseFileResultPath(getContext(), data.getData());
Log.d(TAG, "filePath:" + path);
emitter.onSuccess(path);
}).compose(RxUtils::toSimpleSingle).subscribe(new MySingleObserver<String>() {
@Override
public void onSubscribe(Disposable d) {
importSourceDis = d;
addDisposable(d);
}
@Override
public void onSuccess(@NonNull String s) {
importDataS(s);
dialog.dismiss();
}
@Override
public void onError(Throwable e) {
ToastUtils.showError("文件读取失败");
dialog.dismiss();
}
});
} else if (requestCode == APPCONST.REQUEST_EDIT_BOOK_SOURCE) {
refreshSources();
}

@ -40,6 +40,20 @@ public class UriFileUtil {
return uri;
}
public static String getChooseFileResultPath(Context context, Uri uri) {
String chooseFilePath = null;
if ("file".equalsIgnoreCase(uri.getScheme())) {//使用第三方应用打开
chooseFilePath = uri.getPath();
return chooseFilePath;
}
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {//4.4以后
chooseFilePath = getPath(context, uri);
} else {//4.4以下下系统调用方法
chooseFilePath = getRealPathFromUri(context, uri);
}
return chooseFilePath;
}
public static String getRealPathFromUri(Context context, Uri contentUri) {
Cursor cursor = null;
try {

@ -34,6 +34,7 @@ import xyz.fycz.myreader.util.utils.StringUtils;
@Keep
@SuppressWarnings({"unused"})
public interface JsExtensions {
String TAG = JsExtensions.class.getSimpleName();

@ -358,7 +358,7 @@ public class FileUtils {
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
return null;
return "";
}finally {
IOUtils.close(br);
}

@ -14,6 +14,7 @@ import xyz.fycz.myreader.entity.StrResponse;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.model.mulvalmap.ConMVMap;
import xyz.fycz.myreader.util.help.StringHelper;
import xyz.fycz.myreader.util.utils.NetworkUtils;
/**
@ -50,6 +51,7 @@ public abstract class BaseReadCrawler implements ReadCrawler {
return Observable.create(emitter -> {
ConMVMap<SearchBookBean, Book> bookMap = getBooksFromSearchHtml(response.body());
for (Book book : bookMap.values()){
book.setId(StringHelper.getStringRandom(25));
if (!TextUtils.isEmpty(book.getImgUrl())){
book.setImgUrl(NetworkUtils.getAbsoluteURL(getNameSpace(), book.getImgUrl()));
}

@ -15,7 +15,6 @@ import java.util.Map;
* @author fengyue
* @date 2020/4/28 16:18
*/
public interface ReadCrawler {
String getSearchLink(); // 书源的搜索url
String getCharset(); // 书源的字符编码

@ -11,11 +11,13 @@ import io.reactivex.Observable;
import io.reactivex.disposables.Disposable;
import xyz.fycz.myreader.entity.FindKind;
import xyz.fycz.myreader.entity.StrResponse;
import xyz.fycz.myreader.entity.thirdsource.ExploreKind;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.entity.rule.BookSource;
import xyz.fycz.myreader.greendao.entity.rule.FindRule;
import xyz.fycz.myreader.model.sourceAnalyzer.BookSourceManager;
import xyz.fycz.myreader.model.third2.analyzeRule.AnalyzeRule;
import xyz.fycz.myreader.util.utils.GsonUtils;
import xyz.fycz.myreader.util.utils.StringUtils;
import xyz.fycz.myreader.webapi.crawler.base.BaseFindCrawler;
@ -54,6 +56,18 @@ public class ThirdFindCrawler extends BaseFindCrawler {
public Observable<Boolean> initData() {
return Observable.create(emitter -> {
try {
if (StringUtils.isJsonArray(findRuleBean.getUrl())) {
List<ExploreKind> kinds = GsonUtils.parseJArray(findRuleBean.getUrl(), ExploreKind.class);
StringBuilder sb = new StringBuilder();
for (ExploreKind kind : kinds){
String url = kind.getUrl() == null ? "" : kind.getUrl();
sb.append(kind.getTitle()).append("::").append(url).append("\n");
}
if (sb.length() > 0){
sb.deleteCharAt(sb.length() - 1);
}
findRuleBean.setUrl(sb.toString());
}
String[] kindA;
String findRule;
if (!TextUtils.isEmpty(findRuleBean.getUrl()) && !source.containsGroup(findError)) {

Loading…
Cancel
Save