From 21dc20dff1120e46fd769147dc6690c60dfc2bbc Mon Sep 17 00:00:00 2001 From: chenjuntao Date: Wed, 18 Sep 2019 11:12:34 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=A4=BE=E5=8C=BA=E6=8F=90?= =?UTF-8?q?=E9=97=AE=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD=E5=BC=BA=E5=8C=96?= =?UTF-8?q?=20https://gitlab.ghzs.com/pm/halo-app-issues/issues/618?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/gh/common/util/Extensions.kt | 8 + .../java/com/gh/gamecenter/entity/MeEntity.kt | 3 + .../gamecenter/personal/PersonalFragment.java | 9 +- .../qa/entity/QuestionsDetailEntity.kt | 2 - .../detail/QuestionDetailItemData.kt | 9 + .../detail/QuestionsDetailAdapter.java | 356 ---------- .../detail/QuestionsDetailAdapter.kt | 407 ++++++++++++ .../detail/QuestionsDetailFragment.java | 616 ------------------ .../detail/QuestionsDetailFragment.kt | 571 ++++++++++++++++ .../detail/QuestionsDetailViewModel.kt | 116 +++- .../invite/QuestionsInviteAdapter.kt | 8 +- .../retrofit/service/ApiService.java | 19 + .../button_question_detail_invite.xml | 9 + .../item_question_detail_recommended_user.xml | 59 ++ ...em_question_detail_similar_answer_hint.xml | 15 + 15 files changed, 1225 insertions(+), 982 deletions(-) create mode 100644 app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionDetailItemData.kt delete mode 100644 app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailAdapter.java create mode 100644 app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailAdapter.kt delete mode 100644 app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailFragment.java create mode 100644 app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailFragment.kt create mode 100644 app/src/main/res/drawable/button_question_detail_invite.xml create mode 100644 app/src/main/res/layout/item_question_detail_recommended_user.xml create mode 100644 app/src/main/res/layout/item_question_detail_similar_answer_hint.xml diff --git a/app/src/main/java/com/gh/common/util/Extensions.kt b/app/src/main/java/com/gh/common/util/Extensions.kt index 080b4c2af3..59e01c2066 100644 --- a/app/src/main/java/com/gh/common/util/Extensions.kt +++ b/app/src/main/java/com/gh/common/util/Extensions.kt @@ -15,6 +15,7 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity import androidx.lifecycle.* import androidx.viewpager.widget.ViewPager +import com.facebook.drawee.view.SimpleDraweeView import com.gh.common.constant.Config import com.gh.gamecenter.BuildConfig import com.gh.gamecenter.R @@ -308,6 +309,13 @@ fun Int.toSimpleCount(): String { return NumberUtils.transSimpleCount(this) } +/** + * Image related + */ +fun SimpleDraweeView.display(url: String) { + ImageUtils.display(this, url) +} + /** * 测试用包裹 */ diff --git a/app/src/main/java/com/gh/gamecenter/entity/MeEntity.kt b/app/src/main/java/com/gh/gamecenter/entity/MeEntity.kt index 792c6d9188..231896e0b9 100644 --- a/app/src/main/java/com/gh/gamecenter/entity/MeEntity.kt +++ b/app/src/main/java/com/gh/gamecenter/entity/MeEntity.kt @@ -98,6 +98,9 @@ class MeEntity(@SerializedName("is_community_voted") @SerializedName("is_appointment") var isGameReserved: Boolean = false, // 是否已预约了游戏 + @SerializedName("is_smart_invite") + var isSmartInvited: Boolean = false, // 是否在具体问题详情页面点了智能邀请按钮 + @SerializedName("permissions") val moderatorPermissions: Permissions = Permissions()) : Parcelable diff --git a/app/src/main/java/com/gh/gamecenter/personal/PersonalFragment.java b/app/src/main/java/com/gh/gamecenter/personal/PersonalFragment.java index 1a13f79d9e..d0eb038703 100644 --- a/app/src/main/java/com/gh/gamecenter/personal/PersonalFragment.java +++ b/app/src/main/java/com/gh/gamecenter/personal/PersonalFragment.java @@ -339,8 +339,13 @@ public class PersonalFragment extends BaseFragment implements Observer? = null) \ No newline at end of file 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 deleted file mode 100644 index 08e05f7cab..0000000000 --- a/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailAdapter.java +++ /dev/null @@ -1,356 +0,0 @@ -package com.gh.gamecenter.qa.questions.detail; - -import android.content.Context; -import android.graphics.Color; -import android.graphics.drawable.Drawable; -import androidx.annotation.StringRes; -import androidx.core.content.ContextCompat; -import androidx.recyclerview.widget.RecyclerView; -import android.text.TextUtils; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.gh.base.OnListClickListener; -import com.gh.common.constant.ItemViewType; -import com.gh.common.util.DataUtils; -import com.gh.common.util.DisplayUtils; -import com.gh.common.util.ImageUtils; -import com.gh.common.util.NumberUtils; -import com.gh.gamecenter.R; -import com.gh.gamecenter.adapter.viewholder.FooterViewHolder; -import com.gh.gamecenter.adapter.viewholder.ReuseViewHolder; -import com.gh.gamecenter.baselist.ListAdapter; -import com.gh.gamecenter.entity.CommunityEntity; -import com.gh.gamecenter.qa.column.detail.AskColumnDetailActivity; -import com.gh.gamecenter.qa.entity.AnswerEntity; -import com.gh.gamecenter.qa.entity.QuestionsDetailEntity; -import com.google.android.flexbox.FlexboxLayout; - -import java.util.ArrayList; -import java.util.List; - -import butterknife.BindView; - -/** - * Created by khy on 7/12/17. - */ - -public class QuestionsDetailAdapter extends ListAdapter { - private final static int ITEM_EMPTY_COUNT = 1; - - private boolean mIsNoneData; - - private OnListClickListener mListClickListener; - - private QuestionsDetailEntity mQuestionsDetailEntity; - - private String mEntrance; - - QuestionsDetailAdapter(Context context, OnListClickListener listClickListener, String entrance) { - super(context); - mListClickListener = listClickListener; - mEntrance = entrance; - } - - public void setQuestionsEntity(QuestionsDetailEntity questionsDetailEntity) { - mQuestionsDetailEntity = questionsDetailEntity; - notifyDataSetChanged(); - } - - public String getQuestionsTitle() { - return mQuestionsDetailEntity != null ? mQuestionsDetailEntity.getTitle() : ""; - } - - @Override - protected void setListData(List updateData) { - if (updateData != null && updateData.size() == 0) { - mIsNoneData = true; - } else { - mIsNoneData = false; - } - mEntityList = new ArrayList<>(updateData); - notifyDataSetChanged(); - } - - @Override - public int getItemViewType(int position) { - if (position == 0 && mQuestionsDetailEntity != null) { - return ItemViewType.ITEM_HEADER; - } else if (position == getItemCount() - 1) { - return ItemViewType.ITEM_FOOTER; - } else if (mEntityList == null || mEntityList.isEmpty()) { - return ItemViewType.ITEM_EMPTY; - } else { - return ItemViewType.ITEM_BODY; - } - } - - @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view; - switch (viewType) { - case ItemViewType.ITEM_HEADER: - view = mLayoutInflater.inflate(R.layout.questionsdetail_item, parent, false); - return new QuestionsDetailItemViewHolder(view, mListClickListener); - case ItemViewType.ITEM_FOOTER: - view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false); - return new FooterViewHolder(view, mListClickListener); - case ItemViewType.ITEM_BODY: - view = mLayoutInflater.inflate(R.layout.ask_answer_item, parent, false); - return new AnswerViewHolder(view, mListClickListener); - case ItemViewType.ITEM_EMPTY: - view = mLayoutInflater.inflate(R.layout.reuse_nodata_skip, parent, false); - return new EmptyViewHolder(view); - default: - return null; - } - - } - - @Override - public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { - switch (getItemViewType(position)) { - case ItemViewType.ITEM_HEADER: - initQuestionsDetailItemViewHolder((QuestionsDetailItemViewHolder) holder); - break; - case ItemViewType.ITEM_EMPTY: - EmptyViewHolder emptyViewHolder = (EmptyViewHolder) holder; - if (mQuestionsDetailEntity != null && mQuestionsDetailEntity.isAnswerFold()) { - emptyViewHolder.tvHint.setText(""); - } else { - emptyViewHolder.tvHint.setText("暂无回答"); - } - - if (mQuestionsDetailEntity != null && !TextUtils.isEmpty(mQuestionsDetailEntity.getMe().getMyAnswerId())) { - emptyViewHolder.tvBtn.setVisibility(View.GONE); - } else { - emptyViewHolder.tvBtn.setVisibility(View.VISIBLE); - } - emptyViewHolder.tvBtn.setText("我来回答"); - emptyViewHolder.itemView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(200))); - emptyViewHolder.itemView.setOnClickListener(v -> mListClickListener.onListClick(holder.itemView, 1, null)); - break; - case ItemViewType.ITEM_FOOTER: - FooterViewHolder footerViewHolder = (FooterViewHolder) holder; - footerViewHolder.initItemPadding(); - LinearLayout item = (LinearLayout) footerViewHolder.itemView; - footerViewHolder.lineLeft.setVisibility(View.GONE); - footerViewHolder.lineRight.setVisibility(View.GONE); - if (mIsNetworkError) { - footerViewHolder.loading.setVisibility(View.GONE); - footerViewHolder.hint.setText(R.string.loading_failed_retry); - footerViewHolder.hint.setCompoundDrawables(null, null, null, null); - footerViewHolder.hint.setPadding(0, 0, 0, 0); - item.setGravity(Gravity.CENTER); - } else if (mIsOver) { - footerViewHolder.loading.setVisibility(View.GONE); - footerViewHolder.hint.setText(R.string.questionsdetail_fold_hint); - footerViewHolder.hint.setPadding(DisplayUtils.dip2px(mContext, 20), 0, 0, 0); - Drawable drawable = ContextCompat.getDrawable(mContext, R.drawable.questionsdetail_footer_icon); - item.setGravity(Gravity.CENTER_VERTICAL); - if (drawable != null) { - drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight()); - footerViewHolder.hint.setCompoundDrawables(null, null, drawable, null); - footerViewHolder.hint.setCompoundDrawablePadding(20); - } - } else { - footerViewHolder.loading.setVisibility(View.VISIBLE); - footerViewHolder.hint.setText(R.string.loading); - footerViewHolder.hint.setCompoundDrawables(null, null, null, null); - footerViewHolder.hint.setPadding(0, 0, 0, 0); - item.setGravity(Gravity.CENTER); - } - if (!mIsOver || (mQuestionsDetailEntity != null && mQuestionsDetailEntity.isAnswerFold())) { - footerViewHolder.itemView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); - } else { - footerViewHolder.itemView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0)); - } - - break; - case ItemViewType.ITEM_BODY: - int index = position - ListAdapter.TOP_ITEM_COUNT; - if (index != -1) - ((AnswerViewHolder) holder).initAnswerViewHolder(mContext, mEntityList.get(index), mEntrance, "问题详情"); - break; - } - } - - private void initQuestionsDetailItemViewHolder(QuestionsDetailItemViewHolder holder) { - List images = mQuestionsDetailEntity.getImages(); - if (mQuestionsDetailEntity.getImages().size() == 0) { - holder.mPic2.setVisibility(View.INVISIBLE); - } else if (mQuestionsDetailEntity.getImages().size() == 1) { - holder.mPic2.setVisibility(View.INVISIBLE); - holder.mPic3.setVisibility(View.INVISIBLE); - holder.mPic3Desc.setVisibility(View.GONE); - holder.mPic3Mask.setVisibility(View.GONE); - } else if(mQuestionsDetailEntity.getImages().size() == 2) { - holder.mPic3.setVisibility(View.INVISIBLE); - holder.mPic3Desc.setVisibility(View.GONE); - holder.mPic3Mask.setVisibility(View.GONE); - } else if(mQuestionsDetailEntity.getImages().size() == 3) { - holder.mPic3Desc.setVisibility(View.GONE); - holder.mPic3Mask.setVisibility(View.GONE); - } - - for (int i = 0; i < images.size(); i++) { - switch (i) { - case 0: - holder.mPic1.setVisibility(View.VISIBLE); - ImageUtils.display(holder.mPic1, images.get(i)); - break; - case 1: - holder.mPic2.setVisibility(View.VISIBLE); - ImageUtils.display(holder.mPic2, images.get(i)); - break; - case 2: - holder.mPic3.setVisibility(View.VISIBLE); - ImageUtils.display(holder.mPic3, images.get(i)); - if (images.size() > 3) { - holder.mPic3Mask.setVisibility(View.VISIBLE); - holder.mPic3Desc.setVisibility(View.VISIBLE); - holder.mPic3Desc.setText("+" + (images.size() - 3)); - } - break; - } - } - - if (images.size() > 0) { - holder.mImgLl.setVisibility(View.VISIBLE); - } else { - holder.mImgLl.setVisibility(View.GONE); - } - - List tags = mQuestionsDetailEntity.getTags(); - holder.mTagRl.removeAllViews(); - for (int i = 0; i < tags.size(); i++) { - if (!TextUtils.isEmpty(tags.get(i))) addTag(holder.mTagRl, tags.get(i), false); - } -// addTag(holder.mTagRl, mQuestionsDetailEntity.getCommunityName(), true); - String description = mQuestionsDetailEntity.getDescription(); - if (TextUtils.isEmpty(description)) { - holder.mDes.setVisibility(View.GONE); - } else { - holder.mDes.setVisibility(View.VISIBLE); - holder.mDes.setText(description); - } - if (!TextUtils.isEmpty(mQuestionsDetailEntity.getMe().getMyAnswerId())) { - setAnswerTv(holder.answerTv, R.string.question_detail_myanswer); - } else if (mQuestionsDetailEntity.isExistDrafts()) { - setAnswerTv(holder.answerTv, R.string.question_detail_resume_answer); - } else { - setAnswerTv(holder.answerTv, R.string.question_detail_answer); - } - - if (mQuestionsDetailEntity.getMe().isQuestionOwn()) { - holder.concern.setBackgroundResource(R.drawable.questions_detail_tag_bg); - holder.concern.setTextColor(ContextCompat.getColor(mContext, R.color.hint)); - holder.concern.setText("编辑问题"); - } else if (mQuestionsDetailEntity.getMe().isQuestionFollowed()) { - holder.concern.setBackgroundResource(R.drawable.questions_detail_tag_bg); - holder.concern.setTextColor(ContextCompat.getColor(mContext, R.color.hint)); - holder.concern.setText("已关注"); - } else { - holder.concern.setBackgroundResource(R.drawable.button_normal_style); - holder.concern.setTextColor(Color.WHITE); - holder.concern.setText("关注问题"); - } - - if (mQuestionsDetailEntity.getRelatedQuestion() != null) { - holder.mRelatedQuestionContainer.setVisibility(View.VISIBLE); - holder.mRelatedQuestionContainer.setOnClickListener(v -> { - mContext.startActivity(QuestionsDetailActivity.getIntent( - mContext, - mQuestionsDetailEntity.getRelatedQuestion().getId(), - mEntrance, - "关联问题")); - }); - holder.mRelatedQuestionTitle.setText(mQuestionsDetailEntity.getRelatedQuestion().getTitle()); - holder.mRelatedQuestionAnswerCount.setText( - (NumberUtils.transSimpleCount(mQuestionsDetailEntity.getRelatedQuestion().getAnswerCount()) + "回答")); - } else { - holder.mRelatedQuestionContainer.setVisibility(View.GONE); - } - - holder.mTitle.setText(mQuestionsDetailEntity.getTitle()); - holder.concernCount.setText((NumberUtils.transSimpleCount(mQuestionsDetailEntity.getFollowCount()) + "人关注")); - - if (mQuestionsDetailEntity.getAnswersCount() == 0) { - holder.mAnswercount.setVisibility(View.GONE); - } else { - holder.mAnswercount.setVisibility(View.VISIBLE); - holder.mAnswercount.setText(mContext.getString(R.string.ask_answer_count, NumberUtils.transSimpleCount(mQuestionsDetailEntity.getAnswersCount()))); - } - } - - private void addTag(FlexboxLayout mTagRl, String tag, boolean isLastTag) { - View view = LayoutInflater.from(mContext).inflate(R.layout.questionsdedit_tag_item, null); - TextView tagTv = (TextView) view; - tagTv.setText(tag); - tagTv.setBackgroundResource(R.drawable.button_normal_style); - tagTv.setTextColor(Color.WHITE); - FlexboxLayout.LayoutParams params = new FlexboxLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT); - params.setMargins(0, DisplayUtils.dip2px(mContext, 5), !isLastTag ? DisplayUtils.dip2px(mContext, 8) : 0, - DisplayUtils.dip2px(mContext, 5)); - tagTv.setLayoutParams(params); - mTagRl.addView(view); - - view.setOnClickListener(v -> { - DataUtils.onMtaEvent(mContext, "问题标签", mQuestionsDetailEntity.getCommunity().getName(), mQuestionsDetailEntity.getTitle() + "-" + tag); - mContext.startActivity(AskColumnDetailActivity.Companion.getIntentByTag(mContext, tag, - new CommunityEntity(mQuestionsDetailEntity.getCommunity().getId(), - mQuestionsDetailEntity.getCommunity().getName()), mEntrance, "问题详情")); - }); - } - - private void setAnswerTv(TextView answerTv, @StringRes int answerTvId) { - String answerText = mContext.getString(answerTvId); - answerTv.setText(answerText); - - Drawable drawable; - if (mContext.getString(R.string.question_detail_myanswer).equals(answerText)) { - drawable = ContextCompat.getDrawable(mContext, R.drawable.questionsdetail_myanswer_icon); - } else { - drawable = ContextCompat.getDrawable(mContext, R.drawable.questionsdetail_answer_icon); - } - drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight()); - answerTv.setCompoundDrawables(drawable, null, null, null); - } - - @Override - public int getItemCount() { - if (mQuestionsDetailEntity == null) { - return 0; - } - - if (mIsNoneData && (mEntityList == null || mEntityList.isEmpty())) { - if (mQuestionsDetailEntity.isAnswerFold()) { - return FOOTER_ITEM_COUNT + TOP_ITEM_COUNT; - } else { - return FOOTER_ITEM_COUNT + TOP_ITEM_COUNT + ITEM_EMPTY_COUNT; - } - } - - return mEntityList == null ? FOOTER_ITEM_COUNT + TOP_ITEM_COUNT : mEntityList.size() + FOOTER_ITEM_COUNT + TOP_ITEM_COUNT; - } - - boolean isOver() { - return mIsOver; - } - - class EmptyViewHolder extends ReuseViewHolder { - @BindView(R.id.reuse_nodata_skip_tv_hint) - TextView tvHint; - @BindView(R.id.reuse_nodata_skip_tv_btn) - TextView tvBtn; - - public EmptyViewHolder(View itemView) { - super(itemView); - } - } -} diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailAdapter.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailAdapter.kt new file mode 100644 index 0000000000..8036f03a08 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailAdapter.kt @@ -0,0 +1,407 @@ +package com.gh.gamecenter.qa.questions.detail + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.text.TextUtils +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.LinearLayout +import android.widget.TextView +import androidx.annotation.StringRes +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import butterknife.BindView +import com.gh.base.BaseRecyclerViewHolder +import com.gh.base.OnListClickListener +import com.gh.common.constant.ItemViewType +import com.gh.common.util.* +import com.gh.gamecenter.R +import com.gh.gamecenter.adapter.viewholder.FooterViewHolder +import com.gh.gamecenter.adapter.viewholder.ReuseViewHolder +import com.gh.gamecenter.baselist.ListAdapter +import com.gh.gamecenter.entity.CommunityEntity +import com.gh.gamecenter.qa.column.detail.AskColumnDetailActivity +import com.gh.gamecenter.qa.entity.InviteEntity +import com.gh.gamecenter.qa.entity.QuestionsDetailEntity +import com.gh.gamecenter.qa.questions.invite.QuestionsInviteAdapter +import com.google.android.flexbox.FlexboxLayout + +class QuestionsDetailAdapter( + context: Context, + private var mListClickListener: OnListClickListener, + private var mQuestionEntity: QuestionsDetailEntity? = null, + private val mViewModel: QuestionsDetailViewModel, + private val mEntrance: String) : ListAdapter(context) { + + private var mIsNoneData: Boolean = false + + fun setQuestionsEntity(questionsDetailEntity: QuestionsDetailEntity) { + mQuestionEntity = questionsDetailEntity + notifyDataSetChanged() + } + + fun getQuestionsTitle(): String { + return mQuestionEntity?.title ?: "" + } + + override fun setListData(updateData: List?) { + mIsNoneData = updateData != null && updateData.isEmpty() + mEntityList = ArrayList(updateData!!) + notifyDataSetChanged() + } + + override fun getItemViewType(position: Int): Int { + return when { + position == 0 && mQuestionEntity != null -> ItemViewType.ITEM_HEADER + + position == itemCount - 1 -> ItemViewType.ITEM_FOOTER + + mEntityList == null || mEntityList.isEmpty() -> ItemViewType.ITEM_EMPTY + + mEntityList[position - TOP_ITEM_COUNT].answer != null -> ItemViewType.ITEM_BODY + + mEntityList[position - TOP_ITEM_COUNT].similarAnswer != null -> TYPE_SIMILAR_ANSWER + + mEntityList[position - TOP_ITEM_COUNT].showSimilarAnswerHint != null -> TYPE_SIMILAR_ANSWER_HINT + + mEntityList[position - TOP_ITEM_COUNT].recommendedUserToInvite != null -> TYPE_RECOMMEND_USER_TO_INVITE + + else -> ItemViewType.ITEM_FOOTER + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + val view: View + when (viewType) { + ItemViewType.ITEM_HEADER -> { + view = mLayoutInflater.inflate(R.layout.questionsdetail_item, parent, false) + return QuestionsDetailItemViewHolder(view, mListClickListener) + } + ItemViewType.ITEM_FOOTER -> { + view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false) + return FooterViewHolder(view, mListClickListener) + } + ItemViewType.ITEM_BODY, TYPE_SIMILAR_ANSWER -> { + view = mLayoutInflater.inflate(R.layout.ask_answer_item, parent, false) + return AnswerViewHolder(view, mListClickListener) + } + ItemViewType.ITEM_EMPTY -> { + view = mLayoutInflater.inflate(R.layout.reuse_nodata_skip, parent, false) + return EmptyViewHolder(view) + } + TYPE_SIMILAR_ANSWER_HINT -> { + view = mLayoutInflater.inflate(R.layout.item_question_detail_similar_answer_hint, parent, false) + return SimilarAnswerHint(view) + } + TYPE_RECOMMEND_USER_TO_INVITE -> { + view = mLayoutInflater.inflate(R.layout.item_question_detail_recommended_user, parent, false) + return RecommendedUserToInviteViewHolder(view) + } + else -> { + view = mLayoutInflater.inflate(R.layout.reuse_nodata_skip, parent, false) + return EmptyViewHolder(view) + } + } + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + when (getItemViewType(position)) { + ItemViewType.ITEM_HEADER -> initQuestionsDetailItemViewHolder(holder as QuestionsDetailItemViewHolder) + ItemViewType.ITEM_EMPTY -> { + val emptyViewHolder = holder as EmptyViewHolder + if (mQuestionEntity != null && mQuestionEntity!!.isAnswerFold) { + emptyViewHolder.tvHint.text = "" + } else { + emptyViewHolder.tvHint.text = "暂无回答" + } + + if (mQuestionEntity != null && !TextUtils.isEmpty(mQuestionEntity!!.me.myAnswerId)) { + emptyViewHolder.tvBtn.visibility = View.GONE + } else { + emptyViewHolder.tvBtn.visibility = View.VISIBLE + } + emptyViewHolder.tvBtn.text = "我来回答" + emptyViewHolder.itemView.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(200f)) + emptyViewHolder.itemView.setOnClickListener { mListClickListener.onListClick(holder.itemView, 1, null) } + } + ItemViewType.ITEM_FOOTER -> { + val footerViewHolder = holder as FooterViewHolder + footerViewHolder.initItemPadding() + val item = footerViewHolder.itemView as LinearLayout + footerViewHolder.lineLeft.visibility = View.GONE + footerViewHolder.lineRight.visibility = View.GONE + if (mIsNetworkError) { + footerViewHolder.loading.visibility = View.GONE + footerViewHolder.hint.setText(R.string.loading_failed_retry) + footerViewHolder.hint.setCompoundDrawables(null, null, null, null) + footerViewHolder.hint.setPadding(0, 0, 0, 0) + item.gravity = Gravity.CENTER + } else if (mIsOver) { + footerViewHolder.loading.visibility = View.GONE + footerViewHolder.hint.setText(R.string.questionsdetail_fold_hint) + footerViewHolder.hint.setPadding(DisplayUtils.dip2px(mContext, 20f), 0, 0, 0) + val drawable = ContextCompat.getDrawable(mContext, R.drawable.questionsdetail_footer_icon) + item.gravity = Gravity.CENTER_VERTICAL + if (drawable != null) { + drawable.setBounds(0, 0, drawable.minimumWidth, drawable.minimumHeight) + footerViewHolder.hint.setCompoundDrawables(null, null, drawable, null) + footerViewHolder.hint.compoundDrawablePadding = 20 + } + } else { + footerViewHolder.loading.visibility = View.VISIBLE + footerViewHolder.hint.setText(R.string.loading) + footerViewHolder.hint.setCompoundDrawables(null, null, null, null) + footerViewHolder.hint.setPadding(0, 0, 0, 0) + item.gravity = Gravity.CENTER + } + if (!mIsOver || mQuestionEntity != null && mQuestionEntity!!.isAnswerFold) { + footerViewHolder.itemView.setLayoutParams(ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)) + } else { + footerViewHolder.itemView.setLayoutParams(ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0)) + } + } + ItemViewType.ITEM_BODY -> { + val index = position - TOP_ITEM_COUNT + if (index != -1) { + (holder as AnswerViewHolder).initAnswerViewHolder(mContext, mEntityList[index].answer, mEntrance, "问题详情") + } + } + TYPE_RECOMMEND_USER_TO_INVITE -> { + (holder as RecommendedUserToInviteViewHolder).bindView(mViewModel, mQuestionEntity!!, mEntityList[position - TOP_ITEM_COUNT].recommendedUserToInvite!!) + } + TYPE_SIMILAR_ANSWER -> { + val index = position - TOP_ITEM_COUNT + if (index != -1) { + (holder as AnswerViewHolder).initAnswerViewHolder(mContext, mEntityList[index].similarAnswer, mEntrance, "问题详情") + } + } + } + } + + @SuppressLint("SetTextI18n") + private fun initQuestionsDetailItemViewHolder(holder: QuestionsDetailItemViewHolder) { + val tags = mQuestionEntity?.tags ?: arrayListOf() + val images = mQuestionEntity?.images ?: arrayListOf() + val description = mQuestionEntity?.description ?: "" + val relatedQuestion = mQuestionEntity?.relatedQuestion + + // 标签 + holder.mTagRl.removeAllViews() + for (tag in tags) { + if (!TextUtils.isEmpty(tag)) { + addTag(holder.mTagRl, tag, false) + } + } + + // 缩略图 + holder.mImgLl.goneIf(images.isEmpty()) + holder.mPic1.visibleIf(images.isNotEmpty()) + holder.mPic2.visibleIf(images.size > 1) + holder.mPic3.visibleIf(images.size > 2) + holder.mPic3Desc.goneIf(images.size <= 3) + holder.mPic3Mask.goneIf(images.size <= 3) + + for (i in images.indices) { + when (i) { + 0 -> holder.mPic1.display(images[i]) + 1 -> holder.mPic2.display(images[i]) + 2 -> { + holder.mPic3.display(images[i]) + holder.mPic3Desc.text = "+" + (images.size - 3) + } + } + } + + // 问题描述 + holder.mDes.text = description + holder.mDes.goneIf(TextUtils.isEmpty(description)) + + // "我来回答" + if (!TextUtils.isEmpty(mQuestionEntity!!.me.myAnswerId)) { + updateAnswerTv(holder.answerTv, R.string.question_detail_myanswer) + } else if (mQuestionEntity!!.isExistDrafts) { + updateAnswerTv(holder.answerTv, R.string.question_detail_resume_answer) + } else { + updateAnswerTv(holder.answerTv, R.string.question_detail_answer) + } + + // "关注问题" + when { + mQuestionEntity!!.me.isQuestionOwn -> { + holder.concern.setBackgroundResource(R.drawable.questions_detail_tag_bg) + holder.concern.setTextColor(ContextCompat.getColor(mContext, R.color.hint)) + holder.concern.text = "编辑问题" + } + mQuestionEntity!!.me.isQuestionFollowed -> { + holder.concern.setBackgroundResource(R.drawable.questions_detail_tag_bg) + holder.concern.setTextColor(ContextCompat.getColor(mContext, R.color.hint)) + holder.concern.text = "已关注" + } + else -> { + holder.concern.setBackgroundResource(R.drawable.button_normal_style) + holder.concern.setTextColor(Color.WHITE) + holder.concern.text = "关注问题" + } + } + + // "关联问题"区域 + holder.mRelatedQuestionContainer.goneIf(relatedQuestion == null) + relatedQuestion?.let { + holder.mRelatedQuestionContainer.setOnClickListener { + mContext.startActivity(QuestionsDetailActivity.getIntent( + mContext, + relatedQuestion.id, + mEntrance, + "关联问题")) + } + holder.mRelatedQuestionTitle.text = relatedQuestion.title + holder.mRelatedQuestionAnswerCount.text = NumberUtils.transSimpleCount(relatedQuestion.answerCount!!) + "回答" + } + + holder.mTitle.text = mQuestionEntity?.title + holder.concernCount.text = NumberUtils.transSimpleCount(mQuestionEntity?.getFollowCount() + ?: 0) + "人关注" + + holder.mAnswercount.goneIf(mQuestionEntity?.answersCount == 0) + holder.mAnswercount.text = mContext.getString(R.string.ask_answer_count, NumberUtils.transSimpleCount(mQuestionEntity?.answersCount + ?: 0)) + } + + private fun addTag(mTagRl: FlexboxLayout, tag: String, isLastTag: Boolean) { + val view = LayoutInflater.from(mContext).inflate(R.layout.questionsdedit_tag_item, null) + val tagTv = view as TextView + tagTv.text = tag + tagTv.setBackgroundResource(R.drawable.button_normal_style) + tagTv.setTextColor(Color.WHITE) + val params = FlexboxLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT) + params.setMargins(0, DisplayUtils.dip2px(mContext, 5f), if (!isLastTag) DisplayUtils.dip2px(mContext, 8f) else 0, + DisplayUtils.dip2px(mContext, 5f)) + tagTv.layoutParams = params + mTagRl.addView(view) + + view.setOnClickListener { + DataUtils.onMtaEvent(mContext, "问题标签", mQuestionEntity!!.community.name, mQuestionEntity!!.title + "-" + tag) + mContext.startActivity(AskColumnDetailActivity.getIntentByTag(mContext, tag, + CommunityEntity(mQuestionEntity!!.community.id, + mQuestionEntity!!.community.name), mEntrance, "问题详情")) + } + } + + private fun updateAnswerTv(answerTv: TextView, @StringRes stringId: Int) { + answerTv.text = mContext.getString(stringId) + + val drawable = if (R.string.question_detail_myanswer == stringId) { + ContextCompat.getDrawable(mContext, R.drawable.questionsdetail_myanswer_icon) + } else { + ContextCompat.getDrawable(mContext, R.drawable.questionsdetail_answer_icon) + } + drawable?.setBounds(0, 0, drawable.minimumWidth, drawable.minimumHeight) + answerTv.setCompoundDrawables(drawable, null, null, null) + } + + override fun getItemCount(): Int { + if (mQuestionEntity == null) { + return 0 + } + + if (mIsNoneData && (mEntityList == null || mEntityList.isEmpty())) { + return if (mQuestionEntity!!.isAnswerFold) { + FOOTER_ITEM_COUNT + TOP_ITEM_COUNT + } else { + FOOTER_ITEM_COUNT + TOP_ITEM_COUNT + ITEM_EMPTY_COUNT + } + } + + return if (mEntityList == null) FOOTER_ITEM_COUNT + TOP_ITEM_COUNT else mEntityList.size + FOOTER_ITEM_COUNT + TOP_ITEM_COUNT + } + + fun isOver(): Boolean { + return mIsOver + } + + class EmptyViewHolder(itemView: View) : ReuseViewHolder(itemView) { + @BindView(R.id.reuse_nodata_skip_tv_hint) + lateinit var tvHint: TextView + @BindView(R.id.reuse_nodata_skip_tv_btn) + lateinit var tvBtn: TextView + } + + class RecommendedUserToInviteViewHolder(itemView: View) : BaseRecyclerViewHolder(itemView) { + + @BindView(R.id.inviteBtn) + lateinit var inviteBtn: View + @BindView(R.id.recyclerview) + lateinit var recyclerView: RecyclerView + + var adapter: SimpleInviteAdapter? = null + + fun bindView(viewModel: QuestionsDetailViewModel, question: QuestionsDetailEntity, userList: List) { + + inviteBtn.visibleIf(question.me.isQuestionOwn && !question.me.isSmartInvited) + inviteBtn.setOnClickListener { + DialogUtils.showAlertDialog( + inviteBtn.context, + "智能邀请", + "将为你智能邀请用户来回答!你还可以手动邀请喔~", + "确定", + "取消", + { viewModel.doSmartInvitation() }, + null + ) + } + + if (adapter == null) { + adapter = SimpleInviteAdapter(recyclerView.context, object : OnListClickListener { + override fun onListClick(view: View?, position: Int, data: T) { + when (view?.id) { + R.id.questionsinvite_item_invite -> { + val inviteEntity = data as InviteEntity + val me = inviteEntity.me + if (me == null || !me.isUserInvite) { + recyclerView.context.ifLogin("问题详情-邀请回答-[邀请]") { viewModel.invite(inviteEntity.id!!) } + } + } + } + } + }, "问题详情") + } + recyclerView.adapter = adapter + recyclerView.layoutManager = LinearLayoutManager(recyclerView.context) + + adapter?.setData(userList) + } + } + + class SimpleInviteAdapter(context: Context, onListClickListener: OnListClickListener, entrance: String) + : QuestionsInviteAdapter(context, onListClickListener, entrance) { + override fun getItemViewType(position: Int): Int { + return ItemViewType.ITEM_BODY + } + + override fun getItemCount(): Int { + return if (mEntityList != null && mEntityList.size != 0) mEntityList.size else 0 + } + + fun setData(dataList: List) { + setListData(dataList) + } + } + + class SimilarAnswerHint(itemView: View) : BaseRecyclerViewHolder(itemView) + + companion object { + private const val ITEM_EMPTY_COUNT = 1 + + private const val TYPE_RECOMMEND_USER_TO_INVITE = 987 + + private const val TYPE_SIMILAR_ANSWER = 988 + + private const val TYPE_SIMILAR_ANSWER_HINT = 989 + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailFragment.java b/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailFragment.java deleted file mode 100644 index e367a92e3f..0000000000 --- a/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailFragment.java +++ /dev/null @@ -1,616 +0,0 @@ -package com.gh.gamecenter.qa.questions.detail; - -import android.app.Activity; -import android.app.Dialog; -import android.content.Intent; -import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; -import android.os.Bundle; -import android.text.TextUtils; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.view.WindowManager; -import android.widget.LinearLayout; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; -import androidx.fragment.app.FragmentActivity; -import androidx.lifecycle.Lifecycle; -import androidx.lifecycle.ViewModelProviders; -import androidx.recyclerview.widget.DefaultItemAnimator; -import androidx.recyclerview.widget.RecyclerView; - -import com.ethanhua.skeleton.Skeleton; -import com.gh.base.fragment.BaseDialogWrapperFragment; -import com.gh.common.TimeElapsedHelper; -import com.gh.common.util.CheckLoginUtils; -import com.gh.common.util.ConcernUtils; -import com.gh.common.util.DataUtils; -import com.gh.common.util.DialogUtils; -import com.gh.common.util.DisplayUtils; -import com.gh.common.util.EntranceUtils; -import com.gh.common.util.GdtHelper; -import com.gh.common.util.LogUtils; -import com.gh.common.util.MtaHelper; -import com.gh.common.util.PermissionHelper; -import com.gh.common.util.ShareUtils; -import com.gh.common.util.StringUtils; -import com.gh.common.util.UrlFilterUtils; -import com.gh.common.view.VerticalItemDecoration; -import com.gh.gamecenter.R; -import com.gh.gamecenter.SuggestionActivity; -import com.gh.gamecenter.ViewImageActivity; -import com.gh.gamecenter.baselist.ListAdapter; -import com.gh.gamecenter.baselist.ListFragment; -import com.gh.gamecenter.baselist.LoadType; -import com.gh.gamecenter.entity.Permissions; -import com.gh.gamecenter.entity.SpecialColumn; -import com.gh.gamecenter.eventbus.EBReuse; -import com.gh.gamecenter.mvvm.Status; -import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity; -import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity; -import com.gh.gamecenter.qa.answer.fold.AnswerFoldActivity; -import com.gh.gamecenter.qa.entity.AnswerDraftEntity; -import com.gh.gamecenter.qa.entity.AnswerEntity; -import com.gh.gamecenter.qa.entity.Questions; -import com.gh.gamecenter.qa.entity.QuestionsDetailEntity; -import com.gh.gamecenter.qa.questions.edit.QuestionEditActivity; -import com.gh.gamecenter.qa.questions.edit.TagsSelectFragment; -import com.gh.gamecenter.qa.questions.edit.manager.HistoryActivity; -import com.gh.gamecenter.qa.questions.invite.QuestionsInviteActivity; -import com.gh.gamecenter.retrofit.Response; -import com.gh.gamecenter.retrofit.RetrofitManager; -import com.gh.gamecenter.suggest.SuggestType; -import com.lightgame.utils.Utils; -import com.qq.gdt.action.ActionType; - -import org.greenrobot.eventbus.Subscribe; -import org.greenrobot.eventbus.ThreadMode; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -import butterknife.BindView; -import io.reactivex.Observable; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.schedulers.Schedulers; -import retrofit2.HttpException; - -import static com.gh.gamecenter.personal.PersonalFragment.LOGIN_TAG; - -/** - * Created by khy on 7/12/17. - */ -public class QuestionsDetailFragment - extends ListFragment - implements TagsSelectFragment.OnModeratorPatchTagsCallback { - - public static final int QUESTIONS_DETAIL_ANSWER_REQUEST = 110; - public static final int QUESTIONS_EDIT_REQUEST = 111; - public static final int QUESTIONS_MODERATOR_HISTORY_REQUEST = 112; - - private SpecialColumn mSpecialColumn = null; - - @BindView(R.id.reuse_tv_none_data) - TextView mNoDataTv; - @BindView(R.id.list_skeleton) - View mSkeletonMaskView; - - private QuestionsDetailAdapter mAdapter; - - private QuestionsDetailEntity mQuestionsDetailEntity; - - private String mQuestionsId; - - private boolean mIsCheckConcern; - - private String mPath; - private TimeElapsedHelper mElapsedHelper; - - public static QuestionsDetailFragment getInstance(String questionsId) { - QuestionsDetailFragment fragment = new QuestionsDetailFragment(); - Bundle args = new Bundle(); - args.putString(EntranceUtils.KEY_QUESTIONS_ID, questionsId); - fragment.setArguments(args); - return fragment; - } - - protected RecyclerView.ItemDecoration getItemDecoration() { - return new VerticalItemDecoration(getContext(), 8, false); - } - - @Override - protected int getLayoutId() { - return R.layout.fragment_list_base_skeleton_no_loading; - } - - @Override - protected ListAdapter provideListAdapter() { - return mAdapter == null ? mAdapter = new QuestionsDetailAdapter(getContext(), this, mEntrance) : mAdapter; - } - - @Override - protected QuestionsDetailViewModel provideListViewModel() { - QuestionsDetailViewModel.Factory factory = new QuestionsDetailViewModel.Factory(mQuestionsId); - return ViewModelProviders.of(this, factory).get(QuestionsDetailViewModel.class); - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (requestCode == QUESTIONS_DETAIL_ANSWER_REQUEST) { - if (resultCode == AnswerEditActivity.SAVE_DRAFTS) { - postDraftsSuccess(); - } else if (resultCode == RESULT_REFRESH) { - onLoadRefresh(); - } else if (resultCode == Activity.RESULT_OK) { - if (data != null) { - postAnswerSuccess(data.getStringExtra(EntranceUtils.KEY_ANSWER_ID)); - } - } - } else if (requestCode == QUESTIONS_EDIT_REQUEST && resultCode == Activity.RESULT_OK) { - if (data != null && data.getParcelableExtra(QuestionsDetailEntity.class.getSimpleName()) != null) { - mQuestionsDetailEntity = data.getParcelableExtra(QuestionsDetailEntity.class.getSimpleName()); - mAdapter.setQuestionsEntity(mQuestionsDetailEntity); - } - } else if (requestCode == QUESTIONS_EDIT_REQUEST && resultCode == Activity.RESULT_CANCELED) { - onPermissionError(); - } else if (requestCode == QUESTIONS_MODERATOR_HISTORY_REQUEST && resultCode == Activity.RESULT_OK) { - onLoadRefresh(); - } - } - - @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - initMenu(R.menu.menu_questions_detail); - } - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - Bundle arguments = getArguments(); - if (arguments != null) { - mIsCheckConcern = arguments.getBoolean(EntranceUtils.KEY_CHECK_QUESTION_CONCERN, false); - mQuestionsId = arguments.getString(EntranceUtils.KEY_QUESTIONS_ID); - mPath = arguments.getString(EntranceUtils.KEY_PATH); - mSpecialColumn = arguments.getParcelable(EntranceUtils.KEY_DATA); - } - super.onCreate(savedInstanceState); - - mNoDataTv.setText(R.string.content_delete_hint); - - mElapsedHelper = new TimeElapsedHelper(this); - - mSkeletonScreen = Skeleton.bind(mSkeletonMaskView).load(R.layout.fragment_question_detail_skeleton).shimmer(false).show(); - - mListViewModel.getHeadLiveData().observe(this, detailResource -> { - Objects.requireNonNull(detailResource); - if (detailResource.status == Status.SUCCESS) { - QuestionsDetailEntity data = detailResource.data; - Objects.requireNonNull(data); - if (TextUtils.isEmpty(data.getMe().getMyAnswerId())) { - getUserAnswerDrafts(); - } - data.setId(mQuestionsId); - mQuestionsDetailEntity = data; - mAdapter.setQuestionsEntity(data); - - GdtHelper.INSTANCE.logAction(ActionType.PAGE_VIEW, - GdtHelper.CONTENT_TYPE, "QUESTION", - GdtHelper.CONTENT_ID, mQuestionsId); - - setNavigationTitle(mQuestionsDetailEntity.getCommunity().getName() + " - 问题详情"); - DataUtils.onMtaEvent(getContext(), "详情页面", "问题详情", data.getTitle()); - } else if (detailResource.status == Status.ERROR) { - try { - HttpException e = detailResource.exception; - if (e != null && e.code() == 404 && e.response().errorBody().string().length() > 0) { - Utils.toast(getContext(), R.string.content_delete_toast); - if (mIsCheckConcern) { - showCancelConcernDialog(); - } - } - } catch (IOException e1) { - e1.printStackTrace(); - } - } - }); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - ((DefaultItemAnimator) mListRv.getItemAnimator()).setSupportsChangeAnimations(false); - mReuseNoConn.setOnClickListener(view1 -> { // 重新设置重连点击 - onRefresh(); - }); - - mCachedView.getViewTreeObserver().addOnScrollChangedListener(() -> { - View topView = mLayoutManager.findViewByPosition(0); - if (mQuestionsDetailEntity != null) { - if (topView == null || -topView.getTop() > 240) { - setNavigationTitle(mQuestionsDetailEntity.getTitle()); - } else { - setNavigationTitle(mQuestionsDetailEntity.getCommunity().getName() + " - 问题详情"); - } - } - }); - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - if (mQuestionsDetailEntity != null) { - MtaHelper.onEventWithTime( - "问题阅读量_按社区", - mElapsedHelper.getElapsedTime(), - mQuestionsDetailEntity.getCommunity().getName(), - StringUtils.combineTwoString(mQuestionsDetailEntity.getTitle(), mQuestionsDetailEntity.getId())); - - MtaHelper.onEventWithTime( - "问题阅读量_按位置", - mElapsedHelper.getElapsedTime(), - mPath, - StringUtils.combineTwoString(mQuestionsDetailEntity.getTitle(), mQuestionsDetailEntity.getId())); - - MtaHelper.onEventWithTime( - "问题阅读量_社区加位置", - mElapsedHelper.getElapsedTime(), - mQuestionsDetailEntity.getCommunity().getName(), - mPath); - - Questions questions = new Questions(); - questions.setId(mQuestionsId); - questions.setTitle(mQuestionsDetailEntity.getTitle()); - LogUtils.uploadQuestionReadTime(mEntrance, - mElapsedHelper.getElapsedTime(), - questions, - mQuestionsDetailEntity.getCommunity().getId(), - mQuestionsDetailEntity.getCommunity().getName(), - mSpecialColumn); - } - } - - @Override - public Observable> provideDataObservable(int page) { - return RetrofitManager.getInstance(getContext()).getApi() - .getQuestionsAnswer(mQuestionsId, UrlFilterUtils.getFilterQuery("fold", "false"), page); - } - - @Override - public void onListClick(View view, int position, Object data) { - super.onListClick(view, position, data); - int imgPosition = -1; - switch (view.getId()) { - case R.id.footerview_item: - if (mAdapter.isNetworkError()) { - mListViewModel.load(LoadType.RETRY); - } else if (mAdapter.isOver()) { - if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) { - startActivity(AnswerFoldActivity.getIntent(getContext(), mQuestionsDetailEntity.getId(), mEntrance + "+(问题详情)")); - } - } - break; - case R.id.ask_answer_item_constraintlayout: - case R.id.ask_answer_item_img: - case R.id.ask_answer_item_content: - case R.id.ask_answer_item_title: - AnswerEntity entity = (AnswerEntity) data; - startActivityForResult(AnswerDetailActivity.getIntent(getContext(), entity.getId(), mEntrance, "问题详情-答案列表") - , QUESTIONS_DETAIL_ANSWER_REQUEST); - break; - case R.id.questionsdetail_item_pic1: - imgPosition = 0; - case R.id.questionsdetail_item_pic2: - if (imgPosition == -1) imgPosition = 1; - case R.id.questionsdetail_item_pic3: - if (imgPosition == -1) imgPosition = 2; - if (mQuestionsDetailEntity.getImages().size() > imgPosition) { - Intent intent = ViewImageActivity.getViewImageIntent(getContext(), new ArrayList<>(mQuestionsDetailEntity.getImages()) - , imgPosition, mEntrance + "+(问题详情-答案列表)"); - startActivity(intent); - } - break; - case R.id.questionsdetail_answer: - if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) - CheckLoginUtils.checkLogin(getContext(), "问题详情-[我来回答]", () -> { - if (mQuestionsDetailEntity != null && !TextUtils.isEmpty(mQuestionsDetailEntity.getMe().getMyAnswerId())) { - Intent intent = AnswerDetailActivity.getIntent(getContext(), mQuestionsDetailEntity.getMe().getMyAnswerId(), - mEntrance, "问题详情-答案列表"); - startActivityForResult(intent, QUESTIONS_DETAIL_ANSWER_REQUEST); - } else { - startActivityForResult(AnswerEditActivity.Companion.getIntent(getContext(), mQuestionsId - , getQuestionsTitle(), mQuestionsDetailEntity.getCommunity().getName()), QUESTIONS_DETAIL_ANSWER_REQUEST); - } - }); - break; - case R.id.questionsdetail_invite: - startActivity(QuestionsInviteActivity.getIntent(getContext(), mQuestionsDetailEntity, mEntrance + "+(问题详情)")); - break; - case R.id.questionsdetail_concern: - CheckLoginUtils.checkLogin(getContext(), "问题详情-[关注问题]", () -> { - if (mQuestionsDetailEntity.getMe().isQuestionOwn()) { - startActivityForResult(QuestionEditActivity.Companion.getIntent(getContext(), mQuestionsDetailEntity), QUESTIONS_EDIT_REQUEST); - } else if (!mQuestionsDetailEntity.getMe().isQuestionFollowed()) { - ConcernUtils.INSTANCE.postConcernQuestions(getContext(), mQuestionsId - , new ConcernUtils.onConcernListener() { - @Override - public void onSuccess() { - mQuestionsDetailEntity.getMe().setQuestionFollowed(true); - mQuestionsDetailEntity.setFollowCount(mQuestionsDetailEntity.getFollowCount() + 1); - mAdapter.notifyItemChanged(0); - - GdtHelper.INSTANCE.logAction(ActionType.ADD_TO_WISHLIST, - GdtHelper.CONTENT_TYPE, "QUESTION", - GdtHelper.CONTENT_ID, mQuestionsId); - - toast("已关注 "); - } - - @Override - public void onError() { - - } - }); - } else { - cancelConcern(); - } - }); - break; - - case R.id.reuse_nodata_skip: - CheckLoginUtils.checkLogin(getContext(), "问题详情-[我来回答]", () -> { - PermissionHelper.checkReadPhoneStateAndStoragePermissionBeforeAction(requireContext(), () -> { - startActivityForResult(AnswerEditActivity.Companion.getIntent(requireContext(), mQuestionsId - , getQuestionsTitle(), mQuestionsDetailEntity.getCommunity().getName()), QUESTIONS_DETAIL_ANSWER_REQUEST); - }); - }); - break; - } - } - - - @Override - public void onMenuItemClick(MenuItem menuItem) { - if (mQuestionsDetailEntity == null) return; - switch (menuItem.getItemId()) { - case R.id.menu_more: - showMoreItemDialog(); - break; - } - } - - private void showMoreItemDialog() { - if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED) || mQuestionsDetailEntity != null) { - View view = LayoutInflater.from(getContext()).inflate(R.layout.menu_question_detail_more_item, null); - Dialog dialog = new Dialog(getActivity()); - dialog.setContentView(view); - Window window = dialog.getWindow(); - if (window != null) { - window.setGravity(Gravity.RIGHT | Gravity.TOP); - window.setBackgroundDrawable(new ColorDrawable(0)); - window.setDimAmount(0.2f); - WindowManager.LayoutParams lp = window.getAttributes(); - lp.x = DisplayUtils.dip2px(getContext(), 17); - lp.y = DisplayUtils.dip2px(getContext(), 45); // 减去卡片高度 - window.setAttributes(lp); - } - dialog.show(); - View item1 = view.findViewById(R.id.more_item1); - View item2 = view.findViewById(R.id.more_item2); - View managerItem = view.findViewById(R.id.more_manager); - managerItem.setVisibility(mQuestionsDetailEntity.getMe().isModerator() ? View.VISIBLE : View.GONE); - item1.setOnClickListener(v -> { - dialog.dismiss(); - // 跳转意见反馈 - SuggestionActivity.startSuggestionActivity(getContext(), SuggestType.normal, "report", - "问题投诉(" + mQuestionsDetailEntity.getId() + "):"); - }); - item2.setOnClickListener(v -> { - GdtHelper.INSTANCE.logAction(ActionType.SHARE, - GdtHelper.CONTENT_TYPE, "QUESTION", - GdtHelper.CONTENT_ID, mQuestionsId); - - dialog.dismiss(); - String shareIcon; - if (mQuestionsDetailEntity.getImages().size() > 0) { - shareIcon = mQuestionsDetailEntity.getImages().get(0); - } else { - shareIcon = getString(R.string.share_ghzs_logo); - } - String description = mQuestionsDetailEntity.getDescription(); - if (TextUtils.isEmpty(description)) { - description = getString(R.string.ask_share_default_summary); - } - ShareUtils.getInstance(getActivity()).showShareWindows(getActivity(), view - , getString(R.string.share_questions_url, mQuestionsDetailEntity.getId()) - , shareIcon - , getString(R.string.ask_share_questions_title, mQuestionsDetailEntity.getTitle(), mQuestionsDetailEntity.getAnswersCount()) - , description, ShareUtils.ShareType.askNormal); - }); - - managerItem.setOnClickListener(v -> { - dialog.dismiss(); - showManagerPatchDialog(); - }); - } - } - - private void showManagerPatchDialog() { - if (getContext() == null) return; - final String patchTag = "修改标签"; - final String patchQuestion = "修改问题"; - final String hideQuestion = "隐藏问题"; - final String historyVersion = "历史版本"; - final List arrReportType = new ArrayList<>(); - - Permissions permissions = mQuestionsDetailEntity.getMe().getModeratorPermissions(); - if (permissions.getUpdateQuestionTag() > Permissions.GUEST) { - arrReportType.add(patchTag); - } - if (permissions.getUpdateQuestion() > Permissions.GUEST) { - arrReportType.add(patchQuestion); - } - if (permissions.getHideQuestion() > Permissions.GUEST) { - arrReportType.add(hideQuestion); - } - if (permissions.getGetModifiedVersions() > Permissions.GUEST) { - arrReportType.add(historyVersion); - } - - int widthPixels = getResources().getDisplayMetrics().widthPixels; - final Dialog dialog = new Dialog(getContext()); - LinearLayout container = new LinearLayout(getContext()); - container.setOrientation(LinearLayout.VERTICAL); - int pad = DisplayUtils.dip2px(getContext(), 12); - container.setPadding(0, pad, 0, pad); - container.setBackgroundColor(Color.WHITE); - - for (final String s : arrReportType) { - TextView itemTv = new TextView(getContext()); - itemTv.setText(s); - itemTv.setTextSize(17); - itemTv.setTextColor(ContextCompat.getColor(getContext(), R.color.title)); - itemTv.setBackgroundResource(R.drawable.textview_white_style); - itemTv.setLayoutParams(new LinearLayout.LayoutParams((widthPixels * 9) / 10, - LinearLayout.LayoutParams.WRAP_CONTENT)); - itemTv.setPadding(DisplayUtils.dip2px(getContext(), 20), pad, 0, pad); - container.addView(itemTv); - - itemTv.setOnClickListener(v -> { - switch (s) { - case patchTag: - TagsSelectFragment tagsFragment = TagsSelectFragment.getInstance(mQuestionsDetailEntity); - BaseDialogWrapperFragment tagDialog = BaseDialogWrapperFragment.getInstance(tagsFragment, false); - tagsFragment.setPatchTagsCallBack(this); - tagDialog.show(getChildFragmentManager(), TagsSelectFragment.class.getSimpleName()); - break; - case patchQuestion: - Intent intent = QuestionEditActivity.getManagerIntent(getContext(), mQuestionsDetailEntity); - startActivityForResult(intent, QUESTIONS_EDIT_REQUEST); - break; - case hideQuestion: - DialogUtils.showAlertDialog(getContext(), "隐藏问题", - mQuestionsDetailEntity.getMe().getModeratorPermissions().getHideQuestion() == Permissions.REPORTER ? - "你的操作将提交给小编审核,确定提交吗?" - : "你的操作将立即生效,确定提交吗?(你的管理权限为:高级)", - "确定", "取消", - () -> mListViewModel.moderatorsHideQuestion(), null); - break; - case historyVersion: - startActivityForResult(HistoryActivity.getIntent(getContext(), - mQuestionsDetailEntity.getId()), QUESTIONS_MODERATOR_HISTORY_REQUEST); - break; - } - dialog.cancel(); - }); - } - - dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); - dialog.setContentView(container); - dialog.show(); - } - - public String getQuestionsTitle() { - return mAdapter.getQuestionsTitle(); - } - - public void postAnswerSuccess(String answerId) { - if (mQuestionsDetailEntity != null) { - mQuestionsDetailEntity.getMe().setMyAnswerId(answerId); - mListViewModel.load(LoadType.REFRESH); - } - } - - public void postDraftsSuccess() { - mQuestionsDetailEntity.setExistDrafts(true); - mAdapter.notifyItemChanged(0); - } - - private void getUserAnswerDrafts() { - RetrofitManager.getInstance(getContext()).getApi() - .getUserAnswerDrafts(mQuestionsId, Utils.getTime(getContext())) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Response() { - @Override - public void onResponse(AnswerDraftEntity draft) { - super.onResponse(draft); - if (draft != null) { - mQuestionsDetailEntity.setExistDrafts(true); - mAdapter.notifyItemChanged(0); - } - } - - @Override - public void onFailure(HttpException e) { - super.onFailure(e); - } - }); - } - - private void cancelConcern() { - ConcernUtils.INSTANCE.deleteConcernQuestions(getContext(), mQuestionsId - , new ConcernUtils.onConcernListener() { - @Override - public void onSuccess() { - toast("取消关注"); - if (mQuestionsDetailEntity == null) { - FragmentActivity activity = getActivity(); - if (activity != null) { - activity.setResult(Activity.RESULT_OK); - activity.finish(); - } - } else { - if (mQuestionsDetailEntity.getFollowCount() > 0) { - mQuestionsDetailEntity.setFollowCount(mQuestionsDetailEntity.getFollowCount() - 1); - } - mQuestionsDetailEntity.getMe().setQuestionFollowed(false); - mAdapter.notifyItemChanged(0); - } - } - - @Override - public void onError() { - - } - }); - } - - private void showCancelConcernDialog() { - DialogUtils.showAlertDialog(getContext() - , "取消关注问题", "问题已被删除,是否取消关注?" - , " 取消关注", "暂不 " - , () -> { - cancelConcern(); - } - , () -> { - if (getActivity() != null) getActivity().finish(); - }); - } - - // 登录事件 - @Subscribe(threadMode = ThreadMode.MAIN) - public void onEventMainThread(EBReuse reuse) { - if (reuse.getType().equals(LOGIN_TAG)) { // 登入 - onRefresh(); - } - } - - @Override - public void onPatchTagsSuccess() { - mAdapter.notifyDataSetChanged(); - } - - @Override - public void onPermissionError() { - mListViewModel.load(LoadType.REFRESH); - } -} diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailFragment.kt new file mode 100644 index 0000000000..cf54ae4ccb --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailFragment.kt @@ -0,0 +1,571 @@ +package com.gh.gamecenter.qa.questions.detail + +import android.app.Activity +import android.app.Dialog +import android.content.Intent +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.os.Bundle +import android.os.Parcelable +import android.text.TextUtils +import android.view.* +import android.widget.LinearLayout +import android.widget.TextView +import androidx.core.content.ContextCompat +import androidx.lifecycle.Lifecycle +import androidx.recyclerview.widget.DefaultItemAnimator +import androidx.recyclerview.widget.RecyclerView +import butterknife.BindView +import com.ethanhua.skeleton.Skeleton +import com.gh.base.fragment.BaseDialogWrapperFragment +import com.gh.base.fragment.BaseFragment +import com.gh.common.TimeElapsedHelper +import com.gh.common.util.* +import com.gh.common.view.VerticalItemDecoration +import com.gh.gamecenter.R +import com.gh.gamecenter.SuggestionActivity +import com.gh.gamecenter.ViewImageActivity +import com.gh.gamecenter.baselist.ListAdapter +import com.gh.gamecenter.baselist.ListFragment +import com.gh.gamecenter.baselist.LoadType +import com.gh.gamecenter.entity.Permissions +import com.gh.gamecenter.entity.SpecialColumn +import com.gh.gamecenter.eventbus.EBReuse +import com.gh.gamecenter.mvvm.Status +import com.gh.gamecenter.personal.PersonalFragment.LOGIN_TAG +import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity +import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity +import com.gh.gamecenter.qa.answer.fold.AnswerFoldActivity +import com.gh.gamecenter.qa.entity.AnswerDraftEntity +import com.gh.gamecenter.qa.entity.AnswerEntity +import com.gh.gamecenter.qa.entity.Questions +import com.gh.gamecenter.qa.entity.QuestionsDetailEntity +import com.gh.gamecenter.qa.questions.edit.QuestionEditActivity +import com.gh.gamecenter.qa.questions.edit.TagsSelectFragment +import com.gh.gamecenter.qa.questions.edit.manager.HistoryActivity +import com.gh.gamecenter.qa.questions.invite.QuestionsInviteActivity +import com.gh.gamecenter.retrofit.Response +import com.gh.gamecenter.retrofit.RetrofitManager +import com.gh.gamecenter.suggest.SuggestType +import com.lightgame.utils.Utils +import com.qq.gdt.action.ActionType +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.schedulers.Schedulers +import org.greenrobot.eventbus.Subscribe +import org.greenrobot.eventbus.ThreadMode +import java.io.IOException + +class QuestionsDetailFragment : + ListFragment(), + TagsSelectFragment.OnModeratorPatchTagsCallback { + + @BindView(R.id.reuse_tv_none_data) + lateinit var mNoDataTv: TextView + @BindView(R.id.list_skeleton) + lateinit var mSkeletonMaskView: View + + private var mAdapter: QuestionsDetailAdapter? = null + + private var mPath: String? = null + private var mQuestionsId: String? = null + private var mIsCheckConcern: Boolean = false + + private var mSpecialColumn: SpecialColumn? = null + private var mElapsedHelper: TimeElapsedHelper? = null + private var mQuestionsDetailEntity: QuestionsDetailEntity? = null + + val questionsTitle: String + get() = mAdapter?.getQuestionsTitle() ?: "" + + override fun getItemDecoration(): RecyclerView.ItemDecoration { + return VerticalItemDecoration(context, 8f, false) + } + + override fun getLayoutId(): Int { + return R.layout.fragment_list_base_skeleton_no_loading + } + + override fun provideListAdapter(): ListAdapter<*> { + return if (mAdapter != null) { + mAdapter!! + } else { + QuestionsDetailAdapter(requireContext(), this, mQuestionsDetailEntity, mListViewModel, mEntrance).apply { mAdapter = this } + } + } + + override fun provideListViewModel(): QuestionsDetailViewModel { + return viewModelProvider(QuestionsDetailViewModel.Factory(mQuestionsId!!)) + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == QUESTIONS_DETAIL_ANSWER_REQUEST) { + if (resultCode == AnswerEditActivity.SAVE_DRAFTS) { + postDraftsSuccess() + } else if (resultCode == BaseFragment.RESULT_REFRESH) { + onLoadRefresh() + } else if (resultCode == Activity.RESULT_OK) { + if (data != null) { + postAnswerSuccess(data.getStringExtra(EntranceUtils.KEY_ANSWER_ID)) + } + } + } else if (requestCode == QUESTIONS_EDIT_REQUEST && resultCode == Activity.RESULT_OK) { + if (data?.getParcelableExtra(QuestionsDetailEntity::class.java.simpleName) != null) { + mQuestionsDetailEntity = data.getParcelableExtra(QuestionsDetailEntity::class.java.simpleName) + mAdapter?.setQuestionsEntity(mQuestionsDetailEntity!!) + } + } else if (requestCode == QUESTIONS_EDIT_REQUEST && resultCode == Activity.RESULT_CANCELED) { + onPermissionError() + } else if (requestCode == QUESTIONS_MODERATOR_HISTORY_REQUEST && resultCode == Activity.RESULT_OK) { + onLoadRefresh() + } + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + initMenu(R.menu.menu_questions_detail) + } + + override fun onCreate(savedInstanceState: Bundle?) { + + arguments?.let { + mIsCheckConcern = it.getBoolean(EntranceUtils.KEY_CHECK_QUESTION_CONCERN, false) + mQuestionsId = it.getString(EntranceUtils.KEY_QUESTIONS_ID) + mPath = it.getString(EntranceUtils.KEY_PATH) + mSpecialColumn = it.getParcelable(EntranceUtils.KEY_DATA) + } + + super.onCreate(savedInstanceState) + + mNoDataTv.setText(R.string.content_delete_hint) + + mElapsedHelper = TimeElapsedHelper(this) + + mSkeletonScreen = Skeleton.bind(mSkeletonMaskView).load(R.layout.fragment_question_detail_skeleton).shimmer(false).show() + + mListViewModel.headLiveData.observeNonNull(this) { detailResource -> + if (detailResource.status == Status.SUCCESS) { + detailResource.data?.let { + if (TextUtils.isEmpty(it.me.myAnswerId)) { + getUserAnswerDrafts() + } + it.id = mQuestionsId + mQuestionsDetailEntity = it + mAdapter?.setQuestionsEntity(it) + + GdtHelper.logAction(ActionType.PAGE_VIEW, GdtHelper.CONTENT_TYPE, "QUESTION", GdtHelper.CONTENT_ID, mQuestionsId) + + setNavigationTitle(mQuestionsDetailEntity!!.community.name + " - 问题详情") + DataUtils.onMtaEvent(context, "详情页面", "问题详情", it.title) + } + } else if (detailResource.status == Status.ERROR) { + try { + val e = detailResource.exception + if (e != null && e.code() == 404 && e.response().errorBody()?.string()!!.isNotEmpty()) { + Utils.toast(context, R.string.content_delete_toast) + if (mIsCheckConcern) { + showCancelConcernDialog() + } + } + } catch (e1: IOException) { + e1.printStackTrace() + } + } + } + + mListViewModel.doRefreshList.observeNonNull(this) { + if (it) { + mAdapter?.notifyDataSetChanged() + } + } + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + (mListRv.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false + mReuseNoConn.setOnClickListener { + // 重新设置重连点击 + onRefresh() + } + + mCachedView.viewTreeObserver.addOnScrollChangedListener { + val topView = mLayoutManager.findViewByPosition(0) + if (mQuestionsDetailEntity != null) { + if (topView == null || -topView.top > 240) { + setNavigationTitle(mQuestionsDetailEntity!!.title) + } else { + setNavigationTitle(mQuestionsDetailEntity!!.community.name + " - 问题详情") + } + } + } + } + + override fun onDestroyView() { + super.onDestroyView() + mQuestionsDetailEntity?.let { + MtaHelper.onEventWithTime( + "问题阅读量_按社区", + mElapsedHelper!!.elapsedTime, + it.community.name, + StringUtils.combineTwoString(it.title, it.id)) + + MtaHelper.onEventWithTime( + "问题阅读量_按位置", + mElapsedHelper!!.elapsedTime, + mPath, + StringUtils.combineTwoString(it.title, it.id)) + + MtaHelper.onEventWithTime( + "问题阅读量_社区加位置", + mElapsedHelper!!.elapsedTime, + it.community.name, + mPath) + + val questions = Questions() + questions.id = mQuestionsId ?: "" + questions.title = it.title + LogUtils.uploadQuestionReadTime(mEntrance, + mElapsedHelper!!.elapsedTime, + questions, + it.community.id, + it.community.name, + mSpecialColumn) + } + } + + override fun onListClick(view: View?, position: Int, data: Any?) { + var imgPosition = -1 + when (view?.id) { + R.id.footerview_item -> if (mAdapter!!.isNetworkError) { + mListViewModel.load(LoadType.RETRY) + } else if (mAdapter!!.isOver()) { + if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) { + startActivity(AnswerFoldActivity.getIntent(context, mQuestionsDetailEntity!!.id, "$mEntrance+(问题详情)")) + } + } + R.id.ask_answer_item_constraintlayout, R.id.ask_answer_item_img, R.id.ask_answer_item_content, R.id.ask_answer_item_title -> { + val entity = data as AnswerEntity + startActivityForResult(AnswerDetailActivity.getIntent(context, entity.id, mEntrance, "问题详情-答案列表"), QUESTIONS_DETAIL_ANSWER_REQUEST) + } + R.id.questionsdetail_item_pic1 -> { + imgPosition = 0 + if (imgPosition == -1) imgPosition = 1 + if (imgPosition == -1) imgPosition = 2 + if (mQuestionsDetailEntity!!.images.size > imgPosition) { + val intent = ViewImageActivity.getViewImageIntent(context, ArrayList(mQuestionsDetailEntity!!.images), imgPosition, "$mEntrance+(问题详情-答案列表)") + startActivity(intent) + } + } + R.id.questionsdetail_item_pic2 -> { + if (imgPosition == -1) imgPosition = 1 + if (imgPosition == -1) imgPosition = 2 + if (mQuestionsDetailEntity!!.images.size > imgPosition) { + val intent = ViewImageActivity.getViewImageIntent(context, ArrayList(mQuestionsDetailEntity!!.images), imgPosition, "$mEntrance+(问题详情-答案列表)") + startActivity(intent) + } + } + R.id.questionsdetail_item_pic3 -> { + if (imgPosition == -1) imgPosition = 2 + if (mQuestionsDetailEntity!!.images.size > imgPosition) { + val intent = ViewImageActivity.getViewImageIntent(context, ArrayList(mQuestionsDetailEntity!!.images), imgPosition, "$mEntrance+(问题详情-答案列表)") + startActivity(intent) + } + } + R.id.questionsdetail_answer -> if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) + CheckLoginUtils.checkLogin(context, "问题详情-[我来回答]") { + if (mQuestionsDetailEntity != null && !TextUtils.isEmpty(mQuestionsDetailEntity!!.me.myAnswerId)) { + val intent = AnswerDetailActivity.getIntent(context, mQuestionsDetailEntity!!.me.myAnswerId, + mEntrance, "问题详情-答案列表") + startActivityForResult(intent, QUESTIONS_DETAIL_ANSWER_REQUEST) + } else { + startActivityForResult(AnswerEditActivity.getIntent(context!!, mQuestionsId, questionsTitle, mQuestionsDetailEntity!!.community.name), QUESTIONS_DETAIL_ANSWER_REQUEST) + } + } + R.id.questionsdetail_invite -> startActivity(QuestionsInviteActivity.getIntent(context, mQuestionsDetailEntity, "$mEntrance+(问题详情)")) + R.id.questionsdetail_concern -> CheckLoginUtils.checkLogin(context, "问题详情-[关注问题]") { + if (mQuestionsDetailEntity!!.me.isQuestionOwn) { + startActivityForResult(QuestionEditActivity.getIntent(context!!, mQuestionsDetailEntity!!), QUESTIONS_EDIT_REQUEST) + } else if (!mQuestionsDetailEntity!!.me.isQuestionFollowed) { + ConcernUtils.postConcernQuestions(context!!, mQuestionsId!!, object : ConcernUtils.onConcernListener { + override fun onSuccess() { + mQuestionsDetailEntity!!.me.isQuestionFollowed = true + mQuestionsDetailEntity!!.setFollowCount(mQuestionsDetailEntity!!.getFollowCount() + 1) + mAdapter!!.notifyItemChanged(0) + + GdtHelper.logAction(ActionType.ADD_TO_WISHLIST, + GdtHelper.CONTENT_TYPE, "QUESTION", + GdtHelper.CONTENT_ID, mQuestionsId) + + toast("已关注 ") + } + + override fun onError() { + + } + }) + } else { + cancelConcern() + } + } + + R.id.reuse_nodata_skip -> ifLogin("问题详情-[我来回答]") { + checkReadPhoneStateAndStoragePermissionBeforeAction { + startActivityForResult( + AnswerEditActivity.getIntent( + requireContext(), + mQuestionsId, + questionsTitle, + mQuestionsDetailEntity!!.community.name), + QUESTIONS_DETAIL_ANSWER_REQUEST) + } + } + } + } + + + override fun onMenuItemClick(menuItem: MenuItem) { + if (mQuestionsDetailEntity == null) return + when (menuItem.itemId) { + R.id.menu_more -> showMoreItemDialog() + } + } + + private fun showMoreItemDialog() { + if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED) || mQuestionsDetailEntity != null) { + val view = LayoutInflater.from(context).inflate(R.layout.menu_question_detail_more_item, null) + val dialog = Dialog(activity!!) + dialog.setContentView(view) + val window = dialog.window + if (window != null) { + window.setGravity(Gravity.RIGHT or Gravity.TOP) + window.setBackgroundDrawable(ColorDrawable(0)) + window.setDimAmount(0.2f) + val lp = window.attributes + lp.x = DisplayUtils.dip2px(context!!, 17f) + lp.y = DisplayUtils.dip2px(context!!, 45f) // 减去卡片高度 + window.attributes = lp + } + dialog.show() + val item1 = view.findViewById(R.id.more_item1) + val item2 = view.findViewById(R.id.more_item2) + val managerItem = view.findViewById(R.id.more_manager) + managerItem.visibility = if (mQuestionsDetailEntity!!.me.isModerator) View.VISIBLE else View.GONE + item1.setOnClickListener { + dialog.dismiss() + // 跳转意见反馈 + SuggestionActivity.startSuggestionActivity(context, SuggestType.normal, "report", + "问题投诉(" + mQuestionsDetailEntity!!.id + "):") + } + item2.setOnClickListener { + GdtHelper.logAction(ActionType.SHARE, + GdtHelper.CONTENT_TYPE, "QUESTION", + GdtHelper.CONTENT_ID, mQuestionsId) + + dialog.dismiss() + val shareIcon: String + if (mQuestionsDetailEntity!!.images.isNotEmpty()) { + shareIcon = mQuestionsDetailEntity!!.images[0] + } else { + shareIcon = getString(R.string.share_ghzs_logo) + } + var description = mQuestionsDetailEntity!!.description + if (TextUtils.isEmpty(description)) { + description = getString(R.string.ask_share_default_summary) + } + ShareUtils.getInstance(activity).showShareWindows( + activity, + view, + getString(R.string.share_questions_url, mQuestionsDetailEntity!!.id), + shareIcon, + getString(R.string.ask_share_questions_title, mQuestionsDetailEntity!!.title, mQuestionsDetailEntity!!.answersCount), + description, + ShareUtils.ShareType.askNormal) + } + + managerItem.setOnClickListener { + dialog.dismiss() + showManagerPatchDialog() + } + } + } + + private fun showManagerPatchDialog() { + if (context == null) return + val patchTag = "修改标签" + val patchQuestion = "修改问题" + val hideQuestion = "隐藏问题" + val historyVersion = "历史版本" + val arrReportType = ArrayList() + + val (_, _, _, _, _, + updateTagPermission, + updateQuestionPermission, + hideQuestionPermission, + getModifiedVersionsPermission) = mQuestionsDetailEntity?.me?.moderatorPermissions!! + if (updateTagPermission > Permissions.GUEST) { + arrReportType.add(patchTag) + } + if (updateQuestionPermission > Permissions.GUEST) { + arrReportType.add(patchQuestion) + } + if (hideQuestionPermission > Permissions.GUEST) { + arrReportType.add(hideQuestion) + } + if (getModifiedVersionsPermission > Permissions.GUEST) { + arrReportType.add(historyVersion) + } + + val widthPixels = resources.displayMetrics.widthPixels + val dialog = Dialog(requireContext()) + val container = LinearLayout(context) + container.orientation = LinearLayout.VERTICAL + val pad = DisplayUtils.dip2px(requireContext(), 12f) + container.setPadding(0, pad, 0, pad) + container.setBackgroundColor(Color.WHITE) + + for (s in arrReportType) { + val itemTv = TextView(context) + itemTv.text = s + itemTv.textSize = 17f + itemTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.title)) + itemTv.setBackgroundResource(R.drawable.textview_white_style) + itemTv.layoutParams = LinearLayout.LayoutParams(widthPixels * 9 / 10, + LinearLayout.LayoutParams.WRAP_CONTENT) + itemTv.setPadding(DisplayUtils.dip2px(context!!, 20f), pad, 0, pad) + container.addView(itemTv) + + itemTv.setOnClickListener { + when (s) { + patchTag -> { + val tagsFragment = TagsSelectFragment.getInstance(mQuestionsDetailEntity!!) + val tagDialog = BaseDialogWrapperFragment.getInstance(tagsFragment, false) + tagsFragment.setPatchTagsCallBack(this) + tagDialog.show(childFragmentManager, TagsSelectFragment::class.java.simpleName) + } + patchQuestion -> { + val intent = QuestionEditActivity.getManagerIntent(requireContext(), mQuestionsDetailEntity!!) + startActivityForResult(intent, QUESTIONS_EDIT_REQUEST) + } + hideQuestion -> DialogUtils.showAlertDialog(context, + "隐藏问题", + if (mQuestionsDetailEntity!!.me.moderatorPermissions.hideQuestion == Permissions.REPORTER) + "你的操作将提交给小编审核,确定提交吗?" + else + "你的操作将立即生效,确定提交吗?(你的管理权限为:高级)", + "确定", "取消", + { mListViewModel.moderatorsHideQuestion() }, null) + historyVersion -> { + startActivityForResult( + HistoryActivity.getIntent(requireContext(), mQuestionsDetailEntity?.id!!), + QUESTIONS_MODERATOR_HISTORY_REQUEST) + } + } + dialog.cancel() + } + } + + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE) + dialog.setContentView(container) + dialog.show() + } + + fun postAnswerSuccess(answerId: String) { + if (mQuestionsDetailEntity != null) { + mQuestionsDetailEntity?.me?.myAnswerId = answerId + mListViewModel.load(LoadType.REFRESH) + } + } + + fun postDraftsSuccess() { + mQuestionsDetailEntity?.isExistDrafts = true + mAdapter?.notifyItemChanged(0) + } + + private fun getUserAnswerDrafts() { + RetrofitManager.getInstance(context).api + .getUserAnswerDrafts(mQuestionsId, Utils.getTime(context)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : Response() { + override fun onResponse(draft: AnswerDraftEntity?) { + super.onResponse(draft) + if (draft != null) { + mQuestionsDetailEntity?.isExistDrafts = true + mAdapter!!.notifyItemChanged(0) + } + } + }) + } + + private fun cancelConcern() { + ConcernUtils.deleteConcernQuestions(requireContext(), mQuestionsId!!, object : ConcernUtils.onConcernListener { + override fun onSuccess() { + toast("取消关注") + if (mQuestionsDetailEntity == null) { + val activity = activity + if (activity != null) { + activity.setResult(Activity.RESULT_OK) + activity.finish() + } + } else { + mQuestionsDetailEntity?.let { + if (it.getFollowCount() > 0) { + it.setFollowCount(it.getFollowCount() - 1) + } + it.me.isQuestionFollowed = false + } + mAdapter?.notifyItemChanged(0) + } + } + + override fun onError() { + + } + }) + } + + private fun showCancelConcernDialog() { + DialogUtils.showAlertDialog( + context, + "取消关注问题", + "问题已被删除,是否取消关注?", + " 取消关注", + "暂不 ", + { cancelConcern() }, + { + if (activity != null && activity?.isFinishing == false) { + activity?.finish() + } + }) + } + + // 登录事件 + @Subscribe(threadMode = ThreadMode.MAIN) + fun onEventMainThread(reuse: EBReuse) { + if (reuse.type == LOGIN_TAG) { // 登入 + onRefresh() + } + } + + override fun onPatchTagsSuccess() { + mAdapter?.notifyDataSetChanged() + } + + override fun onPermissionError() { + mListViewModel.load(LoadType.REFRESH) + } + + companion object { + const val QUESTIONS_DETAIL_ANSWER_REQUEST = 110 + const val QUESTIONS_EDIT_REQUEST = 111 + const val QUESTIONS_MODERATOR_HISTORY_REQUEST = 112 + + fun getInstance(questionsId: String): QuestionsDetailFragment { + val fragment = QuestionsDetailFragment() + val args = Bundle() + args.putString(EntranceUtils.KEY_QUESTIONS_ID, questionsId) + fragment.arguments = args + return fragment + } + } +} diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailViewModel.kt index eb0e3e2cd3..167de3434d 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailViewModel.kt @@ -1,30 +1,41 @@ package com.gh.gamecenter.qa.questions.detail +import android.annotation.SuppressLint import android.app.Application +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import com.gh.common.util.ErrorHelper import com.gh.common.util.UrlFilterUtils import com.gh.gamecenter.R import com.gh.gamecenter.baselist.ListHeadViewModel import com.gh.gamecenter.baselist.LoadStatus import com.gh.gamecenter.baselist.LoadType +import com.gh.gamecenter.entity.MeEntity import com.gh.gamecenter.entity.Permissions import com.gh.gamecenter.manager.UserManager +import com.gh.gamecenter.mvvm.Resource import com.gh.gamecenter.qa.entity.AnswerEntity import com.gh.gamecenter.qa.entity.QuestionsDetailEntity +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.Observable import io.reactivex.android.schedulers.AndroidSchedulers 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 QuestionsDetailViewModel(application: Application, val questionId: String) - : ListHeadViewModel(application) { + : ListHeadViewModel(application) { + val doRefreshList = MutableLiveData() override fun provideHeadDataObservable(): Observable { return mApi.getQuestionsById(questionId) @@ -35,7 +46,108 @@ class QuestionsDetailViewModel(application: Application, val questionId: String) } override fun mergeResultLiveData() { - mResultLiveData.addSource(mListLiveData) { mResultLiveData.postValue(it) } + mResultLiveData.addSource(mListLiveData) { + val itemDataList = arrayListOf() + for (answer in it) { + itemDataList.add(QuestionDetailItemData(answer = answer)) + } + // 当回答列表为空时尝试请求 + if (itemDataList.size == 0) { + loadRecommendedUsersAndSimilarAnswers() + } else { + mResultLiveData.postValue(itemDataList) + } + } + } + + @SuppressLint("CheckResult") + fun loadRecommendedUsersAndSimilarAnswers() { + val itemDataList = arrayListOf() + mApi.getQuestionInvitations(questionId) + .subscribeOn(Schedulers.io()) + .flatMap { response -> + mHeadLiveData.value?.data?.let { question -> + itemDataList.add(QuestionDetailItemData(recommendedUserToInvite = response)) + } + return@flatMap mApi.getSimilarAnswers(questionId) + } + .subscribe(object : BiResponse>() { + override fun onSuccess(data: List) { + if (data.isNotEmpty()) { + itemDataList.add(QuestionDetailItemData(showSimilarAnswerHint = true)) + for (answer in data) { + itemDataList.add(QuestionDetailItemData(similarAnswer = answer)) + } + } + + mResultLiveData.postValue(itemDataList) + } + + override fun onFailure(exception: Exception) { + // 请求失败时回落到原始的没有加载推荐的我来回答界面 + mResultLiveData.postValue(arrayListOf()) + } + }) + } + + @SuppressLint("CheckResult") + fun doSmartInvitation() { + mApi.postSmartInvitations(questionId) + .subscribeOn(Schedulers.io()) + .subscribe(object : BiResponse() { + override fun onSuccess(data: ResponseBody) { + mHeadLiveData.value?.data?.let { question -> + question.me.isSmartInvited = true + mHeadLiveData.postValue(Resource.success(question)) + } + doRefreshList.postValue(true) + } + }) + } + + fun invite(userId: String) { + val jsonObject = JSONObject() + try { + jsonObject.put("user_id", userId) + } catch (e: JSONException) { + e.printStackTrace() + } + + val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString()) + RetrofitManager.getInstance(getApplication()).api + .postInvite(body, questionId) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : Response() { + override fun onResponse(response: ResponseBody?) { + Utils.toast(getApplication(), "邀请成功") + mResultLiveData.value?.let { + for (item in it) { + item.recommendedUserToInvite?.let { userList -> + for (user in userList) { + if (userId == user.id) { + if (user.me == null) { + user.me = MeEntity() + } + user.me?.isUserInvite = true + } + } + } + } + mResultLiveData.postValue(it) + } + doRefreshList.postValue(true) + } + + override fun onFailure(e: HttpException?) { + try { + val string = e?.response()?.errorBody()?.string() + ErrorHelper.handleError(getApplication(), string, false) + } catch (e1: Exception) { + e1.printStackTrace() + } + } + }) } fun moderatorsHideQuestion() { 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 2bb6165ef0..b514fe7aea 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 @@ -1,9 +1,9 @@ package com.gh.gamecenter.qa.questions.invite import android.content.Context -import androidx.recyclerview.widget.RecyclerView import android.view.View import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView import com.gh.base.OnListClickListener import com.gh.common.constant.ItemViewType import com.gh.gamecenter.PersonalHomeActivity @@ -15,9 +15,9 @@ import com.gh.gamecenter.entity.MeEntity import com.gh.gamecenter.qa.entity.InviteEntity import java.util.* -class QuestionsInviteAdapter(context: Context, - private val mListClickListener: OnListClickListener, - private val mEntrance: String) : ListAdapter(context) { +open class QuestionsInviteAdapter(context: Context, + private val mListClickListener: OnListClickListener, + private val mEntrance: String) : ListAdapter(context) { override fun setListData(listData: List?) { if (listData != null && listData.isNotEmpty()) { 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 07e6e4e615..d31c0f3a69 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 @@ -40,6 +40,7 @@ import com.gh.gamecenter.entity.SubjectSettingEntity; import com.gh.gamecenter.entity.TagEntity; import com.gh.gamecenter.entity.TimeEntity; import com.gh.gamecenter.entity.ToolBoxEntity; +import com.gh.gamecenter.entity.UserEntity; import com.gh.gamecenter.entity.UserInfoEntity; import com.gh.gamecenter.entity.VersionVoteEntity; import com.gh.gamecenter.entity.VideoDraftEntity; @@ -1927,6 +1928,24 @@ public interface ApiService { @POST("videos") Observable postVideo(@Body RequestBody body); + /** + * 获取相应问题的邀请列表 + */ + @GET("questions/{question_id}/invitations") + Single> getQuestionInvitations(@Path("question_id") String questionId); + + /** + * 对相应问题进行只能邀请 + */ + @POST("questions/{question_id}:smart_invite") + Single postSmartInvitations(@Path("question_id") String questionId); + + /** + * 获取对应问题的相似回答 + */ + @GET("questions/{question_id}/similar_answers") + Single> getSimilarAnswers(@Path("question_id") String questionId); + /** * 提交视频草稿 */ diff --git a/app/src/main/res/drawable/button_question_detail_invite.xml b/app/src/main/res/drawable/button_question_detail_invite.xml new file mode 100644 index 0000000000..91eef82241 --- /dev/null +++ b/app/src/main/res/drawable/button_question_detail_invite.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_question_detail_recommended_user.xml b/app/src/main/res/layout/item_question_detail_recommended_user.xml new file mode 100644 index 0000000000..e9587b9a9d --- /dev/null +++ b/app/src/main/res/layout/item_question_detail_recommended_user.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_question_detail_similar_answer_hint.xml b/app/src/main/res/layout/item_question_detail_similar_answer_hint.xml new file mode 100644 index 0000000000..2cb5219631 --- /dev/null +++ b/app/src/main/res/layout/item_question_detail_similar_answer_hint.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file