parent
31c16a6004
commit
36a2647ccb
@ -0,0 +1,37 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project version="4"> |
||||||
|
<component name="WizardSettings"> |
||||||
|
<option name="children"> |
||||||
|
<map> |
||||||
|
<entry key="imageWizard"> |
||||||
|
<value> |
||||||
|
<PersistentState /> |
||||||
|
</value> |
||||||
|
</entry> |
||||||
|
<entry key="vectorWizard"> |
||||||
|
<value> |
||||||
|
<PersistentState> |
||||||
|
<option name="children"> |
||||||
|
<map> |
||||||
|
<entry key="vectorAssetStep"> |
||||||
|
<value> |
||||||
|
<PersistentState> |
||||||
|
<option name="values"> |
||||||
|
<map> |
||||||
|
<entry key="assetSourceType" value="FILE" /> |
||||||
|
<entry key="outputName" value="ic_group" /> |
||||||
|
<entry key="sourceFile" value="F:\SVG图标\分组.svg" /> |
||||||
|
</map> |
||||||
|
</option> |
||||||
|
</PersistentState> |
||||||
|
</value> |
||||||
|
</entry> |
||||||
|
</map> |
||||||
|
</option> |
||||||
|
</PersistentState> |
||||||
|
</value> |
||||||
|
</entry> |
||||||
|
</map> |
||||||
|
</option> |
||||||
|
</component> |
||||||
|
</project> |
Binary file not shown.
@ -0,0 +1,55 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project version="4"> |
||||||
|
<component name="navEditor-manualLayoutAlgorithm2"> |
||||||
|
<option name="myPositions"> |
||||||
|
<map> |
||||||
|
<entry key="mobile_navigation.xml"> |
||||||
|
<value> |
||||||
|
<LayoutPositions> |
||||||
|
<option name="myPositions"> |
||||||
|
<map> |
||||||
|
<entry key="navigation_dashboard"> |
||||||
|
<value> |
||||||
|
<LayoutPositions> |
||||||
|
<option name="myPosition"> |
||||||
|
<Point> |
||||||
|
<option name="x" value="256" /> |
||||||
|
<option name="y" value="12" /> |
||||||
|
</Point> |
||||||
|
</option> |
||||||
|
</LayoutPositions> |
||||||
|
</value> |
||||||
|
</entry> |
||||||
|
<entry key="navigation_home"> |
||||||
|
<value> |
||||||
|
<LayoutPositions> |
||||||
|
<option name="myPosition"> |
||||||
|
<Point> |
||||||
|
<option name="x" value="12" /> |
||||||
|
<option name="y" value="12" /> |
||||||
|
</Point> |
||||||
|
</option> |
||||||
|
</LayoutPositions> |
||||||
|
</value> |
||||||
|
</entry> |
||||||
|
<entry key="navigation_notifications"> |
||||||
|
<value> |
||||||
|
<LayoutPositions> |
||||||
|
<option name="myPosition"> |
||||||
|
<Point> |
||||||
|
<option name="x" value="12" /> |
||||||
|
<option name="y" value="368" /> |
||||||
|
</Point> |
||||||
|
</option> |
||||||
|
</LayoutPositions> |
||||||
|
</value> |
||||||
|
</entry> |
||||||
|
</map> |
||||||
|
</option> |
||||||
|
</LayoutPositions> |
||||||
|
</value> |
||||||
|
</entry> |
||||||
|
</map> |
||||||
|
</option> |
||||||
|
</component> |
||||||
|
</project> |
@ -0,0 +1,10 @@ |
|||||||
|
_csrfToken=AfAoas8MBYmg6LNiXTCqRB4GqdvAIjLhoMhq0dMR; newstatisticUUID=1600428458_1590109905, |
||||||
|
_csrfToken=JoeVbiYLyXUa1F1afAe7vopVMTCIAy9gjYjgs3vG; newstatisticUUID=1600428473_81078399, |
||||||
|
_csrfToken=HrhdGbLO43Q1sqYB3fE2HFxTOgjA06Qb4tMdk4oP; newstatisticUUID=1600428493_975004371, |
||||||
|
_csrfToken=ipGWAeoYVu786drUzlLunN24Z9aujs5nh5n9BRkO; newstatisticUUID=1600428519_644819972, |
||||||
|
_csrfToken=XagcA1H7EuyKRlcCnYxBEXh96LdxehdF79bAshVq; newstatisticUUID=1600428535_1734949593, |
||||||
|
_csrfToken=b6ZsEBvH8DizXhKHa7XG9s6kPN81vo0FujgQkBss; newstatisticUUID=1600428547_1240575899, |
||||||
|
_csrfToken=AN09KVoEyMW1b7A2h0WICDw0iZRh10YJPHrPMyuF; newstatisticUUID=1600428559_1890659047, |
||||||
|
_csrfToken=NPv5rB13eOhAw2PM5GKUbMCrpPXMHEozqs6fTIA7; newstatisticUUID=1600428572_110329628, |
||||||
|
_csrfToken=it9IyUnSOXK7xC8fQXADlyrem8ZtGNKFSPt65kj1; newstatisticUUID=1600428591_1594511991, |
||||||
|
_csrfToken=HJPozY5Rdj0Ij0HcyXT3L3VW3OLqeOQooCayuMLG; newstatisticUUID=1600428602_278088659 |
@ -0,0 +1,10 @@ |
|||||||
|
_csrfToken=6aY1oV18xaiLFe342vi6RRTJ1CsuZ7PZPqz2Tl9A; newstatisticUUID=1600427331_759036854, |
||||||
|
_csrfToken=PnRLboRVY2ag0eGbG3e3dA3X4B96SpihEkCDGle7; newstatisticUUID=1600427449_1941387289, |
||||||
|
_csrfToken=Ia5w2vTL03IHyPKiS5PJFgocvzHWbMgi4dBEvrox; newstatisticUUID=1600427497_1599098587, |
||||||
|
_csrfToken=GjyWEsVXIta60t4YXkbtO0hsDc2VVBbfKy6GIBRg; newstatisticUUID=1600427528_887702937, |
||||||
|
_csrfToken=iPjMCVKGnvL8QrbsdYIxCDNQZkJVSscN1CQFFSdF; newstatisticUUID=1600427557_1213608979, |
||||||
|
_csrfToken=Iby8oSKxp767d25frgCGjOAWFWbYwwyRA36nBaxO; newstatisticUUID=1600427589_1737201533, |
||||||
|
_csrfToken=IR81KoIAQxXYb6e9Agv8WuXDkAKukMLnlLe9BYha; newstatisticUUID=1600427619_487685580, |
||||||
|
_csrfToken=YM1F8lgqaePVMceunc7z7ndjys5ngAx5sYsemg60; newstatisticUUID=1600427643_2022665645, |
||||||
|
_csrfToken=8bRnXJseSCajlTcG6lhyWOF0rWwDCiMVpCGvKvQj; newstatisticUUID=1600427644_1615074434, |
||||||
|
_csrfToken=AehQ3WVD6wLbFGhFsnSW4DRF6BS1wqVvHU6PbiiX; newstatisticUUID=1600427644_575162687 |
@ -0,0 +1,15 @@ |
|||||||
|
package xyz.fycz.myreader.creator; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import androidx.appcompat.app.AlertDialog; |
||||||
|
import xyz.fycz.myreader.R; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2020/9/20 9:48 |
||||||
|
*/ |
||||||
|
public class MyAlertDialog { |
||||||
|
public static AlertDialog.Builder build(Context context){ |
||||||
|
return new AlertDialog.Builder(context, R.style.alertDialogTheme); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,80 @@ |
|||||||
|
package xyz.fycz.myreader.entity.bookstore; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2020/9/18 20:46 |
||||||
|
*/ |
||||||
|
public class QDBook { |
||||||
|
protected String bid; |
||||||
|
protected String bName; |
||||||
|
protected String bAuth; |
||||||
|
protected String img; |
||||||
|
protected String cat; |
||||||
|
protected int catId; |
||||||
|
protected String cnt; |
||||||
|
protected String desc; |
||||||
|
|
||||||
|
public String getBid() { |
||||||
|
return bid; |
||||||
|
} |
||||||
|
|
||||||
|
public void setBid(String bid) { |
||||||
|
this.bid = bid; |
||||||
|
} |
||||||
|
|
||||||
|
public String getbName() { |
||||||
|
return bName; |
||||||
|
} |
||||||
|
|
||||||
|
public void setbName(String bName) { |
||||||
|
this.bName = bName; |
||||||
|
} |
||||||
|
|
||||||
|
public String getbAuth() { |
||||||
|
return bAuth; |
||||||
|
} |
||||||
|
|
||||||
|
public void setbAuth(String bAuth) { |
||||||
|
this.bAuth = bAuth; |
||||||
|
} |
||||||
|
|
||||||
|
public String getImg() { |
||||||
|
return img; |
||||||
|
} |
||||||
|
|
||||||
|
public void setImg(String img) { |
||||||
|
this.img = img; |
||||||
|
} |
||||||
|
|
||||||
|
public String getCat() { |
||||||
|
return cat; |
||||||
|
} |
||||||
|
|
||||||
|
public void setCat(String cat) { |
||||||
|
this.cat = cat; |
||||||
|
} |
||||||
|
|
||||||
|
public int getCatId() { |
||||||
|
return catId; |
||||||
|
} |
||||||
|
|
||||||
|
public void setCatId(int catId) { |
||||||
|
this.catId = catId; |
||||||
|
} |
||||||
|
|
||||||
|
public String getCnt() { |
||||||
|
return cnt; |
||||||
|
} |
||||||
|
|
||||||
|
public void setCnt(String cnt) { |
||||||
|
this.cnt = cnt; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDesc() { |
||||||
|
return desc; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDesc(String desc) { |
||||||
|
this.desc = desc; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
package xyz.fycz.myreader.entity.bookstore; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2020/9/16 22:56 |
||||||
|
*/ |
||||||
|
public class RankBook extends QDBook{ |
||||||
|
/*bAuth: "净无痕" |
||||||
|
bName: "伏天氏" |
||||||
|
bid: "1011058239" |
||||||
|
cat: "玄幻" |
||||||
|
catId: 21 |
||||||
|
cnt: "636.1万字" |
||||||
|
desc: "东方神州,有人皇立道统,有圣贤宗门传道,有诸侯雄踞一方王国,诸强林立,神州动乱千万载,值此之时,一代天骄叶青帝及东凰大帝横空出世,东方神州一统!然,叶青帝忽然暴毙,世间雕像尽皆被毁,于世间除名,沦为禁忌;从此神州唯东凰大帝独尊!十五年后,东海青州城,一名为叶伏天的少年,开启了他的传奇之路…" |
||||||
|
rankCnt: "5996月票" |
||||||
|
rankNum: 21*/ |
||||||
|
|
||||||
|
|
||||||
|
private String rankCnt; |
||||||
|
private int rankNum; |
||||||
|
|
||||||
|
|
||||||
|
public String getRankCnt() { |
||||||
|
return rankCnt; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRankCnt(String rankCnt) { |
||||||
|
this.rankCnt = rankCnt; |
||||||
|
} |
||||||
|
|
||||||
|
public int getRankNum() { |
||||||
|
return rankNum; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRankNum(int rankNum) { |
||||||
|
this.rankNum = rankNum; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,27 @@ |
|||||||
|
package xyz.fycz.myreader.entity.bookstore; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2020/9/18 20:43 |
||||||
|
*/ |
||||||
|
public class SortBook extends QDBook{ |
||||||
|
/*bAuth: "老鸡吃蘑菇" |
||||||
|
bName: "全世界都不知道我多强" |
||||||
|
bid: 1021781295 |
||||||
|
cat: "玄幻" |
||||||
|
catId: 21 |
||||||
|
cid: 406957810 |
||||||
|
cnt: "72.68万字" |
||||||
|
desc: "【日更过万,质量保证!】当梁凡从地底爬出来之后,才发现不是变秃才能变强!我要控制我自己,要是不小心一拳打爆这个星球怎么办?安静的隐藏在世俗,全世界都不知道我有多强,虽然这个世界妖魔鬼怪很变态,但苟着享" |
||||||
|
state: "连载"*/ |
||||||
|
|
||||||
|
private String state; |
||||||
|
|
||||||
|
public String getState() { |
||||||
|
return state; |
||||||
|
} |
||||||
|
|
||||||
|
public void setState(String state) { |
||||||
|
this.state = state; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,40 @@ |
|||||||
|
package xyz.fycz.myreader.enums; |
||||||
|
|
||||||
|
import java.io.Serializable; |
||||||
|
|
||||||
|
/** |
||||||
|
* 小说源 |
||||||
|
* Created by zhao on 2020/04/13. |
||||||
|
*/ |
||||||
|
|
||||||
|
public enum FindType implements Serializable { |
||||||
|
|
||||||
|
qidian("排行榜[起点中文网]", "https://www.qidian.com/rank"), |
||||||
|
qidianns("排行榜[起点女生网]", "https://www.qidian.com/mm/rank"), |
||||||
|
qb5("书城[全本小说]", "https://www.qb5.tw"), |
||||||
|
biquge("书城[笔趣阁]", "https://www.52bqg.com"); |
||||||
|
private String text; |
||||||
|
private String url; |
||||||
|
private static final long serialVersionUID = 1L; |
||||||
|
|
||||||
|
FindType(String text, String url) { |
||||||
|
this.text = text; |
||||||
|
this.url = url; |
||||||
|
} |
||||||
|
|
||||||
|
public static FindType get(int var0) { |
||||||
|
return values()[var0]; |
||||||
|
} |
||||||
|
|
||||||
|
public static FindType fromString(String string) { |
||||||
|
return valueOf(string); |
||||||
|
} |
||||||
|
|
||||||
|
public String getText() { |
||||||
|
return text; |
||||||
|
} |
||||||
|
|
||||||
|
public String getUrl() { |
||||||
|
return url; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,70 @@ |
|||||||
|
package xyz.fycz.myreader.greendao.entity; |
||||||
|
|
||||||
|
import org.greenrobot.greendao.annotation.Entity; |
||||||
|
import org.greenrobot.greendao.annotation.Id; |
||||||
|
import org.greenrobot.greendao.annotation.NotNull; |
||||||
|
import org.greenrobot.greendao.annotation.Generated; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2020/9/23 22:18 |
||||||
|
*/ |
||||||
|
@Entity |
||||||
|
public class BookGroup { |
||||||
|
@Id |
||||||
|
private String id; |
||||||
|
|
||||||
|
@NotNull |
||||||
|
private int num; |
||||||
|
|
||||||
|
@NotNull |
||||||
|
private String name; |
||||||
|
|
||||||
|
private String desc; |
||||||
|
|
||||||
|
@Generated(hash = 1387727906) |
||||||
|
public BookGroup(String id, int num, @NotNull String name, String desc) { |
||||||
|
this.id = id; |
||||||
|
this.num = num; |
||||||
|
this.name = name; |
||||||
|
this.desc = desc; |
||||||
|
} |
||||||
|
|
||||||
|
@Generated(hash = 511810489) |
||||||
|
public BookGroup() { |
||||||
|
} |
||||||
|
|
||||||
|
public String getId() { |
||||||
|
return this.id; |
||||||
|
} |
||||||
|
|
||||||
|
public void setId(String id) { |
||||||
|
this.id = id; |
||||||
|
} |
||||||
|
|
||||||
|
public String getName() { |
||||||
|
return this.name; |
||||||
|
} |
||||||
|
|
||||||
|
public void setName(String name) { |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDesc() { |
||||||
|
return this.desc; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDesc(String desc) { |
||||||
|
this.desc = desc; |
||||||
|
} |
||||||
|
|
||||||
|
public int getNum() { |
||||||
|
return this.num; |
||||||
|
} |
||||||
|
|
||||||
|
public void setNum(int num) { |
||||||
|
this.num = num; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,77 @@ |
|||||||
|
package xyz.fycz.myreader.greendao.service; |
||||||
|
|
||||||
|
import xyz.fycz.myreader.greendao.GreenDaoManager; |
||||||
|
import xyz.fycz.myreader.greendao.entity.BookGroup; |
||||||
|
import xyz.fycz.myreader.greendao.gen.BookGroupDao; |
||||||
|
import xyz.fycz.myreader.greendao.gen.BookMarkDao; |
||||||
|
import xyz.fycz.myreader.util.StringHelper; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2020/9/26 12:14 |
||||||
|
*/ |
||||||
|
public class BookGroupService extends BaseService{ |
||||||
|
private static volatile BookGroupService sInstance; |
||||||
|
|
||||||
|
public static BookGroupService getInstance() { |
||||||
|
if (sInstance == null){ |
||||||
|
synchronized (BookGroupService.class){ |
||||||
|
if (sInstance == null){ |
||||||
|
sInstance = new BookGroupService(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return sInstance; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取所有书籍分组 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public List<BookGroup> getAllGroups(){ |
||||||
|
return GreenDaoManager.getInstance().getSession().getBookGroupDao() |
||||||
|
.queryBuilder() |
||||||
|
.orderAsc(BookGroupDao.Properties.Num) |
||||||
|
.list(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 通过I的获取书籍分组 |
||||||
|
* @param groupId |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public BookGroup getGroupById(String groupId){ |
||||||
|
return GreenDaoManager.getInstance().getSession().getBookGroupDao() |
||||||
|
.queryBuilder() |
||||||
|
.where(BookGroupDao.Properties.Id.eq(groupId)) |
||||||
|
.unique(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 添加书籍分组 |
||||||
|
* @param bookGroup |
||||||
|
*/ |
||||||
|
public void addBookGroup(BookGroup bookGroup){ |
||||||
|
bookGroup.setNum(countBookGroup()); |
||||||
|
bookGroup.setId(StringHelper.getStringRandom(25)); |
||||||
|
addEntity(bookGroup); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 删除书籍分组 |
||||||
|
* @param bookGroup |
||||||
|
*/ |
||||||
|
public void deleteBookGroup(BookGroup bookGroup){ |
||||||
|
deleteEntity(bookGroup); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private int countBookGroup(){ |
||||||
|
return (int) GreenDaoManager.getInstance().getSession().getBookGroupDao() |
||||||
|
.queryBuilder() |
||||||
|
.count(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,420 @@ |
|||||||
|
package xyz.fycz.myreader.ui.activity; |
||||||
|
|
||||||
|
import android.annotation.SuppressLint; |
||||||
|
import android.content.Intent; |
||||||
|
import android.os.Bundle; |
||||||
|
import android.os.Handler; |
||||||
|
import android.os.Message; |
||||||
|
import android.view.Menu; |
||||||
|
import android.view.MenuItem; |
||||||
|
import android.view.View; |
||||||
|
import android.widget.ProgressBar; |
||||||
|
import androidx.appcompat.widget.Toolbar; |
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager; |
||||||
|
import androidx.recyclerview.widget.RecyclerView; |
||||||
|
import butterknife.BindView; |
||||||
|
import com.scwang.smartrefresh.layout.SmartRefreshLayout; |
||||||
|
import xyz.fycz.myreader.R; |
||||||
|
import xyz.fycz.myreader.application.MyApplication; |
||||||
|
import xyz.fycz.myreader.base.BaseActivity2; |
||||||
|
import xyz.fycz.myreader.callback.ResultCallback; |
||||||
|
import xyz.fycz.myreader.common.APPCONST; |
||||||
|
import xyz.fycz.myreader.creator.ChangeSourceDialog; |
||||||
|
import xyz.fycz.myreader.creator.DialogCreator; |
||||||
|
import xyz.fycz.myreader.entity.bookstore.BookType; |
||||||
|
import xyz.fycz.myreader.entity.bookstore.QDBook; |
||||||
|
import xyz.fycz.myreader.entity.bookstore.RankBook; |
||||||
|
import xyz.fycz.myreader.entity.bookstore.SortBook; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Book; |
||||||
|
import xyz.fycz.myreader.greendao.service.BookService; |
||||||
|
import xyz.fycz.myreader.ui.adapter.BookStoreBookAdapter; |
||||||
|
import xyz.fycz.myreader.ui.adapter.BookStoreBookTypeAdapter; |
||||||
|
import xyz.fycz.myreader.util.SharedPreUtils; |
||||||
|
import xyz.fycz.myreader.util.ToastUtils; |
||||||
|
import xyz.fycz.myreader.webapi.BookStoreApi; |
||||||
|
import xyz.fycz.myreader.webapi.crawler.FindCrawler; |
||||||
|
import xyz.fycz.myreader.webapi.crawler.find.ABC; |
||||||
|
import xyz.fycz.myreader.widget.RefreshLayout; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2020/9/13 21:11 |
||||||
|
*/ |
||||||
|
public class BookstoreActivity extends BaseActivity2 { |
||||||
|
@BindView(R.id.refresh_layout) |
||||||
|
RefreshLayout mRlRefresh; |
||||||
|
@BindView(R.id.rv_type_list) |
||||||
|
RecyclerView rvTypeList; |
||||||
|
@BindView(R.id.rv_book_list) |
||||||
|
RecyclerView rvBookList; |
||||||
|
@BindView(R.id.srl_book_list) |
||||||
|
SmartRefreshLayout srlBookList; |
||||||
|
@BindView(R.id.pb_loading) |
||||||
|
ProgressBar pbLoading; |
||||||
|
|
||||||
|
private FindCrawler findCrawler; |
||||||
|
private LinearLayoutManager mLinearLayoutManager; |
||||||
|
private BookStoreBookTypeAdapter mBookStoreBookTypeAdapter; |
||||||
|
private List<BookType> mBookTypes; |
||||||
|
|
||||||
|
private BookStoreBookAdapter mBookStoreBookAdapter; |
||||||
|
private List<Book> bookList = new ArrayList<>(); |
||||||
|
|
||||||
|
private BookType curType; |
||||||
|
|
||||||
|
private int page = 1; |
||||||
|
|
||||||
|
private String title = ""; |
||||||
|
|
||||||
|
@SuppressLint("HandlerLeak") |
||||||
|
private Handler mHandler = new Handler() { |
||||||
|
@Override |
||||||
|
public void handleMessage(Message msg) { |
||||||
|
if (!MyApplication.isDestroy(BookstoreActivity.this)) { |
||||||
|
switch (msg.what) { |
||||||
|
case 1: |
||||||
|
initTypeList(); |
||||||
|
mRlRefresh.showFinish(); |
||||||
|
break; |
||||||
|
case 2: |
||||||
|
List<Book> bookList = (List<Book>) msg.obj; |
||||||
|
initBookList(bookList); |
||||||
|
srlBookList.setEnableRefresh(true); |
||||||
|
srlBookList.setEnableLoadMore(true); |
||||||
|
pbLoading.setVisibility(View.GONE); |
||||||
|
break; |
||||||
|
case 3: |
||||||
|
pbLoading.setVisibility(View.VISIBLE); |
||||||
|
break; |
||||||
|
case 4: |
||||||
|
pbLoading.setVisibility(View.GONE); |
||||||
|
srlBookList.finishRefresh(false); |
||||||
|
srlBookList.finishLoadMore(false); |
||||||
|
break; |
||||||
|
case 5: |
||||||
|
mRlRefresh.showError(); |
||||||
|
break; |
||||||
|
case 6: |
||||||
|
DialogCreator.createTipDialog(BookstoreActivity.this, |
||||||
|
getResources().getString(R.string.top_sort_tip, title)); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
@Override |
||||||
|
protected int getContentId() { |
||||||
|
return R.layout.actiity_bookstore; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void setUpToolbar(Toolbar toolbar) { |
||||||
|
super.setUpToolbar(toolbar); |
||||||
|
setStatusBarColor(R.color.colorPrimary, true); |
||||||
|
String subTitle = ""; |
||||||
|
if (findCrawler != null) { |
||||||
|
String name = findCrawler.getFindName(); |
||||||
|
title = name.substring(0, name.indexOf("[")); |
||||||
|
subTitle = name.substring(name.indexOf("[") + 1, name.length() - 1); |
||||||
|
} |
||||||
|
getSupportActionBar().setTitle(title); |
||||||
|
getSupportActionBar().setSubtitle(subTitle); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void initData(Bundle savedInstanceState) { |
||||||
|
super.initData(savedInstanceState); |
||||||
|
findCrawler = (FindCrawler) getIntent().getSerializableExtra(APPCONST.FIND_CRAWLER); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void initWidget() { |
||||||
|
super.initWidget(); |
||||||
|
srlBookList.setEnableRefresh(false); |
||||||
|
srlBookList.setEnableLoadMore(false); |
||||||
|
//小说列表下拉加载更多事件
|
||||||
|
srlBookList.setOnLoadMoreListener(refreshLayout -> { |
||||||
|
page++; |
||||||
|
getBooksData(); |
||||||
|
}); |
||||||
|
|
||||||
|
//小说列表上拉刷新事件
|
||||||
|
srlBookList.setOnRefreshListener(refreshLayout -> { |
||||||
|
page = 1; |
||||||
|
getBooksData(); |
||||||
|
}); |
||||||
|
|
||||||
|
mBookStoreBookAdapter = new BookStoreBookAdapter(findCrawler.hasImg(), this); |
||||||
|
rvBookList.setLayoutManager(new LinearLayoutManager(this)); |
||||||
|
rvBookList.setAdapter(mBookStoreBookAdapter); |
||||||
|
mRlRefresh.setOnReloadingListener(this::getData); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void initClick() { |
||||||
|
super.initClick(); |
||||||
|
mBookStoreBookAdapter.setOnItemClickListener((view, pos) -> { |
||||||
|
Book book = bookList.get(pos); |
||||||
|
if (!findCrawler.hasImg()) { |
||||||
|
goToBookDetail(book); |
||||||
|
} else { |
||||||
|
if (BookService.getInstance().isBookCollected(book)) { |
||||||
|
goToBookDetail(book); |
||||||
|
return; |
||||||
|
} |
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(3)); |
||||||
|
ChangeSourceDialog csd = new ChangeSourceDialog(this, book); |
||||||
|
csd.initOneBook(new ResultCallback() { |
||||||
|
@Override |
||||||
|
public void onFinish(Object o, int code) { |
||||||
|
Book searchBook = (Book) o; |
||||||
|
book.setChapterUrl(searchBook.getChapterUrl()); |
||||||
|
book.setSource(searchBook.getSource()); |
||||||
|
goToBookDetail(book); |
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(4)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onError(Exception e) { |
||||||
|
DialogCreator.createTipDialog(BookstoreActivity.this, "未搜索到该书籍,无法进入书籍详情!"); |
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(4)); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void processLogic() { |
||||||
|
super.processLogic(); |
||||||
|
getData(); |
||||||
|
if (findCrawler.hasImg()) { |
||||||
|
SharedPreUtils spu = SharedPreUtils.getInstance(); |
||||||
|
boolean isReadTopTip = spu.getBoolean("isReadTopTip", false); |
||||||
|
if (!isReadTopTip) { |
||||||
|
DialogCreator.createCommonDialog(this, "提示", getResources().getString(R.string.top_sort_tip, title), |
||||||
|
true, "知道了", "不再提示", null, |
||||||
|
(dialog, which) -> spu.putBoolean("isReadTopTip", true)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取页面数据 |
||||||
|
*/ |
||||||
|
private void getData() { |
||||||
|
if (findCrawler instanceof ABC) { |
||||||
|
SharedPreUtils spu = SharedPreUtils.getInstance(); |
||||||
|
if (spu.getString("qdCookie", "").equals("")) { |
||||||
|
((ABC) findCrawler).initCookie(this, new ResultCallback() { |
||||||
|
@Override |
||||||
|
public void onFinish(Object o, int code) { |
||||||
|
spu.putString("qdCookie", (String) o); |
||||||
|
mBookTypes = ((ABC) findCrawler).getRankTypes(); |
||||||
|
curType = mBookTypes.get(0); |
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(1)); |
||||||
|
page = 1; |
||||||
|
getBooksData(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onError(Exception e) { |
||||||
|
mRlRefresh.showError(); |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
}); |
||||||
|
} else { |
||||||
|
mBookTypes = ((ABC) findCrawler).getRankTypes(); |
||||||
|
curType = mBookTypes.get(0); |
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(1)); |
||||||
|
page = 1; |
||||||
|
getBooksData(); |
||||||
|
} |
||||||
|
} else { |
||||||
|
BookStoreApi.getBookTypeList(findCrawler, new ResultCallback() { |
||||||
|
@Override |
||||||
|
public void onFinish(Object o, int code) { |
||||||
|
mBookTypes = (ArrayList<BookType>) o; |
||||||
|
curType = mBookTypes.get(0); |
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(1)); |
||||||
|
page = 1; |
||||||
|
getBooksData(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onError(Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
mHandler.sendEmptyMessage(5); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取小数列表数据 |
||||||
|
*/ |
||||||
|
private void getBooksData() { |
||||||
|
if (findCrawler.getTypePage(curType, page)) { |
||||||
|
srlBookList.finishLoadMoreWithNoMoreData(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
mHandler.sendEmptyMessage(3); |
||||||
|
if (findCrawler instanceof ABC) { |
||||||
|
((ABC) findCrawler).getRankBooks(curType, new ResultCallback() { |
||||||
|
@Override |
||||||
|
public void onFinish(Object o, int code) { |
||||||
|
List<Book> books = new ArrayList<>(); |
||||||
|
for (QDBook rb : (List<QDBook>) o) { |
||||||
|
Book book = new Book(); |
||||||
|
book.setName(rb.getbName()); |
||||||
|
book.setAuthor(rb.getbAuth()); |
||||||
|
book.setImgUrl(rb.getImg()); |
||||||
|
String cat = rb.getCat(); |
||||||
|
book.setType(cat.contains("小说") || cat.length() >= 4 ? cat : cat + "小说"); |
||||||
|
book.setNewestChapterTitle(rb.getDesc()); |
||||||
|
book.setDesc(rb.getDesc()); |
||||||
|
if (rb instanceof RankBook) { |
||||||
|
boolean hasRankCnt = !((RankBook) rb).getRankCnt().equals("null") && |
||||||
|
MyApplication.isApkInDebug(BookstoreActivity.this); |
||||||
|
book.setUpdateDate(hasRankCnt ? book.getType() + "-" + rb.getCnt() : rb.getCnt()); |
||||||
|
book.setNewestChapterId(hasRankCnt ? ((RankBook) rb).getRankCnt() : book.getType()); |
||||||
|
} else if (rb instanceof SortBook) { |
||||||
|
book.setUpdateDate(rb.getCnt()); |
||||||
|
book.setNewestChapterId(((SortBook) rb).getState()); |
||||||
|
} |
||||||
|
books.add(book); |
||||||
|
} |
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(2, books)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onError(Exception e) { |
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(4)); |
||||||
|
ToastUtils.showError("数据加载失败!\n" + e.getMessage()); |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
}); |
||||||
|
} else { |
||||||
|
BookStoreApi.getBookRankList(curType.getUrl(), findCrawler, new ResultCallback() { |
||||||
|
@Override |
||||||
|
public void onFinish(Object o, int code) { |
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(2, o)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onError(Exception e) { |
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(4)); |
||||||
|
ToastUtils.showError("数据加载失败!\n" + e.getMessage()); |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 初始化类别列表 |
||||||
|
*/ |
||||||
|
private void initTypeList() { |
||||||
|
|
||||||
|
//设置布局管理器
|
||||||
|
mLinearLayoutManager = new LinearLayoutManager(this); |
||||||
|
mLinearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); |
||||||
|
rvTypeList.setLayoutManager(mLinearLayoutManager); |
||||||
|
mBookStoreBookTypeAdapter = new BookStoreBookTypeAdapter(this, mBookTypes); |
||||||
|
rvTypeList.setAdapter(mBookStoreBookTypeAdapter); |
||||||
|
|
||||||
|
//点击事件
|
||||||
|
mBookStoreBookTypeAdapter.setOnItemClickListener((pos, view) -> { |
||||||
|
if (curType.equals(mBookTypes.get(pos))) { |
||||||
|
return; |
||||||
|
} |
||||||
|
page = 1; |
||||||
|
curType = mBookTypes.get(pos); |
||||||
|
srlBookList.resetNoMoreData(); |
||||||
|
getBooksData(); |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 初始化小说列表 |
||||||
|
*/ |
||||||
|
private void initBookList(List<Book> bookList) { |
||||||
|
if (page == 1) { |
||||||
|
mBookStoreBookAdapter.refreshItems(bookList); |
||||||
|
this.bookList.clear(); |
||||||
|
this.bookList.addAll(bookList); |
||||||
|
rvBookList.scrollToPosition(0); |
||||||
|
} else { |
||||||
|
this.bookList.addAll(bookList); |
||||||
|
mBookStoreBookAdapter.addItems(bookList); |
||||||
|
} |
||||||
|
|
||||||
|
//刷新动作完成
|
||||||
|
srlBookList.finishRefresh(); |
||||||
|
//加载更多完成
|
||||||
|
srlBookList.finishLoadMore(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 前往书籍详情 |
||||||
|
* |
||||||
|
* @param book |
||||||
|
*/ |
||||||
|
private void goToBookDetail(Book book) { |
||||||
|
Intent intent = new Intent(this, BookDetailedActivity.class); |
||||||
|
intent.putExtra(APPCONST.BOOK, book); |
||||||
|
BookstoreActivity.this.startActivity(intent); |
||||||
|
} |
||||||
|
|
||||||
|
/********************************Event***************************************/ |
||||||
|
/** |
||||||
|
* 创建菜单 |
||||||
|
* |
||||||
|
* @param menu |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public boolean onCreateOptionsMenu(Menu menu) { |
||||||
|
getMenuInflater().inflate(R.menu.menu_store, menu); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean onPrepareOptionsMenu(Menu menu) { |
||||||
|
if (findCrawler.hasImg()) { |
||||||
|
menu.findItem(R.id.action_tip).setVisible(true); |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 导航栏菜单点击事件 |
||||||
|
* |
||||||
|
* @param item |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public boolean onOptionsItemSelected(MenuItem item) { |
||||||
|
switch (item.getItemId()) { |
||||||
|
case R.id.action_tip: |
||||||
|
mHandler.sendEmptyMessage(6); |
||||||
|
return true; |
||||||
|
case R.id.action_refresh: |
||||||
|
mRlRefresh.showLoading(); |
||||||
|
getData(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
@ -1,77 +1,117 @@ |
|||||||
package xyz.fycz.myreader.ui.activity; |
package xyz.fycz.myreader.ui.activity; |
||||||
|
|
||||||
import android.os.Bundle; |
import android.os.Bundle; |
||||||
import android.widget.EditText; |
import android.view.Menu; |
||||||
import android.widget.ImageView; |
import android.view.MenuInflater; |
||||||
import android.widget.RelativeLayout; |
import android.view.MenuItem; |
||||||
|
import androidx.appcompat.widget.SearchView; |
||||||
|
import androidx.appcompat.widget.Toolbar; |
||||||
import androidx.viewpager.widget.ViewPager; |
import androidx.viewpager.widget.ViewPager; |
||||||
import butterknife.BindView; |
import butterknife.BindView; |
||||||
import butterknife.ButterKnife; |
|
||||||
import com.google.android.material.tabs.TabLayout; |
import com.google.android.material.tabs.TabLayout; |
||||||
import xyz.fycz.myreader.R; |
import xyz.fycz.myreader.R; |
||||||
import xyz.fycz.myreader.base.BaseActivity; |
import xyz.fycz.myreader.base.BaseActivity2; |
||||||
import xyz.fycz.myreader.ui.presenter.CatalogActivityPresenter; |
import xyz.fycz.myreader.common.APPCONST; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Book; |
||||||
|
import xyz.fycz.myreader.ui.adapter.TabFragmentPageAdapter; |
||||||
|
import xyz.fycz.myreader.ui.fragment.BookMarkFragment; |
||||||
|
import xyz.fycz.myreader.ui.fragment.CatalogFragment; |
||||||
|
|
||||||
/** |
/** |
||||||
* @author fengyue |
* 书籍目录activity |
||||||
* @date 2020/7/22 8:04 |
|
||||||
*/ |
*/ |
||||||
public class CatalogActivity extends BaseActivity { |
public class CatalogActivity extends BaseActivity2 { |
||||||
@BindView(R.id.tl_tab_menu) |
|
||||||
TabLayout tlTabMenu; |
|
||||||
@BindView(R.id.iv_search) |
@BindView(R.id.catalog_tab) |
||||||
ImageView ivSearch; |
TabLayout catalogTab; |
||||||
@BindView(R.id.rl_common_title) |
@BindView(R.id.toolbar) |
||||||
RelativeLayout rlCommonTitle; |
Toolbar toolbar; |
||||||
@BindView(R.id.vp_content) |
@BindView(R.id.catalog_vp) |
||||||
ViewPager vpContent; |
ViewPager viewPager; |
||||||
@BindView(R.id.iv_back) |
private SearchView searchView; |
||||||
ImageView tvBack; |
|
||||||
|
private Book mBook; |
||||||
@BindView(R.id.et_search) |
|
||||||
EditText etSearch; |
private TabFragmentPageAdapter tabAdapter; |
||||||
@BindView(R.id.iv_cancel) |
|
||||||
ImageView ivCancel; |
/*******************Public**********************************/ |
||||||
|
|
||||||
|
public Book getmBook() { |
||||||
private CatalogActivityPresenter mCatalogPresenter; |
return mBook; |
||||||
|
} |
||||||
|
|
||||||
|
/*********************Initialization****************************/ |
||||||
|
|
||||||
|
|
||||||
@Override |
@Override |
||||||
protected void onCreate(Bundle savedInstanceState) { |
protected void initData(Bundle savedInstanceState) { |
||||||
super.onCreate(savedInstanceState); |
super.initData(savedInstanceState); |
||||||
setContentView(R.layout.activity_catalog); |
mBook = (Book) getIntent().getSerializableExtra(APPCONST.BOOK); |
||||||
ButterKnife.bind(this); |
|
||||||
setStatusBar(0, false); |
|
||||||
mCatalogPresenter = new CatalogActivityPresenter(this); |
|
||||||
mCatalogPresenter.start(); |
|
||||||
} |
} |
||||||
|
|
||||||
public TabLayout getTlTabMenu() { |
@Override |
||||||
return tlTabMenu; |
protected int getContentId() { |
||||||
|
return R.layout.activity_catalog; |
||||||
} |
} |
||||||
|
|
||||||
public ImageView getIvSearch() { |
@Override |
||||||
return ivSearch; |
protected void setUpToolbar(Toolbar toolbar) { |
||||||
|
super.setUpToolbar(toolbar); |
||||||
|
setStatusBarColor(R.color.colorPrimary, true); |
||||||
|
tabAdapter = new TabFragmentPageAdapter(getSupportFragmentManager()); |
||||||
|
tabAdapter.addFragment(new CatalogFragment(), "目录"); |
||||||
|
tabAdapter.addFragment(new BookMarkFragment(), "书签"); |
||||||
} |
} |
||||||
|
|
||||||
public RelativeLayout getRlCommonTitle() { |
@Override |
||||||
return rlCommonTitle; |
protected void initWidget() { |
||||||
|
super.initWidget(); |
||||||
|
viewPager.setAdapter(tabAdapter); |
||||||
|
viewPager.setOffscreenPageLimit(2); |
||||||
|
catalogTab.setupWithViewPager(viewPager); |
||||||
} |
} |
||||||
|
|
||||||
public ViewPager getVpContent() { |
|
||||||
return vpContent; |
/*************************************************************************/ |
||||||
|
@Override |
||||||
|
public boolean onCreateOptionsMenu(Menu menu) { |
||||||
|
MenuInflater inflater = getMenuInflater(); |
||||||
|
inflater.inflate(R.menu.menu_view_search, menu); |
||||||
|
MenuItem search = menu.findItem(R.id.action_search); |
||||||
|
searchView = (SearchView) search.getActionView(); |
||||||
|
searchView.setMaxWidth(getResources().getDisplayMetrics().widthPixels); |
||||||
|
searchView.onActionViewCollapsed(); |
||||||
|
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { |
||||||
|
@Override |
||||||
|
public boolean onQueryTextSubmit(String query) { |
||||||
|
return false; |
||||||
} |
} |
||||||
|
|
||||||
public ImageView getTvBack() { |
@Override |
||||||
return tvBack; |
public boolean onQueryTextChange(String newText) { |
||||||
|
switch (viewPager.getCurrentItem()){ |
||||||
|
case 0: |
||||||
|
((CatalogFragment) tabAdapter.getItem(0)).getmCatalogPresent().startSearch(newText); |
||||||
|
break; |
||||||
|
case 1: |
||||||
|
((BookMarkFragment) tabAdapter.getItem(1)).getmBookMarkPresenter().startSearch(newText); |
||||||
|
break; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
}); |
||||||
|
return super.onCreateOptionsMenu(menu); |
||||||
} |
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean onOptionsItemSelected(MenuItem item) { |
||||||
|
switch (item.getItemId()) { |
||||||
|
case R.id.home: |
||||||
|
|
||||||
public EditText getEtSearch() { |
return true; |
||||||
return etSearch; |
|
||||||
} |
} |
||||||
|
return super.onOptionsItemSelected(item); |
||||||
public ImageView getIvCancel() { |
|
||||||
return ivCancel; |
|
||||||
} |
} |
||||||
|
|
||||||
} |
} |
||||||
|
@ -0,0 +1,54 @@ |
|||||||
|
package xyz.fycz.myreader.ui.adapter; |
||||||
|
|
||||||
|
import androidx.annotation.NonNull; |
||||||
|
import androidx.fragment.app.Fragment; |
||||||
|
import androidx.fragment.app.FragmentManager; |
||||||
|
import androidx.fragment.app.FragmentPagerAdapter; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by Zhouas666 on 2019-03-28 |
||||||
|
* Github: https://github.com/zas023
|
||||||
|
*/ |
||||||
|
public class TabFragmentPageAdapter extends FragmentPagerAdapter { |
||||||
|
|
||||||
|
private List<Fragment> mFragmentList; |
||||||
|
private List<String> mTitleList; |
||||||
|
|
||||||
|
public TabFragmentPageAdapter(@NonNull FragmentManager fm) { |
||||||
|
super(fm); |
||||||
|
mFragmentList = new ArrayList<>(); |
||||||
|
mTitleList = new ArrayList<>(); |
||||||
|
} |
||||||
|
|
||||||
|
public void addFragment(Fragment fragment) { |
||||||
|
mFragmentList.add(fragment); |
||||||
|
} |
||||||
|
|
||||||
|
public void addFragment(Fragment fragment,String title) { |
||||||
|
mFragmentList.add(fragment); |
||||||
|
mTitleList.add(title); |
||||||
|
} |
||||||
|
|
||||||
|
public void addTitle(String title) { |
||||||
|
mTitleList.add(title); |
||||||
|
} |
||||||
|
|
||||||
|
@NonNull |
||||||
|
@Override |
||||||
|
public Fragment getItem(int position) { |
||||||
|
return mFragmentList.get(position); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getCount() { |
||||||
|
return mFragmentList.size(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public CharSequence getPageTitle(int position) { |
||||||
|
return mTitleList.get(position); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,82 @@ |
|||||||
|
package xyz.fycz.myreader.ui.adapter.holder; |
||||||
|
|
||||||
|
import android.app.Activity; |
||||||
|
import android.content.Intent; |
||||||
|
import android.view.View; |
||||||
|
import android.widget.ImageView; |
||||||
|
import android.widget.LinearLayout; |
||||||
|
import android.widget.TextView; |
||||||
|
import com.bumptech.glide.Glide; |
||||||
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners; |
||||||
|
import com.bumptech.glide.request.RequestOptions; |
||||||
|
import xyz.fycz.myreader.R; |
||||||
|
import xyz.fycz.myreader.application.MyApplication; |
||||||
|
import xyz.fycz.myreader.base.adapter.ViewHolderImpl; |
||||||
|
import xyz.fycz.myreader.common.APPCONST; |
||||||
|
import xyz.fycz.myreader.enums.BookSource; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Book; |
||||||
|
import xyz.fycz.myreader.ui.activity.BookDetailedActivity; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2020/9/7 7:35 |
||||||
|
*/ |
||||||
|
public class BookStoreBookHolder extends ViewHolderImpl<Book> { |
||||||
|
|
||||||
|
private ImageView tvBookImg; |
||||||
|
private TextView tvBookName; |
||||||
|
private TextView tvBookAuthor; |
||||||
|
private TextView tvBookTime; |
||||||
|
private TextView tvBookNewestChapter; |
||||||
|
private TextView tvBookSource; |
||||||
|
|
||||||
|
private boolean hasImg; |
||||||
|
private Activity mActivity; |
||||||
|
|
||||||
|
public BookStoreBookHolder(boolean hasImg, Activity mActivity) { |
||||||
|
this.hasImg = hasImg; |
||||||
|
this.mActivity = mActivity; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected int getItemLayoutId() { |
||||||
|
return R.layout.listview_book_store_book_item; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void initView() { |
||||||
|
tvBookImg = findById(R.id.iv_book_img); |
||||||
|
tvBookName = findById(R.id.tv_book_name); |
||||||
|
tvBookAuthor = findById(R.id.tv_book_author); |
||||||
|
tvBookNewestChapter = findById(R.id.tv_book_newest_chapter); |
||||||
|
tvBookTime = findById(R.id.tv_book_time); |
||||||
|
tvBookSource = findById(R.id.tv_book_source); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onBind(Book data, int pos) { |
||||||
|
tvBookName.setText(data.getName()); |
||||||
|
tvBookAuthor.setText(data.getAuthor()); |
||||||
|
tvBookNewestChapter.setText(data.getNewestChapterTitle()); |
||||||
|
tvBookTime.setText(data.getUpdateDate()); |
||||||
|
if (hasImg){ |
||||||
|
tvBookImg.setVisibility(View.VISIBLE); |
||||||
|
if (!MyApplication.isDestroy(mActivity)) { |
||||||
|
Glide.with(getContext()) |
||||||
|
.load(data.getImgUrl()) |
||||||
|
.error(R.mipmap.no_image) |
||||||
|
.placeholder(R.mipmap.no_image) |
||||||
|
//设置圆角
|
||||||
|
.apply(RequestOptions.bitmapTransform(new RoundedCorners(8))) |
||||||
|
.into(tvBookImg); |
||||||
|
} |
||||||
|
} |
||||||
|
if (data.getSource() != null) { |
||||||
|
tvBookSource.setText("书源:" + BookSource.fromString(data.getSource()).text); |
||||||
|
}else { |
||||||
|
tvBookSource.setText(data.getNewestChapterId()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,57 @@ |
|||||||
|
package xyz.fycz.myreader.ui.fragment; |
||||||
|
|
||||||
|
import android.content.Intent; |
||||||
|
import android.widget.RelativeLayout; |
||||||
|
import butterknife.BindView; |
||||||
|
import xyz.fycz.myreader.R; |
||||||
|
import xyz.fycz.myreader.base.BaseFragment; |
||||||
|
import xyz.fycz.myreader.common.APPCONST; |
||||||
|
import xyz.fycz.myreader.ui.activity.BookstoreActivity; |
||||||
|
import xyz.fycz.myreader.webapi.crawler.FindCrawler; |
||||||
|
import xyz.fycz.myreader.webapi.crawler.QB5ReadCrawler; |
||||||
|
import xyz.fycz.myreader.webapi.crawler.find.ABC; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2020/9/13 21:07 |
||||||
|
*/ |
||||||
|
public class FindFragment extends BaseFragment { |
||||||
|
@BindView(R.id.find_rl_qidian_top) |
||||||
|
RelativeLayout mRlQiDianTop; |
||||||
|
@BindView(R.id.find_rl_qidian_ns_top) |
||||||
|
RelativeLayout mRlQiDianNSTop; |
||||||
|
@BindView(R.id.find_rl_qidian_sort) |
||||||
|
RelativeLayout mRlQiDianSort; |
||||||
|
@BindView(R.id.find_rl_qidian_ns_sort) |
||||||
|
RelativeLayout mRlQiDianNSSort; |
||||||
|
@BindView(R.id.find_rl_qb5_store) |
||||||
|
RelativeLayout mRlQB5Store; |
||||||
|
@BindView(R.id.find_rl_biquge_store) |
||||||
|
RelativeLayout mRlBiQuGeStore; |
||||||
|
|
||||||
|
@Override |
||||||
|
protected int getContentId() { |
||||||
|
return R.layout.fragment_find; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void initClick() { |
||||||
|
super.initClick(); |
||||||
|
mRlQiDianTop.setOnClickListener(v -> comeToBookstore(new ABC(false))); |
||||||
|
mRlQiDianNSTop.setOnClickListener(v -> comeToBookstore(new ABC(true))); |
||||||
|
mRlQiDianSort.setOnClickListener(v -> comeToBookstore(new ABC(false, true))); |
||||||
|
mRlQiDianNSSort.setOnClickListener(v -> comeToBookstore(new ABC(true, true))); |
||||||
|
mRlQB5Store.setOnClickListener(v -> comeToBookstore(new QB5ReadCrawler())); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void comeToBookstore(FindCrawler findCrawler){ |
||||||
|
Intent intent = new Intent(getContext(), BookstoreActivity.class); |
||||||
|
intent.putExtra(APPCONST.FIND_CRAWLER, findCrawler); |
||||||
|
startActivity(intent); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isRecreate() { |
||||||
|
return unbinder == null; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,397 @@ |
|||||||
|
package xyz.fycz.myreader.ui.fragment; |
||||||
|
|
||||||
|
import android.annotation.SuppressLint; |
||||||
|
import android.content.*; |
||||||
|
import android.os.Bundle; |
||||||
|
import android.os.Handler; |
||||||
|
import android.os.Message; |
||||||
|
import android.widget.ArrayAdapter; |
||||||
|
import android.widget.RelativeLayout; |
||||||
|
import android.widget.TextView; |
||||||
|
import androidx.annotation.NonNull; |
||||||
|
import androidx.annotation.Nullable; |
||||||
|
import androidx.appcompat.app.AlertDialog; |
||||||
|
import butterknife.BindView; |
||||||
|
import xyz.fycz.myreader.R; |
||||||
|
import xyz.fycz.myreader.application.MyApplication; |
||||||
|
import xyz.fycz.myreader.application.SysManager; |
||||||
|
import xyz.fycz.myreader.backup.BackupAndRestore; |
||||||
|
import xyz.fycz.myreader.backup.UserService; |
||||||
|
import xyz.fycz.myreader.base.BaseFragment; |
||||||
|
import xyz.fycz.myreader.common.APPCONST; |
||||||
|
import xyz.fycz.myreader.creator.DialogCreator; |
||||||
|
import xyz.fycz.myreader.creator.MyAlertDialog; |
||||||
|
import xyz.fycz.myreader.entity.Setting; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Book; |
||||||
|
import xyz.fycz.myreader.greendao.service.BookService; |
||||||
|
import xyz.fycz.myreader.ui.activity.AboutActivity; |
||||||
|
import xyz.fycz.myreader.ui.activity.LoginActivity; |
||||||
|
import xyz.fycz.myreader.ui.activity.MoreSettingActivity; |
||||||
|
import xyz.fycz.myreader.util.SharedPreUtils; |
||||||
|
import xyz.fycz.myreader.util.ToastUtils; |
||||||
|
import xyz.fycz.myreader.util.utils.NetworkUtils; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.text.SimpleDateFormat; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Date; |
||||||
|
|
||||||
|
import static android.app.Activity.RESULT_OK; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2020/9/13 13:20 |
||||||
|
*/ |
||||||
|
public class MineFragment extends BaseFragment { |
||||||
|
@BindView(R.id.mine_rl_user) |
||||||
|
RelativeLayout mRlUser; |
||||||
|
@BindView(R.id.tv_user) |
||||||
|
TextView mTvUser; |
||||||
|
@BindView(R.id.mine_rl_backup) |
||||||
|
RelativeLayout mRlBackup; |
||||||
|
@BindView(R.id.mine_rl_syn) |
||||||
|
RelativeLayout mRlSyn; |
||||||
|
@BindView(R.id.mine_rl_setting) |
||||||
|
RelativeLayout mRlSetting; |
||||||
|
@BindView(R.id.mine_rl_theme_mode) |
||||||
|
RelativeLayout mRlThemeMode; |
||||||
|
@BindView(R.id.tv_theme_mode_select) |
||||||
|
TextView tvThemeModeSelect; |
||||||
|
@BindView(R.id.mine_rl_feedback) |
||||||
|
RelativeLayout mRlFeedback; |
||||||
|
@BindView(R.id.mine_rl_about) |
||||||
|
RelativeLayout mRlAbout; |
||||||
|
|
||||||
|
private boolean isLogin; |
||||||
|
private BackupAndRestore mBackupAndRestore; |
||||||
|
private Setting mSetting; |
||||||
|
private String[] webSynMenu; |
||||||
|
private String[] backupMenu; |
||||||
|
private AlertDialog themeModeDia; |
||||||
|
private int themeMode; |
||||||
|
private String[] themeModeArr; |
||||||
|
@SuppressLint("HandlerLeak") |
||||||
|
private Handler mHandler = new Handler() { |
||||||
|
@Override |
||||||
|
public void handleMessage(@NonNull Message msg) { |
||||||
|
switch (msg.what) { |
||||||
|
case 1: |
||||||
|
mTvUser.setText("登录/注册"); |
||||||
|
break; |
||||||
|
case 2: |
||||||
|
backup(); |
||||||
|
break; |
||||||
|
case 3: |
||||||
|
restore(); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
public MineFragment() { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected int getContentId() { |
||||||
|
return R.layout.fragment_mine; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void initData(Bundle savedInstanceState) { |
||||||
|
super.initData(savedInstanceState); |
||||||
|
isLogin = UserService.isLogin(); |
||||||
|
mBackupAndRestore = new BackupAndRestore(); |
||||||
|
mSetting = SysManager.getSetting(); |
||||||
|
webSynMenu = new String[]{ |
||||||
|
MyApplication.getmContext().getString(R.string.menu_backup_webBackup), |
||||||
|
MyApplication.getmContext().getString(R.string.menu_backup_webRestore), |
||||||
|
MyApplication.getmContext().getString(R.string.menu_backup_autoSyn) |
||||||
|
}; |
||||||
|
backupMenu = new String[]{ |
||||||
|
MyApplication.getmContext().getResources().getString(R.string.menu_backup_backup), |
||||||
|
MyApplication.getmContext().getResources().getString(R.string.menu_backup_restore), |
||||||
|
}; |
||||||
|
themeMode = MyApplication.getApplication().isNightFS() ? 0 : mSetting.isDayStyle() ? 1 : 2; |
||||||
|
themeModeArr = getResources().getStringArray(R.array.theme_mode_arr); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void initWidget(Bundle savedInstanceState) { |
||||||
|
super.initWidget(savedInstanceState); |
||||||
|
if (isLogin) { |
||||||
|
mTvUser.setText(UserService.readUsername()); |
||||||
|
} |
||||||
|
tvThemeModeSelect.setText(themeModeArr[themeMode]); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void initClick() { |
||||||
|
super.initClick(); |
||||||
|
mRlUser.setOnClickListener(v -> { |
||||||
|
if (isLogin) { |
||||||
|
DialogCreator.createCommonDialog(getActivity(), "退出登录", "确定要退出登录吗?" |
||||||
|
, true, (dialog, which) -> { |
||||||
|
File file = MyApplication.getApplication().getFileStreamPath("userConfig.fy"); |
||||||
|
if (file.delete()) { |
||||||
|
ToastUtils.showSuccess("退出成功"); |
||||||
|
isLogin = false; |
||||||
|
mHandler.sendEmptyMessage(1); |
||||||
|
Intent intent = new Intent(getActivity(), LoginActivity.class); |
||||||
|
getActivity().startActivityForResult(intent, APPCONST.REQUEST_LOGIN); |
||||||
|
} else { |
||||||
|
ToastUtils.showError("退出失败(Error:file.delete())"); |
||||||
|
} |
||||||
|
}, (dialog, which) -> dialog.dismiss()); |
||||||
|
} else { |
||||||
|
Intent intent = new Intent(getActivity(), LoginActivity.class); |
||||||
|
getActivity().startActivityForResult(intent, APPCONST.REQUEST_LOGIN); |
||||||
|
} |
||||||
|
}); |
||||||
|
mRlBackup.setOnClickListener(v -> { |
||||||
|
AlertDialog bookDialog = MyAlertDialog.build(getContext()) |
||||||
|
.setTitle(getContext().getResources().getString(R.string.menu_bookcase_backup)) |
||||||
|
.setItems(backupMenu, (dialog, which) -> { |
||||||
|
switch (which) { |
||||||
|
case 0: |
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(2)); |
||||||
|
break; |
||||||
|
case 1: |
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(3)); |
||||||
|
break; |
||||||
|
} |
||||||
|
}) |
||||||
|
.setNegativeButton(null, null) |
||||||
|
.setPositiveButton(null, null) |
||||||
|
.create(); |
||||||
|
bookDialog.show(); |
||||||
|
}); |
||||||
|
mRlSyn.setOnClickListener(v -> { |
||||||
|
if (!UserService.isLogin()) { |
||||||
|
ToastUtils.showWarring("请先登录!"); |
||||||
|
Intent loginIntent = new Intent(getActivity(), LoginActivity.class); |
||||||
|
getActivity().startActivityForResult(loginIntent, APPCONST.REQUEST_LOGIN); |
||||||
|
return; |
||||||
|
} |
||||||
|
if (mSetting.isAutoSyn()) { |
||||||
|
webSynMenu[2] = MyApplication.getmContext().getString(R.string.menu_backup_autoSyn) + "已开启"; |
||||||
|
} else { |
||||||
|
webSynMenu[2] = MyApplication.getmContext().getString(R.string.menu_backup_autoSyn) + "已关闭"; |
||||||
|
} |
||||||
|
MyAlertDialog.build(getContext()) |
||||||
|
.setTitle(getActivity().getString(R.string.menu_bookcase_syn)) |
||||||
|
.setItems(webSynMenu, (dialog, which) -> { |
||||||
|
switch (which) { |
||||||
|
case 0: |
||||||
|
synBookcaseToWeb(false); |
||||||
|
break; |
||||||
|
case 1: |
||||||
|
webRestore(); |
||||||
|
break; |
||||||
|
case 2: |
||||||
|
String tip = ""; |
||||||
|
if (mSetting.isAutoSyn()) { |
||||||
|
mSetting.setAutoSyn(false); |
||||||
|
tip = "每日自动同步已关闭!"; |
||||||
|
} else { |
||||||
|
mSetting.setAutoSyn(true); |
||||||
|
tip = "每日自动同步已开启!"; |
||||||
|
} |
||||||
|
SysManager.saveSetting(mSetting); |
||||||
|
ToastUtils.showSuccess(tip); |
||||||
|
break; |
||||||
|
} |
||||||
|
}) |
||||||
|
.setNegativeButton(null, null) |
||||||
|
.setPositiveButton(null, null) |
||||||
|
.show(); |
||||||
|
}); |
||||||
|
mRlSetting.setOnClickListener(v -> { |
||||||
|
Intent settingIntent = new Intent(getActivity(), MoreSettingActivity.class); |
||||||
|
startActivity(settingIntent); |
||||||
|
}); |
||||||
|
mRlThemeMode.setOnClickListener(v -> { |
||||||
|
if (themeModeDia != null) { |
||||||
|
themeModeDia.show(); |
||||||
|
return; |
||||||
|
} |
||||||
|
themeModeDia = MyAlertDialog.build(getContext()) |
||||||
|
.setTitle("主题模式") |
||||||
|
.setSingleChoiceItems(themeModeArr, themeMode |
||||||
|
, (dialog, which) -> { |
||||||
|
if (themeMode == which) { |
||||||
|
dialog.dismiss(); |
||||||
|
return; |
||||||
|
} |
||||||
|
themeMode = which; |
||||||
|
switch (which) { |
||||||
|
case 0: |
||||||
|
SharedPreUtils.getInstance().putBoolean("isNightFS", true); |
||||||
|
break; |
||||||
|
case 1: |
||||||
|
SharedPreUtils.getInstance().putBoolean("isNightFS", false); |
||||||
|
mSetting.setDayStyle(true); |
||||||
|
SysManager.saveSetting(mSetting); |
||||||
|
break; |
||||||
|
case 2: |
||||||
|
SharedPreUtils.getInstance().putBoolean("isNightFS", false); |
||||||
|
mSetting.setDayStyle(false); |
||||||
|
SysManager.saveSetting(mSetting); |
||||||
|
break; |
||||||
|
} |
||||||
|
dialog.dismiss(); |
||||||
|
tvThemeModeSelect.setText(themeModeArr[themeMode]); |
||||||
|
MyApplication.getApplication().initNightTheme(); |
||||||
|
}) |
||||||
|
.setNegativeButton("取消", null) |
||||||
|
.create(); |
||||||
|
themeModeDia.show(); |
||||||
|
|
||||||
|
}); |
||||||
|
|
||||||
|
mRlAbout.setOnClickListener(v -> { |
||||||
|
Intent aboutIntent = new Intent(getActivity(), AboutActivity.class); |
||||||
|
startActivity(aboutIntent); |
||||||
|
}); |
||||||
|
|
||||||
|
mRlFeedback.setOnClickListener(v -> { |
||||||
|
DialogCreator.createCommonDialog(getContext(), "问题反馈", "请加入QQ群(1085028304)反馈问题!", true, |
||||||
|
"加入QQ群", "取消", (dialog, which) -> { |
||||||
|
if (!MyApplication.joinQQGroup(getContext(),"8PIOnHFuH6A38hgxvD_Rp2Bu-Ke1ToBn")){ |
||||||
|
ClipboardManager mClipboardManager = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE); |
||||||
|
//数据
|
||||||
|
ClipData mClipData = ClipData.newPlainText("Label", "1085028304"); |
||||||
|
//把数据设置到剪切板上
|
||||||
|
assert mClipboardManager != null; |
||||||
|
mClipboardManager.setPrimaryClip(mClipData); |
||||||
|
ToastUtils.showError("未安装手Q或安装的版本不支持!\n已复制QQ群号,您可自行前往QQ添加!"); |
||||||
|
} |
||||||
|
}, null); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void processLogic() { |
||||||
|
super.processLogic(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 备份 |
||||||
|
*/ |
||||||
|
private void backup() { |
||||||
|
ArrayList<Book> mBooks = (ArrayList<Book>) BookService.getInstance().getAllBooks(); |
||||||
|
if (mBooks.size() == 0) { |
||||||
|
ToastUtils.showWarring("当前书架无任何书籍,无法备份!"); |
||||||
|
return; |
||||||
|
} |
||||||
|
DialogCreator.createCommonDialog(getContext(), "确认备份吗?", "新备份会替换原有备份!", true, |
||||||
|
(dialogInterface, i) -> { |
||||||
|
dialogInterface.dismiss(); |
||||||
|
if (mBackupAndRestore.backup("localBackup")) { |
||||||
|
DialogCreator.createTipDialog(getContext(), "备份成功,备份文件路径:" + APPCONST.BACKUP_FILE_DIR); |
||||||
|
} else { |
||||||
|
DialogCreator.createTipDialog(getContext(), "未给予储存权限,备份失败!"); |
||||||
|
} |
||||||
|
}, (dialogInterface, i) -> dialogInterface.dismiss()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 恢复 |
||||||
|
*/ |
||||||
|
private void restore() { |
||||||
|
DialogCreator.createCommonDialog(getContext(), "确认恢复吗?", "恢复书架会覆盖原有书架!", true, |
||||||
|
(dialogInterface, i) -> { |
||||||
|
dialogInterface.dismiss(); |
||||||
|
if (mBackupAndRestore.restore("localBackup")) { |
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(7)); |
||||||
|
// DialogCreator.createTipDialog(mMainActivity,
|
||||||
|
// "恢复成功!\n注意:本功能属于实验功能,书架恢复后,书籍初次加载时可能加载失败,返回重新加载即可!");
|
||||||
|
mSetting = SysManager.getSetting(); |
||||||
|
ToastUtils.showSuccess("书架恢复成功!"); |
||||||
|
} else { |
||||||
|
DialogCreator.createTipDialog(getContext(), "未找到备份文件或未给予储存权限,恢复失败!"); |
||||||
|
} |
||||||
|
}, (dialogInterface, i) -> dialogInterface.dismiss()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 同步书架 |
||||||
|
*/ |
||||||
|
private void synBookcaseToWeb(boolean isAutoSyn) { |
||||||
|
if (!NetworkUtils.isNetWorkAvailable()) { |
||||||
|
if (!isAutoSyn) { |
||||||
|
ToastUtils.showWarring("无网络连接!"); |
||||||
|
} |
||||||
|
return; |
||||||
|
} |
||||||
|
ArrayList<Book> mBooks = (ArrayList<Book>) BookService.getInstance().getAllBooks(); |
||||||
|
if (mBooks.size() == 0) { |
||||||
|
if (!isAutoSyn) { |
||||||
|
ToastUtils.showWarring("当前书架无任何书籍,无法同步!"); |
||||||
|
} |
||||||
|
return; |
||||||
|
} |
||||||
|
Date nowTime = new Date(); |
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd"); |
||||||
|
String nowTimeStr = sdf.format(nowTime); |
||||||
|
SharedPreUtils spb = SharedPreUtils.getInstance(); |
||||||
|
String synTime = spb.getString("synTime"); |
||||||
|
if (!nowTimeStr.equals(synTime) || !isAutoSyn) { |
||||||
|
MyApplication.getApplication().newThread(() -> { |
||||||
|
if (UserService.webBackup()) { |
||||||
|
spb.putString("synTime", nowTimeStr); |
||||||
|
if (!isAutoSyn) { |
||||||
|
DialogCreator.createTipDialog(getContext(), "成功将书架同步至网络!"); |
||||||
|
} |
||||||
|
} else { |
||||||
|
if (!isAutoSyn) { |
||||||
|
DialogCreator.createTipDialog(getContext(), "同步失败,请重试!"); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 恢复 |
||||||
|
*/ |
||||||
|
private void webRestore() { |
||||||
|
if (!NetworkUtils.isNetWorkAvailable()) { |
||||||
|
ToastUtils.showWarring("无网络连接!"); |
||||||
|
return; |
||||||
|
} |
||||||
|
DialogCreator.createCommonDialog(getContext(), "确认同步吗?", "将书架从网络同步至本地会覆盖原有书架!", true, |
||||||
|
(dialogInterface, i) -> { |
||||||
|
dialogInterface.dismiss(); |
||||||
|
MyApplication.getApplication().newThread(() -> { |
||||||
|
if (UserService.webRestore()) { |
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(7)); |
||||||
|
// DialogCreator.createTipDialog(mMainActivity,
|
||||||
|
// "恢复成功!\n注意:本功能属于实验功能,书架恢复后,书籍初次加载时可能加载失败,返回重新加载即可!");、
|
||||||
|
mSetting = SysManager.getSetting(); |
||||||
|
ToastUtils.showSuccess("成功将书架从网络同步至本地!"); |
||||||
|
} else { |
||||||
|
DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!"); |
||||||
|
} |
||||||
|
}); |
||||||
|
}, (dialogInterface, i) -> dialogInterface.dismiss()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { |
||||||
|
if (resultCode == RESULT_OK) { |
||||||
|
switch (requestCode) { |
||||||
|
case APPCONST.REQUEST_LOGIN: |
||||||
|
assert data != null; |
||||||
|
isLogin = data.getBooleanExtra("isLogin", false); |
||||||
|
if (isLogin) { |
||||||
|
mTvUser.setText(UserService.readUsername()); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isRecreate() { |
||||||
|
return unbinder == null; |
||||||
|
} |
||||||
|
} |
@ -1,62 +0,0 @@ |
|||||||
package xyz.fycz.myreader.ui.presenter; |
|
||||||
|
|
||||||
import android.annotation.SuppressLint; |
|
||||||
import android.content.ClipData; |
|
||||||
import android.content.ClipboardManager; |
|
||||||
import android.content.Context; |
|
||||||
import android.content.Intent; |
|
||||||
import android.net.Uri; |
|
||||||
import xyz.fycz.myreader.R; |
|
||||||
import xyz.fycz.myreader.application.MyApplication; |
|
||||||
import xyz.fycz.myreader.base.BasePresenter; |
|
||||||
import xyz.fycz.myreader.creator.DialogCreator; |
|
||||||
import xyz.fycz.myreader.ui.activity.AboutActivity; |
|
||||||
import xyz.fycz.myreader.util.ShareUtils; |
|
||||||
import xyz.fycz.myreader.util.SharedPreUtils; |
|
||||||
import xyz.fycz.myreader.util.ToastUtils; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author fengyue |
|
||||||
* @date 2020/7/31 11:39 |
|
||||||
*/ |
|
||||||
public class AboutPresenter implements BasePresenter { |
|
||||||
|
|
||||||
private AboutActivity mAboutActivity; |
|
||||||
|
|
||||||
public AboutPresenter(AboutActivity mAboutActivity) { |
|
||||||
this.mAboutActivity = mAboutActivity; |
|
||||||
} |
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n") |
|
||||||
@Override |
|
||||||
public void start() { |
|
||||||
mAboutActivity.getLlTitleBack().setOnClickListener(v -> mAboutActivity.finish()); |
|
||||||
mAboutActivity.getTvTitleText().setText("关于"); |
|
||||||
mAboutActivity.getTvVersionName().setText("风月读书v" + MyApplication.getStrVersionName()); |
|
||||||
mAboutActivity.getVmAuthor().setOnClickListener(v -> { |
|
||||||
ClipboardManager mClipboardManager = (ClipboardManager) mAboutActivity.getSystemService(Context.CLIPBOARD_SERVICE); |
|
||||||
//数据
|
|
||||||
ClipData mClipData = ClipData.newPlainText("Label", "fy@fycz.xyz"); |
|
||||||
//把数据设置到剪切板上
|
|
||||||
assert mClipboardManager != null; |
|
||||||
mClipboardManager.setPrimaryClip(mClipData); |
|
||||||
ToastUtils.showSuccess("邮箱复制成功!"); |
|
||||||
}); |
|
||||||
mAboutActivity.getVmShare().setOnClickListener(v -> ShareUtils.share(mAboutActivity, mAboutActivity.getString(R.string.share_text) + |
|
||||||
SharedPreUtils.getInstance().getString("downloadLink"))); |
|
||||||
mAboutActivity.getVmUpdate().setOnClickListener(v -> MyApplication.checkVersionByServer(mAboutActivity, true, null)); |
|
||||||
mAboutActivity.getVmUpdateLog().setOnClickListener(v -> DialogCreator.createAssetTipDialog(mAboutActivity, "更新日志", "updatelog.fy")); |
|
||||||
mAboutActivity.getVmGit().setOnClickListener(v -> openIntent(Intent.ACTION_VIEW, mAboutActivity.getString(R.string.this_github_url))); |
|
||||||
mAboutActivity.getVmDisclaimer().setOnClickListener(v -> DialogCreator.createAssetTipDialog(mAboutActivity, "免责声明", "disclaimer.fy")); |
|
||||||
} |
|
||||||
|
|
||||||
void openIntent(String intentName, String address) { |
|
||||||
try { |
|
||||||
Intent intent = new Intent(intentName); |
|
||||||
intent.setData(Uri.parse(address)); |
|
||||||
mAboutActivity.startActivity(intent); |
|
||||||
} catch (Exception e) { |
|
||||||
ToastUtils.showError(e.getLocalizedMessage()); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,134 +0,0 @@ |
|||||||
package xyz.fycz.myreader.ui.presenter; |
|
||||||
|
|
||||||
import android.content.Context; |
|
||||||
import android.text.Editable; |
|
||||||
import android.text.TextWatcher; |
|
||||||
import android.view.View; |
|
||||||
import android.view.inputmethod.InputMethodManager; |
|
||||||
import androidx.fragment.app.Fragment; |
|
||||||
import androidx.fragment.app.FragmentPagerAdapter; |
|
||||||
import xyz.fycz.myreader.R; |
|
||||||
import xyz.fycz.myreader.application.SysManager; |
|
||||||
import xyz.fycz.myreader.base.BasePresenter; |
|
||||||
import xyz.fycz.myreader.entity.Setting; |
|
||||||
import xyz.fycz.myreader.ui.activity.CatalogActivity; |
|
||||||
import xyz.fycz.myreader.ui.fragment.CatalogFragment; |
|
||||||
import xyz.fycz.myreader.ui.fragment.BookMarkFragment; |
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
|
|
||||||
import static androidx.fragment.app.FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author fengyue |
|
||||||
* @date 2020/7/22 8:10 |
|
||||||
*/ |
|
||||||
public class CatalogActivityPresenter implements BasePresenter { |
|
||||||
|
|
||||||
private CatalogActivity mCatalogActivity; |
|
||||||
private ArrayList<Fragment> mFragments = new ArrayList<>(); |
|
||||||
private String[] tabTitle = {"目录", "书签"}; |
|
||||||
private boolean isDayStyle; |
|
||||||
private FragmentPagerAdapter tabAdapter; |
|
||||||
|
|
||||||
public CatalogActivityPresenter(CatalogActivity mCatalogActivity) { |
|
||||||
this.mCatalogActivity = mCatalogActivity; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void start() { |
|
||||||
Setting setting = SysManager.getSetting(); |
|
||||||
isDayStyle = setting.isDayStyle(); |
|
||||||
//设置日夜间
|
|
||||||
if (!isDayStyle){ |
|
||||||
mCatalogActivity.setStatusBar(R.color.sys_dialog_setting_bg, true); |
|
||||||
mCatalogActivity.getRlCommonTitle().setBackground(mCatalogActivity.getDrawable(R.color.sys_dialog_setting_bg)); |
|
||||||
mCatalogActivity.getTvBack().setImageDrawable(mCatalogActivity.getDrawable(R.mipmap.larrow_white2)); |
|
||||||
mCatalogActivity.getIvCancel().setImageDrawable(mCatalogActivity.getDrawable(R.mipmap.ic_cha_black)); |
|
||||||
mCatalogActivity.getIvSearch().setImageDrawable(mCatalogActivity.getDrawable(R.mipmap.b9)); |
|
||||||
mCatalogActivity.getEtSearch().setTextColor(mCatalogActivity.getResources().getColor(R.color.sys_night_word)); |
|
||||||
mCatalogActivity.getEtSearch().setHintTextColor(mCatalogActivity.getResources().getColor(R.color.sys_night_word)); |
|
||||||
} |
|
||||||
init(); |
|
||||||
|
|
||||||
InputMethodManager manager = ((InputMethodManager) mCatalogActivity.getSystemService(Context.INPUT_METHOD_SERVICE)); |
|
||||||
|
|
||||||
mCatalogActivity.getTvBack().setOnClickListener(v -> mCatalogActivity.finish()); |
|
||||||
mCatalogActivity.getIvSearch().setOnClickListener(v -> { |
|
||||||
mCatalogActivity.getTlTabMenu().setVisibility(View.GONE); |
|
||||||
mCatalogActivity.getIvSearch().setVisibility(View.GONE); |
|
||||||
mCatalogActivity.getEtSearch().setVisibility(View.VISIBLE); |
|
||||||
mCatalogActivity.getIvCancel().setVisibility(View.VISIBLE); |
|
||||||
mCatalogActivity.getEtSearch().setFocusable(true); |
|
||||||
mCatalogActivity.getEtSearch().setFocusableInTouchMode(true); |
|
||||||
mCatalogActivity.getEtSearch().requestFocus(); |
|
||||||
}); |
|
||||||
|
|
||||||
mCatalogActivity.getEtSearch().setOnFocusChangeListener((v, hasFocus) -> { |
|
||||||
if (hasFocus){ |
|
||||||
if (manager != null) manager.showSoftInput(v, InputMethodManager.SHOW_IMPLICIT); |
|
||||||
}else { |
|
||||||
if (manager != null) manager.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
mCatalogActivity.getIvCancel().setOnClickListener(v -> { |
|
||||||
mCatalogActivity.getTlTabMenu().setVisibility(View.VISIBLE); |
|
||||||
mCatalogActivity.getIvSearch().setVisibility(View.VISIBLE); |
|
||||||
mCatalogActivity.getEtSearch().setVisibility(View.GONE); |
|
||||||
mCatalogActivity.getIvCancel().setVisibility(View.GONE); |
|
||||||
if(!"".equals(mCatalogActivity.getEtSearch().getText().toString())){ |
|
||||||
mCatalogActivity.getEtSearch().setText(""); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
mCatalogActivity.getEtSearch().addTextChangedListener(new TextWatcher() { |
|
||||||
@Override |
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void afterTextChanged(Editable s) { |
|
||||||
switch (mCatalogActivity.getVpContent().getCurrentItem()){ |
|
||||||
case 0: |
|
||||||
((CatalogFragment) tabAdapter.getItem(0)).getmCatalogPresent().startSearch(s.toString()); |
|
||||||
break; |
|
||||||
case 1: |
|
||||||
((BookMarkFragment) tabAdapter.getItem(1)).getmBookMarkPresenter().startSearch(s.toString()); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
private void init(){ |
|
||||||
mFragments.add(new CatalogFragment()); |
|
||||||
mFragments.add(new BookMarkFragment()); |
|
||||||
tabAdapter = new FragmentPagerAdapter(mCatalogActivity.getSupportFragmentManager(),BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { |
|
||||||
@Override |
|
||||||
public Fragment getItem(int position) { |
|
||||||
return mFragments.get(position); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public int getCount() { |
|
||||||
return mFragments.size(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public CharSequence getPageTitle(int position) { |
|
||||||
return tabTitle[position]; |
|
||||||
} |
|
||||||
|
|
||||||
}; |
|
||||||
mCatalogActivity.getVpContent().setAdapter(tabAdapter); |
|
||||||
mCatalogActivity.getTlTabMenu().setupWithViewPager(mCatalogActivity.getVpContent()); |
|
||||||
mCatalogActivity.getVpContent().setCurrentItem(0); |
|
||||||
} |
|
||||||
} |
|
@ -1,118 +0,0 @@ |
|||||||
package xyz.fycz.myreader.ui.presenter; |
|
||||||
|
|
||||||
import android.annotation.SuppressLint; |
|
||||||
import android.os.Handler; |
|
||||||
import android.os.Message; |
|
||||||
import android.view.View; |
|
||||||
|
|
||||||
import xyz.fycz.myreader.R; |
|
||||||
import xyz.fycz.myreader.base.BasePresenter; |
|
||||||
import xyz.fycz.myreader.common.APPCONST; |
|
||||||
import xyz.fycz.myreader.enums.Font; |
|
||||||
import xyz.fycz.myreader.ui.activity.FontsActivity; |
|
||||||
import xyz.fycz.myreader.ui.adapter.FontsAdapter; |
|
||||||
import xyz.fycz.myreader.util.IOUtils; |
|
||||||
import xyz.fycz.myreader.util.ToastUtils; |
|
||||||
import xyz.fycz.myreader.util.utils.FileUtils; |
|
||||||
|
|
||||||
import java.io.*; |
|
||||||
import java.util.ArrayList; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by zhao on 2017/8/7. |
|
||||||
*/ |
|
||||||
|
|
||||||
public class FontsPresenter implements BasePresenter { |
|
||||||
|
|
||||||
private FontsActivity mFontsActivity; |
|
||||||
private ArrayList<Font> mFonts; |
|
||||||
private FontsAdapter mFontsAdapter; |
|
||||||
|
|
||||||
|
|
||||||
@SuppressLint("HandlerLeak") |
|
||||||
private Handler mHandler = new Handler(){ |
|
||||||
@Override |
|
||||||
public void handleMessage(Message msg) { |
|
||||||
switch (msg.what){ |
|
||||||
case 1: |
|
||||||
init(); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
public FontsPresenter(FontsActivity fontsActivity) { |
|
||||||
mFontsActivity = fontsActivity; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void start() { |
|
||||||
mFontsActivity.getLlTitleBack().setOnClickListener(new View.OnClickListener() { |
|
||||||
@Override |
|
||||||
public void onClick(View v) { |
|
||||||
mFontsActivity.finish(); |
|
||||||
} |
|
||||||
}); |
|
||||||
mFontsActivity.getTvTitleText().setText(mFontsActivity.getString(R.string.font)); |
|
||||||
init(); |
|
||||||
} |
|
||||||
|
|
||||||
private void init() { |
|
||||||
initFonts(); |
|
||||||
mFontsAdapter = new FontsAdapter(mFontsActivity, R.layout.listview_font_item, mFonts, mFontsActivity); |
|
||||||
mFontsActivity.getLvFonts().setAdapter(mFontsAdapter); |
|
||||||
mFontsActivity.getPbLoading().setVisibility(View.GONE); |
|
||||||
} |
|
||||||
|
|
||||||
private void initFonts() { |
|
||||||
mFonts = new ArrayList<>(); |
|
||||||
mFonts.add(Font.默认字体); |
|
||||||
mFonts.add(Font.方正楷体); |
|
||||||
mFonts.add(Font.经典宋体); |
|
||||||
mFonts.add(Font.方正行楷); |
|
||||||
mFonts.add(Font.迷你隶书); |
|
||||||
mFonts.add(Font.方正黄草); |
|
||||||
mFonts.add(Font.方正硬笔行书); |
|
||||||
mFonts.add(Font.本地字体); |
|
||||||
} |
|
||||||
|
|
||||||
public void notifyChange(){ |
|
||||||
mFontsAdapter.notifyDataSetChanged(); |
|
||||||
} |
|
||||||
|
|
||||||
public void saveLocalFont(String path){ |
|
||||||
File fontFile = new File(path); |
|
||||||
if (!fontFile.exists()){ |
|
||||||
ToastUtils.showWarring("未找到字体文件!"); |
|
||||||
return; |
|
||||||
} |
|
||||||
String fontName = fontFile.getName(); |
|
||||||
if (!fontName.endsWith(".ttf")){ |
|
||||||
ToastUtils.showError("字体更换失败,请选择ttf格式的字体文件!"); |
|
||||||
return; |
|
||||||
} |
|
||||||
String dirPath = fontFile.getParentFile().getAbsolutePath() + "/"; |
|
||||||
if (dirPath.equals(APPCONST.FONT_BOOK_DIR)){ |
|
||||||
mFontsAdapter.saveLocalFontName(fontName); |
|
||||||
return; |
|
||||||
} |
|
||||||
FileInputStream fis = null; |
|
||||||
FileOutputStream fos = null; |
|
||||||
try { |
|
||||||
fis = new FileInputStream(fontFile); |
|
||||||
fos = new FileOutputStream(FileUtils.getFile(APPCONST.FONT_BOOK_DIR + fontName)); |
|
||||||
byte[] bytes = new byte[1021]; |
|
||||||
int len = -1; |
|
||||||
while ((len = fis.read(bytes)) != -1){ |
|
||||||
fos.write(bytes, 0, len); |
|
||||||
} |
|
||||||
fos.flush(); |
|
||||||
mFontsAdapter.saveLocalFontName(fontName); |
|
||||||
} catch (IOException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
ToastUtils.showError("读取字体文件出错!\n" + e.getLocalizedMessage()); |
|
||||||
}finally { |
|
||||||
IOUtils.close(fis, fos); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,137 +0,0 @@ |
|||||||
package xyz.fycz.myreader.ui.presenter; |
|
||||||
|
|
||||||
import android.annotation.SuppressLint; |
|
||||||
import android.app.ProgressDialog; |
|
||||||
import android.content.Intent; |
|
||||||
import android.graphics.Bitmap; |
|
||||||
import android.os.Handler; |
|
||||||
import android.os.Message; |
|
||||||
import android.view.View; |
|
||||||
import xyz.fycz.myreader.backup.UserService; |
|
||||||
import xyz.fycz.myreader.base.BasePresenter; |
|
||||||
import xyz.fycz.myreader.callback.ResultCallback; |
|
||||||
import xyz.fycz.myreader.common.APPCONST; |
|
||||||
import xyz.fycz.myreader.creator.DialogCreator; |
|
||||||
import xyz.fycz.myreader.ui.activity.LoginActivity; |
|
||||||
import xyz.fycz.myreader.ui.activity.RegisterActivity; |
|
||||||
import xyz.fycz.myreader.util.CodeUtil; |
|
||||||
import xyz.fycz.myreader.util.CyptoUtils; |
|
||||||
import xyz.fycz.myreader.util.ToastUtils; |
|
||||||
import xyz.fycz.myreader.util.utils.NetworkUtils; |
|
||||||
|
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author fengyue |
|
||||||
* @date 2020/4/26 20:31 |
|
||||||
*/ |
|
||||||
|
|
||||||
public class LoginPresenter implements BasePresenter { |
|
||||||
private LoginActivity mLoginActivity; |
|
||||||
private String code; |
|
||||||
|
|
||||||
public LoginPresenter(LoginActivity mLoginActivity) { |
|
||||||
this.mLoginActivity = mLoginActivity; |
|
||||||
} |
|
||||||
|
|
||||||
@SuppressLint("HandlerLeak") |
|
||||||
private Handler mHandler = new Handler() { |
|
||||||
@SuppressLint("HandlerLeak") |
|
||||||
@Override |
|
||||||
public void handleMessage(Message msg) { |
|
||||||
switch (msg.what) { |
|
||||||
case 1: |
|
||||||
mLoginActivity.getLoginBtn().setEnabled(true); |
|
||||||
break; |
|
||||||
case 2: |
|
||||||
createCaptcha(); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
@Override |
|
||||||
public void start() { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2)); |
|
||||||
mLoginActivity.getTvTitleText().setText("登录"); |
|
||||||
mLoginActivity.getLlTitleBack().setOnClickListener(v -> mLoginActivity.finish()); |
|
||||||
String username = UserService.readUsername(); |
|
||||||
mLoginActivity.getUser().setText(username); |
|
||||||
mLoginActivity.getUser().requestFocus(username.length()); |
|
||||||
//监听内容改变 -> 控制按钮的点击状态
|
|
||||||
mLoginActivity.getUser().addTextChangedListener(mLoginActivity); |
|
||||||
mLoginActivity.getPassword().addTextChangedListener(mLoginActivity); |
|
||||||
mLoginActivity.getEtCaptcha().addTextChangedListener(mLoginActivity); |
|
||||||
|
|
||||||
mLoginActivity.getIvCaptcha().setOnClickListener(new View.OnClickListener() { |
|
||||||
@Override |
|
||||||
public void onClick(View v) { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2)); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
mLoginActivity.getLoginBtn().setOnClickListener(v -> { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2)); |
|
||||||
if (!code.toLowerCase().equals(mLoginActivity.getEtCaptcha().getText().toString().toLowerCase())){ |
|
||||||
DialogCreator.createTipDialog(mLoginActivity, "验证码错误!"); |
|
||||||
return; |
|
||||||
} |
|
||||||
if (!NetworkUtils.isNetWorkAvailable()) { |
|
||||||
ToastUtils.showError("无网络连接!"); |
|
||||||
return; |
|
||||||
} |
|
||||||
ProgressDialog dialog = DialogCreator.createProgressDialog(mLoginActivity, null, "正在登陆..."); |
|
||||||
mLoginActivity.getLoginBtn().setEnabled(false); |
|
||||||
final String loginName = mLoginActivity.getUser().getText().toString().trim(); |
|
||||||
String loginPwd = mLoginActivity.getPassword().getText().toString(); |
|
||||||
final Map<String, String> userLoginInfo = new HashMap<>(); |
|
||||||
userLoginInfo.put("loginName", loginName); |
|
||||||
userLoginInfo.put("loginPwd", CyptoUtils.encode(APPCONST.KEY, loginPwd)); |
|
||||||
//验证用户名和密码
|
|
||||||
UserService.login(userLoginInfo, new ResultCallback() { |
|
||||||
@Override |
|
||||||
public void onFinish(Object o, int code) { |
|
||||||
String result = (String) o; |
|
||||||
String[] info = result.split(":"); |
|
||||||
int resultCode = Integer.parseInt(info[0].trim()); |
|
||||||
String resultName = info[1].trim(); |
|
||||||
//最后输出结果
|
|
||||||
if (resultCode == 102) { |
|
||||||
UserService.writeConfig(userLoginInfo); |
|
||||||
UserService.writeUsername(loginName); |
|
||||||
mLoginActivity.finish(); |
|
||||||
ToastUtils.showSuccess(resultName); |
|
||||||
} else { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
|
||||||
dialog.dismiss(); |
|
||||||
ToastUtils.showWarring(resultName); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onError(Exception e) { |
|
||||||
ToastUtils.showError("登录失败\n" + e.getLocalizedMessage()); |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
|
||||||
dialog.dismiss(); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
}); |
|
||||||
|
|
||||||
mLoginActivity.getTvRegister().setOnClickListener(new View.OnClickListener() { |
|
||||||
@Override |
|
||||||
public void onClick(View v) { |
|
||||||
Intent intent = new Intent(mLoginActivity, RegisterActivity.class); |
|
||||||
mLoginActivity.startActivity(intent); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
public void createCaptcha() { |
|
||||||
code = CodeUtil.getInstance().createCode(); |
|
||||||
Bitmap codeBitmap = CodeUtil.getInstance().createBitmap(code); |
|
||||||
mLoginActivity.getIvCaptcha().setImageBitmap(codeBitmap); |
|
||||||
} |
|
||||||
} |
|
@ -1,134 +0,0 @@ |
|||||||
package xyz.fycz.myreader.ui.presenter; |
|
||||||
|
|
||||||
import android.content.DialogInterface; |
|
||||||
import android.content.Intent; |
|
||||||
|
|
||||||
import androidx.fragment.app.Fragment; |
|
||||||
import androidx.fragment.app.FragmentPagerAdapter; |
|
||||||
import xyz.fycz.myreader.application.MyApplication; |
|
||||||
import xyz.fycz.myreader.application.SysManager; |
|
||||||
import xyz.fycz.myreader.base.BasePresenter; |
|
||||||
import xyz.fycz.myreader.common.APPCONST; |
|
||||||
import xyz.fycz.myreader.creator.DialogCreator; |
|
||||||
import xyz.fycz.myreader.entity.Setting; |
|
||||||
import xyz.fycz.myreader.ui.activity.MainActivity; |
|
||||||
import xyz.fycz.myreader.ui.fragment.BookcaseFragment; |
|
||||||
import xyz.fycz.myreader.ui.activity.SearchBookActivity; |
|
||||||
import xyz.fycz.myreader.ui.activity.LoginActivity; |
|
||||||
import xyz.fycz.myreader.util.ToastUtils; |
|
||||||
|
|
||||||
import java.io.File; |
|
||||||
import java.util.ArrayList; |
|
||||||
|
|
||||||
import static androidx.fragment.app.FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT; |
|
||||||
import static xyz.fycz.myreader.application.MyApplication.checkVersionByServer; |
|
||||||
|
|
||||||
|
|
||||||
public class MainPresenter implements BasePresenter { |
|
||||||
|
|
||||||
private MainActivity mMainActivity; |
|
||||||
private ArrayList<Fragment> mFragments = new ArrayList<>(); |
|
||||||
|
|
||||||
private String[] tabTitle = {"书架"}; |
|
||||||
|
|
||||||
private BookcaseFragment mBookcaseFragment; |
|
||||||
|
|
||||||
public MainPresenter(MainActivity mainActivity) { |
|
||||||
mMainActivity = mainActivity; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void start() { |
|
||||||
try { |
|
||||||
Setting mSetting = SysManager.getSetting(); |
|
||||||
int settingVersion = mSetting.getSettingVersion(); |
|
||||||
if (settingVersion < APPCONST.SETTING_VERSION){ |
|
||||||
SysManager.resetSetting(); |
|
||||||
//DialogCreator.createTipDialog(mMainActivity, "因组件升级,阅读字体及背景颜色已恢复默认颜色!");
|
|
||||||
} |
|
||||||
}catch (Exception e){ |
|
||||||
SysManager.resetSetting(); |
|
||||||
//DialogCreator.createTipDialog(mMainActivity, "因组件升级,阅读字体及背景颜色已恢复默认颜色");
|
|
||||||
} |
|
||||||
init(); |
|
||||||
checkVersionByServer(mMainActivity, false, (BookcaseFragment) mFragments.get(0)); |
|
||||||
mMainActivity.getIvSearch().setOnClickListener(view -> { |
|
||||||
Intent intent = new Intent(mMainActivity, SearchBookActivity.class); |
|
||||||
mMainActivity.startActivity(intent); |
|
||||||
}); |
|
||||||
mMainActivity.getCivAvatar().setOnClickListener(v -> { |
|
||||||
final File file = MyApplication.getApplication().getFileStreamPath("userConfig.fy"); |
|
||||||
if (file.exists()) { |
|
||||||
DialogCreator.createCommonDialog(mMainActivity, "退出登录", "确定要退出登录吗?" |
|
||||||
, true, new DialogInterface.OnClickListener() { |
|
||||||
@Override |
|
||||||
public void onClick(DialogInterface dialog, int which) { |
|
||||||
if (file.delete()) { |
|
||||||
ToastUtils.showSuccess("退出成功"); |
|
||||||
Intent intent = new Intent(mMainActivity, LoginActivity.class); |
|
||||||
mMainActivity.startActivity(intent); |
|
||||||
} else { |
|
||||||
ToastUtils.showError("退出失败(Error:file.delete())"); |
|
||||||
} |
|
||||||
} |
|
||||||
}, (dialog, which) -> dialog.dismiss()); |
|
||||||
} else { |
|
||||||
Intent intent = new Intent(mMainActivity, LoginActivity.class); |
|
||||||
mMainActivity.startActivity(intent); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 初始化 |
|
||||||
*/ |
|
||||||
private void init() { |
|
||||||
mBookcaseFragment = new BookcaseFragment(); |
|
||||||
mFragments.add(mBookcaseFragment); |
|
||||||
mMainActivity.getVpContent().setAdapter(new FragmentPagerAdapter(mMainActivity.getSupportFragmentManager(), BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { |
|
||||||
@Override |
|
||||||
public Fragment getItem(int position) { |
|
||||||
return mFragments.get(position); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public int getCount() { |
|
||||||
return mFragments.size(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public CharSequence getPageTitle(int position) { |
|
||||||
return tabTitle[position]; |
|
||||||
} |
|
||||||
|
|
||||||
}); |
|
||||||
mMainActivity.getTlTabMenu().setupWithViewPager(mMainActivity.getVpContent()); |
|
||||||
mMainActivity.getVpContent().setCurrentItem(0); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 添加本地书籍 |
|
||||||
* @param path |
|
||||||
*/ |
|
||||||
public void addLocalBook(String path){ |
|
||||||
mBookcaseFragment.getmBookcasePresenter().addLocalBook(path); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 取消编辑状态 |
|
||||||
*/ |
|
||||||
public void cancelEdit(){ |
|
||||||
mBookcaseFragment.getmBookcasePresenter().cancelEdit(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 判断是否处于编辑状态 |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
public boolean ismEditState(){ |
|
||||||
if (mBookcaseFragment.getmBookcasePresenter() == null) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
return mBookcaseFragment.getmBookcasePresenter().ismEditState(); |
|
||||||
} |
|
||||||
} |
|
@ -1,244 +0,0 @@ |
|||||||
package xyz.fycz.myreader.ui.presenter; |
|
||||||
|
|
||||||
import android.annotation.SuppressLint; |
|
||||||
import android.app.ProgressDialog; |
|
||||||
import android.graphics.Bitmap; |
|
||||||
import android.os.Handler; |
|
||||||
import android.os.Message; |
|
||||||
import android.text.Editable; |
|
||||||
import android.text.TextWatcher; |
|
||||||
import android.text.method.LinkMovementMethod; |
|
||||||
import android.view.View; |
|
||||||
import xyz.fycz.myreader.backup.UserService; |
|
||||||
import xyz.fycz.myreader.base.BasePresenter; |
|
||||||
import xyz.fycz.myreader.callback.ResultCallback; |
|
||||||
import xyz.fycz.myreader.creator.DialogCreator; |
|
||||||
import xyz.fycz.myreader.ui.activity.RegisterActivity; |
|
||||||
import xyz.fycz.myreader.util.CodeUtil; |
|
||||||
import xyz.fycz.myreader.util.ToastUtils; |
|
||||||
import xyz.fycz.myreader.util.utils.StringUtils; |
|
||||||
|
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author fengyue |
|
||||||
* @date 2020/4/26 20:31 |
|
||||||
*/ |
|
||||||
|
|
||||||
public class RegisterPresenter implements BasePresenter { |
|
||||||
private RegisterActivity mRegisterActivity; |
|
||||||
private String code; |
|
||||||
private String username = ""; |
|
||||||
private String password = ""; |
|
||||||
private String rpPassword = ""; |
|
||||||
private String inputCode = ""; |
|
||||||
|
|
||||||
public RegisterPresenter(RegisterActivity mRegisterActivity) { |
|
||||||
this.mRegisterActivity = mRegisterActivity; |
|
||||||
} |
|
||||||
|
|
||||||
@SuppressLint("HandlerLeak") |
|
||||||
private Handler mHandler = new Handler() { |
|
||||||
@SuppressLint("HandlerLeak") |
|
||||||
@Override |
|
||||||
public void handleMessage(Message msg) { |
|
||||||
switch (msg.what) { |
|
||||||
case 1: |
|
||||||
createCaptcha(); |
|
||||||
break; |
|
||||||
case 2: |
|
||||||
showTip((String) msg.obj); |
|
||||||
break; |
|
||||||
case 3: |
|
||||||
mRegisterActivity.getTvRegisterTip().setVisibility(View.GONE); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
@Override |
|
||||||
public void start() { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
|
||||||
mRegisterActivity.getTvTitleText().setText("注册"); |
|
||||||
mRegisterActivity.getEtUsername().requestFocus(); |
|
||||||
mRegisterActivity.getLlTitleBack().setOnClickListener(v -> mRegisterActivity.finish()); |
|
||||||
|
|
||||||
mRegisterActivity.getEtUsername().addTextChangedListener(new TextWatcher() { |
|
||||||
@Override |
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void afterTextChanged(Editable s) { |
|
||||||
StringUtils.isNotChinese(s); |
|
||||||
username = s.toString(); |
|
||||||
if (username.length() < 6 || username.length() >14){ |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2, "用户名必须在6-14位之间")); |
|
||||||
} else if(!username.substring(0, 1).matches("^[A-Za-z]$")){ |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2, |
|
||||||
"用户名只能以字母开头")); |
|
||||||
}else if(!username.matches("^[A-Za-z0-9-_]+$")){ |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2, |
|
||||||
"用户名只能由数字、字母、下划线、减号组成")); |
|
||||||
}else { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(3)); |
|
||||||
} |
|
||||||
checkNotNone(); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
mRegisterActivity.getEtPassword().addTextChangedListener(new TextWatcher() { |
|
||||||
@Override |
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void afterTextChanged(Editable s) { |
|
||||||
password = s.toString(); |
|
||||||
if (password.length() < 8 || password.length() > 16){ |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2, "密码必须在8-16位之间")); |
|
||||||
} else if(password.matches("^\\d+$")){ |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2, "密码不能是纯数字")); |
|
||||||
} else { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(3)); |
|
||||||
} |
|
||||||
checkNotNone(); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
mRegisterActivity.getEtRpPassword().addTextChangedListener(new TextWatcher() { |
|
||||||
@Override |
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void afterTextChanged(Editable s) { |
|
||||||
rpPassword = s.toString(); |
|
||||||
if (!rpPassword.equals(password)){ |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2, "两次输入的密码不一致")); |
|
||||||
} else { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(3)); |
|
||||||
} |
|
||||||
checkNotNone(); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
mRegisterActivity.getEtCaptcha().addTextChangedListener(new TextWatcher() { |
|
||||||
@Override |
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void afterTextChanged(Editable s) { |
|
||||||
inputCode = s.toString().trim().toLowerCase(); |
|
||||||
if (!inputCode.equals(code.toLowerCase())){ |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2, "验证码错误")); |
|
||||||
} else { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(3)); |
|
||||||
} |
|
||||||
checkNotNone(); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
mRegisterActivity.getIvCaptcha().setOnClickListener(new View.OnClickListener() { |
|
||||||
@Override |
|
||||||
public void onClick(View v) { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
mRegisterActivity.getBtRegister().setOnClickListener(new View.OnClickListener() { |
|
||||||
@Override |
|
||||||
public void onClick(View v) { |
|
||||||
if (!username.matches("^[A-Za-z][A-Za-z0-9]{5,13}$")){ |
|
||||||
DialogCreator.createTipDialog(mRegisterActivity, "用户名格式错误", |
|
||||||
"用户名必须在6-14位之间\n用户名只能以字母开头\n用户名只能由数字、字母、下划线、减号组成"); |
|
||||||
}else if(password.matches("^\\d+$") || !password.matches("^.{8,16}$")){ |
|
||||||
DialogCreator.createTipDialog(mRegisterActivity, "密码格式错误", |
|
||||||
"密码必须在8-16位之间\n密码不能是纯数字"); |
|
||||||
}else if(!password.equals(rpPassword)){ |
|
||||||
DialogCreator.createTipDialog(mRegisterActivity, "重复密码错误", |
|
||||||
"两次输入的密码不一致"); |
|
||||||
}else if(!inputCode.trim().toLowerCase().equals(code.toLowerCase())){ |
|
||||||
DialogCreator.createTipDialog(mRegisterActivity, "验证码错误"); |
|
||||||
}else if(!mRegisterActivity.getCbAgreement().isChecked()){ |
|
||||||
DialogCreator.createTipDialog(mRegisterActivity, "请勾选同意《用户服务协议》"); |
|
||||||
}else { |
|
||||||
ProgressDialog dialog = DialogCreator.createProgressDialog(mRegisterActivity, null, "正在注册..."); |
|
||||||
Map<String, String> userRegisterInfo = new HashMap<>(); |
|
||||||
userRegisterInfo.put("username", username); |
|
||||||
userRegisterInfo.put("password", password); |
|
||||||
UserService.register(userRegisterInfo, new ResultCallback() { |
|
||||||
@Override |
|
||||||
public void onFinish(Object o, int code) { |
|
||||||
String[] info = ((String) o).split(":"); |
|
||||||
int result = Integer.parseInt(info[0].trim()); |
|
||||||
if (result == 101){ |
|
||||||
UserService.writeUsername(username); |
|
||||||
ToastUtils.showSuccess(info[1]); |
|
||||||
mRegisterActivity.finish(); |
|
||||||
}else { |
|
||||||
ToastUtils.showWarring(info[1]); |
|
||||||
} |
|
||||||
dialog.dismiss(); |
|
||||||
} |
|
||||||
@Override |
|
||||||
public void onError(Exception e) { |
|
||||||
ToastUtils.showError("注册失败:\n" + e.getLocalizedMessage()); |
|
||||||
dialog.dismiss(); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
mRegisterActivity.getTvAgreement().setMovementMethod(LinkMovementMethod.getInstance()); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void createCaptcha() { |
|
||||||
code = CodeUtil.getInstance().createCode(); |
|
||||||
Bitmap codeBitmap = CodeUtil.getInstance().createBitmap(code); |
|
||||||
mRegisterActivity.getIvCaptcha().setImageBitmap(codeBitmap); |
|
||||||
} |
|
||||||
|
|
||||||
public void showTip(String tip) { |
|
||||||
mRegisterActivity.getTvRegisterTip().setVisibility(View.VISIBLE); |
|
||||||
mRegisterActivity.getTvRegisterTip().setText(tip); |
|
||||||
} |
|
||||||
|
|
||||||
public void checkNotNone(){ |
|
||||||
if ("".equals(username) || "".equals(password) || "".equals(rpPassword) || "".equals(inputCode)){ |
|
||||||
mRegisterActivity.getBtRegister().setEnabled(false); |
|
||||||
}else { |
|
||||||
mRegisterActivity.getBtRegister().setEnabled(true); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,354 +0,0 @@ |
|||||||
package xyz.fycz.myreader.ui.presenter; |
|
||||||
|
|
||||||
import android.annotation.SuppressLint; |
|
||||||
import android.content.Context; |
|
||||||
import android.content.Intent; |
|
||||||
import android.os.Build; |
|
||||||
import android.os.Handler; |
|
||||||
import android.os.Message; |
|
||||||
import android.text.Editable; |
|
||||||
import android.text.TextWatcher; |
|
||||||
import android.view.KeyEvent; |
|
||||||
import android.view.View; |
|
||||||
import android.view.inputmethod.EditorInfo; |
|
||||||
import android.view.inputmethod.InputMethodManager; |
|
||||||
|
|
||||||
import xyz.fycz.myreader.application.MyApplication; |
|
||||||
import xyz.fycz.myreader.webapi.crawler.*; |
|
||||||
import xyz.fycz.myreader.entity.SearchBookBean; |
|
||||||
import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; |
|
||||||
import xyz.fycz.myreader.ui.activity.BookDetailedActivity; |
|
||||||
import xyz.fycz.myreader.R; |
|
||||||
import xyz.fycz.myreader.base.BasePresenter; |
|
||||||
import xyz.fycz.myreader.callback.ResultCallback; |
|
||||||
import xyz.fycz.myreader.common.APPCONST; |
|
||||||
import xyz.fycz.myreader.greendao.entity.Book; |
|
||||||
import xyz.fycz.myreader.greendao.entity.SearchHistory; |
|
||||||
import xyz.fycz.myreader.greendao.service.SearchHistoryService; |
|
||||||
import xyz.fycz.myreader.ui.activity.SearchBookActivity; |
|
||||||
import xyz.fycz.myreader.ui.adapter.SearchBookAdapter; |
|
||||||
import xyz.fycz.myreader.ui.adapter.SearchHistoryAdapter; |
|
||||||
import xyz.fycz.myreader.util.StringHelper; |
|
||||||
import xyz.fycz.myreader.webapi.CommonApi; |
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException; |
|
||||||
import java.net.URLEncoder; |
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.Arrays; |
|
||||||
import java.util.Collections; |
|
||||||
|
|
||||||
|
|
||||||
public class SearchBookPrensenter implements BasePresenter { |
|
||||||
|
|
||||||
private SearchBookActivity mSearchBookActivity; |
|
||||||
private SearchBookAdapter mSearchBookAdapter; |
|
||||||
private String searchKey;//搜索关键字
|
|
||||||
private ArrayList<SearchBookBean> mBooksBean = new ArrayList<>(); |
|
||||||
private ConcurrentMultiValueMap<SearchBookBean, Book> mBooks = new ConcurrentMultiValueMap<>(); |
|
||||||
private ArrayList<Book> mAdapterBooks = new ArrayList<>(); |
|
||||||
private ArrayList<SearchHistory> mSearchHistories = new ArrayList<>(); |
|
||||||
private ArrayList<String> mSuggestions = new ArrayList<>(); |
|
||||||
|
|
||||||
private SearchHistoryService mSearchHistoryService; |
|
||||||
|
|
||||||
private SearchHistoryAdapter mSearchHistoryAdapter; |
|
||||||
|
|
||||||
private int curThreadCount; |
|
||||||
|
|
||||||
private int allThreadCount; |
|
||||||
|
|
||||||
private int inputConfirm = 0;//搜索输入确认
|
|
||||||
private int confirmTime = 1000;//搜索输入确认时间(毫秒)
|
|
||||||
|
|
||||||
private static String[] suggestion = {"第一序列", "大道朝天", "伏天氏", "终极斗罗", "我师兄实在太稳健了", "烂柯棋缘", "诡秘之主"}; |
|
||||||
private static String[] suggestion2 = {"不朽凡人", "圣墟", "我是至尊", "龙王传说", "太古神王", "一念永恒", "雪鹰领主", "大主宰"}; |
|
||||||
|
|
||||||
@SuppressLint("HandlerLeak") |
|
||||||
private Handler mHandler = new Handler() { |
|
||||||
@Override |
|
||||||
public void handleMessage(Message msg) { |
|
||||||
switch (msg.what) { |
|
||||||
case 1: |
|
||||||
search(); |
|
||||||
break; |
|
||||||
case 2: |
|
||||||
if (curThreadCount == 0) { |
|
||||||
initSearchList(); |
|
||||||
mSearchBookActivity.getSrlSearchBookList().finishRefresh(); |
|
||||||
mSearchBookActivity.getPbLoading().setVisibility(View.GONE); |
|
||||||
}/*else { |
|
||||||
notifyDataSetChanged(); |
|
||||||
mSearchBookActivity.getSrlSearchBookList().finishRefresh(); |
|
||||||
}*/ |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
public SearchBookPrensenter(SearchBookActivity searchBookActivity) { |
|
||||||
mSearchBookActivity = searchBookActivity; |
|
||||||
mSearchHistoryService = SearchHistoryService.getInstance(); |
|
||||||
for (int i = 0; i < suggestion.length; i++) { |
|
||||||
mSuggestions.add(suggestion[i]); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void start() { |
|
||||||
mSearchBookActivity.getTvTitleText().setText("搜索"); |
|
||||||
mSearchBookActivity.getEtSearchKey().requestFocus();//get the focus
|
|
||||||
//enter事件
|
|
||||||
mSearchBookActivity.getEtSearchKey().setOnEditorActionListener((textView, i, keyEvent) -> { |
|
||||||
if (i == EditorInfo.IME_ACTION_UNSPECIFIED) { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
|
||||||
return (keyEvent.getKeyCode() == KeyEvent.KEYCODE_ENTER); |
|
||||||
} |
|
||||||
return false; |
|
||||||
}); |
|
||||||
//换一批点击事件
|
|
||||||
mSearchBookActivity.getRenewByImage().setOnClickListener(new RenewSuggestionBook()); |
|
||||||
//换一批点击事件
|
|
||||||
mSearchBookActivity.getRenewByText().setOnClickListener(new RenewSuggestionBook()); |
|
||||||
//返回
|
|
||||||
mSearchBookActivity.getLlTitleBack().setOnClickListener(view -> mSearchBookActivity.finish()); |
|
||||||
//搜索框改变事件
|
|
||||||
mSearchBookActivity.getEtSearchKey().addTextChangedListener(new TextWatcher() { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void afterTextChanged(final Editable editable) { |
|
||||||
searchKey = editable.toString(); |
|
||||||
if (StringHelper.isEmpty(searchKey)) { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
}); |
|
||||||
//进入书籍详情页
|
|
||||||
mSearchBookActivity.getGvSearchBooksList().setOnItemClickListener((adapterView, view, i, l) -> { |
|
||||||
Intent intent = new Intent(mSearchBookActivity, BookDetailedActivity.class); |
|
||||||
intent.putExtra(APPCONST.SEARCH_BOOK_BEAN, new ArrayList<>(mBooks.getValues(mBooksBean.get(i)))); |
|
||||||
mSearchBookActivity.startActivity(intent); |
|
||||||
}); |
|
||||||
//搜索按钮点击事件
|
|
||||||
mSearchBookActivity.getTvSearchConform().setOnClickListener(view -> mHandler.sendMessage(mHandler.obtainMessage(1))); |
|
||||||
//suggestion搜索事件
|
|
||||||
mSearchBookActivity.getTgSuggestBook().setOnTagClickListener(tag -> { |
|
||||||
mSearchBookActivity.getEtSearchKey().setText(tag); |
|
||||||
mSearchBookActivity.getEtSearchKey().setSelection(tag.length()); |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
|
||||||
}); |
|
||||||
//历史记录搜索事件
|
|
||||||
mSearchBookActivity.getLvHistoryList().setOnItemClickListener((parent, view, position, id) -> { |
|
||||||
mSearchBookActivity.getEtSearchKey().setText(mSearchHistories.get(position).getContent()); |
|
||||||
mSearchBookActivity.getEtSearchKey().setSelection(mSearchHistories.get(position).getContent().length()); |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
|
||||||
}); |
|
||||||
//清空历史记录
|
|
||||||
mSearchBookActivity.getLlClearHistory().setOnClickListener(v -> { |
|
||||||
mSearchHistoryService.clearHistory(); |
|
||||||
initHistoryList(); |
|
||||||
}); |
|
||||||
//清除单个历史记录
|
|
||||||
mSearchBookActivity.getLvHistoryList().setOnItemLongClickListener((parent, view, position, id) -> { |
|
||||||
if (mSearchHistories.get(position) != null) { |
|
||||||
mSearchHistoryService.deleteHistory(mSearchHistories.get(position)); |
|
||||||
initHistoryList(); |
|
||||||
} |
|
||||||
return true; |
|
||||||
}); |
|
||||||
//上拉刷新
|
|
||||||
mSearchBookActivity.getSrlSearchBookList().setOnRefreshListener(refreshLayout -> mHandler.sendMessage(mHandler.obtainMessage(1))); |
|
||||||
mSearchBookActivity.getSrlSearchBookList().setEnableRefresh(false); |
|
||||||
mSearchBookActivity.getGvSearchBooksList().setNumColumns(1); |
|
||||||
mSearchBookActivity.getGvSearchBooksList().setDragModel(-1); |
|
||||||
initSuggestionBook(); |
|
||||||
initHistoryList(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* 初始化建议书目 |
|
||||||
*/ |
|
||||||
private void initSuggestionBook() { |
|
||||||
mSearchBookActivity.getTgSuggestBook().setTags(suggestion); |
|
||||||
} |
|
||||||
|
|
||||||
private class RenewSuggestionBook implements View.OnClickListener { |
|
||||||
@Override |
|
||||||
public void onClick(View v) { |
|
||||||
String[] s = mSearchBookActivity.getTgSuggestBook().getTags(); |
|
||||||
if (Arrays.equals(s, suggestion)) { |
|
||||||
mSearchBookActivity.getTgSuggestBook().setTags(suggestion2); |
|
||||||
} else { |
|
||||||
mSearchBookActivity.getTgSuggestBook().setTags(suggestion); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 初始化历史列表 |
|
||||||
*/ |
|
||||||
private void initHistoryList() { |
|
||||||
mSearchHistories = mSearchHistoryService.findAllSearchHistory(); |
|
||||||
if (mSearchHistories == null || mSearchHistories.size() == 0) { |
|
||||||
mSearchBookActivity.getLlHistoryView().setVisibility(View.GONE); |
|
||||||
} else { |
|
||||||
mSearchHistoryAdapter = new SearchHistoryAdapter(mSearchBookActivity, R.layout.listview_search_history_item, mSearchHistories); |
|
||||||
mSearchBookActivity.getLvHistoryList().setAdapter(mSearchHistoryAdapter); |
|
||||||
mSearchBookActivity.getLlHistoryView().setVisibility(View.VISIBLE); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 初始化搜索列表 |
|
||||||
*/ |
|
||||||
private void initSearchList() { |
|
||||||
initmBooksBean(); |
|
||||||
mSearchBookAdapter = new SearchBookAdapter(mSearchBookActivity, |
|
||||||
R.layout.listview_search_book_item, mBooksBean, mBooks); |
|
||||||
mSearchBookActivity.getGvSearchBooksList().setAdapter(mSearchBookAdapter); |
|
||||||
mSearchBookActivity.getGvSearchBooksList().setVisibility(View.VISIBLE); |
|
||||||
mSearchBookActivity.getLlSuggestBooksView().setVisibility(View.GONE); |
|
||||||
mSearchBookActivity.getLlHistoryView().setVisibility(View.GONE); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 更新搜索列表 |
|
||||||
*/ |
|
||||||
private void notifyDataSetChanged() { |
|
||||||
if (curThreadCount == 0) { |
|
||||||
mSearchBookActivity.getPbLoading().setVisibility(View.GONE); |
|
||||||
} |
|
||||||
initmBooksBean(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 初始化mBooksBean |
|
||||||
*/ |
|
||||||
private void initmBooksBean() { |
|
||||||
synchronized (this) { |
|
||||||
mBooksBean.clear(); |
|
||||||
mBooksBean.addAll(mBooks.keySet()); |
|
||||||
//排序,基于最符合关键字的搜书结果应该是最短的
|
|
||||||
//TODO ;这里只做了简单的比较排序,还需要继续完善
|
|
||||||
Collections.sort(mBooksBean, (o1, o2) -> { |
|
||||||
if (searchKey.equals(o1.getName())) |
|
||||||
return -1; |
|
||||||
if (searchKey.equals(o2.getName())) |
|
||||||
return 1; |
|
||||||
if (searchKey.equals(o1.getAuthor())) |
|
||||||
return -1; |
|
||||||
if (searchKey.equals(o2.getAuthor())) |
|
||||||
return 1; |
|
||||||
if (o1.getName().length() < o2.getName().length()) |
|
||||||
return -1; |
|
||||||
if (o1.getName().length() == o2.getName().length()) |
|
||||||
return 0; |
|
||||||
return 1; |
|
||||||
}); |
|
||||||
/*MyApplication.runOnUiThread(new Runnable() { |
|
||||||
@Override |
|
||||||
public void run() { |
|
||||||
mSearchBookAdapter.notifyDataSetChanged(); |
|
||||||
} |
|
||||||
});*/ |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 获取搜索数据 |
|
||||||
*/ |
|
||||||
private void getData() { |
|
||||||
mBooksBean.clear(); |
|
||||||
mBooks.clear(); |
|
||||||
allThreadCount = 4; |
|
||||||
curThreadCount = allThreadCount; |
|
||||||
searchBookByCrawler(new BiQuGe44ReadCrawler(), ""); |
|
||||||
searchBookByCrawler(new TianLaiReadCrawler(), ""); |
|
||||||
searchBookByCrawler(new BiQuGeReadCrawler(), "gbk"); |
|
||||||
searchBookByCrawler(new PinShuReadCrawler(), "gbk"); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 搜索 |
|
||||||
*/ |
|
||||||
private void search() { |
|
||||||
mSearchBookActivity.getPbLoading().setVisibility(View.VISIBLE); |
|
||||||
if (StringHelper.isEmpty(searchKey)) { |
|
||||||
mSearchBookActivity.getPbLoading().setVisibility(View.GONE); |
|
||||||
mSearchBookActivity.getGvSearchBooksList().setVisibility(View.GONE); |
|
||||||
mSearchBookActivity.getLlSuggestBooksView().setVisibility(View.VISIBLE); |
|
||||||
initHistoryList(); |
|
||||||
mSearchBookActivity.getGvSearchBooksList().setAdapter(null); |
|
||||||
mSearchBookActivity.getSrlSearchBookList().setEnableRefresh(false); |
|
||||||
} else { |
|
||||||
mSearchBookActivity.getGvSearchBooksList().setVisibility(View.VISIBLE); |
|
||||||
mSearchBookActivity.getLlSuggestBooksView().setVisibility(View.GONE); |
|
||||||
mSearchBookActivity.getLlHistoryView().setVisibility(View.GONE); |
|
||||||
getData(); |
|
||||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |
|
||||||
if (mSearchBookActivity.getGvSearchBooksList().getmScrollView().getScrollY() == 0){ |
|
||||||
mSearchBookActivity.getSrlSearchBookList().setEnableRefresh(true); |
|
||||||
} |
|
||||||
//滑动监听器
|
|
||||||
mSearchBookActivity.getGvSearchBooksList().getmScrollView().setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> { |
|
||||||
mSearchBookActivity.getSrlSearchBookList().setEnableRefresh(scrollY == 0); |
|
||||||
}); |
|
||||||
} |
|
||||||
mSearchHistoryService.addOrUpadteHistory(searchKey); |
|
||||||
//收起软键盘
|
|
||||||
InputMethodManager imm = (InputMethodManager) MyApplication.getmContext().getSystemService(Context.INPUT_METHOD_SERVICE); |
|
||||||
assert imm != null; |
|
||||||
imm.hideSoftInputFromWindow(mSearchBookActivity.getEtSearchKey().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public boolean onBackPressed() { |
|
||||||
if (StringHelper.isEmpty(searchKey)) { |
|
||||||
return false; |
|
||||||
} else { |
|
||||||
mSearchBookActivity.getEtSearchKey().setText(""); |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void searchBookByCrawler(ReadCrawler rc, String charset) { |
|
||||||
String searchKey = this.searchKey; |
|
||||||
if (charset.toLowerCase().equals("gbk")) { |
|
||||||
try { |
|
||||||
searchKey = URLEncoder.encode(this.searchKey, charset); |
|
||||||
} catch (UnsupportedEncodingException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
} |
|
||||||
CommonApi.search(searchKey, rc, new ResultCallback() { |
|
||||||
@Override |
|
||||||
public void onFinish(Object o, int code) { |
|
||||||
ConcurrentMultiValueMap<SearchBookBean, Book> sbb = |
|
||||||
(ConcurrentMultiValueMap<SearchBookBean, Book>) o; |
|
||||||
mBooks.addAll(sbb); |
|
||||||
curThreadCount--; |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2)); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onError(Exception e) { |
|
||||||
curThreadCount--; |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2)); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
@ -0,0 +1,61 @@ |
|||||||
|
package xyz.fycz.myreader.util.utils; |
||||||
|
|
||||||
|
import android.annotation.TargetApi; |
||||||
|
import android.content.Context; |
||||||
|
import android.graphics.Bitmap; |
||||||
|
import android.os.Build; |
||||||
|
import android.renderscript.Allocation; |
||||||
|
import android.renderscript.Element; |
||||||
|
import android.renderscript.RenderScript; |
||||||
|
import android.renderscript.ScriptIntrinsicBlur; |
||||||
|
import androidx.annotation.NonNull; |
||||||
|
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; |
||||||
|
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; |
||||||
|
|
||||||
|
import java.security.MessageDigest; |
||||||
|
|
||||||
|
public class BlurTransformation extends BitmapTransformation { |
||||||
|
private RenderScript rs; |
||||||
|
private int radius; |
||||||
|
|
||||||
|
public BlurTransformation(Context context, int radius) { |
||||||
|
super(); |
||||||
|
rs = RenderScript.create(context); |
||||||
|
this.radius = radius; |
||||||
|
} |
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) |
||||||
|
@Override |
||||||
|
protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) { |
||||||
|
Bitmap blurredBitmap = toTransform.copy(Bitmap.Config.ARGB_8888, true); |
||||||
|
|
||||||
|
// Allocate memory for Renderscript to work with
|
||||||
|
//分配用于渲染脚本的内存
|
||||||
|
Allocation input = Allocation.createFromBitmap(rs, blurredBitmap, Allocation.MipmapControl.MIPMAP_FULL, Allocation.USAGE_SHARED); |
||||||
|
Allocation output = Allocation.createTyped(rs, input.getType()); |
||||||
|
|
||||||
|
// Load up an instance of the specific script that we want to use.
|
||||||
|
//加载我们想要使用的特定脚本的实例。
|
||||||
|
ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); |
||||||
|
script.setInput(input); |
||||||
|
|
||||||
|
// Set the blur radius
|
||||||
|
//设置模糊半径
|
||||||
|
script.setRadius(radius); |
||||||
|
|
||||||
|
// Start the ScriptIntrinsicBlur
|
||||||
|
//启动 ScriptIntrinsicBlur,
|
||||||
|
script.forEach(output); |
||||||
|
|
||||||
|
// Copy the output to the blurred bitmap
|
||||||
|
//将输出复制到模糊的位图
|
||||||
|
output.copyTo(blurredBitmap); |
||||||
|
|
||||||
|
return blurredBitmap; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) { |
||||||
|
messageDigest.update("blur transformation".getBytes()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,80 @@ |
|||||||
|
package xyz.fycz.myreader.util.utils; |
||||||
|
|
||||||
|
import android.graphics.Color; |
||||||
|
import androidx.annotation.ColorInt; |
||||||
|
import androidx.annotation.FloatRange; |
||||||
|
|
||||||
|
@SuppressWarnings({"unused", "WeakerAccess"}) |
||||||
|
public class ColorUtil { |
||||||
|
|
||||||
|
public static String intToString(int intColor) { |
||||||
|
return String.format("#%06X", 0xFFFFFF & intColor); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public static int stripAlpha(@ColorInt int color) { |
||||||
|
return 0xff000000 | color; |
||||||
|
} |
||||||
|
|
||||||
|
@ColorInt |
||||||
|
public static int shiftColor(@ColorInt int color, @FloatRange(from = 0.0f, to = 2.0f) float by) { |
||||||
|
if (by == 1f) return color; |
||||||
|
int alpha = Color.alpha(color); |
||||||
|
float[] hsv = new float[3]; |
||||||
|
Color.colorToHSV(color, hsv); |
||||||
|
hsv[2] *= by; // value component
|
||||||
|
return (alpha << 24) + (0x00ffffff & Color.HSVToColor(hsv)); |
||||||
|
} |
||||||
|
|
||||||
|
@ColorInt |
||||||
|
public static int darkenColor(@ColorInt int color) { |
||||||
|
return shiftColor(color, 0.9f); |
||||||
|
} |
||||||
|
|
||||||
|
@ColorInt |
||||||
|
public static int lightenColor(@ColorInt int color) { |
||||||
|
return shiftColor(color, 1.1f); |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean isColorLight(@ColorInt int color) { |
||||||
|
final double darkness = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255; |
||||||
|
return darkness < 0.4; |
||||||
|
} |
||||||
|
|
||||||
|
@ColorInt |
||||||
|
public static int invertColor(@ColorInt int color) { |
||||||
|
final int r = 255 - Color.red(color); |
||||||
|
final int g = 255 - Color.green(color); |
||||||
|
final int b = 255 - Color.blue(color); |
||||||
|
return Color.argb(Color.alpha(color), r, g, b); |
||||||
|
} |
||||||
|
|
||||||
|
@ColorInt |
||||||
|
public static int adjustAlpha(@ColorInt int color, @FloatRange(from = 0.0, to = 1.0) float factor) { |
||||||
|
int alpha = Math.round(Color.alpha(color) * factor); |
||||||
|
int red = Color.red(color); |
||||||
|
int green = Color.green(color); |
||||||
|
int blue = Color.blue(color); |
||||||
|
return Color.argb(alpha, red, green, blue); |
||||||
|
} |
||||||
|
|
||||||
|
@ColorInt |
||||||
|
public static int withAlpha(@ColorInt int baseColor, @FloatRange(from = 0.0, to = 1.0) float alpha) { |
||||||
|
int a = Math.min(255, Math.max(0, (int) (alpha * 255))) << 24; |
||||||
|
int rgb = 0x00ffffff & baseColor; |
||||||
|
return a + rgb; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Taken from CollapsingToolbarLayout's CollapsingTextHelper class. |
||||||
|
*/ |
||||||
|
public static int blendColors(int color1, int color2, @FloatRange(from = 0.0, to = 1.0) float ratio) { |
||||||
|
final float inverseRatio = 1f - ratio; |
||||||
|
float a = (Color.alpha(color1) * inverseRatio) + (Color.alpha(color2) * ratio); |
||||||
|
float r = (Color.red(color1) * inverseRatio) + (Color.red(color2) * ratio); |
||||||
|
float g = (Color.green(color1) * inverseRatio) + (Color.green(color2) * ratio); |
||||||
|
float b = (Color.blue(color1) * inverseRatio) + (Color.blue(color2) * ratio); |
||||||
|
return Color.argb((int) a, (int) r, (int) g, (int) b); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
package xyz.fycz.myreader.webapi.crawler; |
||||||
|
|
||||||
|
import xyz.fycz.myreader.entity.bookstore.BookType; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Book; |
||||||
|
|
||||||
|
import java.io.Serializable; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2020/9/14 18:36 |
||||||
|
*/ |
||||||
|
public abstract class FindCrawler implements Serializable { |
||||||
|
private static final long serialVersionUID = 1L; |
||||||
|
|
||||||
|
public abstract String getCharset(); |
||||||
|
public abstract String getFindName(); |
||||||
|
public abstract String getFindUrl(); |
||||||
|
public abstract boolean getTypePage(BookType curType, int page); |
||||||
|
public abstract boolean hasImg(); |
||||||
|
public abstract List<BookType> getBookTypeList(String html); |
||||||
|
public abstract List<Book> getRankBookList(String html); |
||||||
|
} |
@ -0,0 +1,287 @@ |
|||||||
|
package xyz.fycz.myreader.webapi.crawler; |
||||||
|
|
||||||
|
import android.text.Html; |
||||||
|
import org.jsoup.Jsoup; |
||||||
|
import org.jsoup.nodes.Document; |
||||||
|
import org.jsoup.nodes.Element; |
||||||
|
import org.jsoup.select.Elements; |
||||||
|
import xyz.fycz.myreader.entity.SearchBookBean; |
||||||
|
import xyz.fycz.myreader.entity.bookstore.BookType; |
||||||
|
import xyz.fycz.myreader.enums.BookSource; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Book; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Chapter; |
||||||
|
import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; |
||||||
|
import xyz.fycz.myreader.util.StringHelper; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
|
||||||
|
public class QB5ReadCrawler extends FindCrawler implements ReadCrawler, BookInfoCrawler { |
||||||
|
private static final String NAME_SPACE = "https://www.qb5.tw"; |
||||||
|
private static final String NOVEL_SEARCH = "https://www.qb5.tw/modules/article/search.php"; |
||||||
|
public static final String FIND_URL = "https://www.qb5.tw"; |
||||||
|
public static final String FIND_NAME = "书城[全本小说]"; |
||||||
|
private static final String SEARCH_KEY = "searchkey"; |
||||||
|
private static final String CHARSET = "GBK"; |
||||||
|
public static final String SEARCH_CHARSET = "GBK"; |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getSearchLink() { |
||||||
|
return NOVEL_SEARCH; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getNameSpace() { |
||||||
|
return NAME_SPACE; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getSearchKey() { |
||||||
|
return SEARCH_KEY; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getCharset() { |
||||||
|
return CHARSET; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getFindName() { |
||||||
|
return FIND_NAME; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getFindUrl() { |
||||||
|
return FIND_URL; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getSearchCharset() { |
||||||
|
return SEARCH_CHARSET; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean hasImg() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
/** |
||||||
|
* 获取书城小说分类列表 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public List<BookType> getBookTypeList(String html) { |
||||||
|
List<BookType> bookTypes = new ArrayList<>(); |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
Elements divs = doc.getElementsByClass("nav_cont"); |
||||||
|
if (divs.size() > 0) { |
||||||
|
Elements uls = divs.get(0).getElementsByTag("ul"); |
||||||
|
if (uls.size() > 0) { |
||||||
|
for (Element li : uls.get(0).children()) { |
||||||
|
Element a = li.child(0); |
||||||
|
BookType bookType = new BookType(); |
||||||
|
bookType.setTypeName(a.attr("title")); |
||||||
|
bookType.setUrl(a.attr("href")); |
||||||
|
if (bookType.getTypeName().contains("首页") || bookType.getTypeName().contains("热门小说")) continue; |
||||||
|
if (!StringHelper.isEmpty(bookType.getTypeName())) { |
||||||
|
bookTypes.add(bookType); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
return bookTypes; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取某一分类小说排行榜列表 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public List<Book> getBookRankList(String html) { |
||||||
|
List<Book> books = new ArrayList<>(); |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
Elements divs = doc.getElementsByClass("r"); |
||||||
|
if (divs.size() > 0) { |
||||||
|
Elements uls = divs.get(0).getElementsByTag("ul"); |
||||||
|
if (uls.size() > 0) { |
||||||
|
for (Element li : uls.get(0).children()) { |
||||||
|
Book book = new Book(); |
||||||
|
Element scanS1 = li.getElementsByClass("s1").get(0); |
||||||
|
Element scanS2 = li.getElementsByClass("s2").get(0); |
||||||
|
Element scanS5 = li.getElementsByClass("s5").get(0); |
||||||
|
book.setType(scanS1.html().replace("[", "").replace("]", "")); |
||||||
|
Element a = scanS2.getElementsByTag("a").get(0); |
||||||
|
book.setName(a.attr("title")); |
||||||
|
book.setChapterUrl(a.attr("href")); |
||||||
|
book.setAuthor(scanS5.html()); |
||||||
|
book.setSource(BookSource.biquge.toString()); |
||||||
|
books.add(book); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return books; |
||||||
|
} |
||||||
|
|
||||||
|
public List<Book> getRankBookList(String html) { |
||||||
|
List<Book> books = new ArrayList<>(); |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
String type = doc.select("meta[name=keywords]").attr("content").replace(",全本小说网", ""); |
||||||
|
Element div = doc.getElementById("tlist"); |
||||||
|
Elements uls = div.getElementsByTag("ul"); |
||||||
|
if (uls.size() > 0) { |
||||||
|
for (Element li : uls.get(0).children()) { |
||||||
|
Book book = new Book(); |
||||||
|
Element aName = li.getElementsByClass("name").get(0); |
||||||
|
Element divZz = li.getElementsByClass("zz").get(0); |
||||||
|
Element divAuthor = li.getElementsByClass("author").get(0); |
||||||
|
Element divSj = li.getElementsByClass("sj").get(0); |
||||||
|
book.setType(type); |
||||||
|
book.setName(aName.attr("title")); |
||||||
|
book.setChapterUrl(aName.attr("href")); |
||||||
|
book.setNewestChapterTitle(divZz.text()); |
||||||
|
book.setAuthor(divAuthor.text()); |
||||||
|
book.setUpdateDate(divSj.text()); |
||||||
|
book.setSource(BookSource.qb5.toString()); |
||||||
|
books.add(book); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return books; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getContentFormHtml(String html) { |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
Element divBook = doc.getElementsByClass("nav-style").get(0); |
||||||
|
String bookName = divBook.getElementsByTag("a").get(1).attr("title"); |
||||||
|
Element divContent = doc.getElementById("content"); |
||||||
|
if (divContent != null) { |
||||||
|
String content = Html.fromHtml(divContent.html()).toString(); |
||||||
|
char c = 160; |
||||||
|
String spaec = "" + c; |
||||||
|
content = content.replace(spaec, " "); |
||||||
|
content = content.replace("全本小说网 www.qb5.tw,最快更新", "") |
||||||
|
.replace(bookName, "") |
||||||
|
.replace("最新章节!", ""); |
||||||
|
return content; |
||||||
|
} else { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public ArrayList<Chapter> getChaptersFromHtml(String html) { |
||||||
|
ArrayList<Chapter> chapters = new ArrayList<>(); |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); |
||||||
|
int num = 0; |
||||||
|
Element zjbox = doc.getElementsByClass("zjbox").get(0); |
||||||
|
Elements as = zjbox.getElementsByTag("a"); |
||||||
|
for (int i = 12; i < as.size(); i++) { |
||||||
|
Element a = as.get(i); |
||||||
|
Chapter chapter = new Chapter(); |
||||||
|
chapter.setNumber(num++); |
||||||
|
chapter.setTitle(a.text()); |
||||||
|
chapter.setUrl(readUrl + a.attr("href")); |
||||||
|
chapters.add(chapter); |
||||||
|
} |
||||||
|
|
||||||
|
return chapters; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从搜索html中得到书列表 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public ConcurrentMultiValueMap<SearchBookBean, Book> getBooksFromSearchHtml(String html) { |
||||||
|
final ConcurrentMultiValueMap<SearchBookBean, Book> books = new ConcurrentMultiValueMap<>(); |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
String urlType = doc.select("meta[property=og:type]").attr("content"); |
||||||
|
if ("novel".equals(urlType)) { |
||||||
|
String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); |
||||||
|
Book book = new Book(); |
||||||
|
book.setChapterUrl(readUrl); |
||||||
|
getBookInfo(html, book); |
||||||
|
SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); |
||||||
|
books.add(sbb, book); |
||||||
|
} else { |
||||||
|
Elements divs = doc.getElementsByClass("grid"); |
||||||
|
Element div = divs.get(0); |
||||||
|
Elements elementsByTag = div.getElementsByTag("tr"); |
||||||
|
for (int i = 1; i < elementsByTag.size(); i++) { |
||||||
|
Element element = elementsByTag.get(i); |
||||||
|
Book book = new Book(); |
||||||
|
Elements info = element.getElementsByTag("td"); |
||||||
|
book.setName(info.get(0).text()); |
||||||
|
book.setChapterUrl(info.get(0).getElementsByTag("a").attr("href")); |
||||||
|
book.setNewestChapterTitle(info.get(1).text()); |
||||||
|
book.setAuthor(info.get(2).text()); |
||||||
|
book.setSource(BookSource.qb5.toString()); |
||||||
|
SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); |
||||||
|
books.add(sbb, book); |
||||||
|
} |
||||||
|
} |
||||||
|
return books; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取小说详细信息 |
||||||
|
* |
||||||
|
* @param html |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public Book getBookInfo(String html, Book book) { |
||||||
|
//小说源
|
||||||
|
book.setSource(BookSource.qb5.toString()); |
||||||
|
Document doc = Jsoup.parse(html); |
||||||
|
//书名
|
||||||
|
String name = doc.select("meta[property=og:title]").attr("content"); |
||||||
|
book.setName(name); |
||||||
|
//作者
|
||||||
|
String author = doc.select("meta[property=og:novel:author]").attr("content"); |
||||||
|
book.setAuthor(author); |
||||||
|
//最新章节
|
||||||
|
String newestChapter = doc.select("meta[property=og:novel:latest_chapter_name]").attr("content"); |
||||||
|
book.setNewestChapterTitle(newestChapter); |
||||||
|
//更新时间
|
||||||
|
String updateTime = doc.select("meta[property=og:novel:update_time]").attr("content"); |
||||||
|
book.setUpdateDate(updateTime); |
||||||
|
//图片url
|
||||||
|
Element divImg = doc.getElementsByClass("img_in").get(0); |
||||||
|
Element img = divImg.getElementsByTag("img").get(0); |
||||||
|
book.setImgUrl(img.attr("src")); |
||||||
|
//简介
|
||||||
|
Element divIntro = doc.getElementById("intro"); |
||||||
|
book.setDesc(divIntro.text()); |
||||||
|
//类型
|
||||||
|
String type = doc.select("meta[property=og:novel:category]").attr("content"); |
||||||
|
book.setType(type); |
||||||
|
return book; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public boolean getTypePage(BookType curType, int page){ |
||||||
|
if (page > 10){ |
||||||
|
return true; |
||||||
|
} |
||||||
|
if (!curType.getTypeName().equals("完本小说")) { |
||||||
|
curType.setUrl(curType.getUrl().substring(0, curType.getUrl().lastIndexOf("_") + 1) + page + "/"); |
||||||
|
}else { |
||||||
|
if (page > 1){ |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
@ -1,75 +0,0 @@ |
|||||||
package xyz.fycz.myreader.webapi.crawler; |
|
||||||
|
|
||||||
import org.jsoup.Jsoup; |
|
||||||
import org.jsoup.nodes.Document; |
|
||||||
import org.jsoup.nodes.Element; |
|
||||||
import org.jsoup.select.Elements; |
|
||||||
import xyz.fycz.myreader.entity.bookstore.BookType; |
|
||||||
import xyz.fycz.myreader.greendao.entity.Book; |
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author fengyue |
|
||||||
* @date 2020/5/27 11:17 |
|
||||||
*/ |
|
||||||
public class QiDianRankList { |
|
||||||
|
|
||||||
public static final String[] TYPE_NAME = { |
|
||||||
"月票榜", "畅销榜", "阅读榜", "推荐榜", "收藏榜" |
|
||||||
}; |
|
||||||
|
|
||||||
/** |
|
||||||
* 获取书城小说分类列表 |
|
||||||
* |
|
||||||
* @param html |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
public static List<BookType> getBookTypeList(String html) { |
|
||||||
List<BookType> bookTypes = new ArrayList<>(); |
|
||||||
Document doc = Jsoup.parse(html); |
|
||||||
Elements divs = doc.getElementsByClass("more"); |
|
||||||
for (int i = 0; i < 5; i++) { |
|
||||||
BookType bookType = new BookType(); |
|
||||||
bookType.setTypeName(TYPE_NAME[i]); |
|
||||||
bookType.setUrl("https:" + divs.get(i).attr("href")); |
|
||||||
bookTypes.add(bookType); |
|
||||||
} |
|
||||||
return bookTypes; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 获取某一分类小说排行榜列表 |
|
||||||
* |
|
||||||
* @param html |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
public static List<Book> getBookRankList(String html) { |
|
||||||
List<Book> books = new ArrayList<>(); |
|
||||||
Document doc = Jsoup.parse(html); |
|
||||||
Elements lis = doc.getElementsByTag("li"); |
|
||||||
if (lis.size() > 0) { |
|
||||||
Elements bookLis = lis.select("data-rid"); |
|
||||||
if (bookLis.size() > 0) { |
|
||||||
for (Element li : bookLis) { |
|
||||||
Book book = new Book(); |
|
||||||
String imgSrc = li.getElementsByClass("book-img-box").get(0) |
|
||||||
.getElementsByTag("img").attr("src"); |
|
||||||
book.setImgUrl("https:" + imgSrc); |
|
||||||
Element bookInfo = li.getElementsByClass("book-mid-info").get(0); |
|
||||||
Elements tagA = bookInfo.getElementsByTag("a"); |
|
||||||
book.setName(tagA.get(0).text()); |
|
||||||
book.setAuthor(tagA.get(1).text()); |
|
||||||
book.setType(tagA.get(2).text()); |
|
||||||
book.setNewestChapterTitle(tagA.get(3).text()); |
|
||||||
String desc = bookInfo.getElementsByClass("intro").get(0).text(); |
|
||||||
book.setDesc(desc); |
|
||||||
books.add(book); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return books; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,117 @@ |
|||||||
|
package xyz.fycz.myreader.webapi.crawler.find; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.graphics.Bitmap; |
||||||
|
import android.util.Log; |
||||||
|
import android.webkit.*; |
||||||
|
import okhttp3.*; |
||||||
|
import org.json.JSONArray; |
||||||
|
import org.json.JSONException; |
||||||
|
import org.json.JSONObject; |
||||||
|
import xyz.fycz.myreader.application.MyApplication; |
||||||
|
import xyz.fycz.myreader.callback.ResultCallback; |
||||||
|
import xyz.fycz.myreader.creator.DialogCreator; |
||||||
|
import xyz.fycz.myreader.entity.bookstore.BookType; |
||||||
|
import xyz.fycz.myreader.entity.bookstore.QDBook; |
||||||
|
import xyz.fycz.myreader.entity.bookstore.RankBook; |
||||||
|
import xyz.fycz.myreader.entity.bookstore.SortBook; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Book; |
||||||
|
import xyz.fycz.myreader.util.IOUtils; |
||||||
|
import xyz.fycz.myreader.util.SharedPreUtils; |
||||||
|
import xyz.fycz.myreader.util.StringHelper; |
||||||
|
import xyz.fycz.myreader.webapi.CommonApi; |
||||||
|
import xyz.fycz.myreader.webapi.crawler.FindCrawler; |
||||||
|
|
||||||
|
import java.io.BufferedReader; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStreamReader; |
||||||
|
import java.text.SimpleDateFormat; |
||||||
|
import java.util.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2020/9/16 22:01 |
||||||
|
*/ |
||||||
|
public class ABC extends FindCrawler { |
||||||
|
private String rankUrl = ""; |
||||||
|
private String sortUrl = ""; |
||||||
|
private String[] sex = {"male", "female"}; |
||||||
|
private String aParam = ""; |
||||||
|
private String imgUrl = ""; |
||||||
|
private String defaultCookie = ""; |
||||||
|
private String yearmonthFormat = ""; |
||||||
|
private LinkedHashMap<String, String> rankName = new LinkedHashMap<>(); |
||||||
|
private LinkedHashMap<String, Integer> sortName = new LinkedHashMap<>(); |
||||||
|
private boolean isFemale; |
||||||
|
private boolean isSort; |
||||||
|
|
||||||
|
public ABC(boolean isFemale) { |
||||||
|
this.isFemale = isFemale; |
||||||
|
} |
||||||
|
|
||||||
|
public ABC(boolean isFemale, boolean isSort) { |
||||||
|
this.isFemale = isFemale; |
||||||
|
this.isSort = isSort; |
||||||
|
} |
||||||
|
|
||||||
|
private void initMaleRankName() { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private void initSortNames() { |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public List<BookType> getRankTypes() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public void getRankBooks(BookType bookType, ResultCallback rc) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private List<QDBook> getBooksFromJson(String json) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getCharset() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getFindName() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getFindUrl() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean getTypePage(BookType curType, int page) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean hasImg() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<BookType> getBookTypeList(String html) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<Book> getRankBookList(String html) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void initCookie(Context mContext, ResultCallback rc) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<set xmlns:android="http://schemas.android.com/apk/res/android"> |
||||||
|
<alpha |
||||||
|
android:duration="1000" |
||||||
|
android:fromAlpha="0" |
||||||
|
android:interpolator="@android:anim/decelerate_interpolator" |
||||||
|
android:toAlpha="1.0"/> |
||||||
|
</set> |
@ -0,0 +1,8 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<set xmlns:android="http://schemas.android.com/apk/res/android"> |
||||||
|
<alpha |
||||||
|
android:duration="1500" |
||||||
|
android:fromAlpha="1.0" |
||||||
|
android:interpolator="@android:anim/decelerate_interpolator" |
||||||
|
android:toAlpha="0"/> |
||||||
|
</set> |
@ -0,0 +1,5 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android"> |
||||||
|
<item android:color="@color/colorAccent" android:state_checked="true" /> |
||||||
|
<item android:color="@color/textSecondary" android:state_checked="false"/> |
||||||
|
</selector> |
@ -1,6 +1,6 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> |
<selector xmlns:android="http://schemas.android.com/apk/res/android"> |
||||||
<item android:color="@color/gray" android:state_enabled="false" /> |
<item android:color="@color/textSecondary" android:state_enabled="false" /> |
||||||
<item android:color="@color/white" android:state_pressed="true" /> |
<item android:color="@color/textAssist" android:state_pressed="true" /> |
||||||
<item android:color="@color/colorAccent"/> |
<item android:color="@color/colorAccent"/> |
||||||
</selector> |
</selector> |
@ -1,9 +1,13 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> |
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> |
||||||
|
<item> |
||||||
|
<shape android:shape="oval"> |
||||||
|
<solid android:color="@color/textSecondary"/> |
||||||
|
</shape> |
||||||
|
</item> |
||||||
<item android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp"> |
<item android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp"> |
||||||
<shape android:shape="oval"> |
<shape android:shape="oval"> |
||||||
<solid android:color="@color/sys_common_bg"/> |
<solid android:color="@color/textPrimaryInverted"/> |
||||||
</shape> |
</shape> |
||||||
</item> |
</item> |
||||||
</layer-list> |
</layer-list> |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue