Files
assistant-android/app/src/main/java/com/gh/gamecenter/message/MessageDetailFragment.java
2025-01-14 15:58:40 +08:00

522 lines
23 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.gh.gamecenter.message;
import static com.gh.gamecenter.common.constant.Constants.LOGIN_TAG;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.gh.common.constant.Config;
import com.gh.common.util.CheckLoginUtils;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.ErrorHelper;
import com.gh.common.util.PostCommentUtils;
import com.gh.gamecenter.MessageDetailActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.adapter.MessageDetailAdapter;
import com.gh.gamecenter.adapter.OnCommentCallBackListener;
import com.gh.gamecenter.common.base.fragment.ToolbarFragment;
import com.gh.gamecenter.common.constant.EntranceConsts;
import com.gh.gamecenter.common.eventbus.EBReuse;
import com.gh.gamecenter.common.retrofit.OkHttpCache;
import com.gh.gamecenter.common.retrofit.Response;
import com.gh.gamecenter.common.utils.TextHelper;
import com.gh.gamecenter.common.utils.TimestampUtils;
import com.gh.gamecenter.core.utils.DisplayUtils;
import com.gh.gamecenter.core.utils.GsonUtils;
import com.gh.gamecenter.core.utils.KeyboardHeightObserver;
import com.gh.gamecenter.core.utils.KeyboardHeightProvider;
import com.gh.gamecenter.core.utils.UrlFilterUtils;
import com.gh.gamecenter.databinding.FragmentMessageDetailBinding;
import com.gh.gamecenter.feature.entity.CommentEntity;
import com.gh.gamecenter.feature.entity.ConcernEntity;
import com.gh.gamecenter.feature.eventbus.EBAddComment;
import com.gh.gamecenter.feature.eventbus.EBDeleteComment;
import com.gh.gamecenter.login.entity.UserInfoEntity;
import com.gh.gamecenter.login.user.UserManager;
import com.gh.gamecenter.manager.CommentManager;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.gh.gamecenter.retrofit.service.ApiService;
import com.halo.assistant.HaloApp;
import com.lightgame.listeners.OnBackPressedListener;
import com.lightgame.utils.Util_System_Keyboard;
import com.lightgame.utils.Utils;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import retrofit2.HttpException;
/**
* Created by CsHeng on 18/12/2017.
* 消息详情界面--评论详情--对话详情
*/
public class MessageDetailFragment extends ToolbarFragment implements OnCommentCallBackListener, OnBackPressedListener, KeyboardHeightObserver {
public static final int REQUEST_UPDATE_COMMENT = 9; // 刷新文章web页面评论数
private FragmentMessageDetailBinding mBinding;
private LinearLayoutManager mLayoutManager;
private MessageDetailAdapter adapter;
private Dialog mSendingDialog;
private ConcernEntity mConcernEntity;
private CommentEntity mCommentEntity; // 回复评论的实体 用完马上清空
private UserInfoEntity mUserInfo;
private String newsId;
private int commentNum = -1; //区分来源 -1资讯关注列表 !=-1 :新闻详情
private KeyboardHeightProvider mKeyboardHeightProvider = null;
private int mOffset = 0;
private TextWatcher watcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.toString().trim().length() > 0) {
mBinding.pieceCommentTypingContainer.answerCommentSendBtn.setEnabled(true);
} else {
mBinding.pieceCommentTypingContainer.answerCommentSendBtn.setEnabled(false);
}
}
@Override
public void afterTextChanged(Editable s) {
}
};
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(CommentEntity.TAG, adapter.getConcernEntity());
}
@Override
protected int getLayoutId() {
return 0;
}
@Override
protected View getInflatedLayout() {
mBinding = FragmentMessageDetailBinding.inflate(getLayoutInflater());
return mBinding.getRoot();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
// mConcernEntity = args.getParcelable(ConcernEntity.TAG);
mConcernEntity = (ConcernEntity) HaloApp.get(ConcernEntity.TAG, true);
mCommentEntity = args.getParcelable(CommentEntity.TAG);
newsId = args.getString(EntranceConsts.KEY_NEWS_ID);
commentNum = args.getInt("commentNum", -1);
//复用问题 mConcernEntity对应的文章有可能和跳转之前的文章不一致
if (mConcernEntity != null && newsId != null && !newsId.equals(mConcernEntity.getId())) {
mConcernEntity = null;
}
setNavigationTitle(getString(R.string.title_message_detail));
adapter = new MessageDetailAdapter(getActivity(), this, mBinding.messageDetailRv, mConcernEntity, mEntrance);
mLayoutManager = new LinearLayoutManager(getContext());
mBinding.messageDetailRv.setLayoutManager(mLayoutManager);
mBinding.messageDetailRv.setAdapter(adapter);
mBinding.pieceCommentTypingContainer.answerCommentEt.addTextChangedListener(watcher);
mBinding.pieceCommentTypingContainer.answerCommentEt.setFilters(new InputFilter[]{TextHelper.getFilter(140, "评论不能多于140字")});
mBinding.pieceCommentTypingContainer.answerCommentSendBtn.setEnabled(false);
mKeyboardHeightProvider = new KeyboardHeightProvider(requireActivity());
mBinding.messageDetailRv.post(mKeyboardHeightProvider::start);
mBinding.pieceCommentTypingContainer.answerCommentEt.setOnFocusChangeListener((v, hasFocus) -> {
if (hasFocus) {
mBinding.pieceCommentTypingContainer.answerCommentEt.setHintTextColor(ContextCompat.getColor(getContext(), com.gh.gamecenter.common.R.color.hint));
} else {
mBinding.pieceCommentTypingContainer.answerCommentEt.setHintTextColor(ContextCompat.getColor(getContext(), com.gh.gamecenter.common.R.color.text_theme));
}
});
mBinding.messageDetailRv.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE
&& !adapter.isOver() && !adapter.isLoading() && mConcernEntity != null
&& mLayoutManager.findLastVisibleItemPosition() == adapter.getItemCount() - 1) {
int offset = adapter.getItemCount() - adapter.getHotCommentListSize() - 3;
if (offset >= 10) { // 防止自动上滑时触发
adapter.addNormalComment();
}
}
}
});
mUserInfo = UserManager.getInstance().getUserInfoEntity();
if (newsId != null && mConcernEntity == null) {
getConcernDigest();
}
if (args.getBoolean("openSoftInput", false)) {//新闻详情的发表评论
setSoftInput(true);
}
mBinding.reuseNoConnection.getRoot().setOnClickListener(v -> {
if (newsId != null && mConcernEntity == null) {
showNoConnection(false);
}
});
mBinding.pieceCommentTypingContainer.answerCommentSendBtn.setOnClickListener(this);
mBinding.shadowView.setOnClickListener(this);
}
private void getConcernDigest() {
ApiService apiService = RetrofitManager.getInstance().getApi();
Observable.zip(
apiService.getNewsRichDigest(newsId),
apiService.getArticlesVisits(UrlFilterUtils.getFilterQuery("article_ids", newsId)),
apiService.getNewsCommentnum(newsId, Utils.getTime(getContext())),
(concernEntity, viewsEntities, commentNumEntities) -> {
if (commentNumEntities.size() > 0) {
if (!TextUtils.isEmpty(concernEntity.getId())) {
concernEntity.setCommentnum(commentNumEntities.get(0).getNum());
}
}
if (viewsEntities.size() > 0) {
concernEntity.setViews(viewsEntities.get(0).getViews());
}
return concernEntity;
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<ConcernEntity>() {
@Override
public void onResponse(ConcernEntity response) {
mConcernEntity = response;
commentNum = mConcernEntity.getCommentnum();
adapter.addConcernEntity(mConcernEntity);
adapter.addHotComment();
if (commentNum == 0) {
setSoftInput(true);
}
}
@Override
public void onFailure(HttpException e) {
showNoConnection(true);
}
});
}
//软键盘控制
private void setSoftInput(boolean isShow) {
if (isShow) {
String entrance = "资讯文章详情-评论详情-回复";
if (mCommentEntity == null) {
entrance = "资讯文章详情-评论详情-评论数";
}
CheckLoginUtils.checkLogin(getContext(), entrance, () -> {
Util_System_Keyboard.showSoftKeyboard(getContext(), mBinding.pieceCommentTypingContainer.answerCommentEt);
mBinding.pieceCommentTypingContainer.answerCommentEt.setFocusable(true);
mBinding.pieceCommentTypingContainer.answerCommentEt.setFocusableInTouchMode(true);
mBinding.pieceCommentTypingContainer.answerCommentEt.requestFocus();
if (mCommentEntity != null && mCommentEntity.getUser() != null) {
mBinding.pieceCommentTypingContainer.answerCommentEt.setHint(getString(R.string.comment_repty_hint, mCommentEntity.getUser().getName()));
} else {
mBinding.pieceCommentTypingContainer.answerCommentEt.setHint(getString(R.string.message_detail_comment_hint));
}
});
} else {
Util_System_Keyboard.hideSoftKeyboard(getActivity());
if (mCommentEntity != null) {
mCommentEntity = null; // 清空当前评论实体
mBinding.pieceCommentTypingContainer.answerCommentEt.setHint(getString(R.string.message_detail_comment_hint));
mBinding.pieceCommentTypingContainer.answerCommentEt.setText("");
}
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onDeleteComment(EBDeleteComment event) {
adapter.notifyCommentRemoved(event.commentEntity);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onAddComment(EBAddComment event) {
commentNum = -1;
getConcernDigest();
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.answer_comment_send_btn:
final String content = mBinding.pieceCommentTypingContainer.answerCommentEt.getText().toString();
if (content.length() == 0) {
Utils.toast(getContext(), "评论内容不能为空!");
return;
}
CheckLoginUtils.checkLogin(requireContext(), "资讯文章详情-评论详情-写评论", () -> {
mSendingDialog = DialogUtils.showWaitDialog(getActivity(), getString(R.string.post_dialog_hint));
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("content", content);
} catch (JSONException e) {
e.printStackTrace();
}
if (newsId == null && mConcernEntity == null || newsId == null && mConcernEntity.getId() == null) {
Utils.toast(getContext(), "评论异常 id null");
mSendingDialog.cancel();
return;
} else if (newsId == null) {
newsId = mConcernEntity.getId();
}
PostCommentUtils.addCommentData(getContext(), newsId, jsonObject, mCommentEntity, new PostCommentUtils.PostCommentListener() {
@Override
public void postSuccess(JSONObject response) {
mSendingDialog.dismiss();
toast("发表成功");
mBinding.pieceCommentTypingContainer.answerCommentEt.setText("");
try {
JSONObject cacheObject = new JSONObject();
JSONObject cacheUser = new JSONObject();
JSONObject userData = new JSONObject();
JSONObject badgeData = new JSONObject();
cacheUser.put("_id", mUserInfo.getUserId());
cacheUser.put("icon", mUserInfo.getIcon());
cacheUser.put("name", mUserInfo.getName());
if (mUserInfo.getBadge() != null) {
badgeData.put("name", mUserInfo.getBadge().getName());
badgeData.put("icon", mUserInfo.getBadge().getIcon());
cacheUser.put("badge", badgeData);
}
userData.put("is_comment_own", true);
cacheObject.put("_id", response.getString("_id"));
cacheObject.put("content", content);
cacheObject.put("time", System.currentTimeMillis() / 1000);
cacheObject.put("vote", 0);
cacheObject.put("user", cacheUser);
cacheObject.put("me", userData);
if (mCommentEntity != null) {
JSONObject cacheParent = new JSONObject();
cacheParent.put("user", new JSONObject(GsonUtils.toJson(mCommentEntity.getUser())));
cacheParent.put("comment", mCommentEntity.getContent());
cacheObject.put("parent", cacheParent);
}
adapter.addNormalComment(true);
modifyNewsCommentOkhttpCache(adapter.findTheLastPriorComment(), cacheObject, newsId);
} catch (JSONException e) {
e.printStackTrace();
}
if (mConcernEntity != null) {
// 完成评论操作,添加评论数
adapter.addCommentCount();
//修改评论缓存
CommentManager.updateOkhttpCacheForId(getContext(), newsId);
CommentManager.updateOkhttpCache(getContext(), newsId);
// 发送评论更新通知
EventBus.getDefault().post(new EBAddComment());
adapter.notifyItemInserted(adapter.getHotCommentListSize() + 2);
adapter.notifyItemChanged(adapter.getItemCount() - 1); //刷新脚布局高度
} else {
showNoConnection(false);
}
setSoftInput(false);
}
@Override
public void postFailed(Throwable e) {
mSendingDialog.dismiss();
String errorString = null;
if (e instanceof HttpException) {
try {
errorString = ((HttpException) e).response().errorBody().string();
} catch (Exception e1) {
e1.printStackTrace();
}
}
ErrorHelper.handleError(requireContext(), errorString, false, "文章及帖子的评论和回复", "社区实名", "", "内容实名", null, mBinding.pieceCommentTypingContainer.answerCommentSendBtn::performClick);
}
});
});
break;
case R.id.shadowView:
Util_System_Keyboard.hideSoftKeyboard(getActivity());
break;
}
}
private void modifyNewsCommentOkhttpCache(int offset, JSONObject commentData, String id) {
String key = TimestampUtils.addTimestamp(Config.API_HOST + "article/" + id + "/comment?limit=10&offset=" + offset);
byte[] data = OkHttpCache.getCache(getContext(), key);
if (data != null) {
try {
JSONArray jsonArray = new JSONArray(new String(data));
JSONArray newComment = new JSONArray();
newComment.put(commentData);
for (int i = 0, size = jsonArray.length() > 9 ? 9 : jsonArray.length(); i < size; i++) {
newComment.put(jsonArray.get(i));
}
OkHttpCache.updateCache(getContext(), key, newComment.toString().getBytes());
if (jsonArray.length() == 10) {
modifyNewsCommentOkhttpCache(offset + 10, jsonArray.getJSONObject(9), id);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
private void showNoConnection(boolean isShow) {
if (isShow) {
mBinding.reuseNoConnection.getRoot().setVisibility(View.VISIBLE);
mBinding.messageDetailRv.setVisibility(View.GONE);
} else {
mBinding.reuseNoConnection.getRoot().setVisibility(View.GONE);
mBinding.messageDetailRv.setVisibility(View.VISIBLE);
if (newsId != null) {
getConcernDigest();
}
}
}
// 登录事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(EBReuse reuse) {
if (reuse.getType().equals(LOGIN_TAG)) { // 登入
mUserInfo = UserManager.getInstance().getUserInfoEntity();
}
}
@Override
public void onCommentCallback(CommentEntity entity) {
mCommentEntity = entity;
setSoftInput(true);
}
@Override
public void onResume() {
super.onResume();
mKeyboardHeightProvider.setKeyboardHeightObserver(this);
}
@Override
public void onPause() {
super.onPause();
mKeyboardHeightProvider.setKeyboardHeightObserver(null);
}
@Override
public void onDestroy() {
super.onDestroy();
mKeyboardHeightProvider.close();
}
@Override
public void onKeyboardHeightChanged(int height, int orientation) {
popInputLayout(height > 0, height);
}
private void popInputLayout(boolean isPopup, int height) {
if (requireActivity() instanceof MessageDetailActivity) {
View shadowView = ((MessageDetailActivity) requireActivity()).getShadowView();
shadowView.setVisibility(isPopup ? View.VISIBLE : View.GONE);
shadowView.setOnClickListener(v -> Util_System_Keyboard.hideSoftKeyboard(getActivity()));
}
mBinding.pieceCommentTypingContainer.commentLine.setVisibility(isPopup ? View.GONE : View.VISIBLE);
mBinding.shadowView.setVisibility(isPopup ? View.VISIBLE : View.GONE);
mBinding.pieceCommentTypingContainer.answerContent.setOrientation(isPopup ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL);
if (isPopup) {
mBinding.pieceCommentTypingContainer.answerContent.setBackground(ContextCompat.getDrawable(requireContext(), R.drawable.bg_shape_white_radius_10_top_only));
} else {
mBinding.pieceCommentTypingContainer.answerContent.setBackgroundColor(ContextCompat.getColor(requireContext(), com.gh.gamecenter.common.R.color.ui_surface));
mOffset = Math.abs(height);
}
mBinding.pieceCommentTypingContainer.placeholderView.setVisibility(isPopup ? View.VISIBLE : View.GONE);
LinearLayout.LayoutParams mScrollViewParams = (LinearLayout.LayoutParams) mBinding.pieceCommentTypingContainer.scrollView.getLayoutParams();
mScrollViewParams.width = isPopup ? LinearLayout.LayoutParams.MATCH_PARENT : 0;
mScrollViewParams.height = isPopup ? DisplayUtils.dip2px(76f) : DisplayUtils.dip2px(28f);
mScrollViewParams.topMargin = isPopup ? DisplayUtils.dip2px(8f) : 0;
mBinding.pieceCommentTypingContainer.scrollView.setLayoutParams(mScrollViewParams);
RelativeLayout.LayoutParams mLayoutParams = (RelativeLayout.LayoutParams) mBinding.pieceCommentTypingContainer.answerCommentContentContainer.getLayoutParams();
mLayoutParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
mLayoutParams.bottomMargin = isPopup ? height + mOffset : 0;
mBinding.pieceCommentTypingContainer.answerCommentContentContainer.setLayoutParams(mLayoutParams);
}
@Override
public boolean onHandleBackPressed() {
if (commentNum != -1 && adapter.getConcernEntity() != null
&& commentNum != adapter.getConcernEntity().getCommentnum()) {
Intent intent = new Intent();
intent.putExtra("commentNum", adapter.getConcernEntity().getCommentnum());
if (getActivity() != null) {
getActivity().setResult(Activity.RESULT_OK, intent);
getActivity().finish();
}
return true;
}
return false;
}
@Override
protected void onDarkModeChanged() {
super.onDarkModeChanged();
if (adapter != null) {
adapter.notifyItemRangeChanged(0, adapter.getItemCount());
}
}
}