优化书籍详情

pull/5/head
fengyuecanzhu 4 years ago
parent f2a98582f1
commit 932ba08c3f
  1. 1
      app/src/main/AndroidManifest.xml
  2. 1
      app/src/main/java/xyz/fycz/myreader/common/APPCONST.java
  3. 2
      app/src/main/java/xyz/fycz/myreader/creator/DialogCreator.java
  4. 8
      app/src/main/java/xyz/fycz/myreader/greendao/service/BookMarkService.java
  5. 7
      app/src/main/java/xyz/fycz/myreader/greendao/service/ChapterService.java
  6. 169
      app/src/main/java/xyz/fycz/myreader/ui/bookinfo/BookDetailedActivity.java
  7. 134
      app/src/main/java/xyz/fycz/myreader/ui/bookinfo/BookInfoActivity.java
  8. 282
      app/src/main/java/xyz/fycz/myreader/ui/bookinfo/BookInfoPresenter.java
  9. 36
      app/src/main/java/xyz/fycz/myreader/ui/bookinfo/CatalogHolder.java
  10. 16
      app/src/main/java/xyz/fycz/myreader/ui/bookinfo/DetailCatalogAdapter.java
  11. 2
      app/src/main/java/xyz/fycz/myreader/ui/home/bookcase/BookcaseDetailedAdapter.java
  12. 3
      app/src/main/java/xyz/fycz/myreader/ui/home/bookcase/BookcasePresenter.java
  13. 1
      app/src/main/java/xyz/fycz/myreader/ui/home/bookstore/BookStorePresenter.java
  14. 5
      app/src/main/java/xyz/fycz/myreader/ui/read/ReadActivity.java
  15. 1
      app/src/main/java/xyz/fycz/myreader/ui/read/ReadPresenter.java
  16. 7
      app/src/main/java/xyz/fycz/myreader/ui/read/catalog/CatalogFragment.java
  17. 31
      app/src/main/java/xyz/fycz/myreader/ui/read/catalog/CatalogPresenter.java
  18. 1
      app/src/main/java/xyz/fycz/myreader/ui/read/catalog/ChapterTitleAdapter.java
  19. 9
      app/src/main/java/xyz/fycz/myreader/ui/search/SearchBookPrensenter.java
  20. 1
      app/src/main/java/xyz/fycz/myreader/webapi/CommonApi.java
  21. 213
      app/src/main/res/layout/activity_book_info.xml
  22. 7
      app/src/main/res/layout/fragment_catalog.xml
  23. 59
      app/src/main/res/layout/layout_book_detail_content.xml
  24. 2
      app/version_code.properties

@ -80,7 +80,6 @@
<activity
android:name=".ui.search.SearchBookActivity"
android:windowSoftInputMode="stateVisible"/>
<activity android:name=".ui.bookinfo.BookInfoActivity"/>
<activity android:name=".ui.bookinfo.BookDetailedActivity"/>
<activity

@ -54,6 +54,7 @@ public class APPCONST {
public static final int REQUEST_CHAPTER_PAGE = 1002;
public static final String RESULT_IS_COLLECTED = "result_is_collected";
public static final String RESULT_LAST_READ_POSITION = "result_last_read_position";
public static final int REQUEST_READ = 1;
public static final CharSequence[] DIALOG_DOWNLOAD = {

@ -380,7 +380,7 @@ public class DialogCreator {
tvBookName.setText(mBook.getName());
llBook.setOnClickListener(v -> {
/*Intent intent = new Intent(context, BookInfoActivity.class);
/*Intent intent = new Intent(context, BookDetailedActivity.class);
intent.putExtra(APPCONST.BOOK, mBook);
context.startActivity(intent);*/
});

@ -8,6 +8,7 @@ import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.greendao.entity.SearchHistory;
import xyz.fycz.myreader.greendao.gen.BookDao;
import xyz.fycz.myreader.greendao.gen.BookMarkDao;
import xyz.fycz.myreader.greendao.gen.ChapterDao;
import xyz.fycz.myreader.greendao.gen.SearchHistoryDao;
import xyz.fycz.myreader.util.DateHelper;
import xyz.fycz.myreader.util.StringHelper;
@ -114,8 +115,11 @@ public class BookMarkService extends BaseService {
* @param bookId
*/
public void deleteBookALLBookMarkById(String bookId) {
String sel = "delete from book_mark where book_id = ?";
rawQuery(sel, new String[]{bookId});
GreenDaoManager.getInstance().getSession().getBookMarkDao()
.queryBuilder()
.where(BookMarkDao.Properties.BookId.eq(bookId))
.buildDelete()
.executeDeleteWithoutDetachingEntities();
}
/**
* 批量删除书签

@ -117,8 +117,11 @@ public class ChapterService extends BaseService {
* @param bookId
*/
public void deleteBookALLChapterById(String bookId) {
String sel = "delete from chapter where book_id = ?";
rawQuery(sel, new String[]{bookId});
GreenDaoManager.getInstance().getSession().getChapterDao()
.queryBuilder()
.where(ChapterDao.Properties.BookId.eq(bookId))
.buildDelete()
.executeDeleteWithoutDetachingEntities();
deleteAllChapterCacheFile(bookId);
}

@ -9,19 +9,20 @@ import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.*;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.OnClick;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.MyApplication;
import xyz.fycz.myreader.base.BaseActivity2;
import xyz.fycz.myreader.base.adapter.BaseListAdapter;
import xyz.fycz.myreader.callback.ResultCallback;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.crawler.BookInfoCrawler;
@ -31,8 +32,12 @@ import xyz.fycz.myreader.creator.ChangeSourceDialog;
import xyz.fycz.myreader.creator.DialogCreator;
import xyz.fycz.myreader.enums.BookSource;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.greendao.service.BookService;
import xyz.fycz.myreader.greendao.service.ChapterService;
import xyz.fycz.myreader.ui.read.ReadActivity;
import xyz.fycz.myreader.ui.read.catalog.CatalogActivity;
import xyz.fycz.myreader.ui.read.catalog.ChapterTitleAdapter;
import xyz.fycz.myreader.util.StringHelper;
import xyz.fycz.myreader.util.TextHelper;
import xyz.fycz.myreader.util.utils.NetworkUtils;
@ -78,14 +83,26 @@ public class BookDetailedActivity extends BaseActivity2 {
private Book mBook;
private ArrayList<Book> aBooks;
private BookService mBookService;
private ChapterService mChapterService;
private ReadCrawler mReadCrawler;
private DetailCatalogAdapter mCatalogAdapter;
private ArrayList<Chapter> mChapters = new ArrayList<>();
private ArrayList<Chapter> mNewestChapters = new ArrayList<>();
private boolean isCollected;
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
if (!"本地书籍".equals(mBook.getType())) {
mChapters.clear();
mNewestChapters.clear();
initBookInfo();
initChapters();
mCatalogAdapter.notifyDataSetChanged();
}
break;
case 2:
createChangeSourceDia();
@ -110,13 +127,17 @@ public class BookDetailedActivity extends BaseActivity2 {
protected void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
mBookService = BookService.getInstance();
mChapterService = ChapterService.getInstance();
aBooks = (ArrayList<Book>) getIntent().getSerializableExtra(APPCONST.SEARCH_BOOK_BEAN);
if (aBooks != null) {
mBook = aBooks.get(0);
} else {
mBook = (Book) getIntent().getSerializableExtra(APPCONST.BOOK);
}
mReadCrawler = ReadCrawlerUtil.getReadCrawler(mBook.getSource());
isCollected = isBookCollected();
if (isCollected) {
mChapters = (ArrayList<Chapter>) mChapterService.findBookAllChapterByBookId(mBook.getId());
}
}
@Override
@ -129,8 +150,22 @@ public class BookDetailedActivity extends BaseActivity2 {
protected void initWidget() {
super.initWidget();
initBookInfo();
//catalog
mCatalogAdapter = new DetailCatalogAdapter();
bookDetailRvCatalog.setLayoutManager(new LinearLayoutManager(this));
bookDetailRvCatalog.setAdapter(mCatalogAdapter);
initChapters();
mCatalogAdapter.setOnItemClickListener((view, pos) -> {
mBook.setHisttoryChapterNum(mChapters.size() - pos - 1);
mBook.setLastReadPosition(0);
goReadActivity();
});
mTvDisclaimer.setOnClickListener(v -> DialogCreator.createAssetTipDialog(this, "免责声明", "disclaimer.fy"));
if (isBookCollected()) {
if (isCollected) {
bookDetailTvAdd.setText("移除书籍");
bookDetailTvOpen.setText("继续阅读");
}
@ -141,40 +176,25 @@ public class BookDetailedActivity extends BaseActivity2 {
protected void initClick() {
super.initClick();
flAddBookcase.setOnClickListener(view -> {
if (!isBookCollected()) {
if (!isCollected) {
mBookService.addBook(mBook);
isCollected = true;
TextHelper.showText("成功加入书架");
bookDetailTvAdd.setText("移除书籍");
} else {
mBookService.deleteBookById(mBook.getId());
isCollected = false;
mBook.setHisttoryChapterNum(0);
mBook.setLastReadPosition(0);
TextHelper.showText("成功移除书籍");
bookDetailTvAdd.setText("加入书架");
bookDetailTvOpen.setText("开始阅读");
}
});
flOpenBook.setOnClickListener(view -> {
final boolean isCollected;
if (isBookCollected()) {
isCollected = true;
} else {
mBookService.addBook(mBook);
isCollected = false;
CommonApi.getBookChapters(mBook.getChapterUrl(), mReadCrawler, new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
mBookService.updateEntity(mBook);
}
@Override
public void onError(Exception e) {
}
});
}
Intent intent = new Intent(this, ReadActivity.class);
intent.putExtra(APPCONST.BOOK, mBook);
intent.putExtra("isCollected", isCollected);
startActivityForResult(intent, APPCONST.REQUEST_READ);
goReadActivity();
});
}
@Override
@ -224,7 +244,7 @@ public class BookDetailedActivity extends BaseActivity2 {
}
private void initOtherInfo() {
mTvDesc.setText(mBook.getDesc());
mTvDesc.setText("\t\t\t\t" + mBook.getDesc());
mTvType.setText(mBook.getType());
Glide.with(this)
.load(mBook.getImgUrl())
@ -236,7 +256,7 @@ public class BookDetailedActivity extends BaseActivity2 {
}
private void createChangeSourceDia() {
if (aBooks == null){
if (aBooks == null) {
mHandler.sendMessage(mHandler.obtainMessage(3));
return;
}
@ -256,7 +276,6 @@ public class BookDetailedActivity extends BaseActivity2 {
.setTitle("切换书源")
.setCancelable(true)
.setSingleChoiceItems(sources, checkedItem, (dialog1, which) -> {
boolean isBookCollected = isBookCollected();
if (finalCheckedItem == which) {
dialog1.dismiss();
return;
@ -268,12 +287,12 @@ public class BookDetailedActivity extends BaseActivity2 {
bookTem.setType(book.getType());
bookTem.setDesc(book.getDesc());
bookTem.setSource(book.getSource());
if (isBookCollected) {
if (isCollected) {
mBookService.updateBook(mBook, bookTem);
}
mBook = bookTem;
mHandler.sendMessage(mHandler.obtainMessage(1));
if (isBookCollected) {
if (isCollected) {
DialogCreator.createTipDialog(this,
"换源成功,由于不同书源的章节数量不一定相同,故换源后历史章节可能出错!");
}
@ -282,6 +301,44 @@ public class BookDetailedActivity extends BaseActivity2 {
dialog.show();
}
private void initChapters() {
if (mChapters.size() == 0 && !"本地书籍".equals(mBook.getType())) {
mReadCrawler = ReadCrawlerUtil.getReadCrawler(mBook.getSource());
CommonApi.getBookChapters(mBook.getChapterUrl(), mReadCrawler, new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
mChapters = (ArrayList<Chapter>) o;
int end = Math.max(0, mChapters.size() - 10);
for (int i = mChapters.size() - 1; i >= end; i--) {
mNewestChapters.add(mChapters.get(i));
}
MyApplication.runOnUiThread(() -> mCatalogAdapter.refreshItems(mNewestChapters));
}
@Override
public void onError(Exception e) {
}
});
} else {
int end = Math.max(0, mChapters.size() - 10);
for (int i = mChapters.size() - 1; i >= end; i--) {
mNewestChapters.add(mChapters.get(i));
mCatalogAdapter.refreshItems(mNewestChapters);
}
}
}
private void goReadActivity(){
if (!isCollected) {
mBookService.addBook(mBook);
}
Intent intent = new Intent(this, ReadActivity.class);
intent.putExtra(APPCONST.BOOK, mBook);
intent.putExtra("isCollected", isCollected);
startActivityForResult(intent, APPCONST.REQUEST_READ);
}
/********************************Event***************************************/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
@ -299,7 +356,7 @@ public class BookDetailedActivity extends BaseActivity2 {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_change_source: //换源
if (!NetworkUtils.isNetWorkAvailable()){
if (!NetworkUtils.isNetWorkAvailable()) {
TextHelper.showText("无网络连接!");
return true;
}
@ -323,13 +380,19 @@ public class BookDetailedActivity extends BaseActivity2 {
}
break;
case R.id.action_reload: //重新加载
if (!"本地书籍".equals(mBook.getType())) {
mChapters.clear();
mNewestChapters.clear();
initWidget();
processLogic();
}
break;
case R.id.action_open_link: //打开链接
if (!"本地书籍".equals(mBook.getType())) {
Uri uri = Uri.parse(mBook.getChapterUrl());
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
break;
default:
break;
@ -337,16 +400,52 @@ public class BookDetailedActivity extends BaseActivity2 {
return super.onOptionsItemSelected(item);
}
/**
* 展开简介
*/
@OnClick(R.id.book_detail_tv_desc)
protected void showMoreDesc() {
if (mTvDesc.getMaxLines() == 5)
mTvDesc.setMaxLines(15);
else
mTvDesc.setMaxLines(5);
}
/**
* 章节列表
*/
@OnClick(R.id.book_detail_tv_catalog_more)
public void goToMoreChapter() {
Intent intent = new Intent(this, CatalogActivity.class);
intent.putExtra(APPCONST.BOOK, mBook);
startActivityForResult(intent, APPCONST.REQUEST_CHAPTER_PAGE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == APPCONST.REQUEST_READ) {
if (resultCode == RESULT_OK) {
switch (requestCode) {
case APPCONST.REQUEST_READ:
if (data == null) {
return;
}
boolean isCollected = data.getBooleanExtra(APPCONST.RESULT_IS_COLLECTED, false);
int lastReadPosition = data.getIntExtra(APPCONST.RESULT_LAST_READ_POSITION, 0);
if (isCollected) {
bookDetailTvAdd.setText("移除书籍");
bookDetailTvOpen.setText("继续阅读");
this.isCollected = true;
mBook.setLastReadPosition(lastReadPosition);
}else {
mBook.setHisttoryChapterNum(0);
mBook.setLastReadPosition(0);
}
mCatalogAdapter.notifyDataSetChanged();
break;
case APPCONST.REQUEST_CHAPTER_PAGE:
int[] chapterAndPage = data.getIntArrayExtra(APPCONST.CHAPTER_PAGE);
mBook.setHisttoryChapterNum(chapterAndPage[0]);
mBook.setLastReadPosition(chapterAndPage[1]);
goReadActivity();
break;
}
}
}

@ -1,134 +0,0 @@
package xyz.fycz.myreader.ui.bookinfo;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import androidx.core.content.ContextCompat;
import android.widget.*;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.base.BaseActivity;
import butterknife.ButterKnife;
import butterknife.BindView;
import xyz.fycz.myreader.common.APPCONST;
public class BookInfoActivity extends BaseActivity {
@BindView(R.id.ll_title_back)
LinearLayout llTitleBack;
@BindView(R.id.tv_title_text)
TextView tvTitleText;
@BindView(R.id.system_title)
LinearLayout systemTitle;
@BindView(R.id.iv_book_img)
ImageView ivBookImg;
@BindView(R.id.tv_book_name)
TextView tvBookName;
@BindView(R.id.tv_book_author)
TextView tvBookAuthor;
@BindView(R.id.tv_book_type)
TextView tvBookType;
@BindView(R.id.tv_book_desc)
TextView tvBookDesc;
@BindView(R.id.btn_add_bookcase)
Button btnAddBookcase;
@BindView(R.id.btn_read_book)
Button btnReadBook;
@BindView(R.id.tv_book_newest_chapter)
TextView tvBookNewestChapter;
@BindView(R.id.tv_disclaimer)
TextView tvDisclaimer;
@BindView(R.id.tv_book_source)
TextView tvBookSource;
@BindView(R.id.btn_change_source)
Button btnChangeSource;
@BindView(R.id.pb_loading)
ProgressBar pbLoading;
private BookInfoPresenter mBookInfoPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_book_info);
ButterKnife.bind(this);
setStatusBar(R.color.sys_line);
mBookInfoPresenter = new BookInfoPresenter(this);
mBookInfoPresenter.start();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == APPCONST.REQUEST_READ) {
if (data == null) {
return;
}
boolean isCollected = data.getBooleanExtra(APPCONST.RESULT_IS_COLLECTED, false);
if (isCollected) {
getBtnAddBookcase().setText("移除书籍");
getBtnReadBook().setText("继续阅读");
}
}
}
public LinearLayout getLlTitleBack() {
return llTitleBack;
}
public TextView getTvTitleText() {
return tvTitleText;
}
public LinearLayout getSystemTitle() {
return systemTitle;
}
public ImageView getIvBookImg() {
return ivBookImg;
}
public TextView getTvBookName() {
return tvBookName;
}
public TextView getTvBookAuthor() {
return tvBookAuthor;
}
public TextView getTvBookType() {
return tvBookType;
}
public TextView getTvBookDesc() {
return tvBookDesc;
}
public Button getBtnAddBookcase() {
return btnAddBookcase;
}
public Button getBtnReadBook() {
return btnReadBook;
}
public TextView getTvBookNewestChapter() {
return tvBookNewestChapter;
}
public TextView getTvDisclaimer() {
return tvDisclaimer;
}
public TextView getTvBookSource() {
return tvBookSource;
}
public Button getBtnChangeSource() {
return btnChangeSource;
}
public ProgressBar getPbLoading() {
return pbLoading;
}
}

@ -1,282 +0,0 @@
package xyz.fycz.myreader.ui.bookinfo;
import android.annotation.SuppressLint;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import androidx.appcompat.app.AlertDialog;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.base.BasePresenter;
import xyz.fycz.myreader.callback.ResultCallback;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.crawler.BookInfoCrawler;
import xyz.fycz.myreader.crawler.ReadCrawler;
import xyz.fycz.myreader.crawler.ReadCrawlerUtil;
import xyz.fycz.myreader.creator.ChangeSourceDialog;
import xyz.fycz.myreader.creator.DialogCreator;
import xyz.fycz.myreader.enums.BookSource;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.service.BookService;
import xyz.fycz.myreader.ui.read.ReadActivity;
import xyz.fycz.myreader.util.StringHelper;
import xyz.fycz.myreader.util.TextHelper;
import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.webapi.CommonApi;
public class BookInfoPresenter implements BasePresenter {
private BookInfoActivity mBookInfoActivity;
private Book mBook;
private ArrayList<Book> aBooks;
private BookService mBookService;
private ReadCrawler mReadCrawler;
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
initBookInfo();
break;
case 2:
createChangeSourceDia();
break;
case 3:
mBookInfoActivity.getPbLoading().setVisibility(View.GONE);
DialogCreator.createTipDialog(mBookInfoActivity, "未搜索到该书籍,书源加载失败!");
break;
case 4:
initOtherInfo();
break;
}
}
};
public BookInfoPresenter(BookInfoActivity bookInfoActivity) {
mBookInfoActivity = bookInfoActivity;
mBookService = BookService.getInstance();
}
@Override
public void start() {
aBooks = (ArrayList<Book>) mBookInfoActivity.getIntent().getSerializableExtra(APPCONST.SEARCH_BOOK_BEAN);
if (aBooks != null) {
mBook = aBooks.get(0);
} else {
mBook = (Book) mBookInfoActivity.getIntent().getSerializableExtra(APPCONST.BOOK);
}
init();
}
private void init() {
mBookInfoActivity.getBtnChangeSource().setOnClickListener(v -> {
if (!NetworkUtils.isNetWorkAvailable()){
TextHelper.showText("无网络连接!");
return;
}
mBookInfoActivity.getPbLoading().setVisibility(View.VISIBLE);
if (aBooks == null) {
ChangeSourceDialog csd = new ChangeSourceDialog(mBookInfoActivity, mBook);
csd.init(new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
aBooks = (ArrayList<Book>) o;
mHandler.sendMessage(mHandler.obtainMessage(2));
}
@Override
public void onError(Exception e) {
mHandler.sendMessage(mHandler.obtainMessage(3));
}
});
} else {
createChangeSourceDia();
}
});
mBookInfoActivity.getTvDisclaimer().setOnClickListener(v -> DialogCreator.createAssetTipDialog(mBookInfoActivity, "免责声明", "disclaimer.fy"));
if (isBookCollected()) {
mBookInfoActivity.getBtnAddBookcase().setText("移除书籍");
mBookInfoActivity.getBtnReadBook().setText("继续阅读");
} else {
mBookInfoActivity.getBtnAddBookcase().setText("加入书架");
mBookInfoActivity.getBtnReadBook().setText("开始阅读");
}
mBookInfoActivity.getLlTitleBack().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mBookInfoActivity.finish();
}
});
mBookInfoActivity.getBtnAddBookcase().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!isBookCollected()) {
mBookService.addBook(mBook);
TextHelper.showText("成功加入书架");
mBookInfoActivity.getBtnAddBookcase().setText("移除书籍");
} else {
mBookService.deleteBookById(mBook.getId());
TextHelper.showText("成功移除书籍");
mBookInfoActivity.getBtnAddBookcase().setText("加入书架");
mBookInfoActivity.getBtnReadBook().setText("开始阅读");
}
}
});
mReadCrawler = ReadCrawlerUtil.getReadCrawler(mBook.getSource());
mBookInfoActivity.getBtnReadBook().setOnClickListener(view -> {
final boolean isCollected;
if (isBookCollected()) {
isCollected = true;
} else {
mBookService.addBook(mBook);
isCollected = false;
CommonApi.getBookChapters(mBook.getChapterUrl(), mReadCrawler, new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
mBookService.updateEntity(mBook);
}
@Override
public void onError(Exception e) {
}
});
}
Intent intent = new Intent(mBookInfoActivity, ReadActivity.class);
intent.putExtra(APPCONST.BOOK, mBook);
intent.putExtra("isCollected", isCollected);
mBookInfoActivity.startActivityForResult(intent, APPCONST.REQUEST_READ);
});
initBookInfo();
}
@SuppressLint("SetTextI18n")
private void initBookInfo() {
mBookInfoActivity.getTvTitleText().setText(mBook.getName());
mBookInfoActivity.getTvBookAuthor().setText(mBook.getAuthor());
if (StringHelper.isEmpty(mBook.getImgUrl())) {
mBook.setImgUrl("");
}
assert mBook.getNewestChapterTitle() != null;
mBookInfoActivity.getTvBookNewestChapter().setText("最新章节:" + mBook.getNewestChapterTitle().replace("最近更新 ", ""));
mBookInfoActivity.getTvBookDesc().setText("");
mBookInfoActivity.getTvBookType().setText("");
mBookInfoActivity.getTvBookName().setText(mBook.getName());
if (!"null".equals(mBook.getSource())) {
mBookInfoActivity.getTvBookSource().setText("书源:" + BookSource.fromString(mBook.getSource()).text);
}
ReadCrawler rc = ReadCrawlerUtil.getReadCrawler(mBook.getSource());
if (rc instanceof BookInfoCrawler && StringHelper.isEmpty(mBook.getImgUrl())) {
BookInfoCrawler bic = (BookInfoCrawler) rc;
CommonApi.getBookInfo(mBook, bic, new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
mHandler.sendMessage(mHandler.obtainMessage(4));
}
@Override
public void onError(Exception e) {
}
});
} else {
initOtherInfo();
}
}
private void initOtherInfo() {
mBookInfoActivity.getTvBookDesc().setText(mBook.getDesc());
mBookInfoActivity.getTvBookType().setText(mBook.getType());
Glide.with(mBookInfoActivity)
.load(mBook.getImgUrl())
.error(R.mipmap.no_image)
.placeholder(R.mipmap.no_image)
//设置圆角
.apply(RequestOptions.bitmapTransform(new RoundedCorners(8)))
.into(mBookInfoActivity.getIvBookImg());
}
private boolean isBookCollected() {
Book book = mBookService.findBookByAuthorAndName(mBook.getName(), mBook.getAuthor());
if (book == null) {
return false;
} else {
mBook = book;
return true;
}
}
private void createChangeSourceDia() {
if (aBooks == null){
mHandler.sendMessage(mHandler.obtainMessage(3));
return;
}
mBookInfoActivity.getPbLoading().setVisibility(View.GONE);
CharSequence[] sources = new CharSequence[aBooks.size()];
int checkedItem = 0;
for (int i = 0; i < sources.length; i++) {
sources[i] = BookSource.fromString(aBooks.get(i).getSource()).text
+ "\n" + aBooks.get(i).getNewestChapterTitle();
if (sources[i].equals(BookSource.fromString(mBook.getSource()).text
+ "\n" + aBooks.get(i).getNewestChapterTitle())) {
checkedItem = i;
}
}
final int finalCheckedItem = checkedItem;
AlertDialog dialog = new AlertDialog.Builder(mBookInfoActivity)
.setTitle("切换书源")
.setCancelable(true)
.setSingleChoiceItems(sources, checkedItem, (dialog1, which) -> {
boolean isBookCollected = isBookCollected();
// mBookService.deleteBook(mBook);
if (finalCheckedItem == which) {
dialog1.dismiss();
return;
}
Book book = aBooks.get(which);
Book bookTem = new Book(mBook);
bookTem.setChapterUrl(book.getChapterUrl());
bookTem.setImgUrl(book.getImgUrl());
bookTem.setType(book.getType());
bookTem.setDesc(book.getDesc());
bookTem.setSource(book.getSource());
if (isBookCollected) {
mBookService.updateBook(mBook, bookTem);
}
mBook = bookTem;
mHandler.sendMessage(mHandler.obtainMessage(1));
if (isBookCollected) {
DialogCreator.createTipDialog(mBookInfoActivity,
"换源成功,由于不同书源的章节数量不一定相同,故换源后历史章节可能出错!");
}
dialog1.dismiss();
}).create();
dialog.show();
/*try {
Field mAlert = AlertDialog.class.getDeclaredField("mAlert");
mAlert.setAccessible(true);
Object mAlertController = mAlert.get(dialog);
Field mMessage = mAlertController.getClass().getDeclaredField("mMessageView");
mMessage.setAccessible(true);
TextView mMessageView = (TextView) mMessage.get(mAlertController);
mMessageView.setTextSize(5);
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}*/
}
}

@ -0,0 +1,36 @@
package xyz.fycz.myreader.ui.bookinfo;
import android.widget.TextView;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.base.ViewHolderImpl;
import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.greendao.service.ChapterService;
import java.io.File;
/**
* @author fengyue
* @date 2020/8/17 15:07
*/
public class CatalogHolder extends ViewHolderImpl<Chapter> {
private TextView tvTitle;
@Override
protected int getItemLayoutId() {
return R.layout.listview_chapter_title_item;
}
@Override
public void initView() {
tvTitle = findById(R.id.tv_chapter_title);
}
@Override
public void onBind(Chapter data, int pos) {
if (ChapterService.isChapterCached(data.getBookId(), data.getTitle())) {
tvTitle.setCompoundDrawablesWithIntrinsicBounds(getContext().getResources().getDrawable(R.drawable.selector_category_load), null, null, null);
} else {
tvTitle.setCompoundDrawablesWithIntrinsicBounds(getContext().getResources().getDrawable(R.drawable.selector_category_unload), null, null, null);
}
tvTitle.setText(data.getTitle());
}
}

@ -0,0 +1,16 @@
package xyz.fycz.myreader.ui.bookinfo;
import xyz.fycz.myreader.base.IViewHolder;
import xyz.fycz.myreader.base.adapter.BaseListAdapter;
import xyz.fycz.myreader.greendao.entity.Chapter;
/**
* @author fengyue
* @date 2020/8/17 15:06
*/
public class DetailCatalogAdapter extends BaseListAdapter<Chapter> {
@Override
protected IViewHolder<Chapter> createViewHolder(int viewType) {
return new CatalogHolder();
}
}

@ -1,7 +1,6 @@
package xyz.fycz.myreader.ui.home.bookcase;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
@ -25,7 +24,6 @@ import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.creator.DialogCreator;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.ui.bookinfo.BookDetailedActivity;
import xyz.fycz.myreader.ui.bookinfo.BookInfoActivity;
import xyz.fycz.myreader.ui.read.ReadActivity;
import xyz.fycz.myreader.util.StringHelper;
import xyz.fycz.myreader.util.TextHelper;

@ -131,6 +131,7 @@ public class BookcasePresenter implements BasePresenter {
case 4:
showErrorLoadingBooks();
if (MyApplication.isApkInDebug(mMainActivity)) {
MyApplication.runOnUiThread(() -> mBookcaseAdapter.notifyDataSetChanged());
downloadAll(false);
}
break;
@ -711,7 +712,9 @@ public class BookcasePresenter implements BasePresenter {
return;
}
if (mChapters.size() == 0) {
if (!isDownloadAll) {
TextHelper.showText("《" + book.getName() + "》章节目录为空,缓存失败,请刷新后重试");
}
return;
}
//取消之前下载

@ -16,7 +16,6 @@ import xyz.fycz.myreader.common.URLCONST;
import xyz.fycz.myreader.entity.bookstore.BookType;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.ui.bookinfo.BookDetailedActivity;
import xyz.fycz.myreader.ui.bookinfo.BookInfoActivity;
import xyz.fycz.myreader.ui.home.MainActivity;
import xyz.fycz.myreader.util.TextHelper;
import xyz.fycz.myreader.webapi.BookStoreApi;

@ -111,9 +111,12 @@ public class ReadActivity extends BaseActivity {
}
private void exit(){
// 返回给BookDetail
// 返回给BookDetail
Intent result = new Intent();
result.putExtra(APPCONST.RESULT_IS_COLLECTED, mReadPresenter.isCollected());
if (mReadPresenter.getmPageLoader() != null) {
result.putExtra(APPCONST.RESULT_LAST_READ_POSITION, mReadPresenter.getmPageLoader().getPagePos());
}
setResult(AppCompatActivity.RESULT_OK, result);
super.onBackPressed();
}

@ -205,7 +205,6 @@ public class ReadPresenter implements BasePresenter {
public ReadPresenter(ReadActivity readActivity) {
mReadActivity = readActivity;
mBookService = BookService.getInstance();
;
mChapterService = ChapterService.getInstance();
mBookMarkService = BookMarkService.getInstance();
mSetting = SysManager.getSetting();

@ -5,6 +5,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import androidx.fragment.app.Fragment;
import butterknife.BindView;
@ -23,6 +24,8 @@ public class CatalogFragment extends Fragment {
ListView lvChapterList;
@BindView(R.id.change_sort)
FloatingActionButton fcChangeSort;
@BindView(R.id.pb_loading)
ProgressBar pbLoading;
Unbinder unbinder;
@ -64,4 +67,8 @@ public class CatalogFragment extends Fragment {
public CatalogPresenter getmCatalogPresent() {
return mCatalogPresent;
}
public ProgressBar getPbLoading() {
return pbLoading;
}
}

@ -5,12 +5,17 @@ import android.content.Intent;
import android.view.View;
import android.widget.AdapterView;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.MyApplication;
import xyz.fycz.myreader.application.SysManager;
import xyz.fycz.myreader.base.BasePresenter;
import xyz.fycz.myreader.callback.ResultCallback;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.crawler.ReadCrawlerUtil;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.greendao.service.ChapterService;
import xyz.fycz.myreader.util.TextHelper;
import xyz.fycz.myreader.webapi.CommonApi;
import java.util.ArrayList;
import java.util.Collections;
@ -50,7 +55,32 @@ public class CatalogPresenter implements BasePresenter {
changeChapterSort();
}
});
mChapters = (ArrayList<Chapter>) mChapterService.findBookAllChapterByBookId(mBook.getId());
if (mChapters.size() != 0) {
initChapterTitleList();
}else {
mCatalogFragment.getPbLoading().setVisibility(View.VISIBLE);
CommonApi.getBookChapters(mBook.getChapterUrl(), ReadCrawlerUtil.getReadCrawler(mBook.getSource()),
new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
mChapters = (ArrayList<Chapter>) o;
MyApplication.runOnUiThread(() -> {
mCatalogFragment.getPbLoading().setVisibility(View.GONE);
initChapterTitleList();
});
}
@Override
public void onError(Exception e) {
e.printStackTrace();
TextHelper.showText("章节目录加载失败!");
MyApplication.runOnUiThread(() -> mCatalogFragment.getPbLoading().setVisibility(View.GONE));
}
});
}
mCatalogFragment.getLvChapterList().setOnItemClickListener((adapterView, view, i, l) -> {
Chapter chapter = mChapterTitleAdapter.getItem(i);
final int position;
@ -76,7 +106,6 @@ public class CatalogPresenter implements BasePresenter {
* 初始化章节目录
*/
private void initChapterTitleList() {
mChapters = (ArrayList<Chapter>) mChapterService.findBookAllChapterByBookId(mBook.getId());
//初始化倒序章节
mConvertChapters.addAll(mChapters);
Collections.reverse(mConvertChapters);

@ -124,7 +124,6 @@ public class ChapterTitleAdapter extends ArrayAdapter<Chapter> {
};
}
public List<Chapter> getmList() {
return mList;
}

@ -12,18 +12,12 @@ import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.listener.OnRefreshListener;
import xyz.fycz.myreader.application.MyApplication;
import xyz.fycz.myreader.crawler.*;
import xyz.fycz.myreader.entity.SearchBookBean;
import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap;
import xyz.fycz.myreader.ui.bookinfo.BookDetailedActivity;
import xyz.fycz.myreader.ui.bookinfo.BookInfoActivity;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.base.BasePresenter;
import xyz.fycz.myreader.callback.ResultCallback;
@ -39,9 +33,6 @@ import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import me.gujun.android.taggroup.TagGroup;
public class SearchBookPrensenter implements BasePresenter {

@ -28,7 +28,6 @@ public class CommonApi extends BaseApi {
@Override
public void onError(Exception e) {
callback.onError(e);
}
});
}

@ -1,213 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/sys_bg2"
android:fitsSystemWindows="true"
tools:context="xyz.fycz.myreader.ui.bookinfo.BookInfoActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/title_base"/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp">
<ImageView
android:id="@+id/iv_book_img"
android:layout_width="80dp"
android:layout_height="120dp"
android:scaleType="fitXY"
app:srcCompat="@mipmap/default_cover"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="5dp"
android:padding="3dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_book_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="bookname"
android:textSize="18sp"
android:maxLines="1"
android:textColor="@color/black"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentBottom="true"
android:paddingTop="5dp"
android:paddingBottom="5dp">
<TextView
android:id="@+id/tv_book_author"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="author"
android:maxLines="1"
android:textSize="14sp"
android:textColor="@color/title_black"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" | "
android:textColor="@color/title_black"/>
<TextView
android:id="@+id/tv_book_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="type"
android:maxLines="1"
android:textSize="14sp"
android:textColor="@color/title_black"/>
</LinearLayout>
<TextView
android:id="@+id/tv_book_newest_chapter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="newestChapter"
android:maxLines="2"
android:textSize="14sp"
android:textColor="@color/title_black"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_book_source"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="bookSource"
android:paddingTop="4dp"
android:maxLines="1"
android:textSize="14sp"
android:textColor="@color/title_black"/>
<Button
android:id="@+id/btn_change_source"
android:layout_width="30dp"
android:layout_height="16dp"
android:layout_marginStart="10dp"
android:textColor="@color/white"
android:background="@color/colorAccent"
android:text="@string/change_source"
android:textSize="12sp">
</Button>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="简介"
android:textColor="@color/black"
android:textSize="16sp"/>
<TextView
android:id="@+id/tv_book_desc"
android:layout_marginTop="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lineSpacingMultiplier="1.2"
android:textSize="16sp"
android:text="desc"
android:textColor="@color/title_black"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:orientation="vertical">
<TextView
android:layout_marginTop="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lineSpacingMultiplier="1.2"
android:textSize="14sp"
android:text="@string/statement"
android:textColor="@color/title_black"
/>
<TextView
android:id="@+id/tv_disclaimer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/disclaimer"
android:textColor="#2196F3"
android:textSize="14sp"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginTop="5dp">
<Button
android:id="@+id/btn_add_bookcase"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="16sp"
android:text="加入书架"/>
<Button
android:id="@+id/btn_read_book"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="16sp"
android:text="立即阅读"/>
</LinearLayout>
</LinearLayout>
<ProgressBar
android:id="@+id/pb_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone"/>
</RelativeLayout>

@ -32,4 +32,11 @@
app:elevation="6dp"
app:pressedTranslationZ="12dp"
/>
<ProgressBar
android:id="@+id/pb_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone"/>
</RelativeLayout>

@ -5,13 +5,13 @@
android:orientation="vertical">
<!--简介-->
<TextView
<!--<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="简介:"
android:textColor="@color/black"
android:textSize="18sp"/>
android:textSize="18sp"/>-->
<TextView
android:id="@+id/book_detail_tv_desc"
android:layout_width="match_parent"
@ -22,44 +22,20 @@
android:padding="15dp"
android:lineSpacingMultiplier="1.2"
android:text="简介: "
android:textColor="@color/title_black"
android:textColor="@color/black"
android:textSize="16sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:orientation="vertical">
<TextView
android:layout_marginTop="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lineSpacingMultiplier="1.2"
android:textSize="14sp"
android:text="@string/statement"
android:textColor="@color/title_black"
/>
<TextView
android:id="@+id/tv_disclaimer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/disclaimer"
android:textColor="#2196F3"
android:textSize="14sp"/>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="10dp"
android:background="@color/sys_window_back"
android:visibility="gone"/>
android:background="@color/sys_window_back"/>
<!--书籍目录-->
<RelativeLayout
android:id="@+id/book_detail_rl_catalog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
android:layout_height="wrap_content">
<TextView
android:id="@+id/book_detail_tv_catalog"
@ -88,6 +64,29 @@
android:foregroundGravity="center" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:orientation="vertical">
<TextView
android:layout_marginTop="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lineSpacingMultiplier="1.2"
android:textSize="14sp"
android:text="@string/statement"
android:textColor="@color/title_black"
/>
<TextView
android:id="@+id/tv_disclaimer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/disclaimer"
android:textColor="#2196F3"
android:textSize="14sp"/>
</LinearLayout>
<!--底部空白,给底部bottom预留位置-->
<!--<View-->

@ -1,2 +1,2 @@
#Sat Aug 15 23:51:09 CST 2020
#Mon Aug 17 18:44:13 CST 2020
VERSION_CODE=142

Loading…
Cancel
Save