From 381ce29ae9a6fa2a12d092614c32808404fde70c Mon Sep 17 00:00:00 2001 From: lyr <15622190878@163.com> Date: Mon, 22 Nov 2021 18:06:43 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E5=85=89=E7=8E=AF=E5=8A=A9=E6=89=8BV5?= =?UTF-8?q?.5.0=E3=80=91=E6=B8=B8=E6=88=8F=E5=8D=95=E8=AF=A6=E6=83=85-?= =?UTF-8?q?=E7=8E=A9=E5=AE=B6=E8=AF=84=E8=AE=BA=20https://git.ghzs.com/pm/?= =?UTF-8?q?halo-app-issues/-/issues/1602=EF=BC=8C=20=E3=80=90=E5=85=89?= =?UTF-8?q?=E7=8E=AF=E5=8A=A9=E6=89=8BV5.5.0=E3=80=91=E6=B8=B8=E6=88=8F?= =?UTF-8?q?=E5=8D=95=E8=AF=A6=E6=83=85-=E9=A1=B6=E9=83=A8=E5=8C=BA?= =?UTF-8?q?=E5=9F=9F/=E6=B8=B8=E6=88=8F=E5=88=97=E8=A1=A8(=E5=AF=B9?= =?UTF-8?q?=E6=8E=A5=E8=A7=86=E9=A2=91=E6=95=B0=E6=8D=AE)=20https://git.gh?= =?UTF-8?q?zs.com/pm/halo-app-issues/-/issues/1601?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/gh/common/util/PostCommentUtils.java | 23 ++ .../detail/GameCollectionDetailAdapter.kt | 328 +++++++++++++++- .../detail/GameCollectionDetailFragment.kt | 352 +++++++++++++++--- .../detail/GameCollectionDetailViewModel.kt | 138 +++---- .../detail/GameCollectionVideoView.kt | 13 +- .../gamecenter/qa/comment/CommentActivity.kt | 75 ++++ .../qa/comment/NewCommentAdapter.kt | 3 + .../qa/comment/NewCommentFragment.kt | 56 ++- .../qa/comment/NewCommentViewModel.kt | 24 +- .../qa/comment/StairsCommentFragment.kt | 3 + .../qa/comment/StairsCommentViewHolder.kt | 3 + .../qa/comment/base/BaseCommentAdapter.kt | 2 + .../CommentConversationFragment.kt | 24 +- .../CommentConversationViewModel.kt | 9 + .../retrofit/service/ApiService.java | 42 +++ .../fragment_game_collection_detail.xml | 21 +- .../game_collection_detail_video_item.xml | 2 +- app/src/main/res/values/strings.xml | 1 + 18 files changed, 963 insertions(+), 156 deletions(-) diff --git a/app/src/main/java/com/gh/common/util/PostCommentUtils.java b/app/src/main/java/com/gh/common/util/PostCommentUtils.java index dec59ec097..7001a34262 100644 --- a/app/src/main/java/com/gh/common/util/PostCommentUtils.java +++ b/app/src/main/java/com/gh/common/util/PostCommentUtils.java @@ -284,6 +284,29 @@ public class PostCommentUtils { }); } + public static void reportGameCollectionComment(final Context context, + final String gameCollectionId, + final String commentId, + final String reportData, + final PostCommentListener listener) { + RequestBody body = RequestBody.create(MediaType.parse("application/json"), reportData); + RetrofitManager.getInstance(context).getApi() + .reportGameCollectionComment(gameCollectionId, commentId, body) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Response() { + @Override + public void onResponse(ResponseBody response) { + listener.postSuccess(null); + } + + @Override + public void onFailure(HttpException e) { + listener.postFailed(e); + } + }); + } + public interface PostCommentListener { void postSuccess(JSONObject response); diff --git a/app/src/main/java/com/gh/gamecenter/gamecollection/detail/GameCollectionDetailAdapter.kt b/app/src/main/java/com/gh/gamecenter/gamecollection/detail/GameCollectionDetailAdapter.kt index f366fac421..32601eec57 100644 --- a/app/src/main/java/com/gh/gamecenter/gamecollection/detail/GameCollectionDetailAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/gamecollection/detail/GameCollectionDetailAdapter.kt @@ -1,19 +1,38 @@ package com.gh.gamecenter.gamecollection.detail import android.content.Context +import android.text.SpannableStringBuilder +import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.LinearLayout +import android.widget.TextView import androidx.databinding.DataBindingUtil +import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView +import com.gh.common.constant.Constants import com.gh.common.constant.ItemViewType +import com.gh.common.json.json +import com.gh.common.util.* +import com.gh.common.view.BugFixedPopupWindow +import com.gh.common.view.GridSpacingItemColorDecoration import com.gh.gamecenter.R import com.gh.gamecenter.adapter.viewholder.FooterViewHolder -import com.gh.gamecenter.adapter.viewholder.GameCollectionItemViewHolder import com.gh.gamecenter.baselist.ListAdapter -import com.gh.gamecenter.entity.GamesCollectionEntity +import com.gh.gamecenter.baselist.LoadType +import com.gh.gamecenter.databinding.ItemArticleDetailCommentBinding +import com.gh.gamecenter.entity.CommentEntity +import com.gh.gamecenter.qa.comment.CommentActivity +import com.gh.gamecenter.qa.comment.CommentPictureAdapter +import com.gh.gamecenter.qa.comment.base.BaseCommentAdapter +import com.halo.assistant.HaloApp +import com.lightgame.utils.Utils +import org.json.JSONObject +import retrofit2.HttpException class GameCollectionDetailAdapter(context: Context, - private val mViewModel: GameCollectionDetailViewModel -): ListAdapter(context) { + private val mEntrance: String, + private val mViewModel: GameCollectionDetailViewModel) : ListAdapter(context) { override fun getItemCount(): Int { return if (mEntityList == null || mEntityList.isEmpty()) return 0 else mEntityList.size + 1 @@ -29,7 +48,15 @@ class GameCollectionDetailAdapter(context: Context, override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return when (viewType) { - ItemViewType.ITEM_BODY -> GameCollectionItemViewHolder(DataBindingUtil.inflate(mLayoutInflater, R.layout.game_collection_item, parent, false)) + ItemViewType.ITEM_BODY -> { + val binding: ItemArticleDetailCommentBinding = DataBindingUtil.inflate( + mLayoutInflater, + R.layout.item_article_detail_comment, + parent, + false + ) + BaseCommentAdapter.CommentItemViewHolder(binding, BaseCommentAdapter.AdapterType.COMMENT) + } else -> FooterViewHolder(mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false)) } @@ -37,11 +64,296 @@ class GameCollectionDetailAdapter(context: Context, override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { when (holder) { - is GameCollectionItemViewHolder -> { - + is BaseCommentAdapter.CommentItemViewHolder -> { + bindComment(holder.binding, mEntityList[position]) } - is FooterViewHolder -> holder.initFooterViewHolder(mViewModel, mIsLoading, mIsNetworkError, mIsOver) + is FooterViewHolder -> { + holder.initFooterViewHolder( + mIsLoading, + mIsNetworkError, + mIsOver, + R.string.game_collection_load_over_hint + ) { + if (isNetworkError) mViewModel.load(LoadType.RETRY) + } + } } } + + private fun bindComment( + binding: ItemArticleDetailCommentBinding, + comment: CommentEntity + ) { + binding.run { + if (!comment.images.isNullOrEmpty()) { + if (commentPictureRv.adapter == null) { + commentPictureRv.apply { + layoutManager = GridLayoutManager(context, 3) + adapter = CommentPictureAdapter(context, comment.images!!, "") + if (itemDecorationCount == 0) { + addItemDecoration(GridSpacingItemColorDecoration(context, 2, R.color.white)) + } + visibility = View.VISIBLE + } + } else { + (commentPictureRv.adapter as CommentPictureAdapter).checkResetData(comment.images!!) + } + } + + this.comment = comment + contentTv.setExpandMaxLines(if (comment.isExpand) Int.MAX_VALUE else 4) + contentTv.setIsExpanded(comment.isExpand) + collapseTv.goneIf(!comment.isExpand) + contentTv.setExpandCallback { + comment.isExpand = true + collapseTv.visibility = View.VISIBLE + this.comment = comment + } + collapseTv.setOnClickListener { + comment.isExpand = false + collapseTv.visibility = View.GONE + contentTv.setExpandMaxLines(4) + contentTv.setIsExpanded(false) + this.comment = comment + } + userIconIv.display( + comment.user.border, + comment.user.icon, + comment.user.auth?.icon + ) + + userIconIv.setOnClickListener { + DirectUtils.directToHomeActivity( + mContext, + comment.user.id, + "", + "游戏单详情-评论" + ) + } + + userNameTv.setOnClickListener { + DirectUtils.directToHomeActivity( + mContext, + comment.user.id, + "", + "游戏单详情-评论" + ) + } + + likeCountTv.text = mViewModel.getLikeText(comment.vote) + + if (comment.me?.isCommentVoted == true) { + likeCountTv.setCompoundDrawablesWithIntrinsicBounds( + R.drawable.comment_vote_select, + 0, + 0, + 0 + ) + } else { + likeCountTv.setCompoundDrawablesWithIntrinsicBounds( + R.drawable.comment_vote_unselect, + 0, + 0, + 0 + ) + } + + likeCountTv.setDebouncedClickListener { + likeCountTv.context.ifLogin("游戏单详情-评论-点赞") { + mViewModel.postVoteGameCollectionComment(comment) { + likeCountTv.setCompoundDrawablesWithIntrinsicBounds( + if (comment.me?.isCommentVoted == true) R.drawable.comment_vote_select else R.drawable.comment_vote_unselect, + 0, + 0, + 0 + ) + likeCountTv.text = mViewModel.getLikeText(comment.vote) + } + } + } + + badgeTv.setOnClickListener { + DialogUtils.showViewBadgeDialog(mContext, comment.user.badge) { + DirectUtils.directToBadgeWall( + mContext, + comment.user.id, + comment.user.name, + comment.user.icon + ) + } + } + + badgeIv.setOnClickListener { badgeTv.performClick() } + + moreIv.setOnClickListener { showCommentOption(it, comment) } + + updateSubComment(this, comment) + + floorHintTv.visibility = View.GONE + + root.setOnClickListener { + mViewModel.gameCollectionDetail?.run { + mContext.startActivity( + CommentActivity.getGameCollectionCommentReplyIntent( + mContext, + id, + comment.id ?: "", + count?.comment ?: 0, + comment + ) + ) + } + } + + commentCountTv.setOnClickListener { + mContext.startActivity( + CommentActivity.getGameCollectionCommentDetailIntent( + mContext, + comment.id ?: "", + mViewModel.gameCollectionId, + false, + mEntrance, + "游戏单详情" + ) + ) + } + + contentTv.text = comment.content + + commentCountTv.text = mViewModel.getCommentText(comment.reply, "回复") + } + } + + private fun updateSubComment( + binding: ItemArticleDetailCommentBinding, + comment: CommentEntity, + ) { + val subCommentList = comment.subCommentList + val ownerUserId = mViewModel.gameCollectionDetail?.user?.id + binding.moreSubCommentBtn.goneIf(comment.reply < 3) + binding.moreSubCommentBtn.text = "查看全部${comment.reply}条回复" + binding.subCommentContainer.goneIf(subCommentList.isNullOrEmpty()) + binding.firstSubCommentTv.goneIf(subCommentList?.firstOrNull() == null) + binding.secondSubCommentTv.goneIf(subCommentList?.secondOrNull() == null) + binding.subCommentContainer.setRoundedColorBackground(R.color.text_F5F5F5, 5F) + + subCommentList?.firstOrNull()?.let { + binding.firstSubCommentTv.text = getSubCommentSpanned( + it.user.name, + if (it.user.id == ownerUserId) "作者" else "", + it.content + ) + } + subCommentList?.secondOrNull()?.let { + binding.secondSubCommentTv.text = getSubCommentSpanned( + it.user.name, + if (it.user.id == ownerUserId) "作者" else "", + it.content + ) + } + binding.subCommentContainer.setOnClickListener { + mContext.startActivity( + CommentActivity.getGameCollectionCommentDetailIntent( + mContext, + comment.id ?: "", + mViewModel.gameCollectionId, + false, + mEntrance, + "游戏单详情" + ) + ) + } + } + + private fun getSubCommentSpanned( + name: String?, + author: String?, + content: String? + ): SpannableStringBuilder { + val finalAuthor = author ?: "" + val finalName = "$name " + val colon = " :" + + val nameSpan = + SpanBuilder(finalName).color(0, finalName.length, R.color.theme_font).build() + val authorSpan = if (finalAuthor.isNotEmpty()) SpanBuilder(finalAuthor).image( + 0, + finalAuthor.length, + R.drawable.ic_hint_author + ).build() else "" + val colonSpan = SpanBuilder(colon).color(0, colon.length, R.color.theme_font).build() + return SpannableStringBuilder().append(nameSpan).append(authorSpan).append(colonSpan) + .append(content) + } + + private fun showCommentOption(view: View, comment: CommentEntity) { + val dialogOptions = listOf("复制", "投诉") + val inflater = LayoutInflater.from(mContext) + val layout = inflater.inflate(R.layout.layout_popup_container, null) + val popupWindow = BugFixedPopupWindow( + layout, + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + val container = layout.findViewById(R.id.container) + for (text in dialogOptions) { + val item = inflater.inflate(R.layout.layout_popup_option_item, container, false) + container.addView(item) + val hitText = item.findViewById(R.id.hint_text) + hitText.text = text + item.setOnClickListener { + popupWindow.dismiss() + when (text) { + "复制" -> CommentUtils.copyText(comment.content, mContext) + + "投诉" -> { + mContext.ifLogin("游戏单详情-评论-投诉") { + DialogUtils.showReportReasonDialog( + mContext, + Constants.REPORT_LIST.toList() as ArrayList + ) { reason, desc -> + val json = json { + "reason" to if (reason != "其他原因") reason else desc + } + + val commentListener = + object : PostCommentUtils.PostCommentListener { + override fun postSuccess(response: JSONObject?) { + Utils.toast(mContext, "感谢您的投诉") + } + + override fun postFailed(error: Throwable?) { + if (error == null) { + Utils.toast(mContext, "投诉失败,请稍后重试") + } else { + if (error is HttpException) { + ErrorHelper.handleError( + HaloApp.getInstance().application, + error.response().errorBody()?.string() + ) + } + } + } + } + + PostCommentUtils.reportGameCollectionComment( + mContext, + mViewModel.gameCollectionId, + comment.id, + json.toString(), + commentListener + ) + } + } + } + } + } + } + + popupWindow.isTouchable = true + popupWindow.isFocusable = true + + popupWindow.showAutoOrientation(view) + } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/gamecollection/detail/GameCollectionDetailFragment.kt b/app/src/main/java/com/gh/gamecenter/gamecollection/detail/GameCollectionDetailFragment.kt index 84eef46d1b..ef2f67bd6c 100644 --- a/app/src/main/java/com/gh/gamecenter/gamecollection/detail/GameCollectionDetailFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/gamecollection/detail/GameCollectionDetailFragment.kt @@ -1,29 +1,48 @@ package com.gh.gamecenter.gamecollection.detail +import android.app.Activity +import android.content.Intent import android.graphics.Color +import android.graphics.drawable.InsetDrawable import android.os.Bundle import android.view.View import androidx.annotation.ColorRes import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat import androidx.lifecycle.Lifecycle +import androidx.recyclerview.widget.DefaultItemAnimator import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import butterknife.OnClick +import com.gh.common.constant.Constants import com.gh.common.history.HistoryHelper import com.gh.common.util.* +import com.gh.common.view.CustomDividerItemDecoration import com.gh.common.xapk.XapkInstaller import com.gh.common.xapk.XapkUnzipStatus import com.gh.download.DownloadManager import com.gh.gamecenter.R import com.gh.gamecenter.baselist.ListFragment +import com.gh.gamecenter.baselist.LoadType import com.gh.gamecenter.databinding.FragmentGameCollectionDetailBinding import com.gh.gamecenter.databinding.LayoutGameCollectionTagBinding import com.gh.gamecenter.entity.* import com.gh.gamecenter.eventbus.EBUserFollow +import com.gh.gamecenter.gamedetail.GameDetailFragment +import com.gh.gamecenter.home.video.ScrollCalculatorHelper import com.gh.gamecenter.manager.UserManager +import com.gh.gamecenter.qa.comment.CommentActivity import com.gh.gamecenter.qa.comment.base.BaseCommentViewModel +import com.gh.gamecenter.setting.VideoSettingFragment +import com.gh.gamecenter.video.detail.CustomManager import com.google.android.material.appbar.AppBarLayout import com.lightgame.download.DataWatcher import com.lightgame.download.DownloadEntity +import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder +import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack +import com.shuyu.gsyvideoplayer.utils.OrientationUtils +import com.shuyu.gsyvideoplayer.video.base.GSYVideoView +import kotlinx.android.synthetic.main.piece_game_detail_video.* import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode import kotlin.math.abs @@ -38,6 +57,8 @@ class GameCollectionDetailFragment : private var mGameCollectionId = "" private var mFromSquare = false private var mIsLight = false + private var mIsPauseTopVideo = false + private var mOrientationUtils: OrientationUtils? = null private val mDataWatcher = object : DataWatcher() { override fun onDataChanged(downloadEntity: DownloadEntity) { mGameAdapter?.notifyItemByDownload(downloadEntity) @@ -56,7 +77,15 @@ class GameCollectionDetailFragment : override fun provideListViewModel() = viewModelProvider(GameCollectionDetailViewModel.Factory(mGameCollectionId)) - override fun provideListAdapter() = mAdapter ?: GameCollectionDetailAdapter(requireContext(), mListViewModel).apply { mAdapter = this } + override fun provideListAdapter() = + mAdapter ?: GameCollectionDetailAdapter(requireContext(), mEntrance, mListViewModel).apply { mAdapter = this } + + override fun getItemDecoration(): RecyclerView.ItemDecoration { + val insetDivider = InsetDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.divider_article_detail_comment), 20F.dip2px(), 0, 20F.dip2px(), 0) + val itemDecoration = CustomDividerItemDecoration(requireContext(), notDecorateTheLastItem = true) + itemDecoration.setDrawable(insetDivider) + return itemDecoration + } override fun onCreate(savedInstanceState: Bundle?) { mGameCollectionId = arguments?.getString(EntranceUtils.KEY_ID) ?: "" @@ -71,33 +100,12 @@ class GameCollectionDetailFragment : initAppbarListener() } - override fun onResume() { - if (isEverPause && mAdapter != null) mGameAdapter?.notifyDataSetChanged() - super.onResume() - DownloadManager.getInstance(context).addObserver(mDataWatcher) - } - - override fun onPause() { - super.onPause() - DownloadManager.getInstance(context).removeObserver(mDataWatcher) - } - - override fun onDestroyView() { - super.onDestroyView() - mEntity?.run { - HistoryHelper.insertGamesCollectionEntity(this) - } - } - private fun initView() { mBinding?.run { inputContainer.run { bottomShareGroup.visibility = View.VISIBLE replyTv.setBackgroundResource(R.drawable.button_round_f5f5f5) replyTv.text = "说点什么吧" - replyTv.setDebouncedClickListener { - startCommentActivity() - } } } } @@ -133,32 +141,42 @@ class GameCollectionDetailFragment : mListRefresh?.isEnabled = absVerticalOffset <= 2 mBinding?.run { - mEntity?.run { - val bgOffset = if (video == null) { - imageItem.root.bottom - DisplayUtils.getStatusBarHeight(resources) - 48F.dip2px() - } else { - videoItem.player.bottom - DisplayUtils.getStatusBarHeight(resources) - 48F.dip2px() + val bgOffset = if (mListViewModel.displayTopVideo) { + videoItem.player.bottom - DisplayUtils.getStatusBarHeight(resources) - 48F.dip2px() + } else { + imageItem.root.bottom - DisplayUtils.getStatusBarHeight(resources) - 48F.dip2px() + } + mIsLight = absVerticalOffset < bgOffset + updateFollowView() + if (mIsLight) { + DisplayUtils.setStatusBarColor(requireActivity(), R.color.transparent, false) + toolbarContainer.setBackgroundColor(Color.TRANSPARENT) + backIv.setImageResource(R.drawable.ic_bar_back_light) + squareIv.setImageResource(R.drawable.ic_game_collection_square_light) + toolbarUserContainer.visibility = View.GONE + if (!mListViewModel.displayTopVideo) { + toolbarLightUserContainer.visibility = View.VISIBLE } - mIsLight = absVerticalOffset < bgOffset - updateFollowView() - if (mIsLight) { - DisplayUtils.setStatusBarColor(requireActivity(), R.color.transparent, false) - toolbarContainer.setBackgroundColor(Color.TRANSPARENT) - backIv.setImageResource(R.drawable.ic_bar_back_light) - squareIv.setImageResource(R.drawable.ic_game_collection_square_light) - toolbarUserContainer.visibility = View.GONE - if (video == null) { - toolbarLightUserContainer.visibility = View.VISIBLE - } - } else { - DisplayUtils.setStatusBarColor(requireActivity(), R.color.white, true) - toolbarContainer.setBackgroundColor(Color.WHITE) - backIv.setImageResource(R.drawable.ic_bar_back) - squareIv.setImageResource(R.drawable.ic_game_collection_square) - toolbarUserContainer.visibility = View.VISIBLE - if (video == null) { - toolbarLightUserContainer.visibility = View.GONE + } else { + DisplayUtils.setStatusBarColor(requireActivity(), R.color.white, true) + toolbarContainer.setBackgroundColor(Color.WHITE) + backIv.setImageResource(R.drawable.ic_bar_back) + squareIv.setImageResource(R.drawable.ic_game_collection_square) + toolbarUserContainer.visibility = View.VISIBLE + if (!mListViewModel.displayTopVideo) { + toolbarLightUserContainer.visibility = View.GONE + } + } + + if (mListViewModel.displayTopVideo) { + if (absVerticalOffset == bgOffset) { + if (videoItem.player.currentState == GSYVideoView.CURRENT_STATE_PLAYING) { + pauseVideo() + mIsPauseTopVideo = true } + } else if (mIsPauseTopVideo && absVerticalOffset == 0 && videoItem.player.currentState == GSYVideoView.CURRENT_STATE_PAUSE) { + resumeVideo() + mIsPauseTopVideo = false } } } @@ -170,6 +188,9 @@ class GameCollectionDetailFragment : updateFollowView() updateStartView() updateLikeView() + mBinding?.run { + commentHintCountTv.text = mEntity?.count?.comment.toString() + } } private fun initTopView() { @@ -184,7 +205,7 @@ class GameCollectionDetailFragment : squareIv.goneIf(mFromSquare) } - if (mEntity?.video == null) { + if (!mListViewModel.displayTopVideo) { imageItem.root.visibility = View.VISIBLE videoItem.root.visibility = View.GONE initImageTypeView() @@ -198,6 +219,7 @@ class GameCollectionDetailFragment : noneGameContainer.root.visibility = View.GONE gameListRv.run { visibility = View.VISIBLE + (itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false layoutManager = LinearLayoutManager(requireContext()) mGameAdapter = GameCollectionDetailGameAdapter(requireContext(), mEntity?.games ?: listOf()) adapter = mGameAdapter @@ -273,6 +295,8 @@ class GameCollectionDetailFragment : } userIcon.display(user?.border, user?.icon, user?.auth?.icon) + + setUpTopVideo(video!!) } } } @@ -292,7 +316,7 @@ class GameCollectionDetailFragment : } private fun updateFollowView() { - if (mEntity?.video == null) { + if (!mListViewModel.displayTopVideo) { updateImageItemFollowView() } else { updateVideoItemFollowView() @@ -348,7 +372,7 @@ class GameCollectionDetailFragment : private fun updateLikeView() { mBinding?.inputContainer?.run { - bottomLikeTv.text = mListViewModel.getLikeText() + bottomLikeTv.text = mListViewModel.getLikeText(mEntity?.count?.vote ?: 0) if (mEntity?.me?.vote == true) { bottomLikeIv.setImageResource(R.drawable.ic_article_detail_liked_bottom_bar) bottomLikeTv.setTextColor(R.color.theme_font.toColor()) @@ -359,17 +383,81 @@ class GameCollectionDetailFragment : } } - private fun startCommentActivity() { - mEntity?.run { -// val intent = CommentActivity.getQuestionCommentIntent( -// requireContext(), -// it.id ?: "", -// it.count.answer, -// true, -// it.community.id, -// true -// ) -// startActivityForResult(intent, CommentActivity.REQUEST_CODE) + private fun setUpTopVideo(topVideo: VideoEntity) { + mBinding?.videoItem?.player?.run { + mOrientationUtils = OrientationUtils(requireActivity(), player) + mOrientationUtils?.isEnable = false + + GSYVideoOptionBuilder() + .setIsTouchWigetFull(false) + .setIsTouchWiget(false) + .setRotateViewAuto(false) + .setShowFullAnimation(false) + .setSeekRatio(1f) + .setUrl(topVideo.url) + .setCacheWithPlay(true) + .setVideoAllCallBack(object : GSYSampleCallBack() { + override fun onQuitFullscreen(url: String?, vararg objects: Any) { + mOrientationUtils?.backToProtVideo() + uploadVideoStreamingPlaying("退出全屏") + } + }) + .build(this) + +// gameName = mGameEntity?.name ?: "" + viewModel = mListViewModel + video = topVideo + updateThumb(topVideo.poster) + + //val trafficVideo = PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SettingsFragment.TRAFFIC_VIDEO_SP_KEY, false) + val videoOption = SPUtils.getString( + Constants.SP_HOME_OR_DETAIL_VIDEO_OPTION, + VideoSettingFragment.VIDEO_OPTION_WIFI + ) + ?: VideoSettingFragment.VIDEO_OPTION_WIFI + when (videoOption) { + VideoSettingFragment.VIDEO_OPTION_ALL -> { + startPlayLogic(isAutoPlay = true) + } + + VideoSettingFragment.VIDEO_OPTION_WIFI -> { + if (NetworkUtils.isWifiConnected(requireContext()) /*|| !trafficVideo*/) { + if (mListViewModel.isTopVideoPartlyCached(topVideo.url)) { + startPlayLogic(isAutoPlay = true) + } else { + // 未有缓存时,为避免影响页面加载,延迟自动播放视频 + postDelayedRunnable({ + if (activity != null && activity?.isFinishing != true) { + startPlayLogic(isAutoPlay = true) + } + }, GameDetailFragment.INITIAL_DELAY) + } + } + } + + else -> { + } + } + + fullscreenButton.setOnClickListener { + val horizontalVideoView = + startWindowFullscreen(requireContext(), true, true) as? GameCollectionVideoView + if (horizontalVideoView == null) { + toastInInternalRelease("全屏失败,请向技术人员提供具体的操作步骤") + return@setOnClickListener + } + mOrientationUtils?.resolveByClick() + horizontalVideoView.uuid = uuid + horizontalVideoView.viewModel = mListViewModel + horizontalVideoView.video = topVideo + horizontalVideoView.updateThumb(topVideo.poster) + horizontalVideoView.violenceUpdateMuteStatus() + uploadVideoStreamingPlaying("开始播放") + uploadVideoStreamingPlaying("点击全屏") + MtaHelper.onEvent("游戏详情_顶部视频", "顶部视频-点击进入全屏", combinedTitleAndId) + } + + observeVolume(this@GameCollectionDetailFragment) } } @@ -387,6 +475,93 @@ class GameCollectionDetailFragment : mListRv.visibility = View.VISIBLE } + override fun onResume() { + if (isEverPause && mGameAdapter != null) mGameAdapter?.notifyDataSetChanged() + super.onResume() + DownloadManager.getInstance(context).addObserver(mDataWatcher) + + if (!mIsPauseTopVideo) { + resumeVideo() + } + } + + override fun onPause() { + super.onPause() + DownloadManager.getInstance(context).removeObserver(mDataWatcher) + + pauseVideo() + if (mListViewModel.displayTopVideo) { + mBinding?.videoItem?.player?.run { + val currentPosition = getCurrentPosition() + val topVideo = mEntity?.video + if (topVideo != null) { + ScrollCalculatorHelper.savePlaySchedule( + MD5Utils.getContentMD5(topVideo.url), + currentPosition + ) + } + } + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + + if (requestCode == CommentActivity.REQUEST_CODE && resultCode == Activity.RESULT_OK) { + val commentCount = data?.getIntExtra(CommentActivity.COMMENT_COUNT, 0) + if (commentCount != 0 && commentCount != null) { + mEntity?.count?.comment = commentCount + mBinding?.inputContainer?.bottomCommentTv?.text = mListViewModel.getCommentText( + mEntity?.count?.comment + ?: 0, "评论" + ) +// updateFilterView() + mListViewModel.load(LoadType.REFRESH) + } + } + } + + override fun onDestroyView() { + super.onDestroyView() + mEntity?.run { + HistoryHelper.insertGamesCollectionEntity(this) + } + } + + override fun onBackPressed(): Boolean { + mOrientationUtils?.backToProtVideo() + + if (CustomManager.backFromWindowFull(requireActivity(), mBinding?.videoItem?.player?.getKey())) { + return true + } + + return super.onBackPressed() + } + + override fun onDestroy() { + super.onDestroy() + releaseVideo() + } + + private fun pauseVideo() { + if (mListViewModel.displayTopVideo) { + mBinding?.videoItem?.player?.onVideoPause() + } + } + + private fun resumeVideo() { + if (mListViewModel.displayTopVideo) { + mBinding?.videoItem?.player?.onVideoResume() + } + } + + private fun releaseVideo() { + if (mListViewModel.displayTopVideo) { + mBinding?.videoItem?.player?.release() + mBinding?.videoItem?.player?.disposableTimer() + } + } + @Subscribe(threadMode = ThreadMode.MAIN) fun onUserFollow(change: EBUserFollow) { mEntity?.me?.isFollower = change.isFollow @@ -395,7 +570,7 @@ class GameCollectionDetailFragment : @OnClick(R.id.backIv, R.id.imageDesIv, R.id.videoItemDesIv, R.id.toolbarLightUserContainer, R.id.toolbarUserContainer, R.id.videoItemUserContainer, R.id.toolbarFollowTv, R.id.videoItemFollowTv, R.id.squareIv, R.id.bottomStarIv, - R.id.bottomLikeIv, R.id.bottomShareIv) + R.id.bottomLikeIv, R.id.bottomShareIv, R.id.replyTv, R.id.bottomCommentIv, R.id.filterEarliestTv, R.id.filterLatestTv) override fun onClick(v: View) { when (v.id) { R.id.backIv -> requireActivity().finish() @@ -437,6 +612,7 @@ class GameCollectionDetailFragment : } R.id.bottomStarIv -> { + if (isSelfOnly()) return debounceActionWithInterval(v.id) { ifLogin("游戏单详情") { mListViewModel?.postFavoriteGameCollection() @@ -445,6 +621,7 @@ class GameCollectionDetailFragment : } R.id.bottomLikeIv -> { + if (isSelfOnly()) return debounceActionWithInterval(v.id) { ifLogin("游戏单详情") { mListViewModel?.postVoteGameCollection() @@ -453,11 +630,53 @@ class GameCollectionDetailFragment : } R.id.bottomShareIv -> { + if (isSelfOnly()) return showMoreItemDialog() } + + R.id.replyTv -> { + if (isSelfOnly()) return + debounceActionWithInterval(v.id) { + startCommentActivity() + } + } + + R.id.bottomCommentIv -> { + mBinding?.run { + appbar.setExpanded(false) + } + } + + R.id.filterEarliestTv -> { + mListViewModel?.changeSort(GameCollectionDetailViewModel.SortType.EARLIEST) + updateSortType() + } + + R.id.filterLatestTv -> { + mListViewModel?.changeSort(GameCollectionDetailViewModel.SortType.LATEST) + updateSortType() + } } } + private fun updateSortType() { + mBinding?.run { + val isEarliestSelected = + mListViewModel.currentSortType == GameCollectionDetailViewModel.SortType.EARLIEST + val selectedTextView = if (isEarliestSelected) filterEarliestTv else filterLatestTv + val unselectedTextView = if (!isEarliestSelected) filterEarliestTv else filterLatestTv + + selectedTextView.setTextColor(R.color.theme_font.toColor()) + unselectedTextView.setTextColor(R.color.text_999999.toColor()) + } + } + + private fun isSelfOnly(): Boolean { + val isSelfOnly = mEntity?.display == "self_only" + if (isSelfOnly) toast("游戏单为仅自己可见状态") + return isSelfOnly + } + private fun showMoreItemDialog() { if (!lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) return mEntity?.run { @@ -468,6 +687,17 @@ class GameCollectionDetailFragment : } } + private fun startCommentActivity() { + mEntity?.run { + val intent = CommentActivity.getGameCollectionCommentIntent( + requireContext(), + id, + count?.comment ?: 0 + ) + startActivityForResult(intent, CommentActivity.REQUEST_CODE) + } + } + private fun getShareEntity(entity: GamesCollectionDetailEntity): NormalShareEntity { return NormalShareEntity( id = entity.id, diff --git a/app/src/main/java/com/gh/gamecenter/gamecollection/detail/GameCollectionDetailViewModel.kt b/app/src/main/java/com/gh/gamecenter/gamecollection/detail/GameCollectionDetailViewModel.kt index 2d4c49589c..aae687b247 100644 --- a/app/src/main/java/com/gh/gamecenter/gamecollection/detail/GameCollectionDetailViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/gamecollection/detail/GameCollectionDetailViewModel.kt @@ -2,12 +2,17 @@ package com.gh.gamecenter.gamecollection.detail import android.annotation.SuppressLint import android.app.Application +import android.net.Uri +import android.os.Build +import android.text.TextUtils import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import com.gh.common.constant.Constants import com.gh.common.util.* import com.gh.gamecenter.R import com.gh.gamecenter.baselist.ListViewModel +import com.gh.gamecenter.baselist.LoadType import com.gh.gamecenter.entity.CommentEntity import com.gh.gamecenter.entity.GamesCollectionDetailEntity import com.gh.gamecenter.eventbus.EBUserFollow @@ -18,12 +23,13 @@ import com.gh.gamecenter.retrofit.Response import com.gh.gamecenter.retrofit.RetrofitManager import com.halo.assistant.HaloApp import com.lightgame.utils.Utils -import io.reactivex.Observable +import io.reactivex.Single import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers import okhttp3.ResponseBody import org.greenrobot.eventbus.EventBus import retrofit2.HttpException +import tv.danmaku.ijk.media.exo2.ExoSourceManager class GameCollectionDetailViewModel(application: Application, val gameCollectionId: String) : @@ -35,6 +41,9 @@ class GameCollectionDetailViewModel(application: Application, val favoriteLiveData = MutableLiveData() val likeLiveData = MutableLiveData() var gameCollectionDetail: GamesCollectionDetailEntity? = null + var currentSortType = SortType.EARLIEST + var displayTopVideo: Boolean = false + var videoIsMuted = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true) init { getGameCollectionDetail() @@ -46,6 +55,9 @@ class GameCollectionDetailViewModel(application: Application, .compose(singleToMain()) .subscribe(object : BiResponse() { override fun onSuccess(data: GamesCollectionDetailEntity) { + // 4.4以下设备不显示顶部视频 + displayTopVideo = data.video != null + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT gameCollectionDetail = data loadResultLiveData.postValue(BaseCommentViewModel.LoadResult.SUCCESS) } @@ -63,22 +75,16 @@ class GameCollectionDetailViewModel(application: Application, }) } - override fun provideDataObservable(page: Int): Observable>? { -// val map = hashMapOf() -//// if (answerId.isNotEmpty()) { -//// map["top_comment_id"] = answerId -//// } -// return mApi.getQuestionComment(questionId, currentSortType.value, page, map) - return Observable.create { - it.onNext(mutableListOf()) - } + override fun provideDataObservable(page: Int) = null + + override fun provideDataSingle(page: Int): Single> { + return mApi.getGameCollectionComments(gameCollectionId, page, currentSortType.value) } override fun mergeResultLiveData() { mResultLiveData.addSource(mListLiveData) { mResultLiveData.postValue(it) } -// mergeListData(it, displayFloor = true) } } fun followingCommand(userId: String, isFollow: Boolean) { @@ -181,64 +187,70 @@ class GameCollectionDetailViewModel(application: Application, }) } - fun getLikeText(): String { - return if (gameCollectionDetail?.count?.vote == 0) "赞同" else "${gameCollectionDetail?.count?.vote}" + @SuppressLint("CheckResult") + fun postVoteGameCollectionComment(comment: CommentEntity, successCallback: (() -> Unit)) { + mApi.voteGameCollectionComment(gameCollectionId, comment.id) + .compose(singleToMain()) + .subscribe(object : BiResponse() { + override fun onSuccess(data: ResponseBody) { + if (comment.me?.isCommentVoted == true) { + comment.vote-- + ToastUtils.showToast("取消点赞") + } else { + comment.vote++ + ToastUtils.showToast("点赞成功") + } + comment.me?.isCommentVoted = !(comment.me?.isCommentVoted ?: false) + successCallback.invoke() + } + + override fun onFailure(exception: Exception) { + super.onFailure(exception) + + if (exception is HttpException) { + ErrorHelper.handleError( + getApplication(), + exception.response()?.errorBody()?.string() + ) + } + } + }) + } + + fun getCommentText(commentCount: Int, defaultComment: String = "评论"): String { + return if (commentCount == 0) defaultComment else "$commentCount" + } + + fun getLikeText(likeCount: Int, defaultLikeText: String = "赞同"): String { + return if (likeCount == 0) defaultLikeText else "$likeCount" } fun getStarText(): String { return if (gameCollectionDetail?.count?.favorite == 0) "收藏" else "${gameCollectionDetail?.count?.favorite}" } -// override fun hideCommentSuccess() { -// questionDetail?.count?.answer = (questionDetail?.count?.answer ?: 0) - 1 -// loadResultLiveData.postValue(LoadResult.SUCCESS) -// } -// -// fun follow() { -// followingCommand(true, questionDetail?.user?.id!!) -// } -// -// fun unFollow() { -// followingCommand(false, questionDetail?.user?.id!!) -// } -// -// private fun followingCommand(isFollow: Boolean, targetUserId: String) { -// val observable = if (isFollow) { -// mApi.postFollowing(targetUserId) -// } else { -// mApi.deleteFollowing(targetUserId) -// } -// observable -// .subscribeOn(Schedulers.io()) -// .observeOn(AndroidSchedulers.mainThread()) -// .subscribe(object : Response() { -// override fun onResponse(response: ResponseBody?) { -// super.onResponse(response) -// if (isFollow) { -// // 关注成功 -// mFollowLiveData.postValue(true) -// } else { -// // 取消关注成功 -// mFollowLiveData.postValue(false) -// } -// -// SyncPageRepository.postSyncData( -// SyncDataEntity( -// questionDetail?.id ?: "", -// SyncFieldConstants.IS_FOLLOWER, -// isFollow, -// checkFieldEntity = true -// ) -// ) -// EventBus.getDefault().post(EBUserFollow(targetUserId, isFollow)) -// } -// -// override fun onFailure(e: HttpException?) { -// super.onFailure(e) -// Utils.toast(getApplication(), R.string.loading_failed_hint) -// } -// }) -// } + fun changeSort(sortType: SortType) { + if (sortType != currentSortType) { + currentSortType = sortType + load(LoadType.REFRESH) + } + } + + fun isTopVideoPartlyCached(topVideoUrl: String): Boolean { + val cache = ExoSourceManager.getCacheSingleInstance(HaloApp.getInstance().application, null) + val key = Uri.parse(topVideoUrl).toString() + return if (!TextUtils.isEmpty(key)) { + val cachedSpans = cache.getCachedSpans(key) + cachedSpans.size != 0 + } else { + false + } + } + + enum class SortType(var value: String) { + EARLIEST("earliest"), + LATEST("latest") + } class Factory(private val gameCollectionId: String) : ViewModelProvider.NewInstanceFactory() { diff --git a/app/src/main/java/com/gh/gamecenter/gamecollection/detail/GameCollectionVideoView.kt b/app/src/main/java/com/gh/gamecenter/gamecollection/detail/GameCollectionVideoView.kt index ebfbdac975..2fb16bded1 100644 --- a/app/src/main/java/com/gh/gamecenter/gamecollection/detail/GameCollectionVideoView.kt +++ b/app/src/main/java/com/gh/gamecenter/gamecollection/detail/GameCollectionVideoView.kt @@ -18,8 +18,7 @@ import com.gh.common.runOnUiThread import com.gh.common.util.* import com.gh.download.cache.ExoCacheManager import com.gh.gamecenter.R -import com.gh.gamecenter.entity.GameDetailEntity -import com.gh.gamecenter.gamedetail.GameDetailViewModel +import com.gh.gamecenter.entity.VideoEntity import com.gh.gamecenter.home.video.ScrollCalculatorHelper import com.gh.gamecenter.video.detail.CustomManager import com.lightgame.utils.Utils @@ -40,15 +39,15 @@ class GameCollectionVideoView @JvmOverloads constructor(context: Context, attrs: private var mVolumeObserver: VolumeObserver var gameName = "" - var video: GameDetailEntity.Video? = null - var viewModel: GameDetailViewModel? = null + var video: VideoEntity? = null + var viewModel: GameCollectionDetailViewModel? = null var uuid = UUID.randomUUID().toString() private var mMuteDisposable: Disposable? = null private var mContentLength = 0.0 private var mIsAutoPlay = false val combinedTitleAndId: String - get() = StringUtils.combineTwoString(video?.title, video?.videoId) + get() = StringUtils.combineTwoString(video?.title, video?.id) init { post { @@ -448,8 +447,8 @@ class GameCollectionVideoView @JvmOverloads constructor(context: Context, attrs: //https://exoplayer.dev/hello-world.html#a-note-on-threading runOnUiThread { - LogUtils.uploadTopVideoStreamingPlaying(action, video?.videoId, video?.title, viewModel?.game?.id, viewModel?.game?.name, - videoPlayModel, videoPlayStatus(), mContentLength, videoTotalTime, videoPlayTs, progress.toInt()) +// LogUtils.uploadTopVideoStreamingPlaying(action, video?.id, video?.title, viewModel?.game?.id, viewModel?.game?.name, +// videoPlayModel, videoPlayStatus(), mContentLength, videoTotalTime, videoPlayTs, progress.toInt()) } } } diff --git a/app/src/main/java/com/gh/gamecenter/qa/comment/CommentActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/comment/CommentActivity.kt index d5dd5326bc..6fa135a620 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/comment/CommentActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/comment/CommentActivity.kt @@ -9,6 +9,7 @@ import butterknife.OnClick import com.gh.base.BaseActivity import com.gh.common.util.DisplayUtils import com.gh.common.util.EntranceUtils +import com.gh.common.util.EntranceUtils.KEY_COMMENT_ID import com.gh.common.util.doOnEnd import com.gh.gamecenter.NormalActivity import com.gh.gamecenter.R @@ -38,6 +39,7 @@ class CommentActivity : BaseActivity() { val videoId = intent.getStringExtra(VIDEO_ID) ?: "" val questionId = intent.getStringExtra(QUESTION_ID) ?: "" val commentId = intent.getStringExtra(EntranceUtils.KEY_COMMENT_ID) ?: "" + val gameCollectionId = intent.getStringExtra(GAME_COLLECTION_ID) ?: "" val isVideoAuthor = intent.getBooleanExtra(IS_VIDEO_AUTHOR, false) val isStairsComment = intent.getBooleanExtra(IS_STAIRS_COMMENT, false) @@ -96,6 +98,17 @@ class CommentActivity : BaseActivity() { commentEntity, commentCallback) } + gameCollectionId.isNotEmpty() -> { + NewCommentFragment.getGameCollectionCommentInstance( + gameCollectionId, + commentId, + showKeyboard, + commentCount, + mShowInputOnly, + useReplyApi, + commentEntity, + commentCallback) + } else -> { NewCommentFragment.getVideoCommentInstance( videoId, @@ -158,6 +171,8 @@ class CommentActivity : BaseActivity() { const val VIDEO_ID = "video_id" + const val GAME_COLLECTION_ID = "game_collection_id" + const val REQUEST_CODE = 8123 @JvmStatic @@ -337,5 +352,65 @@ class CommentActivity : BaseActivity() { } return intent } + + /** + * 评论游戏单 + */ + @JvmStatic + fun getGameCollectionCommentIntent(context: Context, + gameCollectionId: String, + commentCount: Int? = 0): Intent { + val intent = Intent(context, CommentActivity::class.java) + intent.putExtra(GAME_COLLECTION_ID, gameCollectionId) + intent.putExtra(COMMENT_COUNT, commentCount) + intent.putExtra(SHOW_KEYBOARD, true) + intent.putExtra(SHOW_INPUT_ONLY, true) + if (context is Activity) { + context.overridePendingTransition(0, 0) + } + return intent + } + + /** + * 回复游戏单评论 + */ + fun getGameCollectionCommentReplyIntent(context: Context, + gameCollectionId: String, + commentId: String, + commentCount: Int? = 0, + commentEntity: CommentEntity? = null): Intent { + val intent = Intent(context, CommentActivity::class.java) + intent.putExtra(GAME_COLLECTION_ID, gameCollectionId) + intent.putExtra(KEY_COMMENT_ID, commentId) + intent.putExtra(COMMENT_COUNT, commentCount) + intent.putExtra(SHOW_KEYBOARD, true) + intent.putExtra(SHOW_INPUT_ONLY, true) + intent.putExtra(COMMENT_ENTITY, commentEntity) + intent.putExtra(USE_REPLY_API, true) + if (context is Activity) { + context.overridePendingTransition(0, 0) + } + return intent + } + + /** + * 游戏单评论对话 + */ + @JvmStatic + fun getGameCollectionCommentDetailIntent(context: Context, + commentId: String, + gameCollectionId: String, + showKeyboard: Boolean = false, + entrance: String, + path: String): Intent { + val intent = Intent(context, CommentActivity::class.java) + intent.putExtra(EntranceUtils.KEY_ENTRANCE, NormalActivity.mergeEntranceAndPath(entrance, path)) + intent.putExtra(GAME_COLLECTION_ID, gameCollectionId) + intent.putExtra(EntranceUtils.KEY_COMMENT_ID, commentId) + intent.putExtra(EntranceUtils.KEY_SHOW_KEYBOARD_IF_NEEDED, showKeyboard) + intent.putExtra(EntranceUtils.KEY_PATH, path) + intent.putExtra(EntranceUtils.KEY_IS_COMMENT_CONVERSATION, true) + return intent + } } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentAdapter.kt b/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentAdapter.kt index 90e6f16681..75246370ca 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentAdapter.kt @@ -232,6 +232,9 @@ class NewCommentAdapter( CommentType.COMMUNITY_QUESTION, CommentType.COMMUNITY_QUESTION_CONVERSATION -> "问题详情-评论管理" + + CommentType.GAME_COLLECTION, + CommentType.GAME_COLLECTION_CONVERSATION -> "游戏单详情-评论管理" } val userHomePageTabPosition = if (mViewModel.commentType.isVideo()) 2 else 1 diff --git a/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentFragment.kt index 5d8ece9ff1..6d42c54fec 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentFragment.kt @@ -25,6 +25,7 @@ import com.gh.common.syncpage.SyncDataEntity import com.gh.common.syncpage.SyncFieldConstants import com.gh.common.syncpage.SyncPageRepository import com.gh.common.util.* +import com.gh.common.util.EntranceUtils.KEY_COMMENT_ID import com.gh.common.view.VerticalItemDecoration import com.gh.gamecenter.CommentDetailActivity import com.gh.gamecenter.R @@ -37,6 +38,7 @@ import com.gh.gamecenter.eventbus.EBCommentSuccess import com.gh.gamecenter.eventbus.EBDeleteComment import com.gh.gamecenter.eventbus.EBReuse import com.gh.gamecenter.qa.answer.detail.AnswerDetailFragment +import com.gh.gamecenter.qa.comment.CommentActivity.Companion.GAME_COLLECTION_ID import com.gh.gamecenter.qa.comment.CommentActivity.Companion.QUESTION_ID import com.gh.gamecenter.qa.editor.LocalMediaActivity import com.halo.assistant.HaloApp @@ -113,7 +115,9 @@ open class NewCommentFragment : ListFragment protected var mCommunityId: String = "" protected var mVideoId: String = "" protected var mQuestionId: String = "" + protected var mGameCollectionId: String = "" protected var mCommentId: String = "" + protected var mRootCommentId: String = "" protected var mShowInputOnly: Boolean = false // 是否只显示输入框,不显示列表 protected var mIsVideoAuthor: Boolean = false//是否是视频作者 protected var mCommentType = CommentType.ANSWER @@ -135,7 +139,9 @@ open class NewCommentFragment : ListFragment mAnswerId = getString(ANSWER_ID, "") mArticleId = getString(ARTICLE_ID, "") mVideoId = getString(VIDEO_ID, "") - mQuestionId = getString(CommentActivity.QUESTION_ID, "") + mQuestionId = getString(QUESTION_ID, "") + mGameCollectionId = getString(GAME_COLLECTION_ID, "") + mRootCommentId = getString(KEY_COMMENT_ID, "") mCommentCount = getInt(COMMENT_COUNT, 0) mCommentType = getSerializable(COMMENT_TYPE) as? CommentType ?: CommentType.ANSWER mCommunityId = getString(COMMUNITY_ID, "") @@ -358,6 +364,8 @@ open class NewCommentFragment : ListFragment commentId = mCommentId, videoId = mVideoId, questionId = mQuestionId, + gameCollectionId = mGameCollectionId, + rootCommentId = mRootCommentId, commentType = mCommentType, isVideoAuthor = mIsVideoAuthor ) @@ -379,6 +387,9 @@ open class NewCommentFragment : ListFragment CommentType.VIDEO, CommentType.VIDEO_CONVERSATION -> "(视频详情-评论列表)" + + CommentType.GAME_COLLECTION, + CommentType.GAME_COLLECTION_CONVERSATION -> "(游戏单详情-评论列表)" } mAdapter = NewCommentAdapter(requireContext(), mViewModel, true, this, this, entrance) } @@ -543,6 +554,15 @@ open class NewCommentFragment : ListFragment "问题详情-评论-回复" } } + + CommentType.GAME_COLLECTION, + CommentType.GAME_COLLECTION_CONVERSATION -> { + if (mCommentEntity == null) { + "游戏单详情-评论-写评论" + } else { + "游戏单详情-评论-回复" + } + } } } @@ -579,7 +599,7 @@ open class NewCommentFragment : ListFragment mAnswerContent.orientation = LinearLayout.VERTICAL mAnswerContent.background = ContextCompat.getDrawable(requireActivity(), R.drawable.bg_shape_white_radius_10_top_only) mPlaceholderView.visibility = View.VISIBLE - mImageBtn.goneIf(mCommentEntity != null) + mImageBtn.goneIf(mCommentEntity != null || mGameCollectionId.isNotEmpty()) mScrollViewParams.width = LinearLayout.LayoutParams.MATCH_PARENT mScrollViewParams.height = 76f.dip2px() mScrollViewParams.topMargin = 4f.dip2px() @@ -853,5 +873,37 @@ open class NewCommentFragment : ListFragment } + + fun getGameCollectionCommentInstance( + gameCollectionId: String, + commentId: String, + showSoftKeyboardOnStartUp: Boolean, + commentCount: Int, + showInputOnly: Boolean, + useReplyApi: Boolean, + commentEntity: CommentEntity?, + listener: AnswerDetailFragment.CommentListener + ) + : NewCommentFragment { + val commentType = if (useReplyApi) { + CommentType.GAME_COLLECTION_CONVERSATION + } else { + CommentType.GAME_COLLECTION + } + return NewCommentFragment().apply { + mCommentListener = listener + with( + bundleOf( + SHOW_SOFT_KEY_BOARD_ON_STARTUP to showSoftKeyboardOnStartUp, + GAME_COLLECTION_ID to gameCollectionId, + KEY_COMMENT_ID to commentId, + COMMENT_COUNT to commentCount, + COMMENT_TYPE to commentType, + SHOW_INPUT_ONLY to showInputOnly, + COMMENT_ENTITY to commentEntity + ) + ) + } + } } } diff --git a/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentViewModel.kt index 357aa0737a..b21f6ed186 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentViewModel.kt @@ -6,7 +6,6 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider -import com.gh.common.json.json import com.gh.common.syncpage.SyncDataEntity import com.gh.common.syncpage.SyncFieldConstants import com.gh.common.syncpage.SyncPageRepository @@ -14,7 +13,6 @@ import com.gh.common.util.* import com.gh.gamecenter.baselist.ListViewModel import com.gh.gamecenter.entity.CommentDraft import com.gh.gamecenter.entity.CommentEntity -import com.gh.gamecenter.entity.ErrorEntity import com.gh.gamecenter.retrofit.BiResponse import com.gh.gamecenter.retrofit.Response import com.gh.gamecenter.retrofit.RetrofitManager @@ -37,6 +35,8 @@ open class NewCommentViewModel( var communityId: String = "", var videoId: String = "", var questionId: String = "", + var gameCollectionId: String = "", + var rootCommentId: String = "", var commentType: CommentType = CommentType.ANSWER, var isVideoAuthor: Boolean = false ) : ListViewModel(application) { @@ -119,6 +119,9 @@ open class NewCommentViewModel( if (!imageUrls.isNullOrEmpty()) { requestMap["images"] = imageUrls } + if (gameCollectionId.isNotEmpty() && commentEntity != null) { + requestMap["root"] = rootCommentId + } val body = requestMap.createRequestBodyAny() val observable = @@ -154,6 +157,14 @@ open class NewCommentViewModel( api.postReplyToVideoComment(videoId, commentEntity.id, body) } } + + CommentType.GAME_COLLECTION, CommentType.GAME_COLLECTION_CONVERSATION -> { + if (commentEntity == null) { + api.postGameCollectionComment(gameCollectionId, body) + } else { + api.postReplyToGameCollectionComment(gameCollectionId, commentEntity.id, body) + } + } } // TODO Remove this apiResponse crap. @@ -330,6 +341,8 @@ open class NewCommentViewModel( private val communityId: String = "", private val videoId: String = "", private val questionId: String = "", + private val gameCollectionId: String = "", + private val rootCommentId: String = "", private val isVideoAuthor: Boolean = false, private val commentType: CommentType ) : ViewModelProvider.NewInstanceFactory() { @@ -342,7 +355,9 @@ open class NewCommentViewModel( communityId = communityId, videoId = videoId, questionId = questionId, + gameCollectionId = gameCollectionId, commentId = commentId, + rootCommentId = rootCommentId, commentType = commentType, isVideoAuthor = isVideoAuthor ) as T @@ -361,7 +376,10 @@ enum class CommentType { COMMUNITY_QUESTION_CONVERSATION, VIDEO, - VIDEO_CONVERSATION; + VIDEO_CONVERSATION, + + GAME_COLLECTION, + GAME_COLLECTION_CONVERSATION; fun isVideo(): Boolean { return (this == VIDEO || this == VIDEO_CONVERSATION) diff --git a/app/src/main/java/com/gh/gamecenter/qa/comment/StairsCommentFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/comment/StairsCommentFragment.kt index 12be0a6886..bbad14693e 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/comment/StairsCommentFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/comment/StairsCommentFragment.kt @@ -41,6 +41,9 @@ class StairsCommentFragment : NewCommentFragment() { CommentType.COMMUNITY_QUESTION, CommentType.COMMUNITY_QUESTION_CONVERSATION -> "(问题详情-评论列表)" + + CommentType.GAME_COLLECTION, + CommentType.GAME_COLLECTION_CONVERSATION -> "(游戏单详情-评论列表)" } mAdapter = StairsCommentAdapter(requireContext(), mViewModel, true, this, this, entrance) } diff --git a/app/src/main/java/com/gh/gamecenter/qa/comment/StairsCommentViewHolder.kt b/app/src/main/java/com/gh/gamecenter/qa/comment/StairsCommentViewHolder.kt index d0777345a8..5ea550c3fd 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/comment/StairsCommentViewHolder.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/comment/StairsCommentViewHolder.kt @@ -298,6 +298,9 @@ class StairsCommentViewHolder( CommentType.COMMUNITY_QUESTION, CommentType.COMMUNITY_QUESTION_CONVERSATION -> "问题详情-评论管理" + + CommentType.GAME_COLLECTION, + CommentType.GAME_COLLECTION_CONVERSATION -> "游戏单详情-评论管理" } holder.binding.commentUserIcon.setOnClickListener { DirectUtils.directToHomeActivity( diff --git a/app/src/main/java/com/gh/gamecenter/qa/comment/base/BaseCommentAdapter.kt b/app/src/main/java/com/gh/gamecenter/qa/comment/base/BaseCommentAdapter.kt index d5e96a46e0..a8f362f910 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/comment/base/BaseCommentAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/comment/base/BaseCommentAdapter.kt @@ -573,6 +573,8 @@ abstract class BaseCommentAdapter( } else { (binding.commentPictureRv.adapter as CommentPictureAdapter).checkResetData(comment.images!!) } + } else { + binding.commentPictureRv.visibility = View.GONE } binding.comment = comment binding.contentTv.setExpandMaxLines(if (comment.isExpand) Int.MAX_VALUE else 4) diff --git a/app/src/main/java/com/gh/gamecenter/qa/comment/conversation/CommentConversationFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/comment/conversation/CommentConversationFragment.kt index ed25b34f9c..b4062c022d 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/comment/conversation/CommentConversationFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/comment/conversation/CommentConversationFragment.kt @@ -1,11 +1,11 @@ package com.gh.gamecenter.qa.comment.conversation import android.annotation.SuppressLint +import android.app.Activity import android.content.Intent import android.os.Bundle import android.view.LayoutInflater import android.view.View -import androidx.appcompat.app.AppCompatActivity import com.ethanhua.skeleton.Skeleton import com.gh.common.AppExecutor import com.gh.common.syncpage.SyncDataEntity @@ -66,12 +66,14 @@ class CommentConversationFragment : BaseCommentFragment { mApi.getQuestionCommentReply(questionId, commentId, currentSortType.value, page) } + gameCollectionId.isNotEmpty() -> { + mApi.getGameCollectionCommentReply(gameCollectionId, commentId, page) + } else -> null } } @@ -53,6 +57,9 @@ class CommentConversationViewModel(application: Application, questionId.isNotEmpty() -> { mApi.getCommunityQuestionComment(questionId, commentId) } + gameCollectionId.isNotEmpty() -> { + mApi.getGameCollectionComment(gameCollectionId, commentId) + } else -> null } ?: return single.subscribeOn(Schedulers.io()) @@ -87,6 +94,7 @@ class CommentConversationViewModel(application: Application, private val videoId: String = "", private val questionId: String = "", private val communityId: String = "", + private val gameCollectionId: String = "", private val commentId: String) : ViewModelProvider.NewInstanceFactory() { override fun create(modelClass: Class): T { @@ -96,6 +104,7 @@ class CommentConversationViewModel(application: Application, videoId = videoId, questionId = questionId, communityId = communityId, + gameCollectionId = gameCollectionId, commentId = commentId) as T } } diff --git a/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java b/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java index 184ee5ae1c..5814be924c 100644 --- a/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java +++ b/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java @@ -3360,4 +3360,46 @@ public interface ApiService { */ @GET("game_lists?view=hot") Single> getHomeGameCollectionSquareList(@Query("random") String id, @Query("page") int page); + + /** + * 游戏单评论列表 + */ + @GET("api_go/game_list/{game_list_id}/comment") + Single> getGameCollectionComments(@Path("game_list_id") String id, @Query("page") int page, @Query("sort") String sort); + + /** + * 获取单条游戏单评论 + */ + @GET("api_go/game_list/{game_list_id}/comment/{comment_id}") + Single getGameCollectionComment(@Path("game_list_id") String gameCollectionId, @Path("comment_id") String commentId); + + /** + * 获取游戏单评论的回复列表 + */ + @GET("api_go/game_list/{game_list_id}/comment/{comment_id}/reply") + Single> getGameCollectionCommentReply(@Path("game_list_id") String gameCollectionId, @Path("comment_id") String commentId, @Query("page") int page); + + /** + * 游戏单添加评论 + */ + @POST("api_go/game_list/{game_list_id}/comment") + Observable postGameCollectionComment(@Path("game_list_id") String gameCollectionId, @Body RequestBody body); + + /** + * 点赞游戏单评论 + */ + @POST("api_go/game_list/{game_list_id}/comment/{comment_id}/like") + Single voteGameCollectionComment(@Path("game_list_id") String gameCollectionId, @Path("comment_id") String commentId); /** + + /** + * 举报游戏单评论 + */ + @POST("api_go/game_list/{game_list_id}/comment/{comment_id}/report") + Observable reportGameCollectionComment(@Path("game_list_id") String gameCollectionId, @Path("comment_id") String commentId, @Body RequestBody body); + + /** + * 回复游戏单评论 + */ + @POST("api_go/game_list/{game_list_id}/comment/{comment_id}") + Observable postReplyToGameCollectionComment(@Path("game_list_id") String gameCollectionId, @Path("comment_id") String commentId, @Body RequestBody body); } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_game_collection_detail.xml b/app/src/main/res/layout/fragment_game_collection_detail.xml index 204d9bfaa9..43e3b21e33 100644 --- a/app/src/main/res/layout/fragment_game_collection_detail.xml +++ b/app/src/main/res/layout/fragment_game_collection_detail.xml @@ -17,7 +17,8 @@ + android:layout_height="match_parent" + android:layout_above="@+id/input_container"> @@ -249,7 +253,7 @@ app:layout_constraintTop_toTopOf="parent" /> + + - 上拉查看历史礼包 没有更多了 + 创作不易,留言点赞一下 ~ 到底了哦~点击回到顶部 全部 调整顺序