rss收藏增加分组管理 (#4236)
* rss收藏增加分组和标题编辑选项 * 优化变量命名 * 订阅收藏按分组展示 * 优化:订阅收藏分组展示 * 优化 * 优化rss收藏分组管理 * 优化数据库版本控制
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -63,7 +63,7 @@ val appDb by lazy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Database(
|
@Database(
|
||||||
version = 71,
|
version = 72,
|
||||||
exportSchema = true,
|
exportSchema = true,
|
||||||
entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class,
|
entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class,
|
||||||
ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class,
|
ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class,
|
||||||
@@ -99,6 +99,7 @@ val appDb by lazy {
|
|||||||
AutoMigration(from = 68, to = 69),
|
AutoMigration(from = 68, to = 69),
|
||||||
AutoMigration(from = 69, to = 70),
|
AutoMigration(from = 69, to = 70),
|
||||||
AutoMigration(from = 70, to = 71),
|
AutoMigration(from = 70, to = 71),
|
||||||
|
AutoMigration(from = 71, to = 72),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ interface RssArticleDao {
|
|||||||
|
|
||||||
@Query(
|
@Query(
|
||||||
"""select t1.link, t1.sort, t1.origin, t1.`order`, t1.title, t1.content,
|
"""select t1.link, t1.sort, t1.origin, t1.`order`, t1.title, t1.content,
|
||||||
t1.description, t1.image, t1.pubDate, t1.variable, ifNull(t2.read, 0) as read
|
t1.description, t1.image, t1.`group`, t1.pubDate, t1.variable, ifNull(t2.read, 0) as read
|
||||||
from rssArticles as t1 left join rssReadRecords as t2
|
from rssArticles as t1 left join rssReadRecords as t2
|
||||||
on t1.link = t2.record where origin = :origin and sort = :sort
|
on t1.link = t2.record where origin = :origin and sort = :sort
|
||||||
order by `order` desc"""
|
order by `order` desc"""
|
||||||
|
|||||||
@@ -10,6 +10,12 @@ interface RssStarDao {
|
|||||||
@get:Query("select * from rssStars order by starTime desc")
|
@get:Query("select * from rssStars order by starTime desc")
|
||||||
val all: List<RssStar>
|
val all: List<RssStar>
|
||||||
|
|
||||||
|
@Query("select `group` from rssStars group by `group` order by `group`")
|
||||||
|
fun groupList(): Flow<List<String>>
|
||||||
|
|
||||||
|
@Query("select * from rssStars where `group` = :group order by starTime desc")
|
||||||
|
fun getByGroup(group: String): Flow<List<RssStar>>
|
||||||
|
|
||||||
@Query("select * from rssStars where origin = :origin and link = :link")
|
@Query("select * from rssStars where origin = :origin and link = :link")
|
||||||
fun get(origin: String, link: String): RssStar?
|
fun get(origin: String, link: String): RssStar?
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package io.legado.app.data.entities
|
package io.legado.app.data.entities
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.Ignore
|
import androidx.room.Ignore
|
||||||
import io.legado.app.utils.GSON
|
import io.legado.app.utils.GSON
|
||||||
import io.legado.app.utils.fromJsonObject
|
import io.legado.app.utils.fromJsonObject
|
||||||
import kotlinx.parcelize.IgnoredOnParcel
|
import kotlinx.parcelize.IgnoredOnParcel
|
||||||
|
|
||||||
|
|
||||||
@Entity(
|
@Entity(
|
||||||
tableName = "rssArticles",
|
tableName = "rssArticles",
|
||||||
primaryKeys = ["origin", "link"]
|
primaryKeys = ["origin", "link"]
|
||||||
@@ -21,6 +21,8 @@ data class RssArticle(
|
|||||||
var description: String? = null,
|
var description: String? = null,
|
||||||
var content: String? = null,
|
var content: String? = null,
|
||||||
var image: String? = null,
|
var image: String? = null,
|
||||||
|
@ColumnInfo(defaultValue = "默认分组")
|
||||||
|
var group: String = "默认分组",
|
||||||
var read: Boolean = false,
|
var read: Boolean = false,
|
||||||
override var variable: String? = null
|
override var variable: String? = null
|
||||||
) : BaseRssArticle {
|
) : BaseRssArticle {
|
||||||
@@ -49,6 +51,7 @@ data class RssArticle(
|
|||||||
description = description,
|
description = description,
|
||||||
content = content,
|
content = content,
|
||||||
image = image,
|
image = image,
|
||||||
|
group = group,
|
||||||
variable = variable
|
variable = variable
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package io.legado.app.data.entities
|
package io.legado.app.data.entities
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.Ignore
|
import androidx.room.Ignore
|
||||||
import io.legado.app.utils.GSON
|
import io.legado.app.utils.GSON
|
||||||
@@ -21,6 +22,8 @@ data class RssStar(
|
|||||||
var description: String? = null,
|
var description: String? = null,
|
||||||
var content: String? = null,
|
var content: String? = null,
|
||||||
var image: String? = null,
|
var image: String? = null,
|
||||||
|
@ColumnInfo(defaultValue = "默认分组")
|
||||||
|
var group: String = "默认分组",
|
||||||
override var variable: String? = null
|
override var variable: String? = null
|
||||||
) : BaseRssArticle {
|
) : BaseRssArticle {
|
||||||
|
|
||||||
@@ -40,6 +43,7 @@ data class RssStar(
|
|||||||
description = description,
|
description = description,
|
||||||
content = content,
|
content = content,
|
||||||
image = image,
|
image = image,
|
||||||
|
group = group,
|
||||||
variable = variable
|
variable = variable
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,62 +1,84 @@
|
|||||||
|
@file:Suppress("DEPRECATION")
|
||||||
|
|
||||||
package io.legado.app.ui.rss.favorites
|
package io.legado.app.ui.rss.favorites
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentStatePagerAdapter
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import io.legado.app.base.BaseActivity
|
import io.legado.app.base.BaseActivity
|
||||||
import io.legado.app.constant.AppLog
|
import io.legado.app.constant.AppLog
|
||||||
import io.legado.app.data.appDb
|
import io.legado.app.data.appDb
|
||||||
import io.legado.app.data.entities.RssStar
|
|
||||||
import io.legado.app.databinding.ActivityRssFavoritesBinding
|
import io.legado.app.databinding.ActivityRssFavoritesBinding
|
||||||
import io.legado.app.lib.theme.accentColor
|
import io.legado.app.lib.theme.accentColor
|
||||||
import io.legado.app.ui.rss.read.ReadRssActivity
|
import io.legado.app.utils.gone
|
||||||
import io.legado.app.ui.widget.recycler.VerticalDivider
|
|
||||||
import io.legado.app.utils.startActivity
|
|
||||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||||
|
import io.legado.app.utils.visible
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.flow.catch
|
import kotlinx.coroutines.flow.catch
|
||||||
import kotlinx.coroutines.flow.conflate
|
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 收藏夹
|
* 收藏夹
|
||||||
*/
|
*/
|
||||||
class RssFavoritesActivity : BaseActivity<ActivityRssFavoritesBinding>(),
|
class RssFavoritesActivity : BaseActivity<ActivityRssFavoritesBinding>(){
|
||||||
RssFavoritesAdapter.CallBack {
|
|
||||||
|
|
||||||
override val binding by viewBinding(ActivityRssFavoritesBinding::inflate)
|
override val binding by viewBinding(ActivityRssFavoritesBinding::inflate)
|
||||||
private val adapter by lazy { RssFavoritesAdapter(this, this) }
|
private val adapter by lazy { TabFragmentPageAdapter() }
|
||||||
|
private var groupList = mutableListOf<String>()
|
||||||
|
private var rssStarFlowJob: Job? = null
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
initView()
|
binding.viewPager.adapter = adapter
|
||||||
initData()
|
binding.tabLayout.setupWithViewPager(binding.viewPager)
|
||||||
|
binding.tabLayout.setSelectedTabIndicatorColor(accentColor)
|
||||||
|
upFragments()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initView() {
|
private fun upFragments() {
|
||||||
binding.refreshLayout.setColorSchemeColors(accentColor)
|
rssStarFlowJob?.cancel()
|
||||||
binding.recyclerView.let {
|
rssStarFlowJob = lifecycleScope.launch {
|
||||||
it.layoutManager = LinearLayoutManager(this)
|
appDb.rssStarDao.groupList().catch {
|
||||||
it.addItemDecoration(VerticalDivider(this))
|
AppLog.put("订阅分组数据获取失败\n${it.localizedMessage}", it)
|
||||||
it.adapter = adapter
|
}.flowOn(IO).collect {
|
||||||
|
groupList.clear()
|
||||||
|
groupList.addAll(it)
|
||||||
|
if (groupList.size == 1) {
|
||||||
|
binding.tabLayout.gone()
|
||||||
|
} else {
|
||||||
|
binding.tabLayout.visible()
|
||||||
}
|
}
|
||||||
}
|
adapter.notifyDataSetChanged()
|
||||||
|
|
||||||
private fun initData() {
|
|
||||||
lifecycleScope.launch {
|
|
||||||
appDb.rssStarDao.liveAll().catch {
|
|
||||||
AppLog.put("订阅收藏夹界面获取数据失败\n${it.localizedMessage}", it)
|
|
||||||
}.flowOn(IO).conflate().collect {
|
|
||||||
adapter.setItems(it)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun readRss(rssStar: RssStar) {
|
private inner class TabFragmentPageAdapter :
|
||||||
startActivity<ReadRssActivity> {
|
FragmentStatePagerAdapter(supportFragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
|
||||||
putExtra("title", rssStar.title)
|
|
||||||
putExtra("origin", rssStar.origin)
|
override fun getItemPosition(`object`: Any): Int {
|
||||||
putExtra("link", rssStar.link)
|
return POSITION_NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPageTitle(position: Int): CharSequence {
|
||||||
|
return groupList[position]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItem(position: Int): Fragment {
|
||||||
|
val group = groupList[position]
|
||||||
|
return RssFavoritesFragment(group)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCount(): Int {
|
||||||
|
return groupList.size
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun instantiateItem(container: ViewGroup, position: Int): Any {
|
||||||
|
val fragment = super.instantiateItem(container, position) as Fragment
|
||||||
|
return fragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package io.legado.app.ui.rss.favorites
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import io.legado.app.R
|
||||||
|
import io.legado.app.base.BaseDialogFragment
|
||||||
|
import io.legado.app.data.entities.RssArticle
|
||||||
|
import io.legado.app.databinding.DialogRssfavoritesBinding
|
||||||
|
import io.legado.app.lib.theme.primaryColor
|
||||||
|
import io.legado.app.utils.setLayout
|
||||||
|
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class RssFavoritesDialog() : BaseDialogFragment(R.layout.dialog_rssfavorites, true) {
|
||||||
|
|
||||||
|
constructor(rssArticle: RssArticle) : this() {
|
||||||
|
arguments = Bundle().apply {
|
||||||
|
putString("title", rssArticle.title)
|
||||||
|
putString("group", rssArticle.group)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val binding by viewBinding(DialogRssfavoritesBinding::bind)
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
binding.toolBar.setBackgroundColor(primaryColor)
|
||||||
|
val arguments = arguments ?: let {
|
||||||
|
dismiss()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var title = arguments.getString("title") ?: "默认名称"
|
||||||
|
var group = arguments.getString("group") ?: "默认分组"
|
||||||
|
binding.run {
|
||||||
|
editTitle.setText(title)
|
||||||
|
editGroup.setText(group)
|
||||||
|
tvCancel.setOnClickListener {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
tvOk.setOnClickListener {
|
||||||
|
val editTitle = editTitle.text.toString()
|
||||||
|
if(!TextUtils.isEmpty(editTitle)){
|
||||||
|
title = editTitle
|
||||||
|
}
|
||||||
|
val editGroup = editGroup.text.toString()
|
||||||
|
if(!TextUtils.isEmpty(editGroup)){
|
||||||
|
group = editGroup
|
||||||
|
}
|
||||||
|
lifecycleScope.launch {
|
||||||
|
callback?.updateFavorite(title, group)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tvFooterLeft.setOnClickListener {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
callback?.deleteFavorite()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val callback get() = (parentFragment as? Callback) ?: (activity as? Callback)
|
||||||
|
|
||||||
|
interface Callback {
|
||||||
|
|
||||||
|
fun updateFavorite(title: String, group: String)
|
||||||
|
|
||||||
|
fun deleteFavorite()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package io.legado.app.ui.rss.favorites
|
||||||
|
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import io.legado.app.R
|
||||||
|
import io.legado.app.base.VMBaseFragment
|
||||||
|
import io.legado.app.constant.AppLog
|
||||||
|
import io.legado.app.data.appDb
|
||||||
|
import io.legado.app.data.entities.RssStar
|
||||||
|
import io.legado.app.databinding.FragmentRssArticlesBinding
|
||||||
|
import io.legado.app.lib.theme.primaryColor
|
||||||
|
import io.legado.app.ui.rss.read.ReadRssActivity
|
||||||
|
import io.legado.app.ui.widget.recycler.VerticalDivider
|
||||||
|
import io.legado.app.utils.setEdgeEffectColor
|
||||||
|
import io.legado.app.utils.startActivity
|
||||||
|
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||||
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.flow.catch
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class RssFavoritesFragment() : VMBaseFragment<RssFavoritesViewModel>(R.layout.fragment_rss_articles),
|
||||||
|
RssFavoritesAdapter.CallBack {
|
||||||
|
|
||||||
|
constructor(group: String) : this() {
|
||||||
|
arguments = Bundle().apply {
|
||||||
|
putString("group", group)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val binding by viewBinding(FragmentRssArticlesBinding::bind)
|
||||||
|
override val viewModel by viewModels<RssFavoritesViewModel>()
|
||||||
|
private val adapter: RssFavoritesAdapter by lazy {
|
||||||
|
RssFavoritesAdapter(requireContext(), this@RssFavoritesFragment)
|
||||||
|
}
|
||||||
|
private var articlesFlowJob: Job? = null
|
||||||
|
|
||||||
|
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
initView()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initView() = binding.run {
|
||||||
|
refreshLayout.setEnabled(false)
|
||||||
|
recyclerView.setEdgeEffectColor(primaryColor)
|
||||||
|
recyclerView.layoutManager = run {
|
||||||
|
recyclerView.addItemDecoration(VerticalDivider(requireContext()))
|
||||||
|
LinearLayoutManager(requireContext())
|
||||||
|
}
|
||||||
|
recyclerView.adapter = adapter
|
||||||
|
loadArticles()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadArticles() {
|
||||||
|
articlesFlowJob?.cancel()
|
||||||
|
articlesFlowJob = lifecycleScope.launch {
|
||||||
|
val group = arguments?.getString("group") ?: "默认分组"
|
||||||
|
appDb.rssStarDao.getByGroup(group).catch {
|
||||||
|
AppLog.put("订阅文章界面获取数据失败\n${it.localizedMessage}", it)
|
||||||
|
}.flowOn(IO).collect {
|
||||||
|
adapter.setItems(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readRss(rssStar: RssStar) {
|
||||||
|
startActivity<ReadRssActivity> {
|
||||||
|
putExtra("title", rssStar.title)
|
||||||
|
putExtra("origin", rssStar.origin)
|
||||||
|
putExtra("link", rssStar.link)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package io.legado.app.ui.rss.favorites
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import io.legado.app.base.BaseViewModel
|
||||||
|
|
||||||
|
|
||||||
|
class RssFavoritesViewModel(application: Application) : BaseViewModel(application) {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -42,6 +42,7 @@ import io.legado.app.model.Download
|
|||||||
import io.legado.app.ui.association.OnLineImportActivity
|
import io.legado.app.ui.association.OnLineImportActivity
|
||||||
import io.legado.app.ui.file.HandleFileContract
|
import io.legado.app.ui.file.HandleFileContract
|
||||||
import io.legado.app.ui.login.SourceLoginActivity
|
import io.legado.app.ui.login.SourceLoginActivity
|
||||||
|
import io.legado.app.ui.rss.favorites.RssFavoritesDialog
|
||||||
import io.legado.app.utils.ACache
|
import io.legado.app.utils.ACache
|
||||||
import io.legado.app.utils.NetworkUtils
|
import io.legado.app.utils.NetworkUtils
|
||||||
import io.legado.app.utils.get
|
import io.legado.app.utils.get
|
||||||
@@ -53,6 +54,7 @@ import io.legado.app.utils.openUrl
|
|||||||
import io.legado.app.utils.setDarkeningAllowed
|
import io.legado.app.utils.setDarkeningAllowed
|
||||||
import io.legado.app.utils.setTintMutate
|
import io.legado.app.utils.setTintMutate
|
||||||
import io.legado.app.utils.share
|
import io.legado.app.utils.share
|
||||||
|
import io.legado.app.utils.showDialogFragment
|
||||||
import io.legado.app.utils.splitNotBlank
|
import io.legado.app.utils.splitNotBlank
|
||||||
import io.legado.app.utils.startActivity
|
import io.legado.app.utils.startActivity
|
||||||
import io.legado.app.utils.textArray
|
import io.legado.app.utils.textArray
|
||||||
@@ -70,7 +72,7 @@ import java.util.regex.PatternSyntaxException
|
|||||||
/**
|
/**
|
||||||
* rss阅读界面
|
* rss阅读界面
|
||||||
*/
|
*/
|
||||||
class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>() {
|
class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>(), RssFavoritesDialog.Callback {
|
||||||
|
|
||||||
override val binding by viewBinding(ActivityRssReadBinding::inflate)
|
override val binding by viewBinding(ActivityRssReadBinding::inflate)
|
||||||
override val viewModel by viewModels<ReadRssViewModel>()
|
override val viewModel by viewModels<ReadRssViewModel>()
|
||||||
@@ -151,8 +153,12 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
|
|||||||
R.id.menu_rss_refresh -> viewModel.refresh {
|
R.id.menu_rss_refresh -> viewModel.refresh {
|
||||||
binding.webView.reload()
|
binding.webView.reload()
|
||||||
}
|
}
|
||||||
|
R.id.menu_rss_star -> {
|
||||||
R.id.menu_rss_star -> viewModel.favorite()
|
viewModel.addFavorite()
|
||||||
|
viewModel.rssArticle?.let {
|
||||||
|
showDialogFragment(RssFavoritesDialog(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
R.id.menu_share_it -> {
|
R.id.menu_share_it -> {
|
||||||
binding.webView.url?.let {
|
binding.webView.url?.let {
|
||||||
share(it)
|
share(it)
|
||||||
@@ -174,6 +180,16 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
|
|||||||
return super.onCompatOptionsItemSelected(item)
|
return super.onCompatOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun updateFavorite(title: String, group: String) {
|
||||||
|
viewModel.rssArticle?.title = title
|
||||||
|
viewModel.rssArticle?.group = group
|
||||||
|
viewModel.updateFavorite()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deleteFavorite() {
|
||||||
|
viewModel.delFavorite()
|
||||||
|
}
|
||||||
|
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
fun isNightTheme(): Boolean {
|
fun isNightTheme(): Boolean {
|
||||||
return AppConfig.isNightTheme
|
return AppConfig.isNightTheme
|
||||||
@@ -188,7 +204,7 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetJavaScriptEnabled")
|
@SuppressLint("SetJavaScriptEnabled", "JavascriptInterface")
|
||||||
private fun initWebView() {
|
private fun initWebView() {
|
||||||
binding.progressBar.fontColor = accentColor
|
binding.progressBar.fontColor = accentColor
|
||||||
binding.webView.webChromeClient = CustomWebChromeClient()
|
binding.webView.webChromeClient = CustomWebChromeClient()
|
||||||
|
|||||||
@@ -135,6 +135,39 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application), J
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addFavorite() {
|
||||||
|
execute {
|
||||||
|
rssStar ?: rssArticle?.toStar()?.let {
|
||||||
|
appDb.rssStarDao.insert(it)
|
||||||
|
rssStar = it
|
||||||
|
}
|
||||||
|
}.onSuccess {
|
||||||
|
upStarMenuData.postValue(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateFavorite() {
|
||||||
|
execute {
|
||||||
|
rssArticle?.toStar()?.let {
|
||||||
|
appDb.rssStarDao.update(it)
|
||||||
|
rssStar = it
|
||||||
|
}
|
||||||
|
}.onSuccess {
|
||||||
|
upStarMenuData.postValue(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun delFavorite() {
|
||||||
|
execute {
|
||||||
|
rssStar?.let {
|
||||||
|
appDb.rssStarDao.delete(it.origin, it.link)
|
||||||
|
rssStar = null
|
||||||
|
}
|
||||||
|
}.onSuccess {
|
||||||
|
upStarMenuData.postValue(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun saveImage(webPic: String?, uri: Uri) {
|
fun saveImage(webPic: String?, uri: Uri) {
|
||||||
webPic ?: return
|
webPic ?: return
|
||||||
execute {
|
execute {
|
||||||
|
|||||||
@@ -1,30 +1,27 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<io.legado.app.ui.widget.TitleBar
|
<io.legado.app.ui.widget.TitleBar
|
||||||
android:id="@+id/title_bar"
|
android:id="@+id/title_bar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:title="@string/favorites"
|
app:title="@string/favorites" />
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
<com.google.android.material.tabs.TabLayout
|
||||||
android:id="@+id/refresh_layout"
|
android:id="@+id/tab_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:tabMode="scrollable" />
|
||||||
app:layout_constraintTop_toBottomOf="@id/title_bar"
|
|
||||||
app:layout_constraintVertical_bias="0.0">
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.viewpager.widget.ViewPager
|
||||||
android:id="@+id/recycler_view"
|
android:id="@+id/view_pager"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="wrap_content"
|
||||||
|
tools:ignore="SpeakableTextPresentCheck" />
|
||||||
|
|
||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/vw_bg"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:background="@drawable/shape_card_view"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:ignore="UselessParent">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/tool_bar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:theme="?attr/actionBarStyle"
|
||||||
|
app:popupTheme="@style/AppTheme.PopupOverlay"
|
||||||
|
app:title="@string/favorite"
|
||||||
|
app:titleTextAppearance="@style/ToolbarTitle" />
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:overScrollMode="ifContentScrolls">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<io.legado.app.ui.widget.text.TextInputLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="3dp">
|
||||||
|
|
||||||
|
<io.legado.app.lib.theme.view.ThemeEditText
|
||||||
|
android:id="@+id/edit_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/title"
|
||||||
|
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
|
||||||
|
|
||||||
|
</io.legado.app.ui.widget.text.TextInputLayout>
|
||||||
|
|
||||||
|
<io.legado.app.ui.widget.text.TextInputLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="3dp">
|
||||||
|
|
||||||
|
<io.legado.app.lib.theme.view.ThemeEditText
|
||||||
|
android:id="@+id/edit_group"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/group_name"
|
||||||
|
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
|
||||||
|
|
||||||
|
</io.legado.app.ui.widget.text.TextInputLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingLeft="12dp"
|
||||||
|
android:paddingRight="12dp"
|
||||||
|
app:flexWrap="wrap"
|
||||||
|
app:justifyContent="space_between">
|
||||||
|
|
||||||
|
<io.legado.app.ui.widget.text.AccentTextView
|
||||||
|
android:id="@+id/tv_footer_left"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:text="@string/delete"
|
||||||
|
tools:ignore="RtlHardcoded" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<io.legado.app.ui.widget.text.AccentTextView
|
||||||
|
android:id="@+id/tv_cancel"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:text="@string/cancel"
|
||||||
|
tools:ignore="RtlHardcoded" />
|
||||||
|
|
||||||
|
<io.legado.app.ui.widget.text.AccentTextView
|
||||||
|
android:id="@+id/tv_ok"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:text="@string/ok"
|
||||||
|
tools:ignore="RtlHardcoded" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.google.android.flexbox.FlexboxLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
Reference in New Issue
Block a user