kunfei 4 лет назад
Родитель
Сommit
997ea23f60

+ 42 - 11
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<String>()
     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<BookChapter>) -> 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<String>(EventBus.SOURCE_CHANGED) {
-            adapter.notifyItemRangeChanged(
+            searchBookAdapter.notifyItemRangeChanged(
                 0,
-                adapter.itemCount,
+                searchBookAdapter.itemCount,
                 bundleOf(Pair("upCurSource", bookUrl))
             )
         }

+ 24 - 0
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<BookChapter>) -> 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 ->

+ 5 - 6
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<BookChapter, ItemChapterListBinding>(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<Any>
     ) {
         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)
     }
 }

+ 3 - 0
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" />
 
         <io.legado.app.ui.widget.anima.RotateLoading
+            android:id="@+id/loading_toc"
             android:layout_width="36dp"
             android:layout_height="36dp"
             android:visibility="gone"