pull/5/head
fengyuecanzhu 3 years ago
parent c1401bad93
commit 55061acb55
  1. 7
      app/src/main/assets/updatelog.fy
  2. 22
      app/src/main/java/xyz/fycz/myreader/model/SearchEngine.java
  3. 4
      app/src/main/java/xyz/fycz/myreader/model/third2/content/BookChapterList.java
  4. 25
      app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java
  5. 8
      app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java
  6. 6
      app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java
  7. 53
      app/src/main/java/xyz/fycz/myreader/ui/adapter/SourceExchangeAdapter.java
  8. 41
      app/src/main/java/xyz/fycz/myreader/ui/dialog/SourceExchangeDialog.java
  9. 2
      app/src/main/java/xyz/fycz/myreader/util/help/JsExtensions.java
  10. 9
      app/src/main/java/xyz/fycz/myreader/webapi/BookApi.java
  11. 2
      app/src/main/res/layout/activity_search_book.xml
  12. 23
      app/src/main/res/layout/dialog_book_source.xml

@ -1,8 +1,11 @@
2021.06.14
2021.06.15
风月读书v2.1.3
更新内容:
1、优化阅读文字选择
2、修复已知bug
2、优化第三方书源加载
3、优化换源对话框
4、换源对话框新增书源搜索
5、修复已知bug
2021.06.13
风月读书v2.1.2

@ -46,19 +46,12 @@ public class SearchEngine {
private int searchSuccessNum;
private int searchFinishNum;
private boolean isRead = false;//是否在阅读界面换源
private OnSearchListener searchListener;
public SearchEngine() {
threadsNum = SharedPreUtils.getInstance().getInt(App.getmContext().getString(R.string.threadNum), 8);
}
public SearchEngine(boolean isRead) {
this();
this.isRead = isRead;
}
public void setOnSearchListener(OnSearchListener searchListener) {
this.searchListener = searchListener;
}
@ -193,7 +186,6 @@ public class SearchEngine {
ReadCrawler crawler = mSourceList.get(searchSiteIndex);
String searchKey = title;
BookApi.search(searchKey, crawler)
.flatMap(bookMap -> getBookInfo(bookMap, crawler))
.subscribeOn(scheduler)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<ConMVMap<SearchBookBean, Book>>() {
@ -266,20 +258,6 @@ public class SearchEngine {
});
}
public Observable<ConMVMap<SearchBookBean, Book>> getBookInfo(ConMVMap<SearchBookBean, Book> bookMap, ReadCrawler rc) {
return Observable.create(emitter -> {
if (isRead && rc instanceof ThirdCrawler) {
List<Book> books = bookMap.values();
for (Book book : books) {
BookApi.getBookInfo(book, (BookInfoCrawler) rc).subscribe();
}
}
emitter.onNext(bookMap);
emitter.onComplete();
});
}
/************************************************************************/
public interface OnSearchListener {

@ -158,6 +158,10 @@ public class BookChapterList {
chapterList = new ArrayList<>(lh);
Collections.reverse(chapterList);
Log.d(tag, "-目录解析完成" + analyzeNextUrl);
if (chapterList.isEmpty()) {
emitter.onError(new Throwable("目录列表为空"));
return;
}
emitter.onNext(chapterList);
emitter.onComplete();
}

@ -119,9 +119,7 @@ public class BookDetailedActivity extends BaseActivity {
initBookInfo();
mChapters.clear();
mNewestChapters.clear();
if (!isThirdSource()) {
initChapters(true);
}
initChapters(true);
mCatalogAdapter.clear();
}
break;
@ -225,7 +223,7 @@ public class BookDetailedActivity extends BaseActivity {
binding.ic.bookDetailRvCatalog.setLayoutManager(new LinearLayoutManager(this));
binding.ic.bookDetailRvCatalog.setAdapter(mCatalogAdapter);
if (!isThirdSource()) initChapters(false);
initChapters(false);
mCatalogAdapter.setOnItemClickListener((view, pos) -> {
mBook.setHisttoryChapterNum(mChapters.size() - pos - 1);
@ -435,7 +433,7 @@ public class BookDetailedActivity extends BaseActivity {
BookSource source = BookSourceManager.getBookSourceByStr(mBook.getSource());
binding.ih.bookDetailSource.setText(String.format("书源:%s", source.getSourceName()));
ReadCrawler rc = ReadCrawlerUtil.getReadCrawler(source);
if ((rc instanceof BookInfoCrawler && StringHelper.isEmpty(mBook.getImgUrl())) || isThirdSource()) {
if ((rc instanceof BookInfoCrawler && StringHelper.isEmpty(mBook.getImgUrl()))) {
binding.pbLoading.setVisibility(View.VISIBLE);
BookInfoCrawler bic = (BookInfoCrawler) rc;
BookApi.getBookInfo(mBook, bic).compose(RxUtils::toSimpleSingle).subscribe(new MyObserver<Book>() {
@ -443,9 +441,6 @@ public class BookDetailedActivity extends BaseActivity {
public void onNext(@NotNull Book book) {
if (!App.isDestroy(BookDetailedActivity.this)) {
mHandler.sendMessage(mHandler.obtainMessage(4));
if (isThirdSource()) {
initChapters(false);
}
}
}
@ -454,9 +449,6 @@ public class BookDetailedActivity extends BaseActivity {
public void onError(Throwable e) {
if (!App.isDestroy(BookDetailedActivity.this)) {
ToastUtils.showError("书籍详情加载失败!");
if (isThirdSource()) {
initChapters(false);
}
binding.pbLoading.setVisibility(View.GONE);
}
if (App.isDebug()) e.printStackTrace();
@ -569,15 +561,15 @@ public class BookDetailedActivity extends BaseActivity {
mBookService.addBook(mBook);
}
Intent intent = new Intent(this, ReadActivity.class);
/*aBooks = mSourceDialog.getaBooks();
aBooks = mSourceDialog.getaBooks();
if (aBooks != null) {
aBooks.set(mSourceDialog.getSourceIndex(), mBook);
BitIntentDataManager.getInstance().putData(intent, aBooks);
intent.putExtra(APPCONST.SOURCE_INDEX, mSourceDialog.getSourceIndex());
} else {
BitIntentDataManager.getInstance().putData(intent, mBook);
}*/
BitIntentDataManager.getInstance().putData(intent, mBook);
}
// BitIntentDataManager.getInstance().putData(intent, mBook);
intent.putExtra("isCollected", isCollected);
startActivityForResult(intent, APPCONST.REQUEST_READ);
}
@ -729,9 +721,4 @@ public class BookDetailedActivity extends BaseActivity {
}
}
private boolean isThirdSource() {
return mReadCrawler instanceof ThirdCrawler;
}
}

@ -307,7 +307,7 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
mPageLoader = binding.readPvContent.getPageLoader(mBook, mReadCrawler, mSetting);
//Dialog
mSourceDialog = new SourceExchangeDialog(this, mBook, true);
mSourceDialog = new SourceExchangeDialog(this, mBook);
if (aBooks != null) {
mSourceDialog.setABooks(aBooks);
}
@ -472,6 +472,7 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
mSourceDialog.setOnSourceChangeListener((bean, pos) -> {
Book bookTem = (Book) mBook.clone();
bookTem.setInfoUrl(bean.getInfoUrl());
bookTem.setChapterUrl(bean.getChapterUrl());
bookTem.setSource(bean.getSource());
if (!StringHelper.isEmpty(bean.getImgUrl())) {
@ -722,10 +723,11 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
mSourceDialog.show();
} else if (itemId == R.id.action_reload) {
mPageLoader.setPrev(false);
if (!"本地书籍".equals(mBook.getType())) {
if (!"本地书籍".equals(mBook.getType()) && !mChapters.isEmpty()) {
mChapterService.deleteChapterCacheFile(mChapters.get(mPageLoader.getChapterPos()));
}
mPageLoader.refreshChapter(mChapters.get(mPageLoader.getChapterPos()));
if (!mChapters.isEmpty())
mPageLoader.refreshChapter(mChapters.get(mPageLoader.getChapterPos()));
} else if (itemId == R.id.action_add_bookmark) {
if (mChapters == null || mChapters.size() == 0) {
if ("本地书籍".equals(mBook.getType())) {

@ -243,7 +243,11 @@ public class SearchBookActivity extends BaseActivity {
mHandler.sendMessage(mHandler.obtainMessage(1));
});
initHistoryList();
mHandler.postDelayed(() -> binding.etSearchKey.requestFocus(), 200);
mHandler.postDelayed(() -> {
binding.etSearchKey.requestFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED);
}, 400);
}
@Override

@ -1,26 +1,75 @@
package xyz.fycz.myreader.ui.adapter;
import android.widget.Filter;
import android.widget.Filterable;
import xyz.fycz.myreader.base.adapter.BaseListAdapter;
import xyz.fycz.myreader.base.adapter.IViewHolder;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.entity.ReplaceRuleBean;
import xyz.fycz.myreader.model.sourceAnalyzer.BookSourceManager;
import xyz.fycz.myreader.ui.adapter.holder.SourceExchangeHolder;
import xyz.fycz.myreader.ui.dialog.SourceExchangeDialog;
import xyz.fycz.myreader.util.help.StringHelper;
import java.util.ArrayList;
import java.util.List;
/**
* @author fengyue
* @date 2020/9/30 18:42
*/
public class SourceExchangeAdapter extends BaseListAdapter<Book> {
public class SourceExchangeAdapter extends BaseListAdapter<Book> implements Filterable {
private SourceExchangeDialog dialog;
private List<Book> beans;
public SourceExchangeAdapter(SourceExchangeDialog dialog) {
public SourceExchangeAdapter(SourceExchangeDialog dialog, List<Book> beans) {
this.dialog = dialog;
this.beans = beans;
}
@Override
protected IViewHolder createViewHolder(int viewType) {
return new SourceExchangeHolder(dialog);
}
/**
* 过滤器实现搜索
*
* @return
*/
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
String charString = constraint.toString();
List<Book> mFilterList = new ArrayList<>();
if (charString.isEmpty()) {
//没有过滤的内容,则使用源数据
mFilterList = beans;
} else {
for (Book bean : beans) {
//这里根据需求,添加匹配规则
if (BookSourceManager.getSourceNameByStr(bean.getSource())
.contains(charString)) {
mFilterList.add(bean);
}
}
}
FilterResults filterResults = new FilterResults();
filterResults.values = mFilterList;
return filterResults;
}
//把过滤后的值返回出来
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.values != null)
refreshItems((List<Book>) results.values);
else
refreshItems(beans);
}
};
}
}

@ -3,6 +3,7 @@ package xyz.fycz.myreader.ui.dialog;
import android.app.Activity;
import android.app.Dialog;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
@ -10,6 +11,7 @@ import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.SearchView;
import androidx.recyclerview.widget.LinearLayoutManager;
import java.util.ArrayList;
@ -20,6 +22,7 @@ import xyz.fycz.myreader.entity.SearchBookBean;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.model.SearchEngine;
import xyz.fycz.myreader.model.mulvalmap.ConMVMap;
import xyz.fycz.myreader.model.sourceAnalyzer.BookSourceManager;
import xyz.fycz.myreader.ui.adapter.SourceExchangeAdapter;
import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil;
import xyz.fycz.myreader.widget.RefreshProgressBar;
@ -47,7 +50,7 @@ public class SourceExchangeDialog extends Dialog {
private int sourceIndex = -1;
private boolean isRead;//是否在阅读界面换源
private String sourceSearchStr;
/***************************************************************************/
public SourceExchangeDialog(@NonNull Activity activity, Book bookBean) {
@ -56,11 +59,6 @@ public class SourceExchangeDialog extends Dialog {
mShelfBook = bookBean;
}
public SourceExchangeDialog(@NonNull Activity activity, Book bookBean, boolean isRead) {
this(activity, bookBean);
this.isRead = isRead;
}
public void setShelfBook(Book mShelfBook) {
this.mShelfBook = mShelfBook;
}
@ -99,7 +97,6 @@ public class SourceExchangeDialog extends Dialog {
@Override
protected void onStart() {
super.onStart();
//执行业务逻辑
if (aBooks.size() == 0) {
searchEngine.search(mShelfBook.getName(), mShelfBook.getAuthor());
binding.ivStopSearch.setVisibility(View.VISIBLE);
@ -108,6 +105,7 @@ public class SourceExchangeDialog extends Dialog {
if (mAdapter.getItemCount() == 0) {
mAdapter.addItems(aBooks);
}
binding.ivStopSearch.setVisibility(View.GONE);
}
}
@ -135,11 +133,11 @@ public class SourceExchangeDialog extends Dialog {
aBooks = new ArrayList<>();
}
mAdapter = new SourceExchangeAdapter(this);
mAdapter = new SourceExchangeAdapter(this, aBooks);
binding.dialogRvContent.setLayoutManager(new LinearLayoutManager(mActivity));
binding.dialogRvContent.setAdapter(mAdapter);
searchEngine = new SearchEngine(isRead);
searchEngine = new SearchEngine();
searchEngine.initSearchEngine(ReadCrawlerUtil.getEnableReadCrawlers());
}
@ -167,7 +165,13 @@ public class SourceExchangeDialog extends Dialog {
bean.setNewestChapterId("true");
sourceIndex = mAdapter.getItemSize();
}
mAdapter.addItem(items.get(0));
if (TextUtils.isEmpty(sourceSearchStr)) {
mAdapter.addItem(bean);
} else {
if (BookSourceManager.getSourceNameByStr(bean.getSource()).contains(sourceSearchStr)){
mAdapter.addItem(bean);
}
}
aBooks.add(bean);
}
}
@ -201,12 +205,29 @@ public class SourceExchangeDialog extends Dialog {
binding.ivStopSearch.setOnClickListener(v -> searchEngine.stopSearch());
binding.ivRefreshSearch.setOnClickListener(v -> {
searchEngine.stopSearch();
binding.rpb.setIsAutoLoading(true);
binding.ivStopSearch.setVisibility(View.VISIBLE);
mAdapter.clear();
aBooks.clear();
mAdapter.notifyDataSetChanged();
searchEngine.search(mShelfBook.getName(), mShelfBook.getAuthor());
});
binding.searchView.onActionViewExpanded();
binding.searchView.clearFocus();
binding.searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
sourceSearchStr = newText;
mAdapter.getFilter().filter(newText);
return false;
}
});
}

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

@ -1,5 +1,7 @@
package xyz.fycz.myreader.webapi;
import android.util.Log;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
@ -101,7 +103,12 @@ public class BookApi {
*/
public static Observable<List<Chapter>> getBookChapters(Book book, final ReadCrawler rc) {
if (rc instanceof ThirdCrawler) {
return ThirdSourceApi.getBookChaptersByTC(book, (ThirdCrawler) rc);
if (StringHelper.isEmpty(book.getChapterUrl())) {
return ThirdSourceApi.getBookInfoByTC(book, (ThirdCrawler) rc)
.flatMap(book1 -> ThirdSourceApi.getBookChaptersByTC(book, (ThirdCrawler) rc));
} else {
return ThirdSourceApi.getBookChaptersByTC(book, (ThirdCrawler) rc);
}
}
String url = book.getChapterUrl();
if (StringHelper.isEmpty(url)) url = book.getInfoUrl();

@ -1,6 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"

@ -29,8 +29,8 @@
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerInParent="true"
android:padding="8dp"
android:background="?android:attr/selectableItemBackground"
android:padding="8dp"
app:srcCompat="@drawable/ic_refresh" />
<androidx.appcompat.widget.AppCompatImageView
@ -38,22 +38,33 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="?android:attr/selectableItemBackground"
android:layout_toStartOf="@+id/iv_refresh_search"
android:background="?android:attr/selectableItemBackground"
android:padding="8dp"
app:srcCompat="@drawable/ic_stop_black_24dp" />
</RelativeLayout>
<androidx.appcompat.widget.SearchView
android:id="@+id/searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:queryHint="@string/search" />
<xyz.fycz.myreader.widget.RefreshProgressBar
android:id="@+id/rpb"
android:layout_width="match_parent"
android:layout_height="3dp"
android:visibility="visible" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/dialog_rv_content"
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorBackground" />
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/dialog_rv_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorBackground" />
</RelativeLayout>
</LinearLayout>

Loading…
Cancel
Save