ソースを参照

[优化] 漫画功能扩展 #496

HapeLee 10 ヶ月 前
親
コミット
cf5f9c6674

+ 100 - 0
app/src/main/java/io/legado/app/ui/book/manga/ReadMangaActivity.kt

@@ -11,6 +11,7 @@ import android.view.MenuItem
 import android.view.WindowManager
 import android.view.WindowManager
 import android.view.animation.LinearInterpolator
 import android.view.animation.LinearInterpolator
 import androidx.activity.addCallback
 import androidx.activity.addCallback
+import androidx.activity.result.contract.ActivityResultContracts
 import androidx.activity.viewModels
 import androidx.activity.viewModels
 import androidx.appcompat.app.AlertDialog
 import androidx.appcompat.app.AlertDialog
 import androidx.core.view.doOnLayout
 import androidx.core.view.doOnLayout
@@ -29,22 +30,33 @@ import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
 import io.legado.app.BuildConfig
 import io.legado.app.BuildConfig
 import io.legado.app.R
 import io.legado.app.R
 import io.legado.app.base.VMBaseActivity
 import io.legado.app.base.VMBaseActivity
+import io.legado.app.constant.AppLog
 import io.legado.app.constant.BookType
 import io.legado.app.constant.BookType
 import io.legado.app.constant.EventBus
 import io.legado.app.constant.EventBus
+import io.legado.app.data.appDb
 import io.legado.app.data.entities.Book
 import io.legado.app.data.entities.Book
 import io.legado.app.data.entities.BookChapter
 import io.legado.app.data.entities.BookChapter
 import io.legado.app.data.entities.BookProgress
 import io.legado.app.data.entities.BookProgress
 import io.legado.app.data.entities.BookSource
 import io.legado.app.data.entities.BookSource
 import io.legado.app.databinding.ActivityMangaBinding
 import io.legado.app.databinding.ActivityMangaBinding
 import io.legado.app.databinding.ViewLoadMoreBinding
 import io.legado.app.databinding.ViewLoadMoreBinding
+import io.legado.app.exception.NoStackTraceException
+import io.legado.app.help.AppFreezeMonitor.handler
+import io.legado.app.help.book.BookHelp
 import io.legado.app.help.book.isImage
 import io.legado.app.help.book.isImage
+import io.legado.app.help.book.isLocal
 import io.legado.app.help.book.removeType
 import io.legado.app.help.book.removeType
 import io.legado.app.help.config.AppConfig
 import io.legado.app.help.config.AppConfig
+import io.legado.app.help.coroutine.Coroutine
+import io.legado.app.help.source.getSourceType
 import io.legado.app.help.storage.Backup
 import io.legado.app.help.storage.Backup
 import io.legado.app.lib.dialogs.SelectItem
 import io.legado.app.lib.dialogs.SelectItem
 import io.legado.app.lib.dialogs.alert
 import io.legado.app.lib.dialogs.alert
 import io.legado.app.lib.dialogs.selector
 import io.legado.app.lib.dialogs.selector
 import io.legado.app.model.ReadManga
 import io.legado.app.model.ReadManga
+import io.legado.app.model.analyzeRule.AnalyzeRule
+import io.legado.app.model.analyzeRule.AnalyzeRule.Companion.setChapter
+import io.legado.app.model.analyzeRule.AnalyzeRule.Companion.setCoroutineContext
 import io.legado.app.receiver.NetworkChangedListener
 import io.legado.app.receiver.NetworkChangedListener
 import io.legado.app.ui.book.changesource.ChangeBookSourceDialog
 import io.legado.app.ui.book.changesource.ChangeBookSourceDialog
 import io.legado.app.ui.book.info.BookInfoActivity
 import io.legado.app.ui.book.info.BookInfoActivity
@@ -64,7 +76,10 @@ import io.legado.app.ui.book.manga.recyclerview.ScrollTimer
 import io.legado.app.ui.book.manga.recyclerview.WebtoonFrame
 import io.legado.app.ui.book.manga.recyclerview.WebtoonFrame
 import io.legado.app.ui.book.read.MangaMenu
 import io.legado.app.ui.book.read.MangaMenu
 import io.legado.app.ui.book.read.ReadBookActivity.Companion.RESULT_DELETED
 import io.legado.app.ui.book.read.ReadBookActivity.Companion.RESULT_DELETED
+import io.legado.app.ui.book.source.edit.BookSourceEditActivity
 import io.legado.app.ui.book.toc.TocActivityResult
 import io.legado.app.ui.book.toc.TocActivityResult
+import io.legado.app.ui.browser.WebViewActivity
+import io.legado.app.ui.login.SourceLoginActivity
 import io.legado.app.ui.widget.number.NumberPickerDialog
 import io.legado.app.ui.widget.number.NumberPickerDialog
 import io.legado.app.ui.widget.recycler.LoadMoreView
 import io.legado.app.ui.widget.recycler.LoadMoreView
 import io.legado.app.utils.GSON
 import io.legado.app.utils.GSON
@@ -75,8 +90,11 @@ import io.legado.app.utils.fastBinarySearch
 import io.legado.app.utils.findCenterViewPosition
 import io.legado.app.utils.findCenterViewPosition
 import io.legado.app.utils.fromJsonObject
 import io.legado.app.utils.fromJsonObject
 import io.legado.app.utils.gone
 import io.legado.app.utils.gone
+import io.legado.app.utils.isAbsUrl
+import io.legado.app.utils.isTrue
 import io.legado.app.utils.observeEvent
 import io.legado.app.utils.observeEvent
 import io.legado.app.utils.showDialogFragment
 import io.legado.app.utils.showDialogFragment
+import io.legado.app.utils.startActivity
 import io.legado.app.utils.toastOnUi
 import io.legado.app.utils.toastOnUi
 import io.legado.app.utils.toggleSystemBar
 import io.legado.app.utils.toggleSystemBar
 import io.legado.app.utils.viewbindingdelegate.viewBinding
 import io.legado.app.utils.viewbindingdelegate.viewBinding
@@ -135,6 +153,17 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
         LinearInterpolator()
         LinearInterpolator()
     }
     }
 
 
+    private val sourceEditActivity =
+        registerForActivityResult(StartActivityContract(BookSourceEditActivity::class.java)) {
+            if (it.resultCode == RESULT_OK) {
+                viewModel.upBookSource {
+                    handler.post {
+                        binding.mangaMenu.upBookView()
+                    }
+                }
+            }
+        }
+
     private val loadMoreView by lazy {
     private val loadMoreView by lazy {
         LoadMoreView(this).apply {
         LoadMoreView(this).apply {
 //            setBackgroundColor(getCompatColor(R.color.book_ant_10))
 //            setBackgroundColor(getCompatColor(R.color.book_ant_10))
@@ -565,6 +594,77 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
         return super.onCompatCreateOptionsMenu(menu)
         return super.onCompatCreateOptionsMenu(menu)
     }
     }
 
 
+
+    override fun showLogin() {
+        ReadManga.bookSource?.let {
+            startActivity<SourceLoginActivity> {
+                putExtra("type", "bookSource")
+                putExtra("key", it.bookSourceUrl)
+            }
+        }
+    }
+
+    override fun payAction() {
+        val book = ReadManga.book ?: return
+        if (book.isLocal) return
+        val chapter = appDb.bookChapterDao.getChapter(book.bookUrl, ReadManga.durChapterIndex)
+        if (chapter == null) {
+            toastOnUi("no chapter")
+            return
+        }
+        alert(R.string.chapter_pay) {
+            setMessage(chapter.title)
+            yesButton {
+                Coroutine.async(lifecycleScope) {
+                    val source =
+                        ReadManga.bookSource ?: throw NoStackTraceException("no book source")
+                    val payAction = source.getContentRule().payAction
+                    if (payAction.isNullOrBlank()) {
+                        throw NoStackTraceException("no pay action")
+                    }
+                    val analyzeRule = AnalyzeRule(book, source)
+                    analyzeRule.setCoroutineContext(coroutineContext)
+                    analyzeRule.setBaseUrl(chapter.url)
+                    analyzeRule.setChapter(chapter)
+                    analyzeRule.evalJS(payAction).toString()
+                }.onSuccess(IO) {
+                    if (it.isAbsUrl()) {
+                        startActivity<WebViewActivity> {
+                            val bookSource = ReadManga.bookSource
+                            putExtra("title", getString(R.string.chapter_pay))
+                            putExtra("url", it)
+                            putExtra("sourceOrigin", bookSource?.bookSourceUrl)
+                            putExtra("sourceName", bookSource?.bookSourceName)
+                            putExtra("sourceType", bookSource?.getSourceType())
+                        }
+                    } else if (it.isTrue()) {
+                        //购买成功后刷新目录
+                        ReadManga.book?.let {
+                            ReadManga.curMangaChapter = null
+                            BookHelp.delContent(book, chapter)
+                            viewModel.loadChapterList(book)
+                        }
+                    }
+                }.onError {
+                    AppLog.put("执行购买操作出错\n${it.localizedMessage}", it, true)
+                }
+            }
+            noButton()
+        }
+    }
+
+    override fun disableSource() {
+        viewModel.disableSource()
+    }
+
+    override fun openSourceEditActivity() {
+        ReadManga.bookSource?.let {
+            sourceEditActivity.launch {
+                putExtra("sourceUrl", it.bookSourceUrl)
+            }
+        }
+    }
+
     /**
     /**
      * 菜单
      * 菜单
      */
      */

+ 26 - 0
app/src/main/java/io/legado/app/ui/book/manga/ReadMangaViewModel.kt

@@ -24,6 +24,7 @@ import io.legado.app.help.book.removeType
 import io.legado.app.help.book.simulatedTotalChapterNum
 import io.legado.app.help.book.simulatedTotalChapterNum
 import io.legado.app.help.config.AppConfig
 import io.legado.app.help.config.AppConfig
 import io.legado.app.help.coroutine.Coroutine
 import io.legado.app.help.coroutine.Coroutine
+import io.legado.app.model.ReadBook
 import io.legado.app.model.ReadManga
 import io.legado.app.model.ReadManga
 import io.legado.app.model.localBook.LocalBook
 import io.legado.app.model.localBook.LocalBook
 import io.legado.app.model.webBook.WebBook
 import io.legado.app.model.webBook.WebBook
@@ -120,6 +121,31 @@ class ReadMangaViewModel(application: Application) : BaseViewModel(application)
         }
         }
     }
     }
 
 
+    fun upBookSource(success: (() -> Unit)?) {
+        execute {
+            ReadManga.book?.let { book ->
+                ReadManga.bookSource = appDb.bookSourceDao.getBookSource(book.origin)
+            }
+        }.onSuccess {
+            success?.invoke()
+        }
+    }
+
+    fun loadChapterList(book: Book) {
+        execute {
+            loadChapterListAwait(book)
+        }
+    }
+
+    fun disableSource() {
+        execute {
+            ReadManga.bookSource?.let {
+                it.enabled = false
+                appDb.bookSourceDao.update(it)
+            }
+        }
+    }
+
     private suspend fun loadChapterListAwait(book: Book): Boolean {
     private suspend fun loadChapterListAwait(book: Book): Boolean {
         ReadManga.bookSource?.let {
         ReadManga.bookSource?.let {
             val oldBook = book.copy()
             val oldBook = book.copy()

+ 28 - 1
app/src/main/java/io/legado/app/ui/book/read/MangaMenu.kt

@@ -7,6 +7,7 @@ import android.util.AttributeSet
 import android.view.LayoutInflater
 import android.view.LayoutInflater
 import android.view.animation.Animation
 import android.view.animation.Animation
 import android.widget.FrameLayout
 import android.widget.FrameLayout
+import androidx.appcompat.widget.PopupMenu
 import androidx.core.view.isGone
 import androidx.core.view.isGone
 import androidx.core.view.isVisible
 import androidx.core.view.isVisible
 import com.google.android.material.slider.Slider
 import com.google.android.material.slider.Slider
@@ -37,6 +38,22 @@ class MangaMenu @JvmOverloads constructor(
     private val binding = ViewMangaMenuBinding.inflate(LayoutInflater.from(context), this, true)
     private val binding = ViewMangaMenuBinding.inflate(LayoutInflater.from(context), this, true)
     private val callBack: CallBack get() = activity as CallBack
     private val callBack: CallBack get() = activity as CallBack
     var canShowMenu: Boolean = false
     var canShowMenu: Boolean = false
+
+    private val sourceMenu by lazy {
+        PopupMenu(context, binding.tvSourceAction).apply {
+            inflate(R.menu.book_read_source)
+            setOnMenuItemClickListener {
+                when (it.itemId) {
+                    R.id.menu_login -> callBack.showLogin()
+                    R.id.menu_chapter_pay -> callBack.payAction()
+                    R.id.menu_edit_source -> callBack.openSourceEditActivity()
+                    R.id.menu_disable_source -> callBack.disableSource()
+                }
+                true
+            }
+        }
+    }
+
     private val menuTopIn: Animation by lazy {
     private val menuTopIn: Animation by lazy {
         loadAnimation(context, R.anim.anim_readbook_top_in)
         loadAnimation(context, R.anim.anim_readbook_top_in)
     }
     }
@@ -207,11 +224,17 @@ class MangaMenu @JvmOverloads constructor(
             }
             }
             true
             true
         }
         }
+        tvBookName.setOnClickListener{
+            callBack.openBookInfoActivity()
+        }
         tvChapterName.setOnClickListener(chapterViewClickListener)
         tvChapterName.setOnClickListener(chapterViewClickListener)
         tvChapterName.setOnLongClickListener(chapterViewLongClickListener)
         tvChapterName.setOnLongClickListener(chapterViewLongClickListener)
         tvChapterUrl.setOnClickListener(chapterViewClickListener)
         tvChapterUrl.setOnClickListener(chapterViewClickListener)
         tvChapterUrl.setOnLongClickListener(chapterViewLongClickListener)
         tvChapterUrl.setOnLongClickListener(chapterViewLongClickListener)
-
+        tvSourceAction.setOnLongClickListener {
+            sourceMenu.show()
+            true
+        }
         tvNext.setOnClickListener {
         tvNext.setOnClickListener {
             ReadManga.moveToNextChapter(true)
             ReadManga.moveToNextChapter(true)
         }
         }
@@ -282,6 +305,10 @@ class MangaMenu @JvmOverloads constructor(
         fun showFooterConfig()
         fun showFooterConfig()
         fun showScrollModeDialog()
         fun showScrollModeDialog()
         fun onAutoPageToggle2()
         fun onAutoPageToggle2()
+        fun showLogin()
+        fun payAction()
+        fun openSourceEditActivity()
+        fun disableSource()
     }
     }
 
 
 }
 }