File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,7 @@ import io.legado.app.data.dao.KeyboardAssistsDao
|
|||||||
import io.legado.app.data.dao.ReadRecordDao
|
import io.legado.app.data.dao.ReadRecordDao
|
||||||
import io.legado.app.data.dao.ReplaceRuleDao
|
import io.legado.app.data.dao.ReplaceRuleDao
|
||||||
import io.legado.app.data.dao.RssArticleDao
|
import io.legado.app.data.dao.RssArticleDao
|
||||||
|
import io.legado.app.data.dao.RssReadRecordDao
|
||||||
import io.legado.app.data.dao.RssSourceDao
|
import io.legado.app.data.dao.RssSourceDao
|
||||||
import io.legado.app.data.dao.RssStarDao
|
import io.legado.app.data.dao.RssStarDao
|
||||||
import io.legado.app.data.dao.RuleSubDao
|
import io.legado.app.data.dao.RuleSubDao
|
||||||
@@ -63,7 +64,7 @@ val appDb by lazy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Database(
|
@Database(
|
||||||
version = 73,
|
version = 74,
|
||||||
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,
|
||||||
@@ -101,6 +102,7 @@ val appDb by lazy {
|
|||||||
AutoMigration(from = 70, to = 71),
|
AutoMigration(from = 70, to = 71),
|
||||||
AutoMigration(from = 71, to = 72),
|
AutoMigration(from = 71, to = 72),
|
||||||
AutoMigration(from = 72, to = 73),
|
AutoMigration(from = 72, to = 73),
|
||||||
|
AutoMigration(from = 73, to = 74),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
@@ -116,6 +118,7 @@ abstract class AppDatabase : RoomDatabase() {
|
|||||||
abstract val bookmarkDao: BookmarkDao
|
abstract val bookmarkDao: BookmarkDao
|
||||||
abstract val rssArticleDao: RssArticleDao
|
abstract val rssArticleDao: RssArticleDao
|
||||||
abstract val rssStarDao: RssStarDao
|
abstract val rssStarDao: RssStarDao
|
||||||
|
abstract val rssReadRecordDao: RssReadRecordDao
|
||||||
abstract val cookieDao: CookieDao
|
abstract val cookieDao: CookieDao
|
||||||
abstract val txtTocRuleDao: TxtTocRuleDao
|
abstract val txtTocRuleDao: TxtTocRuleDao
|
||||||
abstract val readRecordDao: ReadRecordDao
|
abstract val readRecordDao: ReadRecordDao
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package io.legado.app.data.dao
|
|||||||
|
|
||||||
import androidx.room.*
|
import androidx.room.*
|
||||||
import io.legado.app.data.entities.RssArticle
|
import io.legado.app.data.entities.RssArticle
|
||||||
import io.legado.app.data.entities.RssReadRecord
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
@@ -38,13 +37,4 @@ interface RssArticleDao {
|
|||||||
@Query("delete from rssArticles where origin = :origin")
|
@Query("delete from rssArticles where origin = :origin")
|
||||||
fun delete(origin: String)
|
fun delete(origin: String)
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
|
||||||
fun insertRecord(vararg rssReadRecord: RssReadRecord)
|
|
||||||
|
|
||||||
@get:Query("select count(1) from rssReadRecords")
|
|
||||||
val countRead: Int
|
|
||||||
|
|
||||||
@Query("delete from rssReadRecords")
|
|
||||||
fun deleteRecord()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package io.legado.app.data.dao
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import io.legado.app.data.entities.RssReadRecord
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface RssReadRecordDao {
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||||
|
fun insertRecord(vararg rssReadRecord: RssReadRecord)
|
||||||
|
|
||||||
|
@Query("select * from rssReadRecords order by readTime desc")
|
||||||
|
fun getRecord(): List<RssReadRecord>
|
||||||
|
|
||||||
|
@get:Query("select count(1) from rssReadRecords")
|
||||||
|
val countRead: Int
|
||||||
|
|
||||||
|
@Query("delete from rssReadRecords")
|
||||||
|
fun deleteRecord()
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,6 +5,9 @@ import androidx.room.PrimaryKey
|
|||||||
|
|
||||||
@Entity(tableName = "rssReadRecords")
|
@Entity(tableName = "rssReadRecords")
|
||||||
data class RssReadRecord(
|
data class RssReadRecord(
|
||||||
@PrimaryKey val record: String,
|
@PrimaryKey
|
||||||
|
val record: String,
|
||||||
|
val title: String? = null,
|
||||||
|
val readTime: Long? = null,
|
||||||
val read: Boolean = true
|
val read: Boolean = true
|
||||||
)
|
)
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
package io.legado.app.ui.rss.article
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.widget.Toolbar
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import io.legado.app.R
|
||||||
|
import io.legado.app.base.BaseDialogFragment
|
||||||
|
import io.legado.app.base.adapter.ItemViewHolder
|
||||||
|
import io.legado.app.base.adapter.RecyclerAdapter
|
||||||
|
import io.legado.app.data.entities.RssReadRecord
|
||||||
|
import io.legado.app.databinding.DialogRecyclerViewBinding
|
||||||
|
import io.legado.app.databinding.ItemRssReadRecordBinding
|
||||||
|
import io.legado.app.lib.dialogs.alert
|
||||||
|
import io.legado.app.lib.theme.primaryColor
|
||||||
|
import io.legado.app.utils.setLayout
|
||||||
|
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||||
|
|
||||||
|
class ReadRecordDialog : BaseDialogFragment(R.layout.dialog_recycler_view),
|
||||||
|
Toolbar.OnMenuItemClickListener {
|
||||||
|
|
||||||
|
private val viewModel by viewModels<RssSortViewModel>()
|
||||||
|
private val binding by viewBinding(DialogRecyclerViewBinding::bind)
|
||||||
|
private val adapter by lazy {
|
||||||
|
ReadRecordAdapter(requireContext())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
setLayout(0.9f, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
binding.run {
|
||||||
|
toolBar.setBackgroundColor(primaryColor)
|
||||||
|
toolBar.setTitle(R.string.read_record)
|
||||||
|
toolBar.inflateMenu(R.menu.rss_read_record)
|
||||||
|
toolBar.setOnMenuItemClickListener(this@ReadRecordDialog)
|
||||||
|
recyclerView.layoutManager = LinearLayoutManager(requireContext())
|
||||||
|
recyclerView.adapter = adapter
|
||||||
|
}
|
||||||
|
adapter.setItems(viewModel.getRecord())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMenuItemClick(item: MenuItem?): Boolean {
|
||||||
|
when (item?.itemId) {
|
||||||
|
R.id.menu_clear -> {
|
||||||
|
alert(R.string.draw) {
|
||||||
|
val countRead = viewModel.countRead()
|
||||||
|
setMessage(getString(R.string.sure_del) + "\n" + countRead + " " + getString(R.string.read_record))
|
||||||
|
noButton()
|
||||||
|
yesButton{
|
||||||
|
viewModel.delReadRecord()
|
||||||
|
adapter.clearItems()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class ReadRecordAdapter(context: Context) :
|
||||||
|
RecyclerAdapter<RssReadRecord, ItemRssReadRecordBinding>(context) {
|
||||||
|
|
||||||
|
override fun getViewBinding(parent: ViewGroup): ItemRssReadRecordBinding {
|
||||||
|
return ItemRssReadRecordBinding.inflate(inflater, parent, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun convert(
|
||||||
|
holder: ItemViewHolder,
|
||||||
|
binding: ItemRssReadRecordBinding,
|
||||||
|
item: RssReadRecord,
|
||||||
|
payloads: MutableList<Any>
|
||||||
|
) {
|
||||||
|
binding.textTitle.text = item.title
|
||||||
|
binding.textRecord.text = item.record
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun registerListener(holder: ItemViewHolder, binding: ItemRssReadRecordBinding) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -14,7 +14,6 @@ import io.legado.app.R
|
|||||||
import io.legado.app.base.VMBaseActivity
|
import io.legado.app.base.VMBaseActivity
|
||||||
import io.legado.app.databinding.ActivityRssArtivlesBinding
|
import io.legado.app.databinding.ActivityRssArtivlesBinding
|
||||||
import io.legado.app.help.source.sortUrls
|
import io.legado.app.help.source.sortUrls
|
||||||
import io.legado.app.lib.dialogs.alert
|
|
||||||
import io.legado.app.lib.theme.accentColor
|
import io.legado.app.lib.theme.accentColor
|
||||||
import io.legado.app.ui.login.SourceLoginActivity
|
import io.legado.app.ui.login.SourceLoginActivity
|
||||||
import io.legado.app.ui.rss.source.edit.RssSourceEditActivity
|
import io.legado.app.ui.rss.source.edit.RssSourceEditActivity
|
||||||
@@ -92,8 +91,8 @@ class RssSortActivity : VMBaseActivity<ActivityRssArtivlesBinding, RssSortViewMo
|
|||||||
upFragments()
|
upFragments()
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_del_read_record -> {
|
R.id.menu_read_record -> {
|
||||||
delReadRecord()
|
showDialogFragment<ReadRecordDialog>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return super.onCompatOptionsItemSelected(item)
|
return super.onCompatOptionsItemSelected(item)
|
||||||
@@ -114,17 +113,6 @@ class RssSortActivity : VMBaseActivity<ActivityRssArtivlesBinding, RssSortViewMo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun delReadRecord() {
|
|
||||||
alert(R.string.draw) {
|
|
||||||
val countRead = viewModel.countRead()
|
|
||||||
setMessage(getString(R.string.sure_del) + "\n" + countRead + " " + getString(R.string.read_record))
|
|
||||||
noButton()
|
|
||||||
yesButton(){
|
|
||||||
viewModel.delReadRecord()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setSourceVariable() {
|
private fun setSourceVariable() {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val source = viewModel.rssSource
|
val source = viewModel.rssSource
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class RssSortViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
fun switchLayout() {
|
fun switchLayout() {
|
||||||
rssSource?.let {
|
rssSource?.let {
|
||||||
if (it.articleStyle < 2) {
|
if (it.articleStyle < 2) {
|
||||||
it.articleStyle = it.articleStyle + 1
|
it.articleStyle += 1
|
||||||
} else {
|
} else {
|
||||||
it.articleStyle = 0
|
it.articleStyle = 0
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,12 @@ class RssSortViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
|
|
||||||
fun read(rssArticle: RssArticle) {
|
fun read(rssArticle: RssArticle) {
|
||||||
execute {
|
execute {
|
||||||
appDb.rssArticleDao.insertRecord(RssReadRecord(rssArticle.link))
|
val rssReadRecord = RssReadRecord(
|
||||||
|
record = rssArticle.link,
|
||||||
|
title = rssArticle.title,
|
||||||
|
readTime = System.currentTimeMillis()
|
||||||
|
)
|
||||||
|
appDb.rssReadRecordDao.insertRecord(rssReadRecord)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,13 +77,17 @@ class RssSortViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getRecord(): List<RssReadRecord> {
|
||||||
|
return appDb.rssReadRecordDao.getRecord()
|
||||||
|
}
|
||||||
|
|
||||||
fun countRead() : Int {
|
fun countRead() : Int {
|
||||||
return appDb.rssArticleDao.countRead
|
return appDb.rssReadRecordDao.countRead
|
||||||
}
|
}
|
||||||
|
|
||||||
fun delReadRecord() {
|
fun delReadRecord() {
|
||||||
execute {
|
execute {
|
||||||
appDb.rssArticleDao.deleteRecord()
|
appDb.rssReadRecordDao.deleteRecord()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?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:padding="6dp"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_title"
|
||||||
|
android:text="@string/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textIsSelectable="true" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_record"
|
||||||
|
android:text="@string/read_record"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:autoLink="web"
|
||||||
|
android:textIsSelectable="true" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -27,14 +27,14 @@
|
|||||||
android:title="@string/switchLayout"
|
android:title="@string/switchLayout"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_read_record"
|
||||||
|
android:title="@string/read_record"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_clear"
|
android:id="@+id/menu_clear"
|
||||||
android:title="@string/clear"
|
android:title="@string/clear"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/menu_del_read_record"
|
|
||||||
android:title="@string/del_read_record"
|
|
||||||
app:showAsAction="never" />
|
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu 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"
|
||||||
|
tools:ignore="AlwaysShowAction">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_clear"
|
||||||
|
android:title="@string/clear"
|
||||||
|
app:showAsAction="always" />
|
||||||
|
|
||||||
|
</menu>
|
||||||
Reference in New Issue
Block a user