diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt index 52900a035..f3148ff59 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt @@ -8,7 +8,6 @@ import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.Toolbar import androidx.core.os.bundleOf import androidx.fragment.app.viewModels -import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import io.legado.app.R import io.legado.app.base.BaseDialogFragment @@ -17,6 +16,7 @@ import io.legado.app.constant.EventBus import io.legado.app.constant.PreferKey import io.legado.app.data.appDb import io.legado.app.data.entities.Book +import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.SearchBook import io.legado.app.databinding.DialogChapterChangeSourceBinding @@ -33,7 +33,8 @@ import kotlinx.coroutines.launch class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_change_source), Toolbar.OnMenuItemClickListener, - ChangeChapterSourceAdapter.CallBack { + ChangeChapterSourceAdapter.CallBack, + ChangeChapterTocAdapter.Callback { constructor(name: String, author: String, chapterIndex: Int, chapterTitle: String) : this() { arguments = Bundle().apply { @@ -48,11 +49,17 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c private val groups = linkedSetOf() private val callBack: CallBack? get() = activity as? CallBack private val viewModel: ChangeChapterSourceViewModel by viewModels() - private val adapter by lazy { ChangeChapterSourceAdapter(requireContext(), viewModel, this) } private val editSourceResult = registerForActivityResult(StartActivityContract(BookSourceEditActivity::class.java)) { viewModel.startSearch() } + private val searchBookAdapter by lazy { + ChangeChapterSourceAdapter(requireContext(), viewModel, this) + } + private val tocAdapter by lazy { + ChangeChapterTocAdapter(requireContext(), this) + } + private var searchBook: SearchBook? = null override fun onStart() { super.onStart() @@ -64,14 +71,14 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c viewModel.initData(arguments) showTitle() initMenu() + initView() initRecyclerView() initSearchView() initLiveData() } private fun showTitle() { - binding.toolBar.title = viewModel.name - binding.toolBar.subtitle = viewModel.author + binding.toolBar.title = viewModel.chapterTitle } private fun initMenu() { @@ -86,11 +93,16 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c ?.isChecked = AppConfig.changeSourceLoadToc } + private fun initView() { + binding.ivHideToc.setOnClickListener { + binding.clToc.gone() + } + } + private fun initRecyclerView() { - binding.recyclerView.layoutManager = LinearLayoutManager(context) binding.recyclerView.addItemDecoration(VerticalDivider(requireContext())) - binding.recyclerView.adapter = adapter - adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { + binding.recyclerView.adapter = searchBookAdapter + searchBookAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { if (positionStart == 0) { binding.recyclerView.scrollToPosition(0) @@ -103,6 +115,7 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c } } }) + binding.recyclerViewToc.adapter = tocAdapter } private fun initSearchView() { @@ -147,7 +160,7 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c launch { viewModel.searchDataFlow .collect { - adapter.setItems(it) + searchBookAdapter.setItems(it) delay(1000) } } @@ -198,8 +211,22 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c return false } + private val tocSuccess: (toc: List) -> Unit = { + tocAdapter.durChapterIndex = viewModel.chapterIndex + binding.loadingToc.hide() + tocAdapter.setItems(it) + binding.recyclerViewToc.scrollToPosition(tocAdapter.durChapterIndex - 5) + } + override fun openToc(searchBook: SearchBook) { + this.searchBook = searchBook + tocAdapter.setItems(null) binding.clToc.visible() + binding.loadingToc.show() + viewModel.getToc(searchBook, tocSuccess) { + binding.clToc.gone() + toastOnUi(it) + } } override val bookUrl: String? @@ -232,6 +259,10 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c } } + override fun clickChapter(bookChapter: BookChapter) { + TODO("Not yet implemented") + } + private fun changeSource(searchBook: SearchBook) { try { val book = searchBook.toBook() @@ -272,9 +303,9 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c override fun observeLiveBus() { observeEvent(EventBus.SOURCE_CHANGED) { - adapter.notifyItemRangeChanged( + searchBookAdapter.notifyItemRangeChanged( 0, - adapter.itemCount, + searchBookAdapter.itemCount, bundleOf(Pair("upCurSource", bookUrl)) ) } diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceViewModel.kt index 7bd3d05a1..86da71938 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceViewModel.kt @@ -16,6 +16,7 @@ import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.SearchBook import io.legado.app.help.AppConfig import io.legado.app.help.coroutine.CompositeCoroutine +import io.legado.app.model.NoStackTraceException import io.legado.app.model.webBook.WebBook import io.legado.app.utils.getPrefBoolean import io.legado.app.utils.getPrefString @@ -270,6 +271,29 @@ class ChangeChapterSourceViewModel(application: Application) : BaseViewModel(app searchPool?.close() } + fun getToc( + searchBook: SearchBook, + success: (toc: List) -> Unit, + error: (msg: String) -> Unit + ) { + execute { + return@execute tocMap[searchBook.bookUrl] + ?: let { + val book = searchBook.toBook() + val source = appDb.bookSourceDao.getBookSource(book.origin) + ?: throw NoStackTraceException("书源不存在") + if (book.tocUrl.isEmpty()) { + WebBook.getBookInfoAwait(this, source, book) + } + WebBook.getChapterListAwait(this, source, book) + } + }.onSuccess { + success(it) + }.onError { + error(it.localizedMessage ?: "获取目录出错") + } + } + fun disableSource(searchBook: SearchBook) { execute { appDb.bookSourceDao.getBookSource(searchBook.origin)?.let { source -> diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterTocAdapter.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterTocAdapter.kt index 9334cb261..44af00758 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterTocAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterTocAdapter.kt @@ -5,7 +5,6 @@ import android.view.ViewGroup import io.legado.app.R import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter -import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.databinding.ItemChapterListBinding import io.legado.app.lib.theme.ThemeUtils @@ -17,6 +16,8 @@ import io.legado.app.utils.visible class ChangeChapterTocAdapter(context: Context, val callback: Callback) : RecyclerAdapter(context) { + var durChapterIndex = 0 + override fun getViewBinding(parent: ViewGroup): ItemChapterListBinding { return ItemChapterListBinding.inflate(inflater, parent, false) } @@ -28,7 +29,7 @@ class ChangeChapterTocAdapter(context: Context, val callback: Callback) : payloads: MutableList ) { binding.run { - val isDur = callback.durChapterIndex() == item.index + val isDur = durChapterIndex == item.index if (isDur) { tvChapterName.setTextColor(context.accentColor) } else { @@ -58,14 +59,12 @@ class ChangeChapterTocAdapter(context: Context, val callback: Callback) : override fun registerListener(holder: ItemViewHolder, binding: ItemChapterListBinding) { holder.itemView.setOnClickListener { getItem(holder.layoutPosition)?.let { - callback.openChapter(it) + callback.clickChapter(it) } } } interface Callback { - val book: Book? - fun openChapter(bookChapter: BookChapter) - fun durChapterIndex(): Int + fun clickChapter(bookChapter: BookChapter) } } \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_chapter_change_source.xml b/app/src/main/res/layout/dialog_chapter_change_source.xml index 182d44f2f..3f9f6cd9a 100644 --- a/app/src/main/res/layout/dialog_chapter_change_source.xml +++ b/app/src/main/res/layout/dialog_chapter_change_source.xml @@ -29,6 +29,7 @@ android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="0dp" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@+id/refresh_progress_bar" /> @@ -53,10 +54,12 @@ android:id="@+id/recycler_view_toc" android:layout_width="match_parent" android:layout_height="0dp" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@+id/iv_hide_toc" />