parent
06fcfc94b6
commit
1cd3bc1f69
@ -1,124 +1,85 @@ |
|||||||
package io.legado.app.ui.rss.article |
package io.legado.app.ui.rss.article |
||||||
|
|
||||||
import android.app.Application |
import android.app.Application |
||||||
import android.content.Intent |
import android.os.Bundle |
||||||
import androidx.lifecycle.MutableLiveData |
import androidx.lifecycle.MutableLiveData |
||||||
import io.legado.app.App |
import io.legado.app.App |
||||||
import io.legado.app.base.BaseViewModel |
import io.legado.app.base.BaseViewModel |
||||||
import io.legado.app.data.entities.RssArticle |
import io.legado.app.data.entities.RssArticle |
||||||
import io.legado.app.data.entities.RssReadRecord |
|
||||||
import io.legado.app.data.entities.RssSource |
import io.legado.app.data.entities.RssSource |
||||||
import io.legado.app.model.Rss |
import io.legado.app.model.Rss |
||||||
import kotlinx.coroutines.Dispatchers.IO |
import kotlinx.coroutines.Dispatchers |
||||||
import kotlinx.coroutines.Dispatchers.Main |
|
||||||
import kotlinx.coroutines.withContext |
import kotlinx.coroutines.withContext |
||||||
|
|
||||||
|
|
||||||
class RssArticlesViewModel(application: Application) : BaseViewModel(application) { |
class RssArticlesViewModel(application: Application) : BaseViewModel(application) { |
||||||
var callBack: CallBack? = null |
val loadFinally = MutableLiveData<Boolean>() |
||||||
var url: String? = null |
|
||||||
var rssSource: RssSource? = null |
|
||||||
val titleLiveData = MutableLiveData<String>() |
|
||||||
var isLoading = true |
var isLoading = true |
||||||
var order = System.currentTimeMillis() |
var order = System.currentTimeMillis() |
||||||
private var nextPageUrl: String? = null |
private var nextPageUrl: String? = null |
||||||
|
private val articles = arrayListOf<RssArticle>() |
||||||
|
var sortName: String = "" |
||||||
|
var sortUrl: String = "" |
||||||
|
|
||||||
fun initData(intent: Intent, finally: () -> Unit) { |
fun init(bundle: Bundle?) { |
||||||
execute { |
bundle?.let { |
||||||
url = intent.getStringExtra("url") |
sortName = it.getString("sortName") ?: "" |
||||||
url?.let { url -> |
sortUrl = it.getString("sortUrl") ?: "" |
||||||
rssSource = App.db.rssSourceDao().getByKey(url) |
|
||||||
rssSource?.let { |
|
||||||
titleLiveData.postValue(it.sourceName) |
|
||||||
} ?: let { |
|
||||||
rssSource = RssSource(sourceUrl = url) |
|
||||||
} |
|
||||||
} |
|
||||||
}.onFinally { |
|
||||||
finally() |
|
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
fun loadContent() { |
|
||||||
|
fun loadContent(rssSource: RssSource) { |
||||||
isLoading = true |
isLoading = true |
||||||
rssSource?.let { rssSource -> |
Rss.getArticles(sortName, sortUrl, rssSource, null) |
||||||
Rss.getArticles(rssSource, null) |
.onSuccess(Dispatchers.IO) { |
||||||
.onSuccess(IO) { |
nextPageUrl = it.nextPageUrl |
||||||
nextPageUrl = it.nextPageUrl |
it.articles.let { list -> |
||||||
it.articles.let { list -> |
list.forEach { rssArticle -> |
||||||
list.forEach { rssArticle -> |
rssArticle.order = order-- |
||||||
rssArticle.order = order-- |
} |
||||||
} |
App.db.rssArticleDao().insert(*list.toTypedArray()) |
||||||
App.db.rssArticleDao().insert(*list.toTypedArray()) |
if (!rssSource.ruleNextPage.isNullOrEmpty()) { |
||||||
if (!rssSource.ruleNextPage.isNullOrEmpty()) { |
App.db.rssArticleDao().clearOld(rssSource.sourceUrl, order) |
||||||
App.db.rssArticleDao().clearOld(url!!, order) |
loadFinally.postValue(true) |
||||||
withContext(Main) { |
} else { |
||||||
callBack?.loadFinally(true) |
withContext(Dispatchers.Main) { |
||||||
} |
loadFinally.postValue(false) |
||||||
} else { |
|
||||||
withContext(Main) { |
|
||||||
callBack?.loadFinally(false) |
|
||||||
} |
|
||||||
} |
} |
||||||
isLoading = false |
|
||||||
|
|
||||||
} |
} |
||||||
}.onError { |
isLoading = false |
||||||
toast(it.localizedMessage) |
|
||||||
} |
} |
||||||
} |
}.onError { |
||||||
|
toast(it.localizedMessage) |
||||||
|
} |
||||||
} |
} |
||||||
|
|
||||||
fun loadMore() { |
fun loadMore(rssSource: RssSource) { |
||||||
isLoading = true |
isLoading = true |
||||||
val source = rssSource |
|
||||||
val pageUrl = nextPageUrl |
val pageUrl = nextPageUrl |
||||||
if (source != null && !pageUrl.isNullOrEmpty()) { |
if (!pageUrl.isNullOrEmpty()) { |
||||||
Rss.getArticles(source, pageUrl) |
Rss.getArticles(sortName, sortUrl, rssSource, pageUrl) |
||||||
.onSuccess(IO) { |
.onSuccess(Dispatchers.IO) { |
||||||
nextPageUrl = it.nextPageUrl |
nextPageUrl = it.nextPageUrl |
||||||
it.articles.let { list -> |
it.articles.let { list -> |
||||||
if (list.isEmpty()) { |
if (list.isEmpty()) { |
||||||
callBack?.loadFinally(false) |
loadFinally.postValue(true) |
||||||
return@let |
return@let |
||||||
} |
} |
||||||
callBack?.adapter?.getItems()?.let { adapterItems -> |
if (articles.contains(list.first())) { |
||||||
if (adapterItems.contains(list.first())) { |
loadFinally.postValue(false) |
||||||
callBack?.loadFinally(false) |
} else { |
||||||
} else { |
list.forEach { rssArticle -> |
||||||
list.forEach { rssArticle -> |
rssArticle.order = order-- |
||||||
rssArticle.order = order-- |
|
||||||
} |
|
||||||
App.db.rssArticleDao().insert(*list.toTypedArray()) |
|
||||||
} |
} |
||||||
|
App.db.rssArticleDao().insert(*list.toTypedArray()) |
||||||
} |
} |
||||||
} |
} |
||||||
isLoading = false |
isLoading = false |
||||||
} |
} |
||||||
} else { |
} else { |
||||||
callBack?.loadFinally(false) |
loadFinally.postValue(false) |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
fun read(rssArticle: RssArticle) { |
|
||||||
execute { |
|
||||||
App.db.rssArticleDao().insertRecord(RssReadRecord(rssArticle.link)) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
fun clearArticles() { |
|
||||||
execute { |
|
||||||
url?.let { |
|
||||||
App.db.rssArticleDao().delete(it) |
|
||||||
} |
|
||||||
order = System.currentTimeMillis() |
|
||||||
}.onSuccess { |
|
||||||
loadContent() |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
interface CallBack { |
|
||||||
var adapter: RssArticlesAdapter |
|
||||||
fun loadFinally(hasMore: Boolean) |
|
||||||
} |
|
||||||
} |
} |
@ -0,0 +1,102 @@ |
|||||||
|
package io.legado.app.ui.rss.article |
||||||
|
|
||||||
|
import android.app.Activity |
||||||
|
import android.content.Intent |
||||||
|
import android.os.Bundle |
||||||
|
import android.view.Menu |
||||||
|
import android.view.MenuItem |
||||||
|
import androidx.fragment.app.Fragment |
||||||
|
import androidx.fragment.app.FragmentManager |
||||||
|
import androidx.fragment.app.FragmentStatePagerAdapter |
||||||
|
import androidx.lifecycle.Observer |
||||||
|
import io.legado.app.R |
||||||
|
import io.legado.app.base.VMBaseActivity |
||||||
|
import io.legado.app.ui.rss.source.edit.RssSourceEditActivity |
||||||
|
import io.legado.app.utils.getViewModel |
||||||
|
import io.legado.app.utils.gone |
||||||
|
import io.legado.app.utils.visible |
||||||
|
import kotlinx.android.synthetic.main.activity_rss_artivles.* |
||||||
|
import kotlinx.android.synthetic.main.view_refresh_recycler.* |
||||||
|
import org.jetbrains.anko.startActivityForResult |
||||||
|
|
||||||
|
class RssSortActivity : VMBaseActivity<RssSortViewModel>(R.layout.activity_rss_artivles) { |
||||||
|
|
||||||
|
override val viewModel: RssSortViewModel |
||||||
|
get() = getViewModel(RssSortViewModel::class.java) |
||||||
|
private val editSource = 12319 |
||||||
|
private val fragments = linkedMapOf<String, RssArticlesFragment>() |
||||||
|
private lateinit var adapter: TabFragmentPageAdapter |
||||||
|
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) { |
||||||
|
adapter = TabFragmentPageAdapter(supportFragmentManager) |
||||||
|
tab_layout.setupWithViewPager(view_pager) |
||||||
|
view_pager.adapter = adapter |
||||||
|
viewModel.titleLiveData.observe(this, Observer { |
||||||
|
title_bar.title = it |
||||||
|
}) |
||||||
|
viewModel.initData(intent) { |
||||||
|
upFragments() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun onCompatCreateOptionsMenu(menu: Menu): Boolean { |
||||||
|
menuInflater.inflate(R.menu.rss_articles, menu) |
||||||
|
return super.onCompatCreateOptionsMenu(menu) |
||||||
|
} |
||||||
|
|
||||||
|
override fun onCompatOptionsItemSelected(item: MenuItem): Boolean { |
||||||
|
when (item.itemId) { |
||||||
|
R.id.menu_edit_source -> viewModel.rssSource?.sourceUrl?.let { |
||||||
|
startActivityForResult<RssSourceEditActivity>(editSource, Pair("data", it)) |
||||||
|
} |
||||||
|
R.id.menu_clear -> { |
||||||
|
viewModel.url?.let { |
||||||
|
refresh_progress_bar.isAutoLoading = true |
||||||
|
viewModel.clearArticles() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return super.onCompatOptionsItemSelected(item) |
||||||
|
} |
||||||
|
|
||||||
|
private fun upFragments() { |
||||||
|
fragments.clear() |
||||||
|
viewModel.rssSource?.sortUrls()?.forEach { |
||||||
|
fragments[it.key] = RssArticlesFragment.create(it.key, it.value) |
||||||
|
} |
||||||
|
if (fragments.size == 1) { |
||||||
|
tab_layout.gone() |
||||||
|
} else { |
||||||
|
tab_layout.visible() |
||||||
|
} |
||||||
|
adapter.notifyDataSetChanged() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { |
||||||
|
super.onActivityResult(requestCode, resultCode, data) |
||||||
|
when (requestCode) { |
||||||
|
editSource -> if (resultCode == Activity.RESULT_OK) { |
||||||
|
viewModel.initData(intent) { |
||||||
|
upFragments() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private inner class TabFragmentPageAdapter internal constructor(fm: FragmentManager) : |
||||||
|
FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { |
||||||
|
|
||||||
|
override fun getPageTitle(position: Int): CharSequence? { |
||||||
|
return fragments.keys.elementAt(position) |
||||||
|
} |
||||||
|
|
||||||
|
override fun getItem(position: Int): Fragment { |
||||||
|
return fragments.values.elementAt(position) |
||||||
|
} |
||||||
|
|
||||||
|
override fun getCount(): Int { |
||||||
|
return fragments.size |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
package io.legado.app.ui.rss.article |
||||||
|
|
||||||
|
import android.app.Application |
||||||
|
import android.content.Intent |
||||||
|
import androidx.lifecycle.MutableLiveData |
||||||
|
import io.legado.app.App |
||||||
|
import io.legado.app.base.BaseViewModel |
||||||
|
import io.legado.app.data.entities.RssArticle |
||||||
|
import io.legado.app.data.entities.RssReadRecord |
||||||
|
import io.legado.app.data.entities.RssSource |
||||||
|
|
||||||
|
|
||||||
|
class RssSortViewModel(application: Application) : BaseViewModel(application) { |
||||||
|
var url: String? = null |
||||||
|
var rssSource: RssSource? = null |
||||||
|
val titleLiveData = MutableLiveData<String>() |
||||||
|
var order = System.currentTimeMillis() |
||||||
|
|
||||||
|
fun initData(intent: Intent, finally: () -> Unit) { |
||||||
|
execute { |
||||||
|
url = intent.getStringExtra("url") |
||||||
|
url?.let { url -> |
||||||
|
rssSource = App.db.rssSourceDao().getByKey(url) |
||||||
|
rssSource?.let { |
||||||
|
titleLiveData.postValue(it.sourceName) |
||||||
|
} ?: let { |
||||||
|
rssSource = RssSource(sourceUrl = url) |
||||||
|
} |
||||||
|
} |
||||||
|
}.onFinally { |
||||||
|
finally() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fun read(rssArticle: RssArticle) { |
||||||
|
execute { |
||||||
|
App.db.rssArticleDao().insertRecord(RssReadRecord(rssArticle.link)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fun clearArticles() { |
||||||
|
execute { |
||||||
|
url?.let { |
||||||
|
App.db.rssArticleDao().delete(it) |
||||||
|
} |
||||||
|
order = System.currentTimeMillis() |
||||||
|
}.onSuccess { |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<io.legado.app.ui.widget.dynamiclayout.DynamicFrameLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||||
|
android:id="@+id/content_view" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="0dp" |
||||||
|
app:layout_constraintBottom_toBottomOf="parent" |
||||||
|
app:layout_constraintTop_toBottomOf="@id/title_bar"> |
||||||
|
|
||||||
|
<io.legado.app.ui.widget.recycler.RefreshRecyclerView |
||||||
|
android:id="@+id/refresh_recycler_view" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" /> |
||||||
|
|
||||||
|
</io.legado.app.ui.widget.dynamiclayout.DynamicFrameLayout> |
Loading…
Reference in new issue