diff --git a/app/src/main/java/com/gh/common/constant/ItemViewType.java b/app/src/main/java/com/gh/common/constant/ItemViewType.java index b0993ce4ed..2499212c65 100644 --- a/app/src/main/java/com/gh/common/constant/ItemViewType.java +++ b/app/src/main/java/com/gh/common/constant/ItemViewType.java @@ -33,7 +33,6 @@ public class ItemViewType { */ public static final int ITEM_BODY = 100; public static final int ITEM_FOOTER = 101; - public static final int ITEM_TOP = 102; - + public static final int ITEM_HEADER = 102; } diff --git a/app/src/main/java/com/gh/common/util/CommentUtils.java b/app/src/main/java/com/gh/common/util/CommentUtils.java index 59149e8026..0986bd6ee0 100644 --- a/app/src/main/java/com/gh/common/util/CommentUtils.java +++ b/app/src/main/java/com/gh/common/util/CommentUtils.java @@ -19,9 +19,11 @@ import com.gh.gamecenter.R; import com.gh.gamecenter.adapter.OnCommentCallBackListener; import com.gh.gamecenter.adapter.viewholder.CommentViewHolder; import com.gh.gamecenter.entity.CommentEntity; +import com.gh.gamecenter.entity.GameEntity; import com.gh.gamecenter.entity.MeEntity; import com.gh.gamecenter.entity.RatingComment; import com.gh.gamecenter.entity.UserInfoEntity; +import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity; import com.gh.gamecenter.manager.UserManager; import com.gh.gamecenter.retrofit.Response; import com.gh.gamecenter.retrofit.RetrofitManager; @@ -82,7 +84,7 @@ public class CommentUtils { public static void showGameCommentOptions(final Context context, final RatingComment comment, - final String gameId, + final GameEntity game, final String entrance) { final Dialog dialog = new Dialog(context); @@ -96,6 +98,7 @@ public class CommentUtils { dialogType.add("复制"); dialogType.add("举报"); + dialogType.add("回复"); for (String s : dialogType) { @@ -118,7 +121,10 @@ public class CommentUtils { copyText(comment.getContent(), context); break; case "举报": - CheckLoginUtils.checkLogin(context, entrance, () -> showGameCommentReportDialog(gameId, comment, context)); + CheckLoginUtils.checkLogin(context, entrance, () -> showGameCommentReportDialog(game.getId(), comment, context)); + break; + case "回复": + CheckLoginUtils.checkLogin(context, entrance, () -> context.startActivity(RatingReplyActivity.getIntent(context, game, comment))); break; } }); diff --git a/app/src/main/java/com/gh/common/view/ExpendTextView.java b/app/src/main/java/com/gh/common/view/ExpendTextView.java index 352091c8c0..29af50ad6d 100644 --- a/app/src/main/java/com/gh/common/view/ExpendTextView.java +++ b/app/src/main/java/com/gh/common/view/ExpendTextView.java @@ -114,6 +114,12 @@ public class ExpendTextView extends android.support.v7.widget.AppCompatTextView setMovementMethod(CustomLinkMovementMethod.getInstance()); } + + public void setExpendMaxLines(int maxLines) { + mMaxLines = maxLines; + setMaxLines(maxLines); + } + public interface ExpandCallback { void onExpand(); } diff --git a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/ListSectionItemViewHolder.kt b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/ListSectionItemViewHolder.kt new file mode 100644 index 0000000000..728c1457e6 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/ListSectionItemViewHolder.kt @@ -0,0 +1,11 @@ +package com.gh.gamecenter.adapter.viewholder + +import android.view.View +import android.widget.TextView +import com.gh.base.BaseRecyclerViewHolder +import com.gh.gamecenter.R +import kotterknife.bindView + +class ListSectionItemViewHolder(view: View) : BaseRecyclerViewHolder(view) { + val sectionTitle by bindView(R.id.list_section_title) +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/baselist/PagedList.kt b/app/src/main/java/com/gh/gamecenter/baselist/PagedList.kt index 0c4f7bdfdd..87ab911df5 100644 --- a/app/src/main/java/com/gh/gamecenter/baselist/PagedList.kt +++ b/app/src/main/java/com/gh/gamecenter/baselist/PagedList.kt @@ -6,14 +6,17 @@ import com.gh.gamecenter.mvvm.Status class PagedList : ArrayList() { @NonNull - var status: Status = Status.LOADING + var status: Status = Status.SUCCESS + var lastDataCount = 0 fun addAll(elements: Collection, status: Status): Boolean { + this.lastDataCount = elements.size this.status = status return addAll(elements) } fun add(element: T, status: Status): Boolean { + this.lastDataCount = 1 this.status = status return add(element) } diff --git a/app/src/main/java/com/gh/gamecenter/entity/RatingComment.kt b/app/src/main/java/com/gh/gamecenter/entity/RatingComment.kt index acde132740..389cde7b50 100644 --- a/app/src/main/java/com/gh/gamecenter/entity/RatingComment.kt +++ b/app/src/main/java/com/gh/gamecenter/entity/RatingComment.kt @@ -1,7 +1,10 @@ package com.gh.gamecenter.entity +import android.os.Parcelable import com.google.gson.annotations.SerializedName +import kotlinx.android.parcel.Parcelize +@Parcelize class RatingComment(@SerializedName("_id") val id: String = "", val content: String = "", @@ -12,10 +15,10 @@ class RatingComment(@SerializedName("_id") val vote: Int = 0, val star: Int = 0, val reply: Int = 0, - val user: UserEntity, - @SerializedName("attach") - val replyData: Reply?) { - - class Reply(val user: UserEntity, - val content: String) + val user: UserEntity = UserEntity(), + @SerializedName("attached") + var replyData: Reply? = null) : Parcelable { + @Parcelize + class Reply(val user: UserEntity = UserEntity(), + val content: String = "") : Parcelable } diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescCommentsAdapter.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescCommentsAdapter.kt index d1e410fd4b..e2ffaa9957 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescCommentsAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescCommentsAdapter.kt @@ -15,6 +15,7 @@ import com.gh.gamecenter.baselist.ListAdapter import com.gh.gamecenter.databinding.RatingCommentItemBinding import com.gh.gamecenter.entity.RatingComment import com.gh.gamecenter.gamedetail.rating.RatingCommentItemViewHolder +import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity import com.lightgame.utils.Utils class DescCommentsAdapter(context: Context, @@ -42,7 +43,7 @@ class DescCommentsAdapter(context: Context, holder.binding.run { val comment = comments[position] data = comment - if (comment?.me?.isCommented != null && comment.me.isCommented) { + if (comment.me.isCommented) { badge.visibility = View.VISIBLE badge.text = "你的评论" badge.setBackgroundColor(ContextCompat.getColor(mContext, R.color.theme)) @@ -58,14 +59,14 @@ class DescCommentsAdapter(context: Context, } } - private fun setCommentClick(binding: RatingCommentItemBinding, comment: RatingComment) { + private fun setCommentClick(binding: RatingCommentItemBinding, commentData: RatingComment) { binding.run { vote.setOnClickListener { mContext.ifLogin("游戏详情-介绍-点赞评论") { if (!vote.isChecked) { - mViewModel.voteComment(comment.id, callback = { + mViewModel.voteComment(commentData.id, callback = { MtaHelper.onEvent("游戏详情_新", "玩家评论_点赞", mViewModel.game?.name) - vote.text = (comment.vote + 1).toString() + vote.text = (commentData.vote + 1).toString() vote.isChecked = true }) } else { @@ -75,17 +76,20 @@ class DescCommentsAdapter(context: Context, } commentItem.setOnClickListener { MtaHelper.onEvent("游戏详情_新", "玩家评论_点击评论", mViewModel.game?.name) - CommentUtils.showGameCommentOptions(mContext, comment, mViewModel.gameId, "游戏详情-介绍-举报评论") + CommentUtils.showGameCommentOptions(mContext, commentData, mViewModel.game, "游戏详情-介绍-举报评论") } userIcon.setOnClickListener { - PersonalHomeActivity.startTargetActivity(mContext, comment.user.id, mEntrance, "(游戏详情:介绍)") + PersonalHomeActivity.startTargetActivity(mContext, commentData.user.id, mEntrance, "(游戏详情:介绍)") } userName.setOnClickListener { - PersonalHomeActivity.startTargetActivity(mContext, comment.user.id, mEntrance, "(游戏详情:介绍)") + PersonalHomeActivity.startTargetActivity(mContext, commentData.user.id, mEntrance, "(游戏详情:介绍)") } content.setExpandCallback { MtaHelper.onEvent("游戏详情_新", "玩家评论_点击全文", mViewModel.game?.name) } + comment.setOnClickListener { + mContext.startActivity(RatingReplyActivity.getIntent(mContext, mViewModel.game!!, commentData)) + } } } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingAdapter.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingAdapter.kt index 276c30f3e7..af869363d4 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingAdapter.kt @@ -45,7 +45,7 @@ class RatingAdapter(context: Context, override fun getItemViewType(position: Int): Int { return when (position) { itemCount - 1 -> ItemViewType.ITEM_FOOTER - 0 -> ItemViewType.ITEM_TOP + 0 -> ItemViewType.ITEM_HEADER else -> ItemViewType.ITEM_BODY } } @@ -53,7 +53,7 @@ class RatingAdapter(context: Context, override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val view: View return when (viewType) { - ItemViewType.ITEM_TOP -> { + ItemViewType.ITEM_HEADER -> { view = mLayoutInflater.inflate(R.layout.rating_item, parent, false) RatingItemViewHolder(RatingItemBinding.bind(view)) } @@ -128,13 +128,13 @@ class RatingAdapter(context: Context, } } - private fun setCommentClick(binding: RatingCommentItemBinding, comment: RatingComment) { + private fun setCommentClick(binding: RatingCommentItemBinding, commentData: RatingComment) { binding.run { vote.setOnClickListener { mContext.ifLogin("游戏详情-评论-点赞评论") { if (!vote.isChecked) { - mListViewModel.voteComment(comment.id, callback = { - vote.text = (comment.vote + 1).toString() + mListViewModel.voteComment(commentData.id, callback = { + vote.text = (commentData.vote + 1).toString() vote.isChecked = true MtaHelper.onEvent("游戏详情_新", "评论Tab_点赞", mListViewModel.game.name) }) @@ -144,18 +144,30 @@ class RatingAdapter(context: Context, } } commentItem.setOnClickListener { - CommentUtils.showGameCommentOptions(mContext, comment, mListViewModel.game.id, "游戏详情-评论-举报评论") + CommentUtils.showGameCommentOptions(mContext, commentData, mListViewModel.game, "游戏详情-评论-举报评论") MtaHelper.onEvent("游戏详情_新", "评论Tab_点击评论", mListViewModel.game.name) } + replyUserIconContainer.setOnClickListener { + PersonalHomeActivity.startTargetActivity(mContext, commentData.user.id, mEntrance, "游戏详情:评分") + } + replyUserName.setOnClickListener { + PersonalHomeActivity.startTargetActivity(mContext, commentData.user.id, mEntrance, "游戏详情:评分") + } userIcon.setOnClickListener { - PersonalHomeActivity.startTargetActivity(mContext, comment.user.id, mEntrance, "游戏详情:评分") + PersonalHomeActivity.startTargetActivity(mContext, commentData.user.id, mEntrance, "游戏详情:评分") } userName.setOnClickListener { - PersonalHomeActivity.startTargetActivity(mContext, comment.user.id, mEntrance, "游戏详情:评分") + PersonalHomeActivity.startTargetActivity(mContext, commentData.user.id, mEntrance, "游戏详情:评分") } content.setExpandCallback { MtaHelper.onEvent("游戏详情_新", "评论Tab_点击全文", mListViewModel.game.name) } + comment.setOnClickListener { + mContext.startActivity(RatingReplyActivity.getIntent(mContext, mListViewModel.game, commentData)) + } + replyContainer.setOnClickListener { + mContext.startActivity(RatingReplyActivity.getIntent(mContext, mListViewModel.game, commentData)) + } } } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingReplyActivity.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingReplyActivity.kt index ad5baa7b27..2c2a005e87 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingReplyActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingReplyActivity.kt @@ -2,17 +2,27 @@ package com.gh.gamecenter.gamedetail.rating import android.arch.lifecycle.Observer import android.arch.lifecycle.ViewModelProviders +import android.content.Context +import android.content.Intent import android.os.Bundle -import android.support.v4.widget.SwipeRefreshLayout +import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.RecyclerView +import android.view.View +import android.widget.EditText +import butterknife.OnClick import com.gh.base.BaseActivity import com.gh.gamecenter.R +import com.gh.gamecenter.entity.GameEntity +import com.gh.gamecenter.entity.RatingComment +import com.gh.gamecenter.mvvm.Status +import com.lightgame.utils.Utils import kotterknife.bindView class RatingReplyActivity : BaseActivity() { - private val mRefreshLayout by bindView(R.id.rating_reply_refresh) - private val mRecyclerView by bindView(R.id.rating_reply_refresh) + private val mRecyclerView by bindView(R.id.rating_reply_list) + private val mPostReplyButton by bindView(R.id.answer_comment_send_btn) + private val mReplyContent by bindView(R.id.answer_comment_et) private lateinit var mViewModel: RatingReplyViewModel private lateinit var mAdapter: RatingReplyAdapter @@ -23,11 +33,55 @@ class RatingReplyActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val factory = RatingReplyViewModel.Factory("", "") // todo + setNavigationTitle("评论详情") + val game = intent.getParcelableExtra(GameEntity::class.java.simpleName) + val comment = intent.getParcelableExtra(RatingComment::class.java.simpleName) + comment.replyData = null // 不需要显示回复引用区域 + + val factory = RatingReplyViewModel.Factory(game.id, comment.id) mViewModel = ViewModelProviders.of(this, factory).get(RatingReplyViewModel::class.java) mViewModel.resultLiveData.observe(this, Observer { + if (it != null) mAdapter.submitList(it) }) - mAdapter = RatingReplyAdapter(this) + + val layoutManager = LinearLayoutManager(this) + mAdapter = RatingReplyAdapter(this, mViewModel, game, comment) + mRecyclerView.layoutManager = layoutManager + mRecyclerView.adapter = mAdapter + mRecyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) { + super.onScrollStateChanged(recyclerView, newState) + if (layoutManager.findLastVisibleItemPosition() == mAdapter.itemCount - 1 + && RecyclerView.SCROLL_STATE_IDLE == newState) { + val pageList = mAdapter.pageList + if (pageList.status == Status.SUCCESS && pageList.lastDataCount > 10) { + mViewModel.loadData(false) + } + } + } + }) + } + + @OnClick(R.id.answer_comment_send_btn) + fun onViewClick(view: View) { + if (view.id == R.id.answer_comment_send_btn) { + val replyContent = mReplyContent.text.toString() + if (!replyContent.isEmpty()) { + mViewModel.replyComment(null, replyContent) + } else { + Utils.toast(this, "恢复内容不能为空") + } + } + } + + companion object { + @JvmStatic + fun getIntent(context: Context, game: GameEntity, comment: RatingComment): Intent { + val intent = Intent(context, RatingReplyActivity::class.java) + intent.putExtra(GameEntity::class.java.simpleName, game) + intent.putExtra(RatingComment::class.java.simpleName, comment) + return intent + } } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingReplyAdapter.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingReplyAdapter.kt index 25b27f256c..f67d1242b5 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingReplyAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingReplyAdapter.kt @@ -2,40 +2,162 @@ package com.gh.gamecenter.gamedetail.rating import android.content.Context import android.support.v7.widget.RecyclerView +import android.view.View import android.view.ViewGroup +import com.gh.base.BaseRecyclerViewHolder +import com.gh.common.constant.ItemViewType +import com.gh.common.util.ifLogin +import com.gh.gamecenter.R +import com.gh.gamecenter.adapter.viewholder.FooterViewHolder +import com.gh.gamecenter.adapter.viewholder.ListSectionItemViewHolder import com.gh.gamecenter.baselist.PagedList +import com.gh.gamecenter.databinding.RatingCommentItemBinding +import com.gh.gamecenter.databinding.RatingReplyHeadItemBinding +import com.gh.gamecenter.databinding.RatingReplyItemBinding +import com.gh.gamecenter.entity.GameEntity +import com.gh.gamecenter.entity.RatingComment import com.gh.gamecenter.entity.RatingReplyEntity +import com.gh.gamecenter.mvvm.Status import com.lightgame.adapter.BaseRecyclerAdapter +import com.lightgame.utils.Utils -class RatingReplyAdapter(context: Context) : BaseRecyclerAdapter(context) { +class RatingReplyAdapter(context: Context, + val viewModel: RatingReplyViewModel, + val game: GameEntity, + val comment: RatingComment) : BaseRecyclerAdapter(context) { - private var mPageList = PagedList() + var pageList = PagedList() + + private val ITEM_COMMENT = 211 + private val ITEM_SECTION_TITLE = 212 fun submitList(list: PagedList) { - + pageList = list + notifyDataSetChanged() } override fun getItemViewType(position: Int): Int { - return when (position) { - 0 -> 0 - 1 -> 1 - itemCount - 1 -> 3 - else -> super.getItemViewType(position) + return if (position == 0) { + ItemViewType.ITEM_HEADER + } else if (position == 1) { + ITEM_COMMENT + } else if (position == 2 && comment.reply > 0) { + ITEM_SECTION_TITLE + } else if (position == itemCount - 1) { + ItemViewType.ITEM_FOOTER + } else { + ItemViewType.ITEM_BODY } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + val view: View + return when (viewType) { + ItemViewType.ITEM_HEADER -> { + view = mLayoutInflater.inflate(R.layout.rating_reply_head_item, parent, false) + return RatingReplyHeadItemViewHolder(RatingReplyHeadItemBinding.bind(view)) + } + ITEM_COMMENT -> { + view = mLayoutInflater.inflate(R.layout.rating_comment_item, parent, false) + return RatingCommentItemViewHolder(RatingCommentItemBinding.bind(view)) + } + ITEM_SECTION_TITLE -> { + view = mLayoutInflater.inflate(R.layout.list_section_item, parent, false) + return ListSectionItemViewHolder(view) + } + ItemViewType.ITEM_BODY -> { + view = mLayoutInflater.inflate(R.layout.rating_reply_item, parent, false) + return RatingReplyItemViewHolder(RatingReplyItemBinding.bind(view)) + } + ItemViewType.ITEM_FOOTER -> { + view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false) + return FooterViewHolder(view) + } + else -> { + throw IllegalStateException("item view type not found") + } + } } override fun getItemCount(): Int { - return mPageList.size + 3 // 3:game/comment/footer item + return pageList.size + if (comment.reply > 0) 4 else 3 // 4/3:game/comment/footer/section item } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - + when (holder) { + is RatingReplyHeadItemViewHolder -> { + holder.binding.game = game + } + is RatingCommentItemViewHolder -> { + holder.binding.line.visibility = View.GONE + holder.binding.data = comment + holder.binding.content.setExpendMaxLines(Int.MAX_VALUE) + } + is RatingReplyItemViewHolder -> { + val headCount = if (comment.reply > 0) 3 else 2 + val replyEntity = pageList[position - headCount] + holder.binding.run { + data = replyEntity + vote.setOnClickListener { + mContext.ifLogin("游戏详情-评分-评论详情-点赞评论") { + if (!vote.isChecked) { + viewModel.voteReply(replyEntity.id, callback = { + vote.text = (replyEntity.vote + 1).toString() + vote.isChecked = true + }) + } else { + Utils.toast(mContext, "已经点赞了哟~") + } + } + } + } + } + is ListSectionItemViewHolder -> { + holder.sectionTitle.text = ("全部回复(" + comment.reply + ")") + } + is FooterViewHolder -> { + when { + pageList.status == Status.ERROR -> { + holder.lineLeft.visibility = View.GONE + holder.lineRight.visibility = View.GONE + holder.loading.visibility = View.GONE + holder.hint.setText(R.string.loading_failed_retry) + holder.itemView.isClickable = true + holder.itemView.setOnClickListener { viewModel.loadData(false) } + } + pageList.status == Status.LOADING -> { + holder.lineLeft.visibility = View.GONE + holder.lineRight.visibility = View.GONE + holder.loading.visibility = View.VISIBLE + holder.hint.setText(R.string.loading) + holder.itemView.isClickable = false + } + pageList.status == Status.SUCCESS && pageList.size == 0 -> { + holder.lineLeft.visibility = View.GONE + holder.lineRight.visibility = View.GONE + holder.loading.visibility = View.GONE + holder.hint.text = "这里还没有回复,说点什么吧~" + holder.itemView.isClickable = false + } + pageList.lastDataCount < 10 -> { + holder.lineLeft.visibility = View.VISIBLE + holder.lineRight.visibility = View.VISIBLE + holder.loading.visibility = View.GONE + holder.hint.setText(R.string.ask_loadover_hint) + holder.itemView.isClickable = true + } + else -> { + holder.lineLeft.visibility = View.GONE + holder.lineRight.visibility = View.GONE + holder.loading.visibility = View.GONE + holder.hint.setText(R.string.loading_more_hint) + holder.itemView.isClickable = false + } + } + } + } } - class GameItemViewHolder() - + class RatingReplyHeadItemViewHolder(val binding: RatingReplyHeadItemBinding) : BaseRecyclerViewHolder(binding.root) + class RatingReplyItemViewHolder(val binding: RatingReplyItemBinding) : BaseRecyclerViewHolder(binding.root) } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingReplyViewModel.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingReplyViewModel.kt index 7196cf17c2..19c78f9779 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingReplyViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingReplyViewModel.kt @@ -9,11 +9,19 @@ import com.gh.gamecenter.baselist.PagedList import com.gh.gamecenter.entity.RatingReplyEntity import com.gh.gamecenter.mvvm.Status import com.gh.gamecenter.retrofit.BiResponse +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.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable import io.reactivex.schedulers.Schedulers +import okhttp3.MediaType +import okhttp3.RequestBody +import okhttp3.ResponseBody +import org.json.JSONException +import org.json.JSONObject +import retrofit2.HttpException class RatingReplyViewModel(application: Application, private val gameId: String?, @@ -21,6 +29,7 @@ class RatingReplyViewModel(application: Application, var resultLiveData = MediatorLiveData>() + private val mApi = RetrofitManager.getInstance(getApplication()).api private var mDisposable: Disposable? = null private var mPage = 0 @@ -38,35 +47,77 @@ class RatingReplyViewModel(application: Application, } } - mDisposable = RetrofitManager - .getInstance(getApplication()).api - .getRatingReply(gameId, commentId, mPage + 1) + var list = resultLiveData.value + if (list != null) { + list.status = Status.LOADING + } else { + list = PagedList.create(Status.LOADING) + } + resultLiveData.postValue(list) + + mDisposable = mApi + .getCommentReply(gameId, commentId, mPage + 1) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : BiResponse>() { override fun onSuccess(data: List) { - var list = resultLiveData.value - if (list != null) { - list.addAll(data, Status.SUCCESS) - } else { - list = PagedList.create(Status.SUCCESS, data) - } + list.addAll(data, Status.SUCCESS) resultLiveData.postValue(list) mPage++ } override fun onFailure(exception: Exception) { - var list = resultLiveData.value - if (list != null) { - list?.status = Status.ERROR - } else { - list = PagedList.create(Status.SUCCESS) - } + list.status = Status.ERROR resultLiveData.postValue(list) } }) } + fun replyComment(replyId: String?, content: String) { + val json = JSONObject() + try { + json.put("content", content) + } catch (e: JSONException) { + e.printStackTrace() + } + + val body = RequestBody.create(MediaType.parse("application/json"), json.toString()) + val observable = + if (replyId.isNullOrEmpty()) { + mApi.postCommentReply(gameId, commentId, body) + } else { + mApi.postReplyToReply(gameId, commentId, replyId, body) + } + observable + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : Response() { + override fun onResponse(response: ResponseBody?) { + super.onResponse(response) + } + + override fun onFailure(e: HttpException?) { + super.onFailure(e) + Utils.toast(getApplication(), "提交评论回复失败!") + } + }) + } + + fun voteReply(replyId: String, callback: () -> Unit) { + mApi.postReplyVote(gameId, commentId, replyId) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : Response() { + override fun onResponse(response: ResponseBody?) { + callback.invoke() + } + + override fun onFailure(e: HttpException?) { + + } + }) + } + class Factory(private val gameId: String?, private val commentId: String?) : ViewModelProvider.NewInstanceFactory() { diff --git a/app/src/main/java/com/gh/gamecenter/message/MessageAdapter.java b/app/src/main/java/com/gh/gamecenter/message/MessageAdapter.java index 10d339fe54..5da6a0432a 100644 --- a/app/src/main/java/com/gh/gamecenter/message/MessageAdapter.java +++ b/app/src/main/java/com/gh/gamecenter/message/MessageAdapter.java @@ -59,7 +59,7 @@ public class MessageAdapter extends ListAdapter { @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { switch (viewType) { - case ItemViewType.ITEM_TOP: + case ItemViewType.ITEM_HEADER: MessageItemTopBinding topBinding = DataBindingUtil.inflate(mLayoutInflater, R.layout.message_item_top, parent, false); return new MessageTopViewHolder(topBinding, mClickListener); case ItemViewType.ITEM_FOOTER: @@ -76,7 +76,7 @@ public class MessageAdapter extends ListAdapter { @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { switch (getItemViewType(position)) { - case ItemViewType.ITEM_TOP: + case ItemViewType.ITEM_HEADER: MessageTopViewHolder topViewHolder = (MessageTopViewHolder) holder; topViewHolder.mBinding.setUnreadEntity(mUnreadEntity); break; @@ -102,7 +102,7 @@ public class MessageAdapter extends ListAdapter { @Override public int getItemViewType(int position) { if (position == 0) { - return ItemViewType.ITEM_TOP; + return ItemViewType.ITEM_HEADER; } else if (position == getItemCount() - 1) { return ItemViewType.ITEM_FOOTER; } else { diff --git a/app/src/main/java/com/gh/gamecenter/personalhome/PersonalHomeAdapter.kt b/app/src/main/java/com/gh/gamecenter/personalhome/PersonalHomeAdapter.kt index df6edec534..4766b4f4ed 100644 --- a/app/src/main/java/com/gh/gamecenter/personalhome/PersonalHomeAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/personalhome/PersonalHomeAdapter.kt @@ -57,7 +57,7 @@ class PersonalHomeAdapter(context: Context, override fun getItemViewType(position: Int): Int { return when (position) { itemCount - 1 -> ItemViewType.ITEM_FOOTER - 0 -> ItemViewType.ITEM_TOP + 0 -> ItemViewType.ITEM_HEADER else -> ItemViewType.ITEM_BODY } } @@ -65,7 +65,7 @@ class PersonalHomeAdapter(context: Context, override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val view: View return when (viewType) { - ItemViewType.ITEM_TOP -> { + ItemViewType.ITEM_HEADER -> { view = mLayoutInflater.inflate(R.layout.personal_home_top, parent, false) PersonalTopViewHolder(PersonalHomeTopBinding.bind(view)) } diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailAdapter.java b/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailAdapter.java index ebb42f8b76..06b3a0ece3 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailAdapter.java +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailAdapter.java @@ -79,7 +79,7 @@ public class QuestionsDetailAdapter extends ListAdapter { @Override public int getItemViewType(int position) { if (position == 0 && mQuestionsDetailEntity != null) { - return ItemViewType.ITEM_TOP; + return ItemViewType.ITEM_HEADER; } else if (position == getItemCount() - 1) { return ItemViewType.ITEM_FOOTER; } else if (mEntityList == null || mEntityList.isEmpty()) { @@ -93,7 +93,7 @@ public class QuestionsDetailAdapter extends ListAdapter { public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view; switch (viewType) { - case ItemViewType.ITEM_TOP: + case ItemViewType.ITEM_HEADER: view = mLayoutInflater.inflate(R.layout.questionsdetail_item, parent, false); return new QuestionsDetailItemViewHolder(view, mListClickListener); case ItemViewType.ITEM_FOOTER: @@ -114,7 +114,7 @@ public class QuestionsDetailAdapter extends ListAdapter { @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { switch (getItemViewType(position)) { - case ItemViewType.ITEM_TOP: + case ItemViewType.ITEM_HEADER: initQuestionsDetailItemViewHolder((QuestionsDetailItemViewHolder) holder); break; case ItemViewType.ITEM_EMPTY: diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/invite/QuestionsInviteAdapter.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/invite/QuestionsInviteAdapter.kt index 3eb20fc76f..685cc3e7e3 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/questions/invite/QuestionsInviteAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/invite/QuestionsInviteAdapter.kt @@ -30,7 +30,7 @@ class QuestionsInviteAdapter(context: Context, override fun getItemViewType(position: Int): Int { return when { position == itemCount - 1 -> ItemViewType.ITEM_FOOTER - mEntityList[position].isHeaderItem!! -> ItemViewType.ITEM_TOP + mEntityList[position].isHeaderItem!! -> ItemViewType.ITEM_HEADER else -> ItemViewType.ITEM_BODY } } @@ -48,7 +48,7 @@ class QuestionsInviteAdapter(context: Context, return QuestionsInviteViewHolder(view, mListClickListener) } - ItemViewType.ITEM_TOP -> { + ItemViewType.ITEM_HEADER -> { return HeaderHolder(QuestioninviteHeaderItemBinding.inflate(mLayoutInflater, parent, false)) } @@ -71,7 +71,7 @@ class QuestionsInviteAdapter(context: Context, (holder as QuestionsInviteViewHolder).initQuestionsInviteViewHolder(mContext, entity) holder.itemView.setOnClickListener { PersonalHomeActivity.startTargetActivity(mContext, entity.id, mEntrance, "问题详情-邀请回答") } } - ItemViewType.ITEM_TOP -> { + ItemViewType.ITEM_HEADER -> { val headerEntity = mEntityList[position] (holder as HeaderHolder).binding.title = headerEntity.headerName } diff --git a/app/src/main/java/com/gh/gamecenter/qa/select/VotingAdapter.java b/app/src/main/java/com/gh/gamecenter/qa/select/VotingAdapter.java index 6a6fc2d43a..66df800248 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/select/VotingAdapter.java +++ b/app/src/main/java/com/gh/gamecenter/qa/select/VotingAdapter.java @@ -54,7 +54,7 @@ public class VotingAdapter extends ListAdapter { @Override public int getItemViewType(int position) { if (position == 0) { - return ItemViewType.ITEM_TOP; + return ItemViewType.ITEM_HEADER; } else if (position == getItemCount() - 1) { return ItemViewType.ITEM_FOOTER; } @@ -65,7 +65,7 @@ public class VotingAdapter extends ListAdapter { public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view; switch (viewType) { - case ItemViewType.ITEM_TOP: + case ItemViewType.ITEM_HEADER: view = mLayoutInflater.inflate(R.layout.voting_top_item, parent, false); return new ReuseViewHolder(view); case ItemViewType.ITEM_BODY: @@ -109,7 +109,7 @@ public class VotingAdapter extends ListAdapter { footerViewHolder.hint.setText(R.string.loading_more_hint); } break; - case ItemViewType.ITEM_TOP: + case ItemViewType.ITEM_HEADER: holder.itemView.findViewById(R.id.voting_top_btn).setOnClickListener(v -> mListClickListener.onListClick(v, -1, null)); break; diff --git a/app/src/main/java/com/gh/gamecenter/qa/subject/AskSubjectAdapter.java b/app/src/main/java/com/gh/gamecenter/qa/subject/AskSubjectAdapter.java index 25af42a6d8..9aacb7363d 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/subject/AskSubjectAdapter.java +++ b/app/src/main/java/com/gh/gamecenter/qa/subject/AskSubjectAdapter.java @@ -68,7 +68,7 @@ public class AskSubjectAdapter extends ListAdapter { public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view; switch (viewType) { - case ItemViewType.ITEM_TOP: + case ItemViewType.ITEM_HEADER: view = mLayoutInflater.inflate(R.layout.ask_subject_top_item, parent, false); AskSubjectTopItemBinding binding = DataBindingUtil.bind(view); return new AskSubjectViewHolder(binding, mListClickListener); @@ -85,7 +85,7 @@ public class AskSubjectAdapter extends ListAdapter { @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { switch (getItemViewType(position)) { - case ItemViewType.ITEM_TOP: + case ItemViewType.ITEM_HEADER: AskSubjectViewHolder subjectViewHolder = (AskSubjectViewHolder) holder; subjectViewHolder.mBinding.setEntity(mSubjectEntity); if (mEntityList == null || mEntityList.isEmpty()) { @@ -141,7 +141,7 @@ public class AskSubjectAdapter extends ListAdapter { @Override public int getItemViewType(int position) { - if (position == 0) return ItemViewType.ITEM_TOP; + if (position == 0) return ItemViewType.ITEM_HEADER; if (position == getItemCount() - 1) return ItemViewType.ITEM_FOOTER; return ItemViewType.ITEM_BODY; } 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 d850a209e9..60e0434b43 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 @@ -1627,8 +1627,32 @@ public interface ApiService { * 获取游戏评分回复列表 */ @GET("games/{game_id}/comments/{comment_id}/replies") - Single> getRatingReply(@Path("game_id") String gameId, - @Path("commit_id") String commitId, - @Query("page") int page); + Single> getCommentReply(@Path("game_id") String gameId, + @Path("comment_id") String commitId, + @Query("page") int page); + /** + * 回复评论 + */ + @POST("games/{game_id}/comments/{comment_id}/replies") + Observable postCommentReply(@Path("game_id") String gameId, + @Path("comment_id") String commitId, + @Body RequestBody body); + + /** + * 回复评论回复 + */ + @POST("games/{game_id}/comments/{comment_id}/replies/{reply_id}:reply") + Observable postReplyToReply(@Path("game_id") String gameId, + @Path("comment_id") String commitId, + @Path("reply_id") String replyId, + @Body RequestBody body); + + /** + * 点赞恢复信息 + */ + @POST("games/{game_id}/comments/{comment_id}/replies/{reply_id}:vote") + Observable postReplyVote(@Path("game_id") String gameId, + @Path("comment_id") String commitId, + @Path("reply_id") String replyId); } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_rating_reply.xml b/app/src/main/res/layout/activity_rating_reply.xml index 7174246e5f..4d459eb7f3 100644 --- a/app/src/main/res/layout/activity_rating_reply.xml +++ b/app/src/main/res/layout/activity_rating_reply.xml @@ -1,16 +1,22 @@ - + android:layout_height = "match_parent" + android:orientation = "vertical" > - + + - - \ No newline at end of file + android:layout_height = "match_parent" + android:layout_marginBottom = "50dp" /> + + + + + diff --git a/app/src/main/res/layout/list_section_item.xml b/app/src/main/res/layout/list_section_item.xml new file mode 100644 index 0000000000..7e24b01bf3 --- /dev/null +++ b/app/src/main/res/layout/list_section_item.xml @@ -0,0 +1,12 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/rating_comment_item.xml b/app/src/main/res/layout/rating_comment_item.xml index f8e60dc807..c480e15a43 100644 --- a/app/src/main/res/layout/rating_comment_item.xml +++ b/app/src/main/res/layout/rating_comment_item.xml @@ -254,7 +254,7 @@ android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_marginTop = "11dp" - android:text = "查看更多恢复" + android:text = "查看更多回复" android:textColor = "@color/theme" android:textSize = "11sp" app:layout_constraintRight_toRightOf = "parent" diff --git a/app/src/main/res/layout/rating_reply_head_item.xml b/app/src/main/res/layout/rating_reply_head_item.xml index 51ea796ace..4c9c90d439 100644 --- a/app/src/main/res/layout/rating_reply_head_item.xml +++ b/app/src/main/res/layout/rating_reply_head_item.xml @@ -13,6 +13,8 @@ android:id = "@+id/game_container" android:layout_width = "match_parent" android:layout_height = "wrap_content" + android:layout_marginTop = "8dp" + android:layout_marginBottom = "8dp" android:background = "@color/all_white" android:gravity = "center_vertical" android:orientation = "horizontal" @@ -29,6 +31,7 @@ @@ -87,6 +91,7 @@ android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_marginTop = "7dp" + android:text = "@{game.apk.size() > 0?'V' + game.apk.get(0).version + ` | ` + game.apk.get(0).size: ``}" android:textColor = "@color/hint" android:textSize = "11sp" /> diff --git a/app/src/main/res/layout/rating_reply_item.xml b/app/src/main/res/layout/rating_reply_item.xml new file mode 100644 index 0000000000..f21b350111 --- /dev/null +++ b/app/src/main/res/layout/rating_reply_item.xml @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +