优化
This commit is contained in:
@@ -108,6 +108,7 @@ abstract class RecyclerAdapter<ITEM, VB : ViewBinding>(protected val context: Co
|
|||||||
@Synchronized
|
@Synchronized
|
||||||
fun setItems(items: List<ITEM>?, itemCallback: DiffUtil.ItemCallback<ITEM>) {
|
fun setItems(items: List<ITEM>?, itemCallback: DiffUtil.ItemCallback<ITEM>) {
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
|
val oldItems = this.items.toList()
|
||||||
val callback = object : DiffUtil.Callback() {
|
val callback = object : DiffUtil.Callback() {
|
||||||
override fun getOldListSize(): Int {
|
override fun getOldListSize(): Int {
|
||||||
return itemCount
|
return itemCount
|
||||||
@@ -118,7 +119,7 @@ abstract class RecyclerAdapter<ITEM, VB : ViewBinding>(protected val context: Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
||||||
val oldItem = getItem(oldItemPosition - getHeaderCount())
|
val oldItem = oldItems.getOrNull(oldItemPosition - getHeaderCount())
|
||||||
?: return true
|
?: return true
|
||||||
val newItem = items?.getOrNull(newItemPosition - getHeaderCount())
|
val newItem = items?.getOrNull(newItemPosition - getHeaderCount())
|
||||||
?: return true
|
?: return true
|
||||||
@@ -129,7 +130,7 @@ abstract class RecyclerAdapter<ITEM, VB : ViewBinding>(protected val context: Co
|
|||||||
oldItemPosition: Int,
|
oldItemPosition: Int,
|
||||||
newItemPosition: Int
|
newItemPosition: Int
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val oldItem = getItem(oldItemPosition - getHeaderCount())
|
val oldItem = oldItems.getOrNull(oldItemPosition - getHeaderCount())
|
||||||
?: return true
|
?: return true
|
||||||
val newItem = items?.getOrNull(newItemPosition - getHeaderCount())
|
val newItem = items?.getOrNull(newItemPosition - getHeaderCount())
|
||||||
?: return true
|
?: return true
|
||||||
@@ -137,7 +138,7 @@ abstract class RecyclerAdapter<ITEM, VB : ViewBinding>(protected val context: Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
|
override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
|
||||||
val oldItem = getItem(oldItemPosition - getHeaderCount())
|
val oldItem = oldItems.getOrNull(oldItemPosition - getHeaderCount())
|
||||||
?: return null
|
?: return null
|
||||||
val newItem = items?.getOrNull(newItemPosition - getHeaderCount())
|
val newItem = items?.getOrNull(newItemPosition - getHeaderCount())
|
||||||
?: return null
|
?: return null
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ object BookType {
|
|||||||
|
|
||||||
@Target(AnnotationTarget.VALUE_PARAMETER)
|
@Target(AnnotationTarget.VALUE_PARAMETER)
|
||||||
@Retention(AnnotationRetention.SOURCE)
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
@IntDef(text, updateError, audio, image, webFile, local)
|
@IntDef(text, updateError, audio, image, webFile, local, archive)
|
||||||
annotation class Type
|
annotation class Type
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ interface TxtTocRuleDao {
|
|||||||
@get:Query("select * from txtTocRules where enable != 1 order by serialNumber")
|
@get:Query("select * from txtTocRules where enable != 1 order by serialNumber")
|
||||||
val disabled: List<TxtTocRule>
|
val disabled: List<TxtTocRule>
|
||||||
|
|
||||||
|
@get:Query("select count(*) from txtTocRules")
|
||||||
|
val count: Int
|
||||||
|
|
||||||
@Query("select * from txtTocRules where id = :id")
|
@Query("select * from txtTocRules where id = :id")
|
||||||
fun get(id: Long): TxtTocRule?
|
fun get(id: Long): TxtTocRule?
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import io.legado.app.R
|
|||||||
import io.legado.app.constant.IntentAction
|
import io.legado.app.constant.IntentAction
|
||||||
import io.legado.app.data.entities.BookSource
|
import io.legado.app.data.entities.BookSource
|
||||||
import io.legado.app.help.CacheManager
|
import io.legado.app.help.CacheManager
|
||||||
|
import io.legado.app.help.IntentData
|
||||||
import io.legado.app.service.CheckSourceService
|
import io.legado.app.service.CheckSourceService
|
||||||
import io.legado.app.utils.startService
|
import io.legado.app.utils.startService
|
||||||
import splitties.init.appCtx
|
import splitties.init.appCtx
|
||||||
@@ -26,9 +27,9 @@ object CheckSource {
|
|||||||
sources.map {
|
sources.map {
|
||||||
selectedIds.add(it.bookSourceUrl)
|
selectedIds.add(it.bookSourceUrl)
|
||||||
}
|
}
|
||||||
|
IntentData.put("checkSourceSelectedIds", selectedIds)
|
||||||
context.startService<CheckSourceService> {
|
context.startService<CheckSourceService> {
|
||||||
action = IntentAction.start
|
action = IntentAction.start
|
||||||
putExtra("selectIds", selectedIds)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -212,11 +212,8 @@ object LocalBook {
|
|||||||
val files = ArchiveUtils.deCompress(archiveFileDoc, filter = filter)
|
val files = ArchiveUtils.deCompress(archiveFileDoc, filter = filter)
|
||||||
if (files.isEmpty()) throw NoStackTraceException(appCtx.getString(R.string.unsupport_archivefile_entry))
|
if (files.isEmpty()) throw NoStackTraceException(appCtx.getString(R.string.unsupport_archivefile_entry))
|
||||||
return files.map {
|
return files.map {
|
||||||
saveBookFile(
|
saveBookFile(FileInputStream(it), saveFileName ?: it.name).let { uri ->
|
||||||
FileInputStream(it),
|
importFile(uri).apply {
|
||||||
saveFileName ?: it.name
|
|
||||||
).let {
|
|
||||||
importFile(it).apply {
|
|
||||||
//附加压缩包名称 以便解压文件被删后再解压
|
//附加压缩包名称 以便解压文件被删后再解压
|
||||||
origin = "${BookType.localTag}::${archiveFileDoc.name}"
|
origin = "${BookType.localTag}::${archiveFileDoc.name}"
|
||||||
addType(BookType.archive)
|
addType(BookType.archive)
|
||||||
@@ -255,8 +252,8 @@ object LocalBook {
|
|||||||
importFile(uri)
|
importFile(uri)
|
||||||
}
|
}
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
AppLog.put("ImportFile Error:\nFile ${fileDoc.toString()}\n${it.localizedMessage}", it)
|
AppLog.put("ImportFile Error:\nFile $fileDoc\n${it.localizedMessage}", it)
|
||||||
errorCount = errorCount + 1
|
errorCount += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (errorCount == uris.size) throw NoStackTraceException("ImportFiles Error:\nAll input files occur error")
|
if (errorCount == uris.size) throw NoStackTraceException("ImportFiles Error:\nAll input files occur error")
|
||||||
@@ -409,8 +406,8 @@ object LocalBook {
|
|||||||
if (localBook.isArchive) {
|
if (localBook.isArchive) {
|
||||||
// 压缩包
|
// 压缩包
|
||||||
val archiveUri = saveBookFile(it, localBook.archiveName)
|
val archiveUri = saveBookFile(it, localBook.archiveName)
|
||||||
val newBook = importArchiveFile(archiveUri, localBook.originName) {
|
val newBook = importArchiveFile(archiveUri, localBook.originName) { name ->
|
||||||
it.contains(localBook.originName)
|
name.contains(localBook.originName)
|
||||||
}.first()
|
}.first()
|
||||||
localBook.origin = newBook.origin
|
localBook.origin = newBook.origin
|
||||||
localBook.bookUrl = newBook.bookUrl
|
localBook.bookUrl = newBook.bookUrl
|
||||||
|
|||||||
@@ -407,7 +407,7 @@ class TextFile(private val book: Book) {
|
|||||||
*/
|
*/
|
||||||
private fun getTocRules(): List<TxtTocRule> {
|
private fun getTocRules(): List<TxtTocRule> {
|
||||||
var rules = appDb.txtTocRuleDao.enabled
|
var rules = appDb.txtTocRuleDao.enabled
|
||||||
if (rules.isEmpty()) {
|
if (appDb.txtTocRuleDao.count == 0) {
|
||||||
rules = DefaultData.txtTocRules.apply {
|
rules = DefaultData.txtTocRules.apply {
|
||||||
appDb.txtTocRuleDao.insert(*this.toTypedArray())
|
appDb.txtTocRuleDao.insert(*this.toTypedArray())
|
||||||
}.filter {
|
}.filter {
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ abstract class BaseReadAloudService : BaseService(),
|
|||||||
internal var pageIndex = 0
|
internal var pageIndex = 0
|
||||||
private var needResumeOnAudioFocusGain = false
|
private var needResumeOnAudioFocusGain = false
|
||||||
private var dsJob: Job? = null
|
private var dsJob: Job? = null
|
||||||
|
var pageChanged = false
|
||||||
|
|
||||||
private val broadcastReceiver = object : BroadcastReceiver() {
|
private val broadcastReceiver = object : BroadcastReceiver() {
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
@@ -157,7 +158,7 @@ abstract class BaseReadAloudService : BaseService(),
|
|||||||
contentList.add(text)
|
contentList.add(text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (play) play()
|
if (play) play() else pageChanged = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import io.legado.app.data.entities.BookSource
|
|||||||
import io.legado.app.exception.ContentEmptyException
|
import io.legado.app.exception.ContentEmptyException
|
||||||
import io.legado.app.exception.NoStackTraceException
|
import io.legado.app.exception.NoStackTraceException
|
||||||
import io.legado.app.exception.TocEmptyException
|
import io.legado.app.exception.TocEmptyException
|
||||||
|
import io.legado.app.help.IntentData
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
import io.legado.app.help.source.exploreKinds
|
import io.legado.app.help.source.exploreKinds
|
||||||
import io.legado.app.model.CheckSource
|
import io.legado.app.model.CheckSource
|
||||||
@@ -65,12 +66,12 @@ class CheckSourceService : BaseService() {
|
|||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
when (intent?.action) {
|
when (intent?.action) {
|
||||||
IntentAction.start -> intent.getStringArrayListExtra("selectIds")?.let {
|
IntentAction.start -> IntentData.get<ArrayList<String>>("checkSourceSelectedIds")?.let {
|
||||||
check(it)
|
check(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
IntentAction.resume -> upNotification()
|
IntentAction.resume -> upNotification()
|
||||||
else -> stopSelf()
|
IntentAction.stop -> stopSelf()
|
||||||
}
|
}
|
||||||
return super.onStartCommand(intent, flags, startId)
|
return super.onStartCommand(intent, flags, startId)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ class HttpReadAloudService : BaseReadAloudService(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun play() {
|
override fun play() {
|
||||||
|
pageChanged = false
|
||||||
exoPlayer.stop()
|
exoPlayer.stop()
|
||||||
if (contentList.isEmpty()) {
|
if (contentList.isEmpty()) {
|
||||||
AppLog.putDebug("朗读列表为空")
|
AppLog.putDebug("朗读列表为空")
|
||||||
@@ -285,8 +286,12 @@ class HttpReadAloudService : BaseReadAloudService(),
|
|||||||
override fun resumeReadAloud() {
|
override fun resumeReadAloud() {
|
||||||
super.resumeReadAloud()
|
super.resumeReadAloud()
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
exoPlayer.play()
|
if (pageChanged) {
|
||||||
upPlayPos()
|
play()
|
||||||
|
} else {
|
||||||
|
exoPlayer.play()
|
||||||
|
upPlayPos()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ abstract class BaseImportBookActivity<VM : ViewModel> : VMBaseActivity<ActivityI
|
|||||||
binding.titleBar.findViewById(R.id.search_view)
|
binding.titleBar.findViewById(R.id.search_view)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val localBookTreeSelect = registerForActivityResult(HandleFileContract()) {
|
val localBookTreeSelect = registerForActivityResult(HandleFileContract()) {
|
||||||
it.uri?.let { treeUri ->
|
it.uri?.let { treeUri ->
|
||||||
AppConfig.defaultBookTreeUri = treeUri.toString()
|
AppConfig.defaultBookTreeUri = treeUri.toString()
|
||||||
localBookTreeSelectListener?.invoke(true)
|
localBookTreeSelectListener?.invoke(true)
|
||||||
@@ -61,10 +61,12 @@ abstract class BaseImportBookActivity<VM : ViewModel> : VMBaseActivity<ActivityI
|
|||||||
*/
|
*/
|
||||||
protected suspend fun setBookStorage() = suspendCoroutine { block ->
|
protected suspend fun setBookStorage() = suspendCoroutine { block ->
|
||||||
localBookTreeSelectListener = {
|
localBookTreeSelectListener = {
|
||||||
|
localBookTreeSelectListener = null
|
||||||
block.resume(it)
|
block.resume(it)
|
||||||
}
|
}
|
||||||
//测试书籍保存位置是否设置
|
//测试书籍保存位置是否设置
|
||||||
if (!AppConfig.defaultBookTreeUri.isNullOrBlank()) {
|
if (!AppConfig.defaultBookTreeUri.isNullOrBlank()) {
|
||||||
|
localBookTreeSelectListener = null
|
||||||
block.resume(true)
|
block.resume(true)
|
||||||
return@suspendCoroutine
|
return@suspendCoroutine
|
||||||
}
|
}
|
||||||
@@ -78,9 +80,11 @@ abstract class BaseImportBookActivity<VM : ViewModel> : VMBaseActivity<ActivityI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
noButton {
|
noButton {
|
||||||
|
localBookTreeSelectListener = null
|
||||||
block.resume(false)
|
block.resume(false)
|
||||||
}
|
}
|
||||||
onCancelled {
|
onCancelled {
|
||||||
|
localBookTreeSelectListener = null
|
||||||
block.resume(false)
|
block.resume(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,14 @@ class RemoteBookActivity : BaseImportBookActivity<RemoteBookViewModel>(),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun observeLiveBus() {
|
||||||
|
viewModel.permissionDenialLiveData.observe(this) {
|
||||||
|
localBookTreeSelect.launch {
|
||||||
|
title = getString(R.string.select_book_folder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun initView() {
|
private fun initView() {
|
||||||
binding.layTop.setBackgroundColor(backgroundColor)
|
binding.layTop.setBackgroundColor(backgroundColor)
|
||||||
binding.recyclerView.layoutManager = LinearLayoutManager(this)
|
binding.recyclerView.layoutManager = LinearLayoutManager(this)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package io.legado.app.ui.book.import.remote
|
package io.legado.app.ui.book.import.remote
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
import io.legado.app.base.BaseViewModel
|
import io.legado.app.base.BaseViewModel
|
||||||
import io.legado.app.constant.AppLog
|
import io.legado.app.constant.AppLog
|
||||||
import io.legado.app.constant.BookType
|
import io.legado.app.constant.BookType
|
||||||
@@ -25,6 +26,7 @@ class RemoteBookViewModel(application: Application) : BaseViewModel(application)
|
|||||||
var sortKey = RemoteBookSort.Default
|
var sortKey = RemoteBookSort.Default
|
||||||
var sortAscending = false
|
var sortAscending = false
|
||||||
val dirList = arrayListOf<RemoteBook>()
|
val dirList = arrayListOf<RemoteBook>()
|
||||||
|
val permissionDenialLiveData = MutableLiveData<Int>()
|
||||||
|
|
||||||
var dataCallback: DataCallback? = null
|
var dataCallback: DataCallback? = null
|
||||||
|
|
||||||
@@ -141,6 +143,9 @@ class RemoteBookViewModel(application: Application) : BaseViewModel(application)
|
|||||||
}.onError {
|
}.onError {
|
||||||
AppLog.put("导入出错\n${it.localizedMessage}", it)
|
AppLog.put("导入出错\n${it.localizedMessage}", it)
|
||||||
context.toastOnUi("导入出错\n${it.localizedMessage}")
|
context.toastOnUi("导入出错\n${it.localizedMessage}")
|
||||||
|
if (it is SecurityException) {
|
||||||
|
permissionDenialLiveData.postValue(1)
|
||||||
|
}
|
||||||
}.onFinally {
|
}.onFinally {
|
||||||
finally.invoke()
|
finally.invoke()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class BookSourceAdapter(context: Context, val callBack: CallBack) :
|
|||||||
ItemTouchCallback.Callback {
|
ItemTouchCallback.Callback {
|
||||||
|
|
||||||
private val selected = linkedSetOf<BookSource>()
|
private val selected = linkedSetOf<BookSource>()
|
||||||
|
private val finalMessageRegex = Regex("成功|失败")
|
||||||
|
|
||||||
val selection: List<BookSource>
|
val selection: List<BookSource>
|
||||||
get() {
|
get() {
|
||||||
@@ -94,9 +95,7 @@ class BookSourceAdapter(context: Context, val callBack: CallBack) :
|
|||||||
cbBookSource.text = item.getDisPlayNameGroup()
|
cbBookSource.text = item.getDisPlayNameGroup()
|
||||||
swtEnabled.isChecked = item.enabled
|
swtEnabled.isChecked = item.enabled
|
||||||
cbBookSource.isChecked = selected.contains(item)
|
cbBookSource.isChecked = selected.contains(item)
|
||||||
ivDebugText.text = Debug.debugMessageMap[item.bookSourceUrl] ?: ""
|
upCheckSourceMessage(binding, item)
|
||||||
ivDebugText.visibility =
|
|
||||||
if (ivDebugText.text.toString().isNotBlank()) View.VISIBLE else View.GONE
|
|
||||||
upShowExplore(ivExplore, item)
|
upShowExplore(ivExplore, item)
|
||||||
} else {
|
} else {
|
||||||
payload.keySet().map {
|
payload.keySet().map {
|
||||||
@@ -105,21 +104,7 @@ class BookSourceAdapter(context: Context, val callBack: CallBack) :
|
|||||||
"upName" -> cbBookSource.text = item.getDisPlayNameGroup()
|
"upName" -> cbBookSource.text = item.getDisPlayNameGroup()
|
||||||
"upExplore" -> upShowExplore(ivExplore, item)
|
"upExplore" -> upShowExplore(ivExplore, item)
|
||||||
"selected" -> cbBookSource.isChecked = selected.contains(item)
|
"selected" -> cbBookSource.isChecked = selected.contains(item)
|
||||||
"checkSourceMessage" -> {
|
"checkSourceMessage" -> upCheckSourceMessage(binding, item)
|
||||||
ivDebugText.text = Debug.debugMessageMap[item.bookSourceUrl] ?: ""
|
|
||||||
val isEmpty = ivDebugText.text.toString().isEmpty()
|
|
||||||
var isFinalMessage =
|
|
||||||
ivDebugText.text.toString().contains(Regex("成功|失败"))
|
|
||||||
if (!Debug.isChecking && !isFinalMessage) {
|
|
||||||
Debug.updateFinalMessage(item.bookSourceUrl, "校验失败")
|
|
||||||
ivDebugText.text = Debug.debugMessageMap[item.bookSourceUrl] ?: ""
|
|
||||||
isFinalMessage = true
|
|
||||||
}
|
|
||||||
ivDebugText.visibility =
|
|
||||||
if (!isEmpty) View.VISIBLE else View.GONE
|
|
||||||
ivProgressBar.visibility =
|
|
||||||
if (isFinalMessage || isEmpty || !Debug.isChecking) View.GONE else View.VISIBLE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,6 +205,22 @@ class BookSourceAdapter(context: Context, val callBack: CallBack) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun upCheckSourceMessage(binding: ItemBookSourceBinding, item: BookSource) = binding.run {
|
||||||
|
val msg = Debug.debugMessageMap[item.bookSourceUrl] ?: ""
|
||||||
|
ivDebugText.text = msg
|
||||||
|
val isEmpty = msg.isEmpty()
|
||||||
|
var isFinalMessage = msg.contains(finalMessageRegex)
|
||||||
|
if (!Debug.isChecking && !isFinalMessage) {
|
||||||
|
Debug.updateFinalMessage(item.bookSourceUrl, "校验失败")
|
||||||
|
ivDebugText.text = Debug.debugMessageMap[item.bookSourceUrl] ?: ""
|
||||||
|
isFinalMessage = true
|
||||||
|
}
|
||||||
|
ivDebugText.visibility =
|
||||||
|
if (!isEmpty) View.VISIBLE else View.GONE
|
||||||
|
ivProgressBar.visibility =
|
||||||
|
if (isFinalMessage || isEmpty || !Debug.isChecking) View.GONE else View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
fun selectAll() {
|
fun selectAll() {
|
||||||
getItems().forEach {
|
getItems().forEach {
|
||||||
selected.add(it)
|
selected.add(it)
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ import android.view.MenuItem
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
@@ -30,7 +32,6 @@ import io.legado.app.ui.widget.recycler.ItemTouchCallback
|
|||||||
import io.legado.app.ui.widget.recycler.VerticalDivider
|
import io.legado.app.ui.widget.recycler.VerticalDivider
|
||||||
import io.legado.app.utils.*
|
import io.legado.app.utils.*
|
||||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
|
||||||
import kotlinx.coroutines.flow.conflate
|
import kotlinx.coroutines.flow.conflate
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@@ -108,7 +109,7 @@ class TxtTocRuleDialog() : BaseDialogFragment(R.layout.dialog_toc_regex),
|
|||||||
launch {
|
launch {
|
||||||
appDb.txtTocRuleDao.observeAll().conflate().collect { tocRules ->
|
appDb.txtTocRuleDao.observeAll().conflate().collect { tocRules ->
|
||||||
initSelectedName(tocRules)
|
initSelectedName(tocRules)
|
||||||
adapter.setItems(tocRules)
|
adapter.setItems(tocRules, adapter.diffItemCallBack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,6 +192,43 @@ class TxtTocRuleDialog() : BaseDialogFragment(R.layout.dialog_toc_regex),
|
|||||||
RecyclerAdapter<TxtTocRule, ItemTocRegexBinding>(context),
|
RecyclerAdapter<TxtTocRule, ItemTocRegexBinding>(context),
|
||||||
ItemTouchCallback.Callback {
|
ItemTouchCallback.Callback {
|
||||||
|
|
||||||
|
val diffItemCallBack = object : DiffUtil.ItemCallback<TxtTocRule>() {
|
||||||
|
|
||||||
|
override fun areItemsTheSame(oldItem: TxtTocRule, newItem: TxtTocRule): Boolean {
|
||||||
|
return oldItem.id == newItem.id
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: TxtTocRule, newItem: TxtTocRule): Boolean {
|
||||||
|
if (oldItem.name != newItem.name) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (oldItem.enable != newItem.enable) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (oldItem.example != newItem.example) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getChangePayload(oldItem: TxtTocRule, newItem: TxtTocRule): Any? {
|
||||||
|
val payload = Bundle()
|
||||||
|
if (oldItem.name != newItem.name) {
|
||||||
|
payload.putBoolean("upName", true)
|
||||||
|
}
|
||||||
|
if (oldItem.enable != newItem.enable) {
|
||||||
|
payload.putBoolean("enabled", newItem.enable)
|
||||||
|
}
|
||||||
|
if (oldItem.example != newItem.example) {
|
||||||
|
payload.putBoolean("upExample", true)
|
||||||
|
}
|
||||||
|
if (payload.isEmpty) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return payload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun getViewBinding(parent: ViewGroup): ItemTocRegexBinding {
|
override fun getViewBinding(parent: ViewGroup): ItemTocRegexBinding {
|
||||||
return ItemTocRegexBinding.inflate(inflater, parent, false)
|
return ItemTocRegexBinding.inflate(inflater, parent, false)
|
||||||
}
|
}
|
||||||
@@ -202,14 +240,22 @@ class TxtTocRuleDialog() : BaseDialogFragment(R.layout.dialog_toc_regex),
|
|||||||
payloads: MutableList<Any>
|
payloads: MutableList<Any>
|
||||||
) {
|
) {
|
||||||
binding.apply {
|
binding.apply {
|
||||||
if (payloads.isEmpty()) {
|
val bundle = payloads.getOrNull(0) as? Bundle
|
||||||
|
if (bundle == null) {
|
||||||
root.setBackgroundColor(context.backgroundColor)
|
root.setBackgroundColor(context.backgroundColor)
|
||||||
rbRegexName.text = item.name
|
rbRegexName.text = item.name
|
||||||
titleExample.text = item.example
|
titleExample.text = item.example
|
||||||
rbRegexName.isChecked = item.name == selectedName
|
rbRegexName.isChecked = item.name == selectedName
|
||||||
swtEnabled.isChecked = item.enable
|
swtEnabled.isChecked = item.enable
|
||||||
} else {
|
} else {
|
||||||
rbRegexName.isChecked = item.name == selectedName
|
bundle.keySet().map {
|
||||||
|
when (it) {
|
||||||
|
"upNmae" -> rbRegexName.text = item.name
|
||||||
|
"upExample" -> titleExample.text = item.example
|
||||||
|
"enabled" -> swtEnabled.isChecked = item.enable
|
||||||
|
"upSelect" -> rbRegexName.isChecked = item.name == selectedName
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,16 +265,14 @@ class TxtTocRuleDialog() : BaseDialogFragment(R.layout.dialog_toc_regex),
|
|||||||
rbRegexName.setOnCheckedChangeListener { buttonView, isChecked ->
|
rbRegexName.setOnCheckedChangeListener { buttonView, isChecked ->
|
||||||
if (buttonView.isPressed && isChecked) {
|
if (buttonView.isPressed && isChecked) {
|
||||||
selectedName = getItem(holder.layoutPosition)?.name
|
selectedName = getItem(holder.layoutPosition)?.name
|
||||||
updateItems(0, itemCount - 1, true)
|
updateItems(0, itemCount - 1, bundleOf("upSelect" to null))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
swtEnabled.setOnCheckedChangeListener { buttonView, isChecked ->
|
swtEnabled.setOnCheckedChangeListener { buttonView, isChecked ->
|
||||||
if (buttonView.isPressed) {
|
if (buttonView.isPressed) {
|
||||||
getItem(holder.layoutPosition)?.let {
|
getItem(holder.layoutPosition)?.let {
|
||||||
it.enable = isChecked
|
it.enable = isChecked
|
||||||
launch(IO) {
|
viewModel.update(it)
|
||||||
appDb.txtTocRuleDao.update(it)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,9 +281,7 @@ class TxtTocRuleDialog() : BaseDialogFragment(R.layout.dialog_toc_regex),
|
|||||||
}
|
}
|
||||||
ivDelete.setOnClickListener {
|
ivDelete.setOnClickListener {
|
||||||
getItem(holder.layoutPosition)?.let { item ->
|
getItem(holder.layoutPosition)?.let { item ->
|
||||||
launch(IO) {
|
viewModel.del(item)
|
||||||
appDb.txtTocRuleDao.delete(item)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -259,9 +301,7 @@ class TxtTocRuleDialog() : BaseDialogFragment(R.layout.dialog_toc_regex),
|
|||||||
for ((index, item) in getItems().withIndex()) {
|
for ((index, item) in getItems().withIndex()) {
|
||||||
item.serialNumber = index + 1
|
item.serialNumber = index + 1
|
||||||
}
|
}
|
||||||
launch(IO) {
|
viewModel.update(*getItems().toTypedArray())
|
||||||
appDb.txtTocRuleDao.update(*getItems().toTypedArray())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
isMoved = false
|
isMoved = false
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user