Skip to content

Commit

Permalink
[Feat]: 媒体进度保存功能
Browse files Browse the repository at this point in the history
  • Loading branch information
why committed Dec 18, 2023
1 parent 6c02d2a commit 16d7d4b
Show file tree
Hide file tree
Showing 24 changed files with 515 additions and 69 deletions.
6 changes: 2 additions & 4 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,7 @@
<activity
android:name="com.xiaoyv.bangumi.ui.discover.blog.detail.BlogActivity"
android:configChanges="orientation|keyboard|screenSize"
android:exported="false"
android:launchMode="singleTask" />
android:exported="false" />
<activity
android:name="com.xiaoyv.bangumi.ui.profile.edit.EditProfileActivity"
android:configChanges="orientation|keyboard|screenSize"
Expand All @@ -130,8 +129,7 @@
<activity
android:name="com.xiaoyv.bangumi.ui.feature.topic.TopicActivity"
android:configChanges="orientation|keyboard|screenSize"
android:exported="false"
android:launchMode="singleTask" />
android:exported="false" />
<activity
android:name="com.xiaoyv.bangumi.ui.feature.user.UserActivity"
android:configChanges="orientation|keyboard|screenSize"
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/java/com/xiaoyv/bangumi/helper/RouteHelper.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.xiaoyv.bangumi.helper

import android.content.Intent
import android.webkit.URLUtil
import androidx.activity.result.ActivityResultLauncher
import androidx.core.os.bundleOf
import com.blankj.utilcode.util.ActivityUtils
Expand Down Expand Up @@ -70,6 +71,11 @@ object RouteHelper {

debugLog { "Handle Url: $titleLink" }

if (URLUtil.isNetworkUrl(titleLink) && !titleLink.contains("bgm") && !titleLink.contains("bangumi")) {
jumpWeb(titleLink, fitToolbar = true)
return true
}

when {
// 话题
titleLink.contains(BgmPathType.TYPE_TOPIC) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ package com.xiaoyv.bangumi.ui.discover.index.detail.page
import android.os.Bundle
import androidx.core.os.bundleOf
import androidx.fragment.app.activityViewModels
import com.xiaoyv.bangumi.R
import com.xiaoyv.bangumi.base.BaseListFragment
import com.xiaoyv.bangumi.helper.RouteHelper
import com.xiaoyv.bangumi.ui.discover.index.detail.IndexDetailViewModel
import com.xiaoyv.blueprint.constant.NavKey
import com.xiaoyv.common.api.parser.entity.IndexAttachEntity
import com.xiaoyv.common.config.annotation.BgmPathType
import com.xiaoyv.common.config.annotation.IndexTabCatType
import com.xiaoyv.common.config.annotation.TopicType
import com.xiaoyv.common.kts.setOnDebouncedChildClickListener
import com.xiaoyv.widget.binder.BaseQuickDiffBindingAdapter

/**
Expand All @@ -32,6 +37,19 @@ class IndexAttachFragment : BaseListFragment<IndexAttachEntity, IndexAttachViewM
super.initView()
}

override fun initListener() {
super.initListener()

contentAdapter.setOnDebouncedChildClickListener(R.id.item_index) {
when (it.pathType) {
BgmPathType.TYPE_SUBJECT -> RouteHelper.jumpMediaDetail(it.id)
BgmPathType.TYPE_PERSON -> RouteHelper.jumpPerson(it.id, false)
BgmPathType.TYPE_CHARACTER -> RouteHelper.jumpPerson(it.id, true)
BgmPathType.TYPE_EP -> RouteHelper.jumpTopicDetail(it.id, TopicType.TYPE_EP)
}
}
}

override fun onCreateContentAdapter(): BaseQuickDiffBindingAdapter<IndexAttachEntity, *> {
return IndexAttachAdapter()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package com.xiaoyv.bangumi.ui.media.action

import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.os.bundleOf
import androidx.core.view.updateLayoutParams
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentManager
import com.blankj.utilcode.util.ScreenUtils
import com.blankj.utilcode.util.SnackbarUtils
import com.xiaoyv.bangumi.R
import com.xiaoyv.bangumi.databinding.FragmentMediaActionEpBinding
import com.xiaoyv.bangumi.ui.media.detail.overview.binder.OverviewEpBinder
import com.xiaoyv.blueprint.constant.NavKey
import com.xiaoyv.blueprint.kts.launchUI
import com.xiaoyv.common.api.BgmApiManager
import com.xiaoyv.common.api.parser.entity.MediaDetailEntity
import com.xiaoyv.common.config.annotation.BgmPathType
import com.xiaoyv.common.helper.UserHelper
import com.xiaoyv.common.kts.hideSnackBar
import com.xiaoyv.common.kts.setOnDebouncedChildClickListener
import com.xiaoyv.common.kts.showSnackBar
import com.xiaoyv.widget.kts.dpi
import com.xiaoyv.widget.kts.errorMsg
import com.xiaoyv.widget.kts.getParcelObjList
import com.xiaoyv.widget.kts.updateWindowParams
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlin.math.roundToInt

/**
* Class: [MediaEpActionDialog]
*
* @author why
* @since 12/18/23
*/
class MediaEpActionDialog : DialogFragment() {
private var onSaveListener: ((Int) -> Unit)? = null

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
) = FragmentMediaActionEpBinding.inflate(inflater, container, false).root

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val mediaId = arguments?.getString(NavKey.KEY_STRING).orEmpty()
val mediaName = arguments?.getString(NavKey.KEY_STRING_SECOND).orEmpty()
val myProgress = arguments?.getInt(NavKey.KEY_INTEGER) ?: 0
val progresses =
arguments?.getParcelObjList<MediaDetailEntity.MediaProgress>(NavKey.KEY_PARCELABLE_LIST)
.orEmpty()

val binding = FragmentMediaActionEpBinding.bind(view)
initView(binding, mediaId, mediaName, progresses, myProgress)
}

private fun initView(
binding: FragmentMediaActionEpBinding,
mediaId: String,
mediaName: String,
progresses: List<MediaDetailEntity.MediaProgress>,
myProgress: Int,
) {
binding.tvTitle.text = mediaName
binding.ivCancel.setOnClickListener {
dismissAllowingStateLoss()
}

// 格子填充
val epAdapter = OverviewEpBinder.ItemEpAdapter(
selectedMode = true,
selectIndex = myProgress - 1
)
binding.rvEp.updateLayoutParams<ConstraintLayout.LayoutParams> {
matchConstraintMaxHeight = (ScreenUtils.getAppScreenHeight() * 0.7f).roundToInt()
}
binding.rvEp.hasFixedSize()
binding.rvEp.adapter = epAdapter

// 点击更新颜色
epAdapter.setOnDebouncedChildClickListener(R.id.item_ep) {
epAdapter.selectIndex = epAdapter.itemIndexOfFirst(it)
if (epAdapter.selectIndex >= 0 && epAdapter.selectIndex < epAdapter.itemCount) {
epAdapter.notifyItemRangeChanged(
0,
epAdapter.itemCount,
OverviewEpBinder.ItemEpAdapter.PAYLOAD_REFRESH_COLOR
)

finishEp(mediaId, it.number)
}

dismissAllowingStateLoss()
}

launchUI {
epAdapter.submitList(withContext(Dispatchers.IO) {
progresses.filterNot { it.isNotEp }
})
}
}

/**
* 保存进度
*/
private fun finishEp(mediaId: String, number: String) {
launchUI(
error = {
it.printStackTrace()

showSnackBar(it.errorMsg, error = true)
},
block = {
require(mediaId.isNotBlank()) { "条目信息丢失" }
require(number.isNotBlank()) { "章节信息丢失" }

showSnackBar("正在保存进度...", SnackbarUtils.LENGTH_INDEFINITE)

withContext(Dispatchers.IO) {
BgmApiManager.bgmWebApi.updateMediaProgress(mediaId, watch = number)
}

UserHelper.notifyActionChange(BgmPathType.TYPE_EP)
hideSnackBar()

onSaveListener?.invoke(number.toIntOrNull() ?: 0)
}
)
}

override fun onStart() {
super.onStart()
val dialog = dialog ?: return
val window = dialog.window ?: return

window.setBackgroundDrawableResource(android.R.color.transparent)
window.setDimAmount(0.25f)
window.updateWindowParams {
width = ScreenUtils.getScreenWidth() - 32.dpi
gravity = Gravity.CENTER
}
}

companion object {
fun show(
fragmentManager: FragmentManager,
mediaId: String,
mediaName: String,
totalEp: ArrayList<MediaDetailEntity.MediaProgress>?,
myProgress: Int = 0,
onSaveListener: ((Int) -> Unit)? = null,
) {
MediaEpActionDialog().apply {
this.onSaveListener = onSaveListener
this.arguments = bundleOf(
NavKey.KEY_STRING to mediaId,
NavKey.KEY_STRING_SECOND to mediaName,
NavKey.KEY_PARCELABLE_LIST to totalEp,
NavKey.KEY_INTEGER to myProgress
)
}.show(fragmentManager, "MediaEpActionDialog")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class MediaSaveActionDialog : DialogFragment() {
}
}

private var onUpdateResult: (MediaCollectForm) -> Unit = {}
private var onUpdateResult: (MediaDetailEntity) -> Unit = { _ -> }

override fun onCreateView(
inflater: LayoutInflater,
Expand Down Expand Up @@ -154,7 +154,7 @@ class MediaSaveActionDialog : DialogFragment() {
},
block = {
showLoading(binding)
val collectState = withContext(Dispatchers.IO) {
val media = withContext(Dispatchers.IO) {
val paramMap = mapOf(
"referer" to form.referer.ifBlank { "subject" },
"interest" to form.interest,
Expand All @@ -165,18 +165,13 @@ class MediaSaveActionDialog : DialogFragment() {
"update" to form.update.ifBlank { "保存" },
)

val collectState = BgmApiManager.bgmWebApi.updateInterest(
BgmApiManager.bgmWebApi.updateInterest(
map = paramMap,
mediaId = form.mediaId,
gh = form.gh
).parserMediaDetail().collectState

if (collectState.gh.isNotBlank()) {
return@withContext collectState
}
throw IllegalStateException("更新失败!")
).parserMediaDetail()
}
onUpdateResult(collectState)
onUpdateResult(media)

hideLoading(binding)

Expand Down Expand Up @@ -298,7 +293,7 @@ class MediaSaveActionDialog : DialogFragment() {
fun show(
fragmentManager: FragmentManager,
collectForm: MediaCollectForm?,
onUpdateResultListener: (MediaCollectForm) -> Unit = {},
onUpdateResultListener: (MediaDetailEntity) -> Unit = {},
) {
MediaSaveActionDialog()
.apply {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import androidx.core.os.bundleOf
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.LinearLayoutManager
import com.xiaoyv.bangumi.R
import com.xiaoyv.bangumi.databinding.FragmentOverviewBinding
import com.xiaoyv.bangumi.helper.RouteHelper
import com.xiaoyv.bangumi.ui.media.action.MediaEpActionDialog
import com.xiaoyv.bangumi.ui.media.action.MediaSaveActionDialog
import com.xiaoyv.bangumi.ui.media.detail.MediaDetailViewModel
import com.xiaoyv.blueprint.base.mvvm.normal.BaseViewModelFragment
Expand Down Expand Up @@ -89,6 +91,30 @@ class OverviewFragment : BaseViewModelFragment<FragmentOverviewBinding, Overview
}

override fun initListener() {
// 章节完成度点击
overviewAdapter.setOnDebouncedChildClickListener(R.id.tv_ep_my_progress) {
val position = overviewAdapter.itemIndexOfFirst(it)
val entity = viewModel.mediaDetailLiveData.value
?: return@setOnDebouncedChildClickListener

// 更新我的进度
if (entity.progressList.isEmpty().not()) {
MediaEpActionDialog.show(
childFragmentManager,
viewModel.mediaId,
viewModel.requireMediaName,
entity.progressList,
entity.myProgress
) { myProgress ->
entity.myProgress = myProgress

// 刷新章节的进度 Item
it.entity = entity
overviewAdapter[position] = it
}
}
}

overviewAdapter.setOnDebouncedChildClickListener(com.xiaoyv.common.R.id.tv_more) {
when (it.type) {
OverviewAdapter.TYPE_EP -> {
Expand Down Expand Up @@ -160,17 +186,22 @@ class OverviewFragment : BaseViewModelFragment<FragmentOverviewBinding, Overview
}
}


private fun showCollectPanel(item: OverviewAdapter.Item, position: Int) {
if (!UserHelper.isLogin) {
RouteHelper.jumpLogin()
return
}
val forceCast = item.entity.forceCast<MediaDetailEntity>()
MediaSaveActionDialog.show(childFragmentManager, forceCast.collectState) {

val media = item.entity.forceCast<MediaDetailEntity>()
MediaSaveActionDialog.show(childFragmentManager, media.collectState) {
val entity = viewModel.refreshCollectState(it) ?: return@show
item.entity = entity
// 刷新收藏的 Item
overviewAdapter[position] = item

// 刷新章节的进度 Item
overviewAdapter.getItem(position + 1)?.entity = entity
overviewAdapter.notifyItemChanged(position + 1)
}
}

Expand Down
Loading

0 comments on commit 16d7d4b

Please sign in to comment.