parent
64abf589b1
commit
39160c8ff0
@ -1,74 +0,0 @@ |
||||
package xyz.fycz.myreader.entity; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2022/2/17 18:56 |
||||
*/ |
||||
public class AdBean { |
||||
//是否云控
|
||||
private boolean isCloud; |
||||
//是否有广告
|
||||
private boolean hasAd; |
||||
//应用处于后台一段时间展示开屏广告(单位:分钟)
|
||||
private int backAdTime; |
||||
//应用回到前台展示广告间隔(单位:分钟)
|
||||
private int intervalAdTime; |
||||
//是否在详情页展示信息流广告
|
||||
private boolean showFlowAd; |
||||
|
||||
public AdBean() { |
||||
} |
||||
|
||||
public AdBean(boolean hasAd, int backAdTime, int intervalAdTime) { |
||||
this.hasAd = hasAd; |
||||
this.backAdTime = backAdTime; |
||||
this.intervalAdTime = intervalAdTime; |
||||
} |
||||
|
||||
public AdBean(boolean hasAd, int backAdTime, int intervalAdTime, boolean showFlowAd) { |
||||
this.hasAd = hasAd; |
||||
this.backAdTime = backAdTime; |
||||
this.intervalAdTime = intervalAdTime; |
||||
this.showFlowAd = showFlowAd; |
||||
} |
||||
|
||||
public boolean isCloud() { |
||||
return isCloud; |
||||
} |
||||
|
||||
public void setCloud(boolean cloud) { |
||||
isCloud = cloud; |
||||
} |
||||
|
||||
public boolean isHasAd() { |
||||
return hasAd; |
||||
} |
||||
|
||||
public void setHasAd(boolean hasAd) { |
||||
this.hasAd = hasAd; |
||||
} |
||||
|
||||
public int getBackAdTime() { |
||||
return backAdTime; |
||||
} |
||||
|
||||
public void setBackAdTime(int backAdTime) { |
||||
this.backAdTime = backAdTime; |
||||
} |
||||
|
||||
public int getIntervalAdTime() { |
||||
return intervalAdTime; |
||||
} |
||||
|
||||
public void setIntervalAdTime(int intervalAdTime) { |
||||
this.intervalAdTime = intervalAdTime; |
||||
} |
||||
|
||||
public boolean isShowFlowAd() { |
||||
return showFlowAd; |
||||
} |
||||
|
||||
public void setShowFlowAd(boolean showFlowAd) { |
||||
this.showFlowAd = showFlowAd; |
||||
} |
||||
} |
@ -0,0 +1,10 @@ |
||||
package xyz.fycz.myreader.entity.ad |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2022/3/3 15:00 |
||||
*/ |
||||
data class AdBean( |
||||
val status: Int,// 广告展示状态:0:不展示,1:展示信息流广告,2:展示插屏广告 |
||||
val interval: Int,// 广告展示间隔(单位:分钟) |
||||
) |
@ -0,0 +1,137 @@ |
||||
package xyz.fycz.myreader.entity.ad; |
||||
|
||||
import androidx.annotation.NonNull; |
||||
|
||||
import xyz.fycz.myreader.util.utils.GsonExtensionsKt; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2022/2/17 18:56 |
||||
*/ |
||||
public class AdConfig { |
||||
//是否云控
|
||||
private boolean isCloud; |
||||
//是否有广告
|
||||
private boolean hasAd; |
||||
//配置过期时间
|
||||
private int expireTime; |
||||
//应用处于后台一段时间展示开屏广告(单位:分钟)
|
||||
private int backAdTime; |
||||
//应用回到前台展示广告间隔(单位:分钟)
|
||||
private int intervalAdTime; |
||||
//单次激励视频可去广告时间(单位:小时),为0时表示关闭去广告
|
||||
private int removeAdTime; |
||||
//每日最大去除广告次数
|
||||
private int maxRemove; |
||||
//累计最高去除时间(单位:小时)
|
||||
private int totalRemove; |
||||
//详情页广告配置
|
||||
private AdBean detail; |
||||
//搜索页广告配置
|
||||
private AdBean search; |
||||
|
||||
public AdConfig() { |
||||
} |
||||
|
||||
public AdConfig(boolean hasAd, int expireTime, int backAdTime, int intervalAdTime, int removeAdTime, int maxRemove, int totalRemove) { |
||||
this.hasAd = hasAd; |
||||
this.expireTime = expireTime; |
||||
this.backAdTime = backAdTime; |
||||
this.intervalAdTime = intervalAdTime; |
||||
this.removeAdTime = removeAdTime; |
||||
this.maxRemove = maxRemove; |
||||
this.totalRemove = totalRemove; |
||||
} |
||||
|
||||
public boolean isCloud() { |
||||
return isCloud; |
||||
} |
||||
|
||||
public void setCloud(boolean cloud) { |
||||
isCloud = cloud; |
||||
} |
||||
|
||||
public boolean isHasAd() { |
||||
return hasAd; |
||||
} |
||||
|
||||
public void setHasAd(boolean hasAd) { |
||||
this.hasAd = hasAd; |
||||
} |
||||
|
||||
public int getBackAdTime() { |
||||
return backAdTime; |
||||
} |
||||
|
||||
public void setBackAdTime(int backAdTime) { |
||||
this.backAdTime = backAdTime; |
||||
} |
||||
|
||||
public int getIntervalAdTime() { |
||||
return intervalAdTime; |
||||
} |
||||
|
||||
public void setIntervalAdTime(int intervalAdTime) { |
||||
this.intervalAdTime = intervalAdTime; |
||||
} |
||||
|
||||
public int getExpireTime() { |
||||
return expireTime; |
||||
} |
||||
|
||||
public void setExpireTime(int expireTime) { |
||||
this.expireTime = expireTime; |
||||
} |
||||
|
||||
public int getRemoveAdTime() { |
||||
return removeAdTime; |
||||
} |
||||
|
||||
public void setRemoveAdTime(int removeAdTime) { |
||||
this.removeAdTime = removeAdTime; |
||||
} |
||||
|
||||
public int getMaxRemove() { |
||||
return maxRemove; |
||||
} |
||||
|
||||
public void setMaxRemove(int maxRemove) { |
||||
this.maxRemove = maxRemove; |
||||
} |
||||
|
||||
public int getTotalRemove() { |
||||
return totalRemove; |
||||
} |
||||
|
||||
public void setTotalRemove(int totalRemove) { |
||||
this.totalRemove = totalRemove; |
||||
} |
||||
|
||||
public AdBean getDetail() { |
||||
if (detail == null) { |
||||
detail = new AdBean(2, 60); |
||||
} |
||||
return detail; |
||||
} |
||||
|
||||
public void setDetail(AdBean detail) { |
||||
this.detail = detail; |
||||
} |
||||
|
||||
public AdBean getSearch() { |
||||
if (search == null) { |
||||
search = new AdBean(0, 60); |
||||
} |
||||
return search; |
||||
} |
||||
|
||||
public void setSearch(AdBean search) { |
||||
this.search = search; |
||||
} |
||||
|
||||
@NonNull |
||||
@Override |
||||
public String toString() { |
||||
return GsonExtensionsKt.getGSON().toJson(this); |
||||
} |
||||
} |
@ -0,0 +1,12 @@ |
||||
package xyz.fycz.myreader.entity.lanzou |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2022/3/3 8:53 |
||||
*/ |
||||
data class LanZouFile( |
||||
var id: String, |
||||
var name_all: String, |
||||
var size: String, |
||||
var time: String |
||||
) |
@ -1,10 +1,10 @@ |
||||
package xyz.fycz.myreader.entity |
||||
package xyz.fycz.myreader.entity.lanzou |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2022/1/22 20:15 |
||||
*/ |
||||
data class LanZouBean( |
||||
data class LanZouParseBean( |
||||
var zt: Int, |
||||
var dom: String, |
||||
var url: String, |
@ -0,0 +1,77 @@ |
||||
package xyz.fycz.myreader.greendao.entity; |
||||
|
||||
import org.greenrobot.greendao.annotation.Entity; |
||||
import org.greenrobot.greendao.annotation.Id; |
||||
import org.greenrobot.greendao.annotation.Generated; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2022/3/3 14:40 |
||||
*/ |
||||
@Entity |
||||
public class SubscribeFile { |
||||
@Id |
||||
private String id; |
||||
|
||||
private String name; |
||||
|
||||
private String url; |
||||
|
||||
private String date; |
||||
|
||||
private String size; |
||||
|
||||
@Generated(hash = 1850023033) |
||||
public SubscribeFile(String id, String name, String url, String date, |
||||
String size) { |
||||
this.id = id; |
||||
this.name = name; |
||||
this.url = url; |
||||
this.date = date; |
||||
this.size = size; |
||||
} |
||||
|
||||
@Generated(hash = 1590903919) |
||||
public SubscribeFile() { |
||||
} |
||||
|
||||
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 getUrl() { |
||||
return this.url; |
||||
} |
||||
|
||||
public void setUrl(String url) { |
||||
this.url = url; |
||||
} |
||||
|
||||
public String getDate() { |
||||
return this.date; |
||||
} |
||||
|
||||
public void setDate(String date) { |
||||
this.date = date; |
||||
} |
||||
|
||||
public String getSize() { |
||||
return this.size; |
||||
} |
||||
|
||||
public void setSize(String size) { |
||||
this.size = size; |
||||
} |
||||
} |
@ -0,0 +1,116 @@ |
||||
package xyz.fycz.myreader.ui.activity |
||||
|
||||
import android.os.Bundle |
||||
import androidx.appcompat.widget.Toolbar |
||||
import androidx.recyclerview.widget.LinearLayoutManager |
||||
import xyz.fycz.myreader.R |
||||
import xyz.fycz.myreader.base.BaseActivity |
||||
import xyz.fycz.myreader.base.adapter.BaseListAdapter |
||||
import xyz.fycz.myreader.base.adapter.IViewHolder |
||||
import xyz.fycz.myreader.common.URLCONST |
||||
import xyz.fycz.myreader.databinding.ActivitySourceSubscribeBinding |
||||
import xyz.fycz.myreader.entity.lanzou.LanZouFile |
||||
import xyz.fycz.myreader.greendao.entity.SubscribeFile |
||||
import xyz.fycz.myreader.ui.adapter.holder.SourceFileHolder |
||||
import xyz.fycz.myreader.util.ToastUtils |
||||
import xyz.fycz.myreader.webapi.LanZouApi |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2022/3/3 9:56 |
||||
*/ |
||||
class SourceSubscribeActivity : BaseActivity() { |
||||
private lateinit var binding: ActivitySourceSubscribeBinding |
||||
private lateinit var fileAdapter: BaseListAdapter<SubscribeFile> |
||||
private var page = 1 |
||||
|
||||
override fun bindView() { |
||||
binding = ActivitySourceSubscribeBinding.inflate(layoutInflater) |
||||
setContentView(binding.root) |
||||
} |
||||
|
||||
override fun setUpToolbar(toolbar: Toolbar?) { |
||||
super.setUpToolbar(toolbar) |
||||
setStatusBarColor(R.color.colorPrimary, true) |
||||
supportActionBar?.title = "书源订阅" |
||||
} |
||||
|
||||
override fun initData(savedInstanceState: Bundle?) { |
||||
super.initData(savedInstanceState) |
||||
fileAdapter = object : BaseListAdapter<SubscribeFile>() { |
||||
override fun createViewHolder(viewType: Int): IViewHolder<SubscribeFile> { |
||||
return SourceFileHolder() |
||||
} |
||||
} |
||||
binding.rvFiles.layoutManager = LinearLayoutManager(this) |
||||
binding.rvFiles.adapter = fileAdapter |
||||
loadFiles() |
||||
} |
||||
|
||||
override fun initWidget() { |
||||
super.initWidget() |
||||
binding.srlFiles.setOnLoadMoreListener { loadFiles() } |
||||
binding.srlFiles.setOnRefreshListener { |
||||
page = 1 |
||||
loadFiles() |
||||
} |
||||
binding.loading.setOnReloadingListener { |
||||
page = 1 |
||||
loadFiles() |
||||
} |
||||
} |
||||
|
||||
private fun loadFiles() { |
||||
LanZouApi.getFoldFiles(URLCONST.SUB_SOURCE_URL, page, "fm9a") |
||||
.onSuccess { |
||||
if (it != null) { |
||||
if (page == 1) { |
||||
if (it.isEmpty()) { |
||||
binding.loading.showEmpty() |
||||
} else { |
||||
binding.loading.showFinish() |
||||
fileAdapter.refreshItems(lanZouFile2SubscribeFile(it)) |
||||
if (it.size < 50) { |
||||
binding.srlFiles.finishRefreshWithNoMoreData() |
||||
} else { |
||||
binding.srlFiles.finishRefresh() |
||||
} |
||||
} |
||||
} else { |
||||
fileAdapter.addItems(lanZouFile2SubscribeFile(it)) |
||||
if (it.size < 50) { |
||||
binding.srlFiles.finishLoadMoreWithNoMoreData() |
||||
} else { |
||||
binding.srlFiles.finishLoadMore() |
||||
} |
||||
} |
||||
page++ |
||||
} else { |
||||
binding.loading.showError() |
||||
} |
||||
}.onError { |
||||
ToastUtils.showError("" + it.localizedMessage) |
||||
} |
||||
} |
||||
|
||||
override fun initClick() { |
||||
super.initClick() |
||||
} |
||||
|
||||
private fun lanZouFile2SubscribeFile(lanZouFile: List<LanZouFile>): ArrayList<SubscribeFile> { |
||||
val files = ArrayList<SubscribeFile>() |
||||
lanZouFile.forEach { |
||||
val param = it.name_all.removeSuffix(".txt").split("#") |
||||
files.add( |
||||
SubscribeFile( |
||||
param[0], |
||||
param[1], |
||||
URLCONST.LAN_ZOU_URL + "/${it.id}", |
||||
param[2], |
||||
it.size |
||||
) |
||||
) |
||||
} |
||||
return files |
||||
} |
||||
} |
@ -0,0 +1,58 @@ |
||||
package xyz.fycz.myreader.ui.adapter |
||||
|
||||
import android.widget.Filter |
||||
import xyz.fycz.myreader.base.adapter.IViewHolder |
||||
import xyz.fycz.myreader.greendao.entity.rule.BookSource |
||||
import xyz.fycz.myreader.ui.adapter.holder.SubscribeSourceHolder |
||||
import java.util.* |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2022/3/3 12:08 |
||||
*/ |
||||
class SubscribeSourceAdapter( |
||||
val sources: List<BookSource>, |
||||
private val onDelListener: OnDelListener |
||||
) : BaseSourceAdapter() { |
||||
override fun createViewHolder(viewType: Int): IViewHolder<BookSource> { |
||||
return SubscribeSourceHolder(checkMap, onDelListener) |
||||
} |
||||
|
||||
override fun getFilter(): Filter { |
||||
return object : Filter() { |
||||
override fun performFiltering(constraint: CharSequence): FilterResults { |
||||
val charString = constraint.toString() |
||||
var mFilterList: MutableList<BookSource> = ArrayList() |
||||
if (charString.isEmpty()) { |
||||
//没有过滤的内容,则使用源数据 |
||||
mFilterList = sources.toMutableList() |
||||
} else { |
||||
for (source in sources) { |
||||
//这里根据需求,添加匹配规则 |
||||
if (source.sourceName.contains(charString) || |
||||
source.sourceGroup.contains(charString) |
||||
) { |
||||
mFilterList.add(source) |
||||
} |
||||
} |
||||
} |
||||
val filterResults = FilterResults() |
||||
filterResults.values = mFilterList |
||||
return filterResults |
||||
} |
||||
|
||||
//把过滤后的值返回出来 |
||||
override fun publishResults(constraint: CharSequence, results: FilterResults) { |
||||
refreshItems(results.values as List<BookSource>) |
||||
} |
||||
} |
||||
} |
||||
fun removeItem(pos: Int) { |
||||
mList.removeAt(pos) |
||||
notifyItemRemoved(pos) |
||||
if (pos != mList.size) notifyItemRangeChanged(pos, mList.size - pos) |
||||
} |
||||
interface OnDelListener { |
||||
fun onDel(which: Int, source: BookSource) |
||||
} |
||||
} |
@ -0,0 +1,36 @@ |
||||
package xyz.fycz.myreader.ui.adapter.holder |
||||
|
||||
import android.annotation.SuppressLint |
||||
import android.widget.TextView |
||||
import androidx.recyclerview.widget.RecyclerView |
||||
import xyz.fycz.myreader.R |
||||
import xyz.fycz.myreader.base.adapter.ViewHolderImpl |
||||
import xyz.fycz.myreader.entity.lanzou.LanZouFile |
||||
import xyz.fycz.myreader.greendao.entity.SubscribeFile |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2022/3/3 10:17 |
||||
*/ |
||||
class SourceFileHolder : ViewHolderImpl<SubscribeFile>() { |
||||
|
||||
private lateinit var name: TextView |
||||
private lateinit var sizeTime: TextView |
||||
|
||||
override fun getItemLayoutId(): Int { |
||||
return R.layout.item_lan_zou_file |
||||
} |
||||
|
||||
override fun initView() { |
||||
name = findById(R.id.tv_file_name) |
||||
sizeTime = findById(R.id.tv_file_size_time) |
||||
} |
||||
|
||||
@SuppressLint("SetTextI18n") |
||||
override fun onBind(holder: RecyclerView.ViewHolder?, data: SubscribeFile?, pos: Int) { |
||||
data?.let { |
||||
name.text = data.name |
||||
sizeTime.text = "${data.size} ${data.date}" |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,96 @@ |
||||
package xyz.fycz.myreader.ui.adapter.holder |
||||
|
||||
import android.widget.CheckBox |
||||
import android.widget.TextView |
||||
import androidx.recyclerview.widget.RecyclerView |
||||
import io.reactivex.Observable |
||||
import io.reactivex.ObservableEmitter |
||||
import io.reactivex.ObservableOnSubscribe |
||||
import io.reactivex.android.schedulers.AndroidSchedulers |
||||
import io.reactivex.schedulers.Schedulers |
||||
import xyz.fycz.myreader.R |
||||
import xyz.fycz.myreader.base.adapter.ViewHolderImpl |
||||
import xyz.fycz.myreader.base.adapter2.onClick |
||||
import xyz.fycz.myreader.base.observer.MyObserver |
||||
import xyz.fycz.myreader.greendao.DbManager |
||||
import xyz.fycz.myreader.greendao.entity.rule.BookSource |
||||
import xyz.fycz.myreader.model.sourceAnalyzer.BookSourceManager |
||||
import xyz.fycz.myreader.ui.adapter.SubscribeSourceAdapter |
||||
import xyz.fycz.myreader.util.ToastUtils |
||||
import xyz.fycz.myreader.util.help.StringHelper |
||||
import xyz.fycz.myreader.util.utils.RxUtils |
||||
import java.util.* |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2022/3/3 12:11 |
||||
*/ |
||||
class SubscribeSourceHolder( |
||||
private val mCheckMap: HashMap<BookSource, Boolean>, |
||||
private val onDelListener: SubscribeSourceAdapter.OnDelListener |
||||
) : ViewHolderImpl<BookSource>() { |
||||
|
||||
private var cbSource: CheckBox? = null |
||||
private var tvEnable: TextView? = null |
||||
private var tvDisable: TextView? = null |
||||
private var tvDelete: TextView? = null |
||||
|
||||
override fun getItemLayoutId(): Int { |
||||
return R.layout.item_subscribe_source |
||||
} |
||||
|
||||
override fun initView() { |
||||
cbSource = findById(R.id.cb_source) |
||||
tvEnable = findById(R.id.tv_enable) |
||||
tvDisable = findById(R.id.tv_disable) |
||||
tvDelete = findById(R.id.tv_delete) |
||||
} |
||||
|
||||
override fun onBind(holder: RecyclerView.ViewHolder, data: BookSource, pos: Int) { |
||||
banOrUse(data) |
||||
cbSource?.isChecked = mCheckMap[data] == true |
||||
tvEnable?.onClick { |
||||
data.enable = true |
||||
banOrUse(data) |
||||
DbManager.getDaoSession().bookSourceDao.insertOrReplace(data) |
||||
} |
||||
tvDisable?.onClick { |
||||
data.enable = false |
||||
banOrUse(data) |
||||
DbManager.getDaoSession().bookSourceDao.insertOrReplace(data) |
||||
} |
||||
tvDelete?.onClick { |
||||
Observable.create { e: ObservableEmitter<Boolean?> -> |
||||
BookSourceManager.removeBookSource(data) |
||||
e.onNext(true) |
||||
}.compose { RxUtils.toSimpleSingle(it) } |
||||
.subscribe(object : MyObserver<Boolean?>() { |
||||
override fun onNext(aBoolean: Boolean) { |
||||
onDelListener.onDel(pos, data) |
||||
} |
||||
|
||||
override fun onError(e: Throwable) { |
||||
ToastUtils.showError("删除失败") |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
|
||||
private fun banOrUse(data: BookSource) { |
||||
if (data.enable) { |
||||
cbSource?.setTextColor(context.resources.getColor(R.color.textPrimary)) |
||||
if (!StringHelper.isEmpty(data.sourceGroup)) { |
||||
cbSource?.text = String.format("%s [%s]", data.sourceName, data.sourceGroup) |
||||
} else { |
||||
cbSource?.text = data.sourceName |
||||
} |
||||
} else { |
||||
cbSource?.setTextColor(context.resources.getColor(R.color.textSecondary)) |
||||
if (!StringHelper.isEmpty(data.sourceGroup)) { |
||||
cbSource?.text = String.format("(禁用中)%s [%s]", data.sourceName, data.sourceGroup) |
||||
} else { |
||||
cbSource?.text = String.format("(禁用中)%s", data.sourceName) |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,202 @@ |
||||
package xyz.fycz.myreader.ui.fragment |
||||
|
||||
import android.content.DialogInterface |
||||
import android.content.Intent |
||||
import android.os.Bundle |
||||
import android.view.* |
||||
import android.widget.PopupMenu |
||||
import androidx.recyclerview.widget.LinearLayoutManager |
||||
import io.reactivex.Single |
||||
import io.reactivex.SingleEmitter |
||||
import xyz.fycz.myreader.R |
||||
import xyz.fycz.myreader.base.BaseFragment |
||||
import xyz.fycz.myreader.base.adapter2.onClick |
||||
import xyz.fycz.myreader.base.observer.MySingleObserver |
||||
import xyz.fycz.myreader.databinding.FragmentSubscribeSourceBinding |
||||
import xyz.fycz.myreader.greendao.DbManager |
||||
import xyz.fycz.myreader.greendao.entity.rule.BookSource |
||||
import xyz.fycz.myreader.model.sourceAnalyzer.BookSourceManager |
||||
import xyz.fycz.myreader.ui.activity.BookSourceActivity |
||||
import xyz.fycz.myreader.ui.activity.SourceSubscribeActivity |
||||
import xyz.fycz.myreader.ui.adapter.SubscribeSourceAdapter |
||||
import xyz.fycz.myreader.ui.dialog.DialogCreator |
||||
import xyz.fycz.myreader.util.ToastUtils |
||||
import xyz.fycz.myreader.util.utils.RxUtils |
||||
import xyz.fycz.myreader.widget.DividerItemDecoration |
||||
import java.util.ArrayList |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2022/3/3 11:36 |
||||
*/ |
||||
class SubscribeSourceFragment(private val sourceActivity: BookSourceActivity) : BaseFragment() { |
||||
private lateinit var binding: FragmentSubscribeSourceBinding |
||||
private var mBookSources: MutableList<BookSource>? = null |
||||
private var mAdapter: SubscribeSourceAdapter? = null |
||||
private var featuresMenu: PopupMenu? = null |
||||
override fun bindView(inflater: LayoutInflater, container: ViewGroup): View { |
||||
binding = FragmentSubscribeSourceBinding.inflate(inflater, container, false) |
||||
return binding.root |
||||
} |
||||
|
||||
override fun initData(savedInstanceState: Bundle?) { |
||||
super.initData(savedInstanceState) |
||||
Single.create { emitter: SingleEmitter<List<BookSource>> -> |
||||
emitter.onSuccess(BookSourceManager.getAllLocalSource()) |
||||
}.compose { RxUtils.toSimpleSingle(it) } |
||||
.subscribe(object : MySingleObserver<List<BookSource>>() { |
||||
override fun onSuccess(sources: List<BookSource>) { |
||||
mBookSources = sources.toMutableList() |
||||
initSourceList() |
||||
} |
||||
|
||||
override fun onError(e: Throwable) { |
||||
ToastUtils.showError(" 数据加载失败\n${e.localizedMessage}") |
||||
} |
||||
}) |
||||
} |
||||
|
||||
private fun initSourceList() { |
||||
mAdapter = |
||||
SubscribeSourceAdapter(mBookSources!!, object : SubscribeSourceAdapter.OnDelListener { |
||||
override fun onDel(which: Int, source: BookSource) { |
||||
mBookSources?.remove(source) |
||||
mAdapter?.removeItem(which) |
||||
} |
||||
}) |
||||
mAdapter?.setOnItemClickListener { _, pos -> |
||||
mAdapter?.setCheckedItem(pos) |
||||
} |
||||
binding.recyclerView.layoutManager = LinearLayoutManager(context) |
||||
binding.recyclerView.adapter = mAdapter |
||||
//设置分割线 |
||||
binding.recyclerView.addItemDecoration(DividerItemDecoration(context)) |
||||
mAdapter?.refreshItems(mBookSources) |
||||
} |
||||
|
||||
override fun initWidget(savedInstanceState: Bundle?) { |
||||
super.initWidget(savedInstanceState) |
||||
} |
||||
|
||||
override fun initClick() { |
||||
super.initClick() |
||||
binding.tvSubscribeSource.onClick { |
||||
startActivity(Intent(context, SourceSubscribeActivity::class.java)) |
||||
} |
||||
binding.ivGroup.setOnClickListener { view: View? -> |
||||
showSourceGroupMenu(view) |
||||
} |
||||
binding.ivMenu.setOnClickListener { v -> |
||||
if (featuresMenu == null) { |
||||
initFeaturesMenu(v) |
||||
} |
||||
featuresMenu?.show() |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 显示书源分组菜单 |
||||
*/ |
||||
private fun showSourceGroupMenu(view: View?) { |
||||
val popupMenu = PopupMenu(sourceActivity, view, Gravity.END) |
||||
val groupList = BookSourceManager.getGroupList(true) |
||||
popupMenu.menu.add(0, 0, 0, "所有书源") |
||||
for (i in groupList.indices) { |
||||
popupMenu.menu.add(0, 0, i + 1, groupList[i]) |
||||
} |
||||
popupMenu.setOnMenuItemClickListener { menuItem: MenuItem -> |
||||
if (menuItem.order > 0) { |
||||
sourceActivity.searchView.onActionViewExpanded() |
||||
sourceActivity.searchView.clearFocus() |
||||
sourceActivity.searchView.setQuery(menuItem.title, false) |
||||
} else { |
||||
sourceActivity.searchView.onActionViewCollapsed() |
||||
} |
||||
true |
||||
} |
||||
popupMenu.show() |
||||
} |
||||
|
||||
private fun initFeaturesMenu(view: View) { |
||||
featuresMenu = PopupMenu(sourceActivity, view, Gravity.END) |
||||
//获取菜单填充器 |
||||
val inflater = featuresMenu?.menuInflater |
||||
//填充菜单 |
||||
inflater?.inflate(R.menu.menu_subscribe_source, featuresMenu?.menu) |
||||
featuresMenu?.setOnMenuItemClickListener { item: MenuItem -> |
||||
when (item.itemId) { |
||||
R.id.action_select_all -> { |
||||
mAdapter?.setCheckedAll(true) |
||||
} |
||||
R.id.action_reverse_selected -> { |
||||
mAdapter?.reverseChecked() |
||||
} |
||||
R.id.action_reverse_enable_selected -> { |
||||
val bookSources = |
||||
mAdapter?.checkedBookSources |
||||
reverseSources(bookSources) |
||||
} |
||||
R.id.action_delete_selected -> { |
||||
val bookSources = |
||||
mAdapter?.checkedBookSources |
||||
deleteSources(bookSources, false) |
||||
} |
||||
} |
||||
true |
||||
} |
||||
} |
||||
|
||||
private fun reverseSources(mBookSources: MutableList<BookSource>?) { |
||||
if (mBookSources != null) { |
||||
for (source in mBookSources) { |
||||
source.enable = !source.enable |
||||
} |
||||
DbManager.getDaoSession().bookSourceDao.insertOrReplaceInTx(mBookSources) |
||||
mAdapter?.notifyDataSetChanged() |
||||
} |
||||
} |
||||
|
||||
private fun deleteSources(mBookSources: MutableList<BookSource>?, isDisabled: Boolean) { |
||||
if (mBookSources == null || mBookSources.size == 0) { |
||||
ToastUtils.showWarring("当前没有选择任何书源,无法删除!") |
||||
return |
||||
} |
||||
val title: String |
||||
val msg: String |
||||
val successTip: String |
||||
if (isDisabled) { |
||||
title = "删除禁用书源" |
||||
msg = "确定要删除所有禁用书源吗?" |
||||
successTip = "禁用书源删除成功" |
||||
} else { |
||||
title = "删除选中书源" |
||||
msg = "确定要删除所有选中书源吗?" |
||||
successTip = "选中书源删除成功" |
||||
} |
||||
DialogCreator.createCommonDialog( |
||||
sourceActivity, title, |
||||
msg, true, |
||||
{ _: DialogInterface?, _: Int -> |
||||
val sources: MutableList<BookSource> = |
||||
ArrayList() |
||||
if (isDisabled) { |
||||
for (source in mBookSources) { |
||||
if (!source.enable) { |
||||
sources.add(source) |
||||
} |
||||
} |
||||
} else { |
||||
sources.addAll(mBookSources) |
||||
} |
||||
BookSourceManager.removeBookSources(sources) |
||||
mBookSources.removeAll(sources) |
||||
mAdapter?.removeItems(sources) |
||||
ToastUtils.showSuccess(successTip) |
||||
}, null |
||||
) |
||||
} |
||||
|
||||
fun startSearch(newText: String?) { |
||||
mAdapter?.filter?.filter(newText) |
||||
} |
||||
} |
@ -0,0 +1,41 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent" |
||||
android:orientation="vertical"> |
||||
|
||||
<include layout="@layout/toolbar" /> |
||||
|
||||
<xyz.fycz.myreader.widget.RefreshLayout |
||||
android:id="@+id/loading" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent" |
||||
android:orientation="vertical"> |
||||
|
||||
<com.scwang.smartrefresh.layout.SmartRefreshLayout |
||||
android:id="@+id/srl_files" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent" |
||||
android:descendantFocusability="blocksDescendants"> |
||||
|
||||
<com.scwang.smartrefresh.header.MaterialHeader |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" /> |
||||
|
||||
<androidx.recyclerview.widget.RecyclerView |
||||
android:id="@+id/rv_files" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent" /> |
||||
|
||||
<com.scwang.smartrefresh.layout.footer.ClassicsFooter |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
app:srlAccentColor="@color/textSecondary" |
||||
app:srlTextFailed="@string/loading_tip" |
||||
app:srlTextLoading="@string/loading_tip" |
||||
app:srlTextNothing="总得有个结尾吧" /> |
||||
</com.scwang.smartrefresh.layout.SmartRefreshLayout> |
||||
|
||||
</xyz.fycz.myreader.widget.RefreshLayout> |
||||
</LinearLayout> |
@ -0,0 +1,86 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent" |
||||
android:background="@color/colorForeground" |
||||
android:orientation="vertical"> |
||||
|
||||
<RelativeLayout |
||||
android:layout_width="match_parent" |
||||
android:layout_height="35dp" |
||||
android:orientation="horizontal"> |
||||
|
||||
<LinearLayout |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent" |
||||
android:layout_alignParentStart="true" |
||||
android:orientation="horizontal"> |
||||
|
||||
<TextView |
||||
android:id="@+id/tv_subscribe_source" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="match_parent" |
||||
android:background="?android:attr/selectableItemBackground" |
||||
android:gravity="center_vertical" |
||||
android:paddingStart="10dp" |
||||
android:paddingEnd="10dp" |
||||
android:text="@string/subscribe_source" |
||||
android:textColor="@color/colorAccent" |
||||
android:textSize="@dimen/text_small_size" /> |
||||
|
||||
<TextView |
||||
android:id="@+id/tv_subscribe_source_tip" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="match_parent" |
||||
android:background="?android:attr/selectableItemBackground" |
||||
android:gravity="center_vertical" |
||||
android:paddingStart="10dp" |
||||
android:paddingEnd="10dp" |
||||
android:text="@string/subscribe_source_tip" |
||||
android:textColor="@color/colorAccent" |
||||
android:textSize="@dimen/text_small_size" /> |
||||
</LinearLayout> |
||||
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView |
||||
android:id="@+id/iv_group" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="match_parent" |
||||
android:layout_toStartOf="@+id/iv_menu" |
||||
android:background="?android:attr/selectableItemBackground" |
||||
android:paddingStart="5dp" |
||||
android:paddingEnd="5dp" |
||||
app:srcCompat="@drawable/ic_filter" |
||||
app:tint="@color/colorAccent" /> |
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView |
||||
android:id="@+id/iv_menu" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="match_parent" |
||||
android:layout_alignParentEnd="true" |
||||
android:layout_gravity="end" |
||||
android:background="?android:attr/selectableItemBackground" |
||||
android:paddingStart="5dp" |
||||
android:paddingEnd="5dp" |
||||
app:srcCompat="@drawable/ic_menu" |
||||
app:tint="@color/colorAccent" /> |
||||
|
||||
</RelativeLayout> |
||||
|
||||
<View |
||||
android:layout_width="match_parent" |
||||
android:layout_height="1dp" |
||||
android:background="@color/colorBackground" /> |
||||
|
||||
<RelativeLayout |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent"> |
||||
|
||||
<xyz.fycz.myreader.widget.scroller.FastScrollRecyclerView |
||||
android:id="@+id/recycler_view" |
||||
android:background="@color/colorForeground" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent" /> |
||||
</RelativeLayout> |
||||
</LinearLayout> |
@ -0,0 +1,36 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:background="?android:attr/selectableItemBackground" |
||||
android:paddingHorizontal="5dp" |
||||
android:orientation="vertical"> |
||||
|
||||
<LinearLayout |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:orientation="vertical" |
||||
android:paddingVertical="10dp" |
||||
android:paddingHorizontal="5dp"> |
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView |
||||
android:id="@+id/tv_file_name" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:textColor="@color/textPrimary" |
||||
android:textSize="@dimen/text_normal_size" /> |
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView |
||||
android:id="@+id/tv_file_size_time" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:textColor="@color/textSecondary" |
||||
android:textSize="@dimen/text_small_size" /> |
||||
</LinearLayout> |
||||
|
||||
|
||||
<View |
||||
android:layout_width="fill_parent" |
||||
android:layout_height="0.5dp" |
||||
android:background="@color/sys_window_back" /> |
||||
</LinearLayout> |
@ -0,0 +1,60 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="50dp" |
||||
android:background="?android:attr/selectableItemBackground" |
||||
android:gravity="center_vertical" |
||||
android:paddingStart="10dp" |
||||
android:paddingEnd="10dp"> |
||||
|
||||
<androidx.appcompat.widget.AppCompatCheckBox |
||||
android:id="@+id/cb_source" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="match_parent" |
||||
android:layout_alignParentStart="true" |
||||
android:layout_toStartOf="@+id/tv_enable" |
||||
android:clickable="false" |
||||
android:textColor="@color/textPrimary" |
||||
android:ellipsize="end" |
||||
android:maxLines="2" |
||||
android:textSize="@dimen/text_normal_size" /> |
||||
|
||||
<TextView |
||||
android:id="@+id/tv_enable" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="match_parent" |
||||
android:layout_toStartOf="@+id/tv_disable" |
||||
android:background="?android:attr/selectableItemBackground" |
||||
android:gravity="center" |
||||
android:paddingStart="5dp" |
||||
android:paddingEnd="5dp" |
||||
android:text="@string/enable_use" |
||||
android:textColor="@color/textSecondary" |
||||
android:textSize="@dimen/text_small_size" /> |
||||
|
||||
<TextView |
||||
android:id="@+id/tv_disable" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="match_parent" |
||||
android:layout_toStartOf="@+id/tv_delete" |
||||
android:background="?android:attr/selectableItemBackground" |
||||
android:gravity="center" |
||||
android:paddingStart="5dp" |
||||
android:paddingEnd="5dp" |
||||
android:text="@string/ban" |
||||
android:textColor="@color/textSecondary" |
||||
android:textSize="@dimen/text_small_size" /> |
||||
|
||||
<TextView |
||||
android:id="@+id/tv_delete" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="match_parent" |
||||
android:layout_alignParentEnd="true" |
||||
android:background="?android:attr/selectableItemBackground" |
||||
android:gravity="center" |
||||
android:paddingStart="5dp" |
||||
android:paddingEnd="5dp" |
||||
android:text="@string/delete" |
||||
android:textColor="@color/textSecondary" |
||||
android:textSize="@dimen/text_small_size" /> |
||||
</RelativeLayout> |
@ -0,0 +1,18 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
<item |
||||
android:id="@+id/action_select_all" |
||||
android:title="@string/select_all" /> |
||||
<item |
||||
android:id="@+id/action_reverse_selected" |
||||
android:title="@string/reverse_selected" /> |
||||
|
||||
<item |
||||
android:id="@+id/action_reverse_enable_selected" |
||||
android:title="@string/reverse_enable_selected" /> |
||||
|
||||
<item |
||||
android:id="@+id/action_delete_selected" |
||||
android:title="@string/delete_selected" /> |
||||
|
||||
</menu> |
Loading…
Reference in new issue