From cb3884ea2e6da6aa802516315804cddb47bb1806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=8E=89=E4=B9=85?= <1484288157@qq.com> Date: Tue, 12 Jan 2021 10:02:30 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E3=80=90=E5=85=89=E7=8E=AF=E5=8A=A9?= =?UTF-8?q?=E6=89=8BV=5F4.7.0=E3=80=91=E8=AE=BA=E5=9D=9B=E4=BA=A4=E4=BA=92?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20https://git.ghzs.com/pm/halo-app-issues/-/?= =?UTF-8?q?issues/1135?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/gh/common/util/CommentUtils.java | 29 +- .../java/com/gh/common/util/ShareUtils.java | 6 +- .../adapter/viewholder/CommentViewHolder.java | 4 +- .../gh/gamecenter/entity/MenuItemEntity.kt | 3 +- .../gamecenter/forum/select/ForumAdapter.kt | 14 +- .../forum/select/ForumSelectFragment.kt | 14 +- .../forum/select/ForumSelectViewModel.kt | 15 +- .../gamedetail/dialog/GameDetailMoreDialog.kt | 2 +- .../BaseAnswerOrArticleItemViewHolder.kt | 2 +- .../qa/answer/detail/AnswerDetailFragment.kt | 264 ++++++++--------- .../detail/ArticleDetailContentViewHolder.kt | 130 +------- .../article/detail/ArticleDetailFragment.kt | 122 +++++--- .../detail/BaseArticleDetailCommentAdapter.kt | 5 +- .../BaseArticleDetailCommentFragment.kt | 16 +- .../BaseArticleDetailCommentViewModel.kt | 16 +- .../comment/ArticleDetailCommentAdapter.kt | 4 +- .../comment/ArticleDetailCommentFragment.kt | 63 +--- .../comment/ArticleDetailCommentViewModel.kt | 4 +- .../qa/article/edit/ArticleEditActivity.kt | 35 +-- .../qa/article/edit/ArticleEditViewModel.kt | 14 +- .../gamecenter/qa/comment/CommentActivity.kt | 33 ++- .../qa/comment/NewCommentAdapter.kt | 67 ++--- .../qa/dialog/ChooseForumDialogFragment.kt | 74 +++++ .../qa/dialog/MoreFunctionPanelDialog.kt | 193 ++++++++++++ .../gh/gamecenter/qa/editor/AnswerFragment.kt | 24 ++ .../gamecenter/qa/editor/AnswerViewModel.kt | 31 +- .../gamecenter/qa/editor/ArticleFragment.kt | 25 +- .../gamecenter/qa/editor/ArticleViewModel.kt | 17 +- .../qa/editor/InsertAnswerWrapperActivity.kt | 28 +- .../qa/editor/InsertArticleWrapperActivity.kt | 29 +- .../qa/questions/detail/AnswerViewHolder.java | 6 +- .../detail/QuestionsDetailFragment.kt | 120 +++----- .../qa/questions/edit/QuestionEditActivity.kt | 34 +-- .../questions/edit/QuestionEditViewModel.kt | 11 +- .../ic_article_detail_star_bottom_bar.png | Bin 0 -> 2712 bytes .../ic_article_detail_stared_bottom_bar.png | Bin 0 -> 1931 bytes .../drawable-xxhdpi/ic_choose_forum_close.png | Bin 0 -> 1831 bytes .../icon_more_panel_close_comment_enable.png | Bin 0 -> 4207 bytes ...icon_more_panel_close_comment_unenable.png | Bin 0 -> 3997 bytes .../icon_more_panel_delete.png | Bin 0 -> 3509 bytes .../drawable-xxhdpi/icon_more_panel_edit.png | Bin 0 -> 3547 bytes .../icon_more_panel_essence.png | Bin 0 -> 3722 bytes .../icon_more_panel_essence_unenable.png | Bin 0 -> 3580 bytes .../drawable-xxhdpi/icon_more_panel_fold.png | Bin 0 -> 3934 bytes .../main/res/drawable/divider_item_line.xml | 18 ++ .../activity_tablayout_no_title_viewpager.xml | 47 +++ app/src/main/res/layout/ask_answer_item.xml | 95 +++--- .../collection_comunity_article_item.xml | 120 +++----- app/src/main/res/layout/comment_item.xml | 2 +- .../main/res/layout/dialog_choose_forum.xml | 50 ++++ .../res/layout/dialog_game_detail_more.xml | 61 ++-- .../res/layout/fragment_answer_detail.xml | 5 +- .../fragment_article_detail_comment.xml | 176 +++++------ app/src/main/res/layout/fragment_comment.xml | 14 +- .../layout/item_article_detail_comment.xml | 15 +- .../layout/item_article_detail_content.xml | 123 +------- app/src/main/res/layout/new_comment_item.xml | 280 ++++++++++++++++++ .../layout/piece_article_input_container.xml | 48 ++- .../layout/piece_comment_typing_container.xml | 2 +- .../piece_comment_typing_container_dark.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- 61 files changed, 1492 insertions(+), 1022 deletions(-) create mode 100644 app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumDialogFragment.kt create mode 100644 app/src/main/java/com/gh/gamecenter/qa/dialog/MoreFunctionPanelDialog.kt create mode 100644 app/src/main/res/drawable-xxhdpi/ic_article_detail_star_bottom_bar.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_article_detail_stared_bottom_bar.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_choose_forum_close.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_more_panel_close_comment_enable.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_more_panel_close_comment_unenable.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_more_panel_delete.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_more_panel_edit.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_more_panel_essence.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_more_panel_essence_unenable.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_more_panel_fold.png create mode 100644 app/src/main/res/drawable/divider_item_line.xml create mode 100644 app/src/main/res/layout/activity_tablayout_no_title_viewpager.xml create mode 100644 app/src/main/res/layout/dialog_choose_forum.xml create mode 100644 app/src/main/res/layout/new_comment_item.xml diff --git a/app/src/main/java/com/gh/common/util/CommentUtils.java b/app/src/main/java/com/gh/common/util/CommentUtils.java index 7e17331a91..5471cfe04b 100644 --- a/app/src/main/java/com/gh/common/util/CommentUtils.java +++ b/app/src/main/java/com/gh/common/util/CommentUtils.java @@ -334,15 +334,16 @@ public class CommentUtils { }); }); } + public static void voteVideoComment(final Context context, - String answerId, - String articleId, - String articleCommunityId, - String videoId, - final CommentEntity commentEntity, - final TextView commentLikeCountTv, - final ImageView commentLikeIv, - final OnVoteListener listener) { + String answerId, + String articleId, + String articleCommunityId, + String videoId, + final CommentEntity commentEntity, + final TextView commentLikeCountTv, + final ImageView commentLikeIv, + final OnVoteListener listener) { String entrance = "视频流-评论-点赞"; CheckLoginUtils.checkLogin(context, entrance, () -> { @@ -389,10 +390,10 @@ public class CommentUtils { } public static void unVoteVideoComment(final Context context, - String videoId, - final CommentEntity commentEntity, - final TextView commentLikeCountTv, - final ImageView commentLikeIv) { + String videoId, + final CommentEntity commentEntity, + final TextView commentLikeCountTv, + final ImageView commentLikeIv) { String entrance = "视频流-评论-取消点赞"; CheckLoginUtils.checkLogin(context, entrance, () -> { RetrofitManager.getInstance(context).getApi() @@ -434,10 +435,10 @@ public class CommentUtils { holder.commentLikeIv.setImageResource(R.drawable.comment_vote_unselect); if (userDataEntity == null || !userDataEntity.isCommentOwner()) { - holder.replyLine.setVisibility(View.VISIBLE); + if (holder.replyLine != null) holder.replyLine.setVisibility(View.VISIBLE); holder.commentReply.setVisibility(View.VISIBLE); } else { - holder.replyLine.setVisibility(View.GONE); + if (holder.replyLine != null) holder.replyLine.setVisibility(View.GONE); holder.commentReply.setVisibility(View.GONE); } diff --git a/app/src/main/java/com/gh/common/util/ShareUtils.java b/app/src/main/java/com/gh/common/util/ShareUtils.java index 98de9e0aad..6d32b49d53 100644 --- a/app/src/main/java/com/gh/common/util/ShareUtils.java +++ b/app/src/main/java/com/gh/common/util/ShareUtils.java @@ -319,7 +319,7 @@ public class ShareUtils { }); } - public void shareGameDetail(Activity activity, String url, String icon, String shareTitle, String shareSummary, ShareEntrance shareEntrance, String id, ShareCallBack callBack) { + public void shareParamsDetail(Activity activity, String url, String icon, String shareTitle, String shareSummary, ShareEntrance shareEntrance, String id, ShareCallBack callBack) { if (activity.isFinishing()) return; this.mActivity = new WeakReference<>(activity); this.shareIcon = icon; @@ -654,6 +654,10 @@ public class ShareUtils { } } + public String getTitle() { + return mTitle; + } + private class ShareRecyclerViewAdapter extends RecyclerView.Adapter { private OnItemClickListener listener; diff --git a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/CommentViewHolder.java b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/CommentViewHolder.java index 68cae4c6e0..6cc6cf9faa 100644 --- a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/CommentViewHolder.java +++ b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/CommentViewHolder.java @@ -9,6 +9,7 @@ import com.facebook.drawee.view.SimpleDraweeView; import com.gh.base.BaseRecyclerViewHolder; import com.gh.gamecenter.R; +import androidx.annotation.Nullable; import butterknife.BindView; /** @@ -33,7 +34,7 @@ public class CommentViewHolder extends BaseRecyclerViewHolder { @BindView(R.id.comment_user_name) public TextView commentUserNameTv; @BindView(R.id.comment_author) - public TextView commentAuthorTv; + public View commentAuthorTv; @BindView(R.id.comment_badge) public View commentBadge; @@ -54,6 +55,7 @@ public class CommentViewHolder extends BaseRecyclerViewHolder { public View commentMore; @BindView(R.id.comment_reply) public View commentReply; + @Nullable @BindView(R.id.reply_dividing_line) public View replyLine; diff --git a/app/src/main/java/com/gh/gamecenter/entity/MenuItemEntity.kt b/app/src/main/java/com/gh/gamecenter/entity/MenuItemEntity.kt index d741082ecd..0afe7ab9fa 100644 --- a/app/src/main/java/com/gh/gamecenter/entity/MenuItemEntity.kt +++ b/app/src/main/java/com/gh/gamecenter/entity/MenuItemEntity.kt @@ -3,5 +3,6 @@ package com.gh.gamecenter.entity data class MenuItemEntity( val text: String = "", val normalIcon: Int = 0, - val disableIcon: Int = 0 + val disableIcon: Int = 0, + val isEnable:Boolean = true ) \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/forum/select/ForumAdapter.kt b/app/src/main/java/com/gh/gamecenter/forum/select/ForumAdapter.kt index cb175c8904..8dc6b38389 100644 --- a/app/src/main/java/com/gh/gamecenter/forum/select/ForumAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/forum/select/ForumAdapter.kt @@ -4,20 +4,21 @@ import android.content.Context import android.view.Gravity import android.view.ViewGroup import androidx.core.content.ContextCompat +import androidx.fragment.app.DialogFragment import androidx.recyclerview.widget.RecyclerView import com.gh.base.BaseRecyclerViewHolder import com.gh.common.util.* import com.gh.gamecenter.R import com.gh.gamecenter.databinding.ForumItemBinding +import com.gh.gamecenter.entity.CommunityEntity import com.gh.gamecenter.entity.ForumEntity import com.gh.gamecenter.eventbus.EBForumFollowChange import com.gh.gamecenter.forum.detail.ForumDetailActivity -import com.gh.gamecenter.forum.home.ForumVisitDao import com.gh.gamecenter.qa.entity.CommunitySelectEntity import com.lightgame.adapter.BaseRecyclerAdapter import org.greenrobot.eventbus.EventBus -class ForumAdapter(context: Context, val mViewModel: ForumSelectViewModel?) : BaseRecyclerAdapter(context) { +class ForumAdapter(val context: Context, val mViewModel: ForumSelectViewModel?, val isSelectForum: Boolean = false, val onSelectCallback: ((entity: CommunityEntity) -> Unit)? = null) : BaseRecyclerAdapter(context) { val datas: ArrayList = arrayListOf() @@ -40,9 +41,14 @@ class ForumAdapter(context: Context, val mViewModel: ForumSelectViewModel?) : Ba val forumEntity = datas[position] holder.binding.entity = forumEntity holder.binding.forumIcon.displayGameIcon(forumEntity.game.getIcon(), forumEntity.game.iconSubscript) + holder.binding.followTv.goneIf(isSelectForum) holder.itemView.setOnClickListener { - MtaHelper.onEvent("论坛首页", "选择论坛", forumEntity.name) - mContext.startActivity(ForumDetailActivity.getIntent(mContext, forumEntity.id, "论坛-选择论坛")) + if (isSelectForum) { + onSelectCallback?.invoke(CommunityEntity(forumEntity.id, forumEntity.name, icon = forumEntity.game.getIcon(), iconSubscript = forumEntity.game.iconSubscript)) + } else { + MtaHelper.onEvent("论坛首页", "选择论坛", forumEntity.name) + mContext.startActivity(ForumDetailActivity.getIntent(mContext, forumEntity.id, "论坛-选择论坛")) + } } holder.binding.followTv.setOnClickListener { mContext.ifLogin("论坛-选择论坛") { diff --git a/app/src/main/java/com/gh/gamecenter/forum/select/ForumSelectFragment.kt b/app/src/main/java/com/gh/gamecenter/forum/select/ForumSelectFragment.kt index d3180a877d..920fbdad81 100644 --- a/app/src/main/java/com/gh/gamecenter/forum/select/ForumSelectFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/forum/select/ForumSelectFragment.kt @@ -8,6 +8,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.gh.common.util.viewModelProvider import com.gh.gamecenter.R +import com.gh.gamecenter.entity.CommunityEntity import com.gh.gamecenter.entity.ForumCategoryEntity import com.gh.gamecenter.eventbus.EBForumFollowChange import com.gh.gamecenter.mvvm.Status @@ -28,6 +29,7 @@ class ForumSelectFragment : NormalFragment() { private var mViewModel: ForumSelectViewModel? = null private var selectCategory: ForumCategoryEntity? = null + var onSelectCallback: ((entity: CommunityEntity) -> Unit)? = null override fun getLayoutId(): Int = R.layout.fragment_forum_select @@ -38,10 +40,12 @@ class ForumSelectFragment : NormalFragment() { mLoadingView.visibility = View.GONE if (it.status == Status.SUCCESS) { if (it.data != null) { - mForumCategoryAdapter?.setListData(it.data) + val data = it.data as ArrayList + if (onSelectCallback != null) data.add(0, ForumCategoryEntity("", "我的关注")) + mForumCategoryAdapter?.setListData(data) if (it.data.isNotEmpty()) { selectCategory = it.data[0] - mViewModel?.getForumByCategoryId(it.data[0].id) + mViewModel?.getForumList(selectCategory) } } mForumCategoryRv.visibility = View.VISIBLE @@ -81,13 +85,13 @@ class ForumSelectFragment : NormalFragment() { mForumCategoryAdapter = ForumCategoryAdapter(requireContext()) { selectCategory = it mLoadingView.visibility = View.VISIBLE - mViewModel?.getForumByCategoryId(it.id) + mViewModel?.getForumList(it) } adapter = mForumCategoryAdapter } mForumRv.apply { layoutManager = LinearLayoutManager(requireContext()) - mForumAdapter = ForumAdapter(requireContext(), mViewModel) + mForumAdapter = ForumAdapter(requireContext(), mViewModel, onSelectCallback != null, onSelectCallback) adapter = mForumAdapter } @@ -97,7 +101,7 @@ class ForumSelectFragment : NormalFragment() { mViewModel?.getForumCategories() } else { mLoadingView.visibility = View.VISIBLE - mViewModel?.getForumByCategoryId(selectCategory?.id ?: "") + mViewModel?.getForumList(selectCategory) } } } diff --git a/app/src/main/java/com/gh/gamecenter/forum/select/ForumSelectViewModel.kt b/app/src/main/java/com/gh/gamecenter/forum/select/ForumSelectViewModel.kt index 6f96f1ade5..3f0fa9650e 100644 --- a/app/src/main/java/com/gh/gamecenter/forum/select/ForumSelectViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/forum/select/ForumSelectViewModel.kt @@ -8,6 +8,7 @@ import com.gh.common.util.UrlFilterUtils import com.gh.gamecenter.entity.ForumCategoryEntity import com.gh.gamecenter.entity.ForumEntity import com.gh.gamecenter.entity.LinkEntity +import com.gh.gamecenter.manager.UserManager import com.gh.gamecenter.mvvm.Resource import com.gh.gamecenter.qa.entity.CommunitySelectOpenEntity import com.gh.gamecenter.retrofit.BiResponse @@ -44,10 +45,15 @@ class ForumSelectViewModel(application: Application) : AndroidViewModel(applicat }) } - fun getForumByCategoryId(categoryId: String) { - RetrofitManager.getInstance(getApplication()).api - .getForumByCategories(categoryId) - .subscribeOn(Schedulers.io()) + fun getForumList(category: ForumCategoryEntity?) { + val observable = if (category?.name != "我的关注") { + RetrofitManager.getInstance(getApplication()).api + .getForumByCategories(category?.id ?: "") + } else { + RetrofitManager.getInstance(getApplication()).api + .getFollowsForum(UserManager.getInstance().userId) + } + observable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : Response>() { override fun onResponse(response: List?) { @@ -76,6 +82,7 @@ class ForumSelectViewModel(application: Application) : AndroidViewModel(applicat } }) } + @SuppressLint("CheckResult") fun unFollowForum(bbsId: String, onSuccess: () -> Unit) { RetrofitManager.getInstance(getApplication()).api diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/dialog/GameDetailMoreDialog.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/dialog/GameDetailMoreDialog.kt index 1b268f6cd4..9aea2ccb09 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/dialog/GameDetailMoreDialog.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/dialog/GameDetailMoreDialog.kt @@ -102,7 +102,7 @@ class GameDetailMoreDialog : BaseDialogFragment(), View.OnTouchListener { shareEntrance = ShareUtils.ShareEntrance.plugin } } - shareUtils.shareGameDetail(requireActivity(), url, gameEntity?.icon, gameEntity?.name, + shareUtils.shareParamsDetail(requireActivity(), url, gameEntity?.icon, gameEntity?.name, gameEntity?.brief, shareEntrance, gameEntity?.id ?: "", null) return shareUtils } diff --git a/app/src/main/java/com/gh/gamecenter/qa/answer/BaseAnswerOrArticleItemViewHolder.kt b/app/src/main/java/com/gh/gamecenter/qa/answer/BaseAnswerOrArticleItemViewHolder.kt index bcd276cf8b..5018ba0bac 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/answer/BaseAnswerOrArticleItemViewHolder.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/answer/BaseAnswerOrArticleItemViewHolder.kt @@ -53,7 +53,7 @@ open class BaseAnswerOrArticleItemViewHolder(itemView: View) : BaseRecyclerViewH val intent = CommentActivity.getAnswerCommentIntent(itemView.context, entity.id!!, entity.commentCount, - entity.commentCount == 0) + false) itemView.context.startActivity(intent) } diff --git a/app/src/main/java/com/gh/gamecenter/qa/answer/detail/AnswerDetailFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/answer/detail/AnswerDetailFragment.kt index 09a5d388e1..35eb1292c4 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/answer/detail/AnswerDetailFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/answer/detail/AnswerDetailFragment.kt @@ -4,19 +4,17 @@ import android.annotation.SuppressLint import android.app.Activity import android.app.Dialog import android.content.Intent -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.animation.LinearInterpolator import android.webkit.JavascriptInterface import android.widget.ImageView import android.widget.LinearLayout -import android.widget.PopupWindow import android.widget.TextView +import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.databinding.BindingAdapter import androidx.databinding.DataBindingUtil @@ -48,6 +46,7 @@ import com.gh.gamecenter.normal.NormalFragment import com.gh.gamecenter.personal.PersonalFragment.LOGIN_TAG import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity import com.gh.gamecenter.qa.comment.CommentActivity +import com.gh.gamecenter.qa.dialog.MoreFunctionPanelDialog import com.gh.gamecenter.qa.editor.OnLinkClickListener import com.gh.gamecenter.qa.entity.AnswerDetailEntity import com.gh.gamecenter.qa.entity.Questions @@ -151,6 +150,8 @@ class AnswerDetailFragment : NormalFragment() { mBinding.richEditor.setInputEnabled(false) mBinding.richEditor.setPadding(20, 15, 20, 15) + mBinding.bottomController.replyTv.text = "说点什么吧" + mBinding.bottomController.replyTv.setRoundedColorBackground(R.color.text_F5F5F5, 19F) mElapsedHelper = TimeElapsedHelper(this) // 只对显示在屏幕上的 fragment 计时 @@ -231,8 +232,8 @@ class AnswerDetailFragment : NormalFragment() { val count = data.getIntExtra(CommentActivity.COMMENT_COUNT, 0) if (count != 0) { mViewModel.answerDetail?.commentCount = count - mBinding.bottomController.tvCommentCount.text = String.format("评论 %s", NumberUtils.transSimpleCount(mViewModel.answerDetail?.commentCount - ?: 0)) + mBinding.bottomController.bottomCommentTv.text = NumberUtils.transSimpleCount(mViewModel.answerDetail?.commentCount + ?: 0) if (EntranceUtils.ENTRANCE_WELCOME == mEntrance) { LogUtils.uploadCommentFromWelcomeDialog() @@ -281,7 +282,7 @@ class AnswerDetailFragment : NormalFragment() { if (e != null && e.code() == 404 && e.response().errorBody()!!.string().isNotEmpty()) { HistoryHelper.deleteAnswerEntity(mAnswerId) - mBinding.bottomController.containerControl.visibility = View.GONE + mBinding.bottomController.root.visibility = View.GONE mNoDataTv.setText(R.string.content_delete_hint) mNoData.visibility = View.VISIBLE mNoConn.visibility = View.GONE @@ -308,7 +309,7 @@ class AnswerDetailFragment : NormalFragment() { } else { mNoConn.visibility = View.VISIBLE mBinding.scrollView.visibility = View.GONE - mBinding.bottomController.containerControl.visibility = View.GONE + mBinding.bottomController.root.visibility = View.GONE mBinding.bottomDividerView.visibility = View.GONE mBinding.bottomShadowView.visibility = View.GONE } @@ -486,25 +487,19 @@ class AnswerDetailFragment : NormalFragment() { mBinding.followTv.visibility = View.GONE } else { mBinding.followTv.isEnabled = true - if (!me.isFollower) { - mBinding.followTv.alpha = 1f - mBinding.followTv.visibility = View.VISIBLE - updateFollowBtn(false) - } else { - mBinding.followTv.visibility = View.GONE - } + updateFollowBtn(me.isFollower) } } private fun toggleComment(enable: Boolean, commentCount: Int) { if (enable) { - mBinding.bottomController.ivComment.setImageResource(R.drawable.community_content_detail_comment_open) - mBinding.bottomController.tvCommentCount.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_242529)) - mBinding.bottomController.tvCommentCount.text = String.format("评论 %d", commentCount) + mBinding.bottomController.bottomCommentIv.setImageResource(R.drawable.community_content_detail_comment_open) + mBinding.bottomController.bottomCommentTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_242529)) + mBinding.bottomController.bottomCommentTv.text = if (commentCount > 0) commentCount.toString() else "评论" } else { - mBinding.bottomController.ivComment.setImageResource(R.drawable.community_content_detail_comment_close) - mBinding.bottomController.tvCommentCount.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_b3b3b3)) - mBinding.bottomController.tvCommentCount.text = "评论已关闭" + mBinding.bottomController.bottomCommentIv.setImageResource(R.drawable.community_content_detail_comment_close) + mBinding.bottomController.bottomCommentTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_b3b3b3)) + mBinding.bottomController.bottomCommentTv.text = "评论已关闭" } } @@ -609,78 +604,76 @@ class AnswerDetailFragment : NormalFragment() { private fun showMoreItemDialog(answer: AnswerDetailEntity) { if (fragmentIsVisible()) { - val view = LayoutInflater.from(context).inflate(R.layout.menu_answer_detail_more_new, null) - val popupWindow = PopupWindow( - view, - LinearLayout.LayoutParams.WRAP_CONTENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ) - popupWindow.apply { - setBackgroundDrawable(ColorDrawable(0)) - isTouchable = true - isFocusable = true - isOutsideTouchable = true - } - view.measure(0, 0) - val viewWidth = view.measuredWidth - popupWindow.showAsDropDown((activity as ToolBarActivity).menu.getItem(2).actionView, -viewWidth - 10, 10) - - val container = view.findViewById(R.id.container) val entities = ArrayList() - entities.add(MenuItemEntity("首页", R.drawable.menu_more_home)) if (answer.user.id != UserManager.getInstance().userId) { - entities.add(MenuItemEntity("投诉", R.drawable.ic_menu_gamedetail_feedback)) + entities.add(MenuItemEntity("投诉", R.drawable.icon_gamedetail_copyright)) } if (answer.me.isModerator) { - entities.add(MenuItemEntity("加精", R.drawable.menu_more_essence_enable, - if (answer.isHighlighted || answer.user.id == UserManager.getInstance().userId) - R.drawable.menu_more_essence_unenable else 0)) - entities.add(MenuItemEntity("折叠", R.drawable.menu_more_fold)) + val isEnable = answer.isHighlighted || answer.user.id == UserManager.getInstance().userId + entities.add(MenuItemEntity("加精", if (isEnable) + R.drawable.icon_more_panel_essence_unenable else R.drawable.icon_more_panel_essence, + isEnable = !isEnable)) + + entities.add(MenuItemEntity("折叠", R.drawable.icon_more_panel_fold)) } if (answer.user.id == UserManager.getInstance().userId) { - entities.add(MenuItemEntity(if (answer.commentable) "关闭评论" else "恢复评论", if (answer.commentable) R.drawable.ic_close_comment else R.drawable.ic_open_comment)) + entities.add(MenuItemEntity(if (answer.commentable) "关闭评论" else "恢复评论", if (answer.commentable) R.drawable.icon_more_panel_close_comment_enable + else R.drawable.icon_more_panel_close_comment_unenable)) } if (answer.me.isModerator || answer.user.id == UserManager.getInstance().userId) { - entities.add(MenuItemEntity("删除", R.drawable.menu_more_delete)) + entities.add(MenuItemEntity("删除", R.drawable.icon_more_panel_delete)) } - entities.forEachIndexed { index, item -> - val menuItem = createMenuItem(index, item) - container.addView(menuItem) - menuItem.setOnClickListener { - popupWindow.dismiss() - when (item.text) { - "首页" -> { - val community = mViewModel.answerDetail?.community - MtaHelper.onEvent("回到首页", "回答详情", community?.name + "+" + StringUtils.combineTwoString(mViewModel.answerDetail?.content, mViewModel.answerDetail?.id)) - DirectUtils.directToCommunity(requireContext(), community) - } - "投诉" -> { - SuggestionActivity.startSuggestionActivity(context, SuggestType.normal, "report", "回答投诉($mAnswerId):") - } - "加精" -> { - addEssenceForum(answer) - } - "折叠" -> { - foldForum(answer) - } - "关闭评论", "恢复评论" -> { - if (mViewModel.answerDetail?.commentable!!) { - DialogUtils.showAlertDialog(requireContext(), "提示", "关闭评论之后,该回答将无法查看和发表评论,确定关闭吗?", - "确定", "取消", { mViewModel.toggleComment(mAnswerId, false) }, null) - } else { - DialogUtils.showAlertDialog(requireContext(), "提示", "确定恢复评论吗?", - "确定", "取消", { mViewModel.toggleComment(mAnswerId, true) }, null) - } - } - "删除" -> { - DialogUtils.showNewAlertDialog(requireContext(), "提示", "删除回答后,其中的所有回复都将被删除", "取消", "删除", {}, { - mViewModel.doHideThisAnswer(mAnswerId) - }) + val shareIcon: String = if (mAnswersImages!!.size > 0) { + mAnswersImages[0] + } else { + getString(R.string.share_ghzs_logo) + } + var shareSummary = mBinding.richEditor.text + if (TextUtils.isEmpty(shareSummary)) { + shareSummary = getString(R.string.ask_share_default_summary) + } + val shareUrl = if (isPublishEnv()) { + getString(R.string.share_answers_url, mAnswerId) + } else { + getString(R.string.share_answers_url_dev, answer.question.id, mAnswerId) + } + val shareUtils = ShareUtils.getInstance(context) + shareUtils.shareParamsDetail(activity, + shareUrl, + shareIcon, + getString(R.string.ask_share_answers_title, answer.user.name, answer.question.title, answer.vote), + shareSummary, + ShareUtils.ShareEntrance.answerNormal, mAnswerId, null) + MoreFunctionPanelDialog.showMoreDialog(requireActivity() as AppCompatActivity, entities, answer.question.title + ?: "", shareUtils) { + when (it.text) { + "投诉" -> { + SuggestionActivity.startSuggestionActivity(context, SuggestType.normal, "report", "回答投诉($mAnswerId):") + } + "加精" -> { + addEssenceForum(answer) + } + "折叠" -> { + foldForum(answer) + } + "关闭评论", "恢复评论" -> { + if (mViewModel.answerDetail?.commentable!!) { + DialogUtils.showAlertDialog(requireContext(), "提示", "关闭评论之后,该回答将无法查看和发表评论,确定关闭吗?", + "确定", "取消", { mViewModel.toggleComment(mAnswerId, false) }, null) + } else { + DialogUtils.showAlertDialog(requireContext(), "提示", "确定恢复评论吗?", + "确定", "取消", { mViewModel.toggleComment(mAnswerId, true) }, null) } } + "删除" -> { + DialogUtils.showNewAlertDialog(requireContext(), "提示", "删除回答后,其中的所有回复都将被删除", "取消", "删除", {}, { + mViewModel.doHideThisAnswer(mAnswerId) + }) + } } } + } } @@ -731,17 +724,12 @@ class AnswerDetailFragment : NormalFragment() { } @OnClick( - R.id.iv_comment, - R.id.tv_comment_count, - R.id.iv_collect, - R.id.tv_collect, - R.id.iv_share, - R.id.tv_share, - R.id.container_dislike, + R.id.replyTv, + R.id.bottomStarContainer, R.id.reuse_no_connection, R.id.status_tv, + R.id.bottomLikeContainer, R.id.answer_count_container, - R.id.container_like, R.id.follow_tv, R.id.user_icon_iv, R.id.questionsdetail_item_pic1, @@ -758,11 +746,11 @@ class AnswerDetailFragment : NormalFragment() { mViewModel.getAnswerDetail(mAnswerId, mEntrance) } - R.id.iv_share, R.id.tv_share -> { - shareAnswer() - } +// R.id.iv_share, R.id.tv_share -> { +// shareAnswer() +// } - R.id.iv_collect, R.id.tv_collect -> { + R.id.bottomStarContainer -> { ifLogin("回答详情-收藏") { mViewModel.answerDetail?.let { if (!it.me.isAnswerFavorite) { @@ -777,42 +765,32 @@ class AnswerDetailFragment : NormalFragment() { startActivity(QuestionsDetailActivity.getIntent(context, mViewModel.answerDetail!!.question.id, mEntrance, "回答详情")) } - R.id.container_like -> debounceActionWithInterval(R.id.container_like, 1000) { - ifLogin("回答详情-赞同") { - if (mViewModel.answerDetail != null && !mViewModel.answerDetail!!.me.isAnswerVoted) { - mViewModel.like(mAnswerId) + R.id.bottomLikeContainer -> { + debounceActionWithInterval(R.id.container_like, 1000) { + ifLogin("回答详情-赞同") { + if (mViewModel.answerDetail != null && !mViewModel.answerDetail!!.me.isAnswerVoted) { + mViewModel.like(mAnswerId) - if (EntranceUtils.ENTRANCE_WELCOME == mEntrance) { - LogUtils.uploadLikeFromWelcomeDialog() - } + if (EntranceUtils.ENTRANCE_WELCOME == mEntrance) { + LogUtils.uploadLikeFromWelcomeDialog() + } - DataUtils.onMtaEvent(context, - "答案点赞量_社区加位置", - mViewModel.answerDetail?.community?.name, - mPath) - } else { - mViewModel.cancelLike(mAnswerId) - } - } - } - - R.id.container_dislike -> debounceActionWithInterval(R.id.container_like, 1000) { - ifLogin("回答详情-反对") { - mViewModel.answerDetail?.let { - if (it.me.isAnswerOpposed) { - mViewModel.cancelDislike(mAnswerId) + DataUtils.onMtaEvent(context, + "答案点赞量_社区加位置", + mViewModel.answerDetail?.community?.name, + mPath) } else { - mViewModel.dislike(mAnswerId) + mViewModel.cancelLike(mAnswerId) } } } } - R.id.iv_comment, R.id.tv_comment_count -> { + R.id.replyTv -> { mViewModel.answerDetail?.run { if (commentable) { DataUtils.onMtaEvent(context, "详情页面", "答案评论详情", content.subStringIfPossible(30)) - showCommentDialog(commentCount == 0) + showCommentDialog(false) } else { toast("作者已关闭评论") } @@ -853,6 +831,8 @@ class AnswerDetailFragment : NormalFragment() { ifLogin("回答详情-[关注]用户") { if (mBinding.followTv.text == "关注") { mViewModel.follow(mViewModel.answerDetail!!.user.id!!) + } else { + mViewModel.unfollow(mViewModel.answerDetail!!.user.id!!) } } } @@ -883,10 +863,6 @@ class AnswerDetailFragment : NormalFragment() { R.id.questionsdetail_item_pic3 -> showQuestionImageDetail(view, 2 - videoSize) R.id.title_tv -> { -// startActivity(QuestionsDetailActivity.getIntent( -// context, -// mViewModel.answerDetail?.question?.id, mEntrance, -// "回答详情")) val intent = QuestionsDetailActivity.getIntent( context, mViewModel.answerDetail?.question?.id, mEntrance, @@ -931,13 +907,13 @@ class AnswerDetailFragment : NormalFragment() { private fun updateCollectView(isCollected: Boolean) { if (isCollected) { - mBinding.bottomController.tvCollect.text = "已收藏" - mBinding.bottomController.ivCollect.setImageResource(R.drawable.community_content_detail_collect_select) - mBinding.bottomController.tvCollect.setTextColor(ContextCompat.getColor(requireContext(), R.color.theme_font)) + mBinding.bottomController.bottomStarIv.setImageResource(R.drawable.community_content_detail_collect_select) + mBinding.bottomController.bottomStarTv.text = "已收藏" + mBinding.bottomController.bottomStarTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.theme_font)) } else { - mBinding.bottomController.tvCollect.text = "收藏" - mBinding.bottomController.ivCollect.setImageResource(R.drawable.community_content_detail_collect_unselect) - mBinding.bottomController.tvCollect.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_242529)) + mBinding.bottomController.bottomStarIv.setImageResource(R.drawable.community_content_detail_collect_unselect) + mBinding.bottomController.bottomStarTv.text = "收藏" + mBinding.bottomController.bottomStarTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_242529)) } } @@ -989,7 +965,7 @@ class AnswerDetailFragment : NormalFragment() { if (mIsShowCommentManager) { mIsShowCommentManager = false - mBinding.bottomController.ivComment.performClick() + mBinding.bottomController.bottomCommentContainer.performClick() } mBinding.richEditor.clearFocus() @@ -1013,7 +989,7 @@ class AnswerDetailFragment : NormalFragment() { private fun hideLoadingViewAndShowContent() { mNoConn.visibility = View.GONE - mBinding.bottomController.containerControl.visibility = View.VISIBLE + mBinding.bottomController.root.visibility = View.VISIBLE mBinding.scrollView.visibility = View.VISIBLE } @@ -1126,21 +1102,11 @@ class AnswerDetailFragment : NormalFragment() { } private fun updateFollowBtn(isFollowed: Boolean) { + mBinding.followTv.visibility = View.VISIBLE if (isFollowed) { - if (mBinding.followTv.visibility == View.GONE) return DrawableView.setTextDrawable(mBinding.followTv, null, "已关注") mBinding.followTv.setTextColor(R.color.text_999999.toColor()) - mBinding.followTv.postDelayed({ - if (context == null) return@postDelayed - mBinding.followTv.animate() - .alpha(0f) - .setInterpolator(LinearInterpolator()) - .doOnEnd { context?.let { mBinding.followTv.visibility = View.GONE } } - .setDuration(500L) - .start() - }, 2000L) } else { - mBinding.followTv.visibility = View.VISIBLE mBinding.followTv.background = DrawableView.getOvalDrawable(R.color.background, 2F) mBinding.followTv.setTextColor(R.color.theme_font.toColor()) DrawableView.setTextDrawable( @@ -1152,22 +1118,24 @@ class AnswerDetailFragment : NormalFragment() { @SuppressLint("SetTextI18n") private fun updateLikeView(alreadyVoted: Boolean, voteCount: Int) { - mBinding.bottomController.tvLike.text = "赞同 ${NumberUtils.transSimpleCount(voteCount)}" +// mBinding.bottomController.bottomLikeTv.text = "赞同 ${NumberUtils.transSimpleCount(voteCount)}" if (alreadyVoted) { - mBinding.bottomController.ivLike.setImageResource(R.drawable.community_content_detail_vote_select) - mBinding.bottomController.tvLike.setTextColor(ContextCompat.getColor(requireContext(), R.color.theme_font)) + mBinding.bottomController.bottomLikeIv.setImageResource(R.drawable.community_content_detail_vote_select) + mBinding.bottomController.bottomLikeTv.text = NumberUtils.transSimpleCount(voteCount) + mBinding.bottomController.bottomLikeTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.theme_font)) } else { - mBinding.bottomController.ivLike.setImageResource(R.drawable.community_content_detail_vote_unselect) - mBinding.bottomController.tvLike.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_242529)) + mBinding.bottomController.bottomLikeIv.setImageResource(R.drawable.community_content_detail_vote_unselect) + mBinding.bottomController.bottomLikeTv.text = "赞同" + mBinding.bottomController.bottomLikeTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_242529)) } } private fun updateDislikeView(disliked: Boolean) { - if (disliked) { - mBinding.bottomController.ivDislike.setImageResource(R.drawable.community_content_detail_oppose_select) - } else { - mBinding.bottomController.ivDislike.setImageResource(R.drawable.community_content_detail_oppose_unselect) - } +// if (disliked) { +// mBinding.bottomController.ivDislike.setImageResource(R.drawable.community_content_detail_oppose_select) +// } else { +// mBinding.bottomController.ivDislike.setImageResource(R.drawable.community_content_detail_oppose_unselect) +// } } private fun showDragHintDialog() { diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/detail/ArticleDetailContentViewHolder.kt b/app/src/main/java/com/gh/gamecenter/qa/article/detail/ArticleDetailContentViewHolder.kt index f50911a941..e6601214d3 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/detail/ArticleDetailContentViewHolder.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/detail/ArticleDetailContentViewHolder.kt @@ -44,77 +44,6 @@ class ArticleDetailContentViewHolder(var binding: ItemArticleDetailContentBindin } }) - likeContainer.setDebouncedClickListener { - MtaHelper.onEvent("帖子详情", "内容区域", "点赞") - root.context.ifLogin("帖子详情-赞同") { - if (!article.me.isCommunityArticleVote) { - viewModel.likeArticle() - if (EntranceUtils.ENTRANCE_WELCOME == mEntrance) { - LogUtils.uploadLikeFromWelcomeDialog() - } - } else { - viewModel.cancelLikeArticle() - } - } - } - - shareContainer.setOnClickListener { - MtaHelper.onEvent("帖子详情", "内容区域", "分享") -// GdtHelper.logAction(ActionType.SHARE, -// GdtHelper.CONTENT_TYPE, "QA_ARTICLE", -// GdtHelper.CONTENT_ID, viewModel.articleId) - - var shareSummary = richEditor.text - val shareIcon: String = if (articleImgUrlList.size > 0) { - articleImgUrlList[0] - } else { - root.context.getString(R.string.share_ghzs_logo) - } - if (TextUtils.isEmpty(shareSummary)) { - shareSummary = root.context.getString(R.string.ask_share_default_summary) - } - val shareUrl = if (isPublishEnv()) { - root.context.getString(R.string.share_community_article_url, article.community.id, article.id) - } else { - root.context.getString(R.string.share_community_article_url_dev, article.community.id, article.id) - } - ShareUtils.getInstance(root.context).showShareWindows( - root.context as Activity?, - root, - shareUrl, - shareIcon, - root.context.getString(R.string.share_community_article_title, article.user.name, article.title, article.count.vote), - shareSummary, - ShareUtils.ShareEntrance.communityArticle, - article.id) - } - - starContainer.setDebouncedClickListener { - MtaHelper.onEvent("帖子详情", "内容区域", "收藏") - root.context.ifLogin(entrance = "帖子详情-收藏") { - viewModel.collectionCommand(!article.me.isCommunityArticleFavorite, callback = { - viewModel.detailEntity?.me?.isCommunityArticleFavorite = it - if (it) { -// GdtHelper.logAction(ActionType.ADD_TO_WISHLIST, -// GdtHelper.CONTENT_TYPE, "QA_ARTICLE", -// GdtHelper.CONTENT_ID, viewModel.articleId) - } - updateCollectView(it) - }) - } - } - - dislikeContainer.setDebouncedClickListener { - MtaHelper.onEvent("帖子详情", "内容区域", "反对") - root.context.ifLogin("帖子详情-反对") { - if (!article.me.isCommunityArticleOppose) { - viewModel.dislikeArticle() - } else { - viewModel.cancelDislikeArticle() - } - } - } - followBtn.setOnClickListener { MtaHelper.onEvent("帖子详情", "内容区域", "关注") root.context.ifLogin("帖子详情-[关注]用户") { @@ -143,14 +72,6 @@ class ArticleDetailContentViewHolder(var binding: ItemArticleDetailContentBindin } binding.run { - if (article.me.isCommunityArticleFavorite) { - starIv.setImageResource(R.drawable.ic_article_detail_stared) - starTv.text = "已收藏" - } else { - starIv.setImageResource(R.drawable.ic_article_detail_star) - starTv.text = "收藏" - } - detail = article userIconIv.display(article.user.border, article.user.icon, article.user.auth?.icon) richEditor.setContentOwner(article.me.isContentOwner) @@ -160,9 +81,9 @@ class ArticleDetailContentViewHolder(var binding: ItemArticleDetailContentBindin } if (article.time.create == article.time.edit) { - releaseTimeTv.text = String.format("发布于 %s", NewsUtils.getFormattedTime(article.time.create)) + releaseTimeTv.text = String.format("发布于%s", NewsUtils.getFormattedTime(article.time.create)) } else { - releaseTimeTv.text = String.format("修改于 %s", NewsUtils.getFormattedTime(article.time.edit)) + releaseTimeTv.text = String.format("发布于%s 最后编辑于%s", NewsUtils.getFormattedTime(article.time.create), NewsUtils.getFormattedTime(article.time.edit)) } richEditor.visibility = View.VISIBLE @@ -199,9 +120,6 @@ class ArticleDetailContentViewHolder(var binding: ItemArticleDetailContentBindin } } badgeTv.setOnClickListener { badgeIv.performClick() } - - updateLikeView(article.me.isCommunityArticleVote, article.count.vote) - updateDislikeView(article.me.isCommunityArticleOppose) } } } @@ -213,16 +131,6 @@ class ArticleDetailContentViewHolder(var binding: ItemArticleDetailContentBindin followBtn.text = "已关注" followBtn.background = null followBtn.setTextColor(ContextCompat.getColor(root.context, R.color.text_999999)) - followBtn.postDelayed({ - followBtn.animate() - .alpha(0f) - .setInterpolator(LinearInterpolator()) - .doOnEnd { - tryWithDefaultCatch { followBtn.visibility = View.GONE } - } - .setDuration(500L) - .start() - }, 2000L) } else { followBtn.setRoundedColorBackground(R.color.text_EEF5FB, 14F) followBtn.setTextColor(ContextCompat.getColor(root.context, R.color.theme_font)) @@ -231,40 +139,6 @@ class ArticleDetailContentViewHolder(var binding: ItemArticleDetailContentBindin } } - @SuppressLint("SetTextI18n") - fun updateLikeView(alreadyLiked: Boolean, likeCount: Int) { - binding.run { - likeTv.text = if (likeCount == 0) "赞同" else likeCount.toString() - if (alreadyLiked) { - likeIv.setImageResource(R.drawable.ic_article_detail_liked) - } else { - likeIv.setImageResource(R.drawable.ic_article_detail_like) - } - } - } - - fun updateDislikeView(disliked: Boolean) { - binding.run { - if (disliked) { - dislikeIv.setImageResource(R.drawable.ic_article_detail_disliked) - } else { - dislikeIv.setImageResource(R.drawable.ic_article_detail_dislike) - } - } - } - - fun updateCollectView(isCollected: Boolean) { - binding.run { - if (isCollected) { - starTv.text = "已收藏" - starIv.setImageResource(R.drawable.ic_article_detail_stared) - } else { - starTv.text = "收藏" - starIv.setImageResource(R.drawable.ic_article_detail_star) - } - } - } - private fun addTag(tag: String, isCommunityName: Boolean = false) { binding.run { if (isCommunityName) { diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/detail/ArticleDetailFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/article/detail/ArticleDetailFragment.kt index ccc2e6adf0..59e49c5920 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/detail/ArticleDetailFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/detail/ArticleDetailFragment.kt @@ -3,15 +3,14 @@ package com.gh.gamecenter.qa.article.detail import android.annotation.SuppressLint import android.app.Activity import android.content.Intent -import android.graphics.drawable.ColorDrawable import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.LinearLayout -import android.widget.PopupWindow import android.widget.TextView +import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.core.view.ViewCompat import androidx.lifecycle.Lifecycle @@ -37,6 +36,7 @@ import com.gh.gamecenter.manager.UserManager import com.gh.gamecenter.personal.PersonalFragment import com.gh.gamecenter.qa.article.edit.ArticleEditActivity import com.gh.gamecenter.qa.comment.CommentActivity +import com.gh.gamecenter.qa.dialog.MoreFunctionPanelDialog import com.gh.gamecenter.qa.entity.ArticleDetailEntity import com.gh.gamecenter.suggest.SuggestType import com.halo.assistant.HaloApp @@ -183,11 +183,29 @@ class ArticleDetailFragment : BaseArticleDetailCommentFragment(R.id.container) val entities = ArrayList() if (mViewModel.detailEntity?.user?.id == UserManager.getInstance().userId) { - entities.add(MenuItemEntity("修改", R.drawable.menu_more_edit)) + entities.add(MenuItemEntity("修改", R.drawable.icon_more_panel_edit)) } if (mViewModel.detailEntity?.user?.id != UserManager.getInstance().userId) { - entities.add(MenuItemEntity("投诉", R.drawable.ic_menu_gamedetail_feedback)) + entities.add(MenuItemEntity("投诉", R.drawable.icon_gamedetail_copyright)) } if (mViewModel.detailEntity?.me!!.isModerator) { - entities.add(MenuItemEntity("加精", R.drawable.menu_more_essence_enable, - if (mViewModel.detailEntity?.isHighlighted == true || mViewModel.detailEntity?.user?.id == UserManager.getInstance().userId) - R.drawable.menu_more_essence_unenable else 0)) + val isEnable = mViewModel.detailEntity?.isHighlighted == true || mViewModel.detailEntity?.user?.id == UserManager.getInstance().userId + entities.add(MenuItemEntity("加精", if (isEnable) + R.drawable.icon_more_panel_essence_unenable else R.drawable.icon_more_panel_essence, isEnable = !isEnable)) } if (mViewModel.detailEntity?.me!!.isModerator || mViewModel.detailEntity?.user?.id == UserManager.getInstance().userId) { - entities.add(MenuItemEntity("删除", R.drawable.menu_more_delete)) + entities.add(MenuItemEntity("删除", R.drawable.icon_more_panel_delete)) } - entities.forEachIndexed { index, item -> - val menuItem = createMenuItem(index, item) - container.addView(menuItem) - menuItem.setOnClickListener { - popupWindow.dismiss() - when (item.text) { - "修改" -> { - startActivityForResult(ArticleEditActivity.getPatchIntent(requireContext(), mViewModel.detailEntity!!), ArticleDetailActivity.ARTICLE_PATCH_REQUEST) - } - "投诉" -> { - SuggestionActivity.startSuggestionActivity(requireContext(), SuggestType.normal, "report", - "帖子投诉(" + mViewModel.articleId + "):") - } - "加精" -> addEssenceForum(mViewModel.detailEntity!!) - "删除" -> { - DialogUtils.showNewAlertDialog(requireContext(), "提示", "删除帖子后,其中的所有评论及回复都将被删除", "取消", "删除", {}, { - mViewModel.doHideThisArticle(mViewModel.detailEntity!!.community.id, mViewModel.articleId) - }) - } + val shareUrl = if (isPublishEnv()) { + requireContext().getString(R.string.share_community_article_url, mViewModel.communityId, mViewModel.detailEntity?.id) + } else { + requireContext().getString(R.string.share_community_article_url_dev, mViewModel.communityId, mViewModel.detailEntity?.id) + } + + val shareIcon: String = if (mViewModel.detailEntity?.images?.isNotEmpty() == true) { + mViewModel.detailEntity?.images!![0] + } else { + requireContext().getString(R.string.share_ghzs_logo) + } + val title = requireContext().getString(R.string.share_community_article_title, mViewModel.detailEntity?.user?.name, + mViewModel.detailEntity?.title, mViewModel.detailEntity?.count?.vote ?: 0) + val shareUtils = ShareUtils.getInstance(requireContext()) + shareUtils.shareParamsDetail(requireActivity(), + shareUrl, + shareIcon, + title, + HtmlUtils.stripHtml(mViewModel.detailEntity?.content), + ShareUtils.ShareEntrance.communityArticle, + mViewModel.detailEntity?.id, null) + MoreFunctionPanelDialog.showMoreDialog(requireActivity() as AppCompatActivity, entities, mViewModel.detailEntity?.title + ?: "", shareUtils) { + when (it.text) { + "修改" -> { + startActivityForResult(ArticleEditActivity.getPatchIntent(requireContext(), mViewModel.detailEntity!!), ArticleDetailActivity.ARTICLE_PATCH_REQUEST) + } + "投诉" -> { + SuggestionActivity.startSuggestionActivity(requireContext(), SuggestType.normal, "report", + "帖子投诉(" + mViewModel.articleId + "):") + } + "加精" -> addEssenceForum(mViewModel.detailEntity!!) + "删除" -> { + DialogUtils.showNewAlertDialog(requireContext(), "提示", "删除帖子后,其中的所有评论及回复都将被删除", "取消", "删除", {}, { + mViewModel.doHideThisArticle(mViewModel.detailEntity!!.community.id, mViewModel.articleId) + }) } } } @@ -465,11 +483,11 @@ class ArticleDetailFragment : BaseArticleDetailCommentFragment : ListFragment() { @@ -39,6 +43,7 @@ abstract class BaseArticleDetailCommentFragment?, displayFloor: Boolean = false) { + fun mergeListData(commentList: List?, displayFloor: Boolean = false, hasFilter: Boolean = true) { topItemData?.let { val mergedList = arrayListOf().apply { - if (mResultLiveData.value?.firstOrNull() != null) { - // 保持头两个 item 的内存地址不变 - add(mResultLiveData.value!![0]) - add(mResultLiveData.value!![1]) + if (hasFilter) { + if (mResultLiveData.value?.firstOrNull() != null) { + // 保持头两个 item 的内存地址不变 + add(mResultLiveData.value!![0]) + add(mResultLiveData.value!![1]) + } else { + add(topItemData!!) + add(CommentItemData(filter = true)) + } } else { add(topItemData!!) - add(CommentItemData(filter = true)) } if (commentList.isNullOrEmpty() && mLoadStatusLiveData.value == LoadStatus.INIT_EMPTY) { add(CommentItemData(errorEmpty = true)) diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentAdapter.kt b/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentAdapter.kt index a75598c149..e59907f961 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentAdapter.kt @@ -65,9 +65,9 @@ class ArticleDetailCommentAdapter(context: Context, binding.comment = comment binding.moreIv.visibility = View.GONE + binding.divider.visibility = View.VISIBLE + binding.commentCountTv.visibility = View.GONE binding.floorHintTv.text = if (comment.floor != 0) "${comment.floor}楼" else "" - binding.commentCountTv.text = mViewModel.getCommentText(comment.reply, "回复") - binding.commentCountTv.setOnClickListener { commentClosure?.invoke(comment) } binding.contentTv.text = comment.content binding.contentTv.maxLines = Int.MAX_VALUE diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentFragment.kt index d64e4456c8..fa1a72d4b0 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentFragment.kt @@ -8,6 +8,7 @@ import android.view.ViewGroup import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.ViewCompat import com.ethanhua.skeleton.Skeleton +import com.gh.common.AppExecutor import com.gh.common.util.* import com.gh.gamecenter.R import com.gh.gamecenter.baselist.ListAdapter @@ -45,7 +46,6 @@ class ArticleDetailCommentFragment : BaseArticleDetailCommentFragment - (toolbarContainer.layoutParams as ViewGroup.MarginLayoutParams).topMargin = insets.systemWindowInsetTop - insets.consumeSystemWindowInsets() - } - mSkeletonScreen = Skeleton.bind(skeletonView).shimmer(false).load(R.layout.fragment_article_detail_comment_skeleton).show() bottomLikeContainer.visibility = View.GONE + bottomStarContainer.visibility = View.GONE bottomCommentContainer.visibility = View.GONE val lp = replyTv.layoutParams as ConstraintLayout.LayoutParams @@ -99,46 +95,7 @@ class ArticleDetailCommentFragment : BaseArticleDetailCommentFragment { - DialogUtils.showNewAlertDialog(requireContext(), "提示", "删除评论后,评论下所有的回复都将被删除", "取消", "删除", null, { - mViewModel.hideCommunityArticleComment(entity.id ?: "") { - EventBus.getDefault().post(EBDeleteCommentDetail(entity.id)) - requireActivity().finish() - } - }) - } - else -> { - //do nothing - } - } - } - - }) - } + closeIv.setOnClickListener { requireActivity().finish() } } override fun onBackPressed(): Boolean { @@ -170,18 +127,18 @@ class ArticleDetailCommentFragment : BaseArticleDetailCommentFragment 2) { + mListRv.smoothScrollToPosition(1) + } + }, 100) } else -> { if (it == BaseArticleDetailCommentViewModel.LoadResult.DELETED) { mReuseNoConn?.visibility = View.GONE mReuseNoData?.visibility = View.VISIBLE toast(R.string.content_delete_toast) - - toolbar.menu?.run { - for (i in 0 until size()) { - getItem(i).isVisible = false - } - } } else { mReuseNoConn?.visibility = View.VISIBLE mReuseNoData?.visibility = View.GONE diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentViewModel.kt index 901c2b185a..8a4e29d54e 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentViewModel.kt @@ -26,7 +26,7 @@ class ArticleDetailCommentViewModel(application: Application, override fun provideDataObservable(page: Int): Observable>? = null override fun mergeResultLiveData() { - mResultLiveData.addSource(mListLiveData) { mergeListData(it) } + mResultLiveData.addSource(mListLiveData) { mergeListData(it, hasFilter = false) } } override fun provideDataSingle(page: Int): Single> { @@ -46,7 +46,7 @@ class ArticleDetailCommentViewModel(application: Application, commentCount = data.reply topItemData = CommentItemData(commentTop = data) loadResultLiveData.postValue(LoadResult.SUCCESS) - mergeListData(mListLiveData.value) + mergeListData(mListLiveData.value, hasFilter = false) } override fun onFailure(exception: Exception) { diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditActivity.kt index 4f0bd794c3..4d5c587799 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditActivity.kt @@ -35,6 +35,7 @@ import com.gh.gamecenter.manager.UserManager import com.gh.gamecenter.mvvm.Status import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity import com.gh.gamecenter.qa.article.draft.ArticleDraftActivity +import com.gh.gamecenter.qa.dialog.ChooseForumDialogFragment import com.gh.gamecenter.qa.entity.ArticleDetailEntity import com.gh.gamecenter.qa.entity.ArticleDraftEntity import com.gh.gamecenter.qa.questions.edit.TagsSelectFragment @@ -171,10 +172,10 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { closeExtendedKeyboard() AppExecutor.uiExecutor.executeWithDelay(Runnable { Util_System_Keyboard.showSoftKeyboard(this) - },100) + }, 100) AppExecutor.uiExecutor.executeWithDelay(Runnable { - mRichEditor.scrollTo(0,1000000) - },500) + mRichEditor.scrollTo(0, 1000000) + }, 500) } checkPostButtonEnable() } @@ -279,14 +280,15 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { setNavigationTitle("发布帖子") mBaseHandler.sendEmptyMessageDelayed(1, SAVE_DRAFTS_INTERVAL_TIME.toLong()) mViewModel.mSelectCommunityData = intent.getParcelableExtra(CommunityEntity::class.java.simpleName) - if (mViewModel.mSelectCommunityData == null) { - showSelectGameDialog() - } else { + if (mViewModel.mSelectCommunityData != null) { setGameName() mGameName.isEnabled = false mGameName.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null) } } + mViewModel.notSelectForum.observe(this, Observer { + if (it) showSelectGameDialog() + }) } override fun getSelectedLabel(): Int = mViewModel.selectedTags.size @@ -503,27 +505,10 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { } private fun showSelectGameDialog() { - val selectGameDialog = Dialog(this) - val view = View.inflate(this, R.layout.dialog_article_game, null) - val recyclerView = view.findViewById(R.id.dialog_game_list) - val back = view.findViewById(R.id.dialog_back) - val loading = view.findViewById(R.id.dialog_loading) - - back.setOnClickListener { - selectGameDialog.cancel() - if (mViewModel.mSelectCommunityData == null) finish() - } - recyclerView.layoutManager = GridLayoutManager(this, 4) - recyclerView.adapter = ArticleSelectGameAdapter(this, loading) { - mViewModel.mSelectCommunityData = CommunityEntity(it.id, it.name, icon = it.game.icon, iconSubscript = it.game.iconSubscript) + ChooseForumDialogFragment.show(this) { + mViewModel.mSelectCommunityData = it setGameName() - selectGameDialog.cancel() } - - selectGameDialog.requestWindowFeature(Window.FEATURE_NO_TITLE) - selectGameDialog.setCanceledOnTouchOutside(false) - selectGameDialog.setContentView(view) - selectGameDialog.show() } private fun setGameName() { diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditViewModel.kt index 1ec0aa922d..cbdbb2aa13 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditViewModel.kt @@ -48,6 +48,7 @@ class ArticleEditViewModel(application: Application) : AndroidViewModel(applicat val postArticleDrafts = MediatorLiveData>() val articleDraftsContent = MediatorLiveData() val error = MutableLiveData() + val notSelectForum = MutableLiveData() var uploadImageSubscription: Disposable? = null @@ -88,25 +89,17 @@ class ArticleEditViewModel(application: Application) : AndroidViewModel(applicat * 根据问题标题获取相应标签(问题编辑无需获取) */ fun checkDataAndLoadTitleTag(isKeyBoardShow: Boolean = false): Boolean { - if (mSelectCommunityData == null) { - ToastUtils.showToast("请选择论坛", if (isKeyBoardShow) Gravity.CENTER else -1) - return false - } - if (TextUtils.isEmpty(title)) { ToastUtils.showToast("标题不能为空", if (isKeyBoardShow) Gravity.CENTER else -1) return false } - // 检查标题长度限制 title?.trim() -// title = title?.replace(" ", "")?.replace("\n", "") title = title?.replace("\n", "") if (title!!.length < QuestionEditViewModel.QUESTION_TITLE_MIN_LENGTH) { ToastUtils.showToast("标题至少${QuestionEditViewModel.QUESTION_TITLE_MIN_LENGTH}个字", if (isKeyBoardShow) Gravity.CENTER else -1) return false } - val articleContent = HtmlUtils.stripHtml(content).length if (articleContent < MIN_ARTICLE_TEXT_LENGTH) { ToastUtils.showToast("正文至少${QuestionEditViewModel.QUESTION_TITLE_MIN_LENGTH}个字", if (isKeyBoardShow) Gravity.CENTER else -1) @@ -116,6 +109,11 @@ class ArticleEditViewModel(application: Application) : AndroidViewModel(applicat ToastUtils.showToast("帖子最多输入${MAX_ARTICLE_TEXT_LENGTH}个字", if (isKeyBoardShow) Gravity.CENTER else -1) return false } + if (mSelectCommunityData == null) { + ToastUtils.showToast("请选择论坛", if (isKeyBoardShow) Gravity.CENTER else -1) + notSelectForum.postValue(true) + return false + } return true } diff --git a/app/src/main/java/com/gh/gamecenter/qa/comment/CommentActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/comment/CommentActivity.kt index 0a3ce8b66e..0cb44fec34 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/comment/CommentActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/comment/CommentActivity.kt @@ -8,10 +8,14 @@ import android.view.View import butterknife.OnClick import com.gh.base.BaseActivity import com.gh.common.util.DisplayUtils +import com.gh.common.util.EntranceUtils import com.gh.common.util.doOnEnd +import com.gh.gamecenter.NormalActivity import com.gh.gamecenter.R import com.gh.gamecenter.entity.CommentEntity import com.gh.gamecenter.qa.answer.detail.AnswerDetailFragment +import com.gh.gamecenter.qa.article.detail.comment.ArticleDetailCommentActivity +import com.gh.gamecenter.qa.article.detail.comment.ArticleDetailCommentFragment import com.lightgame.utils.Util_System_Keyboard import kotlinx.android.synthetic.main.activity_comment.* @@ -39,6 +43,7 @@ class CommentActivity : BaseActivity() { val commentEntity: CommentEntity? = intent.getParcelableExtra(COMMENT_ENTITY) ?: null val useReplyApi: Boolean = intent.getBooleanExtra(USE_REPLY_API, false) + val articleCommentId = intent.getStringExtra(EntranceUtils.KEY_ARTICLE_COMMENT_ID) mShowInputOnly = intent.getBooleanExtra(SHOW_INPUT_ONLY, false) @@ -68,16 +73,18 @@ class CommentActivity : BaseActivity() { } else if (!articleId.isNullOrEmpty()) { NewCommentFragment.getCommunityArticleCommentInstance( articleId, - communityId?:"", + communityId, showKeyboard, commentCount, mShowInputOnly, useReplyApi, commentEntity, commentCallback) + } else if (!articleCommentId.isNullOrEmpty()) { + ArticleDetailCommentFragment().with(intent.extras) } else { NewCommentFragment.getVideoCommentInstance( - videoId?:"", + videoId, showKeyboard, commentCount, isVideoAuthor, @@ -86,7 +93,7 @@ class CommentActivity : BaseActivity() { } } - supportFragmentManager.beginTransaction().replace(R.id.answerCommentPlaceholderView, commentFragment, NewCommentFragment::class.java.simpleName).commitNowAllowingStateLoss() + supportFragmentManager.beginTransaction().replace(R.id.answerCommentPlaceholderView, commentFragment!!, NewCommentFragment::class.java.simpleName).commitNowAllowingStateLoss() maskView.alpha = 0f if (videoId.isNullOrEmpty()) { @@ -158,6 +165,26 @@ class CommentActivity : BaseActivity() { return intent } + @JvmStatic + fun getArticleDetailCommentIntent(context: Context, + commentId: String, + communityId: String, + articleId: String, + showKeyboard: Boolean = false, + position: Int = -1, + entrance: String, + path: String): Intent { + val intent = Intent(context, CommentActivity::class.java) + intent.putExtra(EntranceUtils.KEY_ENTRANCE, NormalActivity.mergeEntranceAndPath(entrance, path)) + intent.putExtra(EntranceUtils.KEY_COMMUNITY_ARTICLE_ID, articleId) + intent.putExtra(EntranceUtils.KEY_COMMUNITY_ID, communityId) + intent.putExtra(EntranceUtils.KEY_POSITION, position) + intent.putExtra(EntranceUtils.KEY_ARTICLE_COMMENT_ID, commentId) + intent.putExtra(EntranceUtils.KEY_SHOW_KEYBOARD_IF_NEEDED, showKeyboard) + intent.putExtra(EntranceUtils.KEY_PATH, path) + return intent + } + @JvmStatic fun getArticleCommentIntent(context: Context, articleId: String, diff --git a/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentAdapter.kt b/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentAdapter.kt index 5a3cf695ed..f9bdc55180 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentAdapter.kt @@ -1,6 +1,7 @@ package com.gh.gamecenter.qa.comment import android.content.Context +import android.text.SpannableStringBuilder import android.text.TextUtils import android.view.View import android.view.ViewGroup @@ -14,6 +15,7 @@ import com.gh.gamecenter.adapter.viewholder.FooterViewHolder import com.gh.gamecenter.baselist.ListAdapter import com.gh.gamecenter.entity.CommentEntity import com.gh.gamecenter.gamedetail.rating.edit.RatingEditActivity +import com.gh.gamecenter.qa.article.detail.BaseArticleDetailCommentAdapter class NewCommentAdapter(context: Context, var mViewModel: NewCommentViewModel, @@ -27,7 +29,7 @@ class NewCommentAdapter(context: Context, val view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false) FooterViewHolder(view) } else { - val view = mLayoutInflater.inflate(R.layout.comment_item, parent, false) + val view = mLayoutInflater.inflate(R.layout.new_comment_item, parent, false) AnswerCommentViewHolder(view) } } @@ -55,11 +57,29 @@ class NewCommentAdapter(context: Context, val commentEntity = mEntityList[position] CommentUtils.setCommentUserView(mContext, holder, commentEntity) CommentUtils.setCommentTime(holder.commentTimeTv, commentEntity.time) + if (commentEntity.parentUser != null) { + val prefix = "回复" + val colon = " :" + val parentUserName = " ${commentEntity.parentUser?.name} " - if (!TextUtils.isEmpty(mViewModel.videoId)) { - holder.commentContentTv.setTextWithHighlightedTextWrappedInsideWrapper( - text = commentEntity.content ?: "", - copyClickedText = true) + val prefixSpan = SpanBuilder(prefix).color(holder.itemView.context, 0, prefix.length, R.color.text_999999).build() + val parentUserNameSpan = SpanBuilder(parentUserName) + .click(0, parentUserName.length, R.color.text_666666) { + DirectUtils.directToHomeActivity(holder.itemView.context, commentEntity.user.id, 1, mEntrance, "") + }.build() + val colonSpan = SpanBuilder(colon).color(holder.itemView.context, 0, colon.length, R.color.text_999999).build() + val authorSpan = if (commentEntity.parentUser?.me?.isCommentOwner == true) { + SpanBuilder("作者").image(0, "作者".length, R.drawable.ic_hint_author).build() + } else { + "" + } + + holder.commentContentTv.text = SpannableStringBuilder() + .append(prefixSpan) + .append(parentUserNameSpan) + .append(authorSpan) + .append(colonSpan) + .append(commentEntity.content) } else { holder.commentContentTv.text = commentEntity.content } @@ -69,43 +89,6 @@ class NewCommentAdapter(context: Context, return@OnLongClickListener true }) - val parentUser = commentEntity.parentUser - if (parentUser != null && !TextUtils.isEmpty(parentUser.name)) { - holder.quoteContainer.visibility = View.VISIBLE - holder.quoteAuthorTv.text = String.format("@%s", parentUser.name) - - val comment: String? - if (parentUser.active) { - comment = parentUser.comment - holder.quoteContentTv.setTextColor(mContext.resources.getColor(R.color.text_5d5d5d)) - } else { - comment = mContext.getString(R.string.comment_hide_hint) - holder.quoteContentTv.setTextColor(mContext.resources.getColor(R.color.text_d5d5d5)) - } - if (!TextUtils.isEmpty(mViewModel.videoId)) { - holder.quoteContentTv.setTextWithHighlightedTextWrappedInsideWrapper( - text = comment ?: "", - copyClickedText = true) - } else { - holder.quoteContentTv.text = comment - } - } else { - holder.quoteContainer.visibility = View.GONE - } - if (parentUser?.active == true) { - holder.quoteContentTv.setOnLongClickListener(View.OnLongClickListener { - isChildLongClick = true - parentUser.comment?.replace(RatingEditActivity.LABEL_REPLACE_REGEX.toRegex(), "")?.copyTextAndToast() - return@OnLongClickListener true - }) - } - if (parentUser?.badge != null) { - holder.quoteAuthorBadgeSdv.visibility = View.VISIBLE - ImageUtils.display(holder.quoteAuthorBadgeSdv, parentUser.badge!!.icon) - } else { - holder.quoteAuthorBadgeSdv.visibility = View.GONE - } - val key = when (mEntrance) { "(答案详情-评论列表)" -> "回答详情-评论管理" "(文章详情-评论列表)" -> "社区文章详情-评论管理" diff --git a/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumDialogFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumDialogFragment.kt new file mode 100644 index 0000000000..492b4e543b --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumDialogFragment.kt @@ -0,0 +1,74 @@ +package com.gh.gamecenter.qa.dialog + +import android.app.Dialog +import android.os.Bundle +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.FragmentTransaction +import com.gh.base.fragment.BaseDialogFragment +import com.gh.gamecenter.R +import com.gh.gamecenter.databinding.DialogChooseForumBinding +import com.gh.gamecenter.entity.CommunityEntity +import com.gh.gamecenter.forum.select.ForumSelectFragment +import com.halo.assistant.HaloApp + +class ChooseForumDialogFragment : BaseDialogFragment() { + private lateinit var binding: DialogChooseForumBinding + var onSelectCallback: ((entity: CommunityEntity) -> Unit)? = null + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + binding = DialogChooseForumBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val beginTransaction = childFragmentManager.beginTransaction() + val forumSelectFragment = childFragmentManager.findFragmentByTag(ForumSelectFragment::class.java.simpleName) as? ForumSelectFragment + ?: ForumSelectFragment() + forumSelectFragment.onSelectCallback = { + onSelectCallback?.invoke(it) + dismissAllowingStateLoss() + } + beginTransaction.replace(binding.container.id, forumSelectFragment, ForumSelectFragment::class.java.simpleName) + beginTransaction.commitAllowingStateLoss() + binding.closeIv.setOnClickListener { dismissAllowingStateLoss() } + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val createDialog = super.onCreateDialog(savedInstanceState) + createDialog.setCanceledOnTouchOutside(true) + + val window = createDialog.window + window?.setGravity(Gravity.BOTTOM) + window?.setWindowAnimations(R.style.community_publication_animation) + return createDialog + } + + override fun onStart() { + super.onStart() + val width = HaloApp.getInstance().application.resources.displayMetrics.widthPixels + val height = dialog?.window?.attributes?.height ?: ViewGroup.LayoutParams.WRAP_CONTENT + dialog?.window?.setLayout(width, height) + } + + + companion object { + fun show(activity: AppCompatActivity, onSelectCallback: ((entity: CommunityEntity) -> Unit)) { + var fragment = activity.supportFragmentManager.findFragmentByTag(ChooseForumDialogFragment::class.java.name) as? ChooseForumDialogFragment + if (fragment == null) { + fragment = ChooseForumDialogFragment() + fragment.onSelectCallback = onSelectCallback + fragment.show(activity.supportFragmentManager, ChooseForumDialogFragment::class.java.name) + } else { + fragment.onSelectCallback = onSelectCallback + val transaction: FragmentTransaction = activity.supportFragmentManager.beginTransaction() + transaction.show(fragment) + transaction.commit() + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/dialog/MoreFunctionPanelDialog.kt b/app/src/main/java/com/gh/gamecenter/qa/dialog/MoreFunctionPanelDialog.kt new file mode 100644 index 0000000000..e81cf7afa2 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/dialog/MoreFunctionPanelDialog.kt @@ -0,0 +1,193 @@ +package com.gh.gamecenter.qa.dialog + +import android.app.Dialog +import android.os.Bundle +import android.view.* +import android.widget.LinearLayout +import android.widget.TextView +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import androidx.fragment.app.FragmentTransaction +import com.gh.base.fragment.BaseDialogFragment +import com.gh.common.util.MtaHelper +import com.gh.common.util.ShareUtils +import com.gh.common.util.dip2px +import com.gh.gamecenter.R +import com.gh.gamecenter.databinding.DialogGameDetailMoreBinding +import com.gh.gamecenter.entity.MenuItemEntity +import com.halo.assistant.HaloApp + +class MoreFunctionPanelDialog : BaseDialogFragment(), View.OnTouchListener { + + private lateinit var binding: DialogGameDetailMoreBinding + private lateinit var mGestureDetector: GestureDetector + private var mInitPositionY = 0f + var menuItems: ArrayList = arrayListOf() + var title: String = "" + var shareUrl: String = "" + var shareUtils: ShareUtils? = null + var onItemClickCallback: ((menuItem: MenuItemEntity) -> Unit)? = null + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + binding = DialogGameDetailMoreBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + binding.gameNameTv.text = title + binding.gameNameTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_666666)) + binding.gameIconView.visibility = View.GONE + binding.feedbackTv.visibility = View.GONE + binding.copyrightTv.visibility = View.GONE + mGestureDetector = GestureDetector(requireContext(), SingleTapConfirm()) + binding.dragClose.setOnTouchListener(this) + binding.shareWechatTv.setOnClickListener { + shareUtils?.wechatShare() + MtaHelper.onEvent("内容分享", "微信好友", shareUtils?.title) + } + binding.sharePyquanTv.setOnClickListener { + shareUtils?.wechatMomentsShare() + MtaHelper.onEvent("内容分享", "微信朋友圈", shareUtils?.title) + } + binding.shareQqTv.setOnClickListener { + shareUtils?.qqShare() + MtaHelper.onEvent("内容分享", "QQ好友", shareUtils?.title) + } + binding.shareQqzoneTv.setOnClickListener { + shareUtils?.qZoneShare() + MtaHelper.onEvent("内容分享", "QQ空间", shareUtils?.title) + } + binding.shareWeiboTv.setOnClickListener { + shareUtils?.sinaWeiboShare() + MtaHelper.onEvent("内容分享", "新浪微博", shareUtils?.title) + } + binding.shareSmsTv.setOnClickListener { + shareUtils?.shortMessageShare() + MtaHelper.onEvent("内容分享", "短信", shareUtils?.title) + } + binding.copyLinkTv.setOnClickListener { + shareUtils?.copyLink(shareUrl) + MtaHelper.onEvent("内容分享", "复制链接", shareUtils?.title) + } + binding.cancelTv.setOnClickListener { + dismissAllowingStateLoss() + } + addActionItem() + } + + private fun addActionItem() { + menuItems.forEachIndexed { _, menuItemEntity -> + val itemView = createItemView(menuItemEntity) + itemView.setOnClickListener { + onItemClickCallback?.invoke(menuItemEntity) + dismissAllowingStateLoss() + } + binding.actionContainer.addView(itemView) + } + } + + private fun createItemView(itemEntity: MenuItemEntity): View { + val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT) + params.leftMargin = 16f.dip2px() + return TextView(requireContext()).apply { + textSize = 11f + text = itemEntity.text + setTextColor(ContextCompat.getColor(requireContext(), if (itemEntity.isEnable) R.color.text_666666 else R.color.text_999999)) + includeFontPadding = false + gravity = Gravity.CENTER + layoutParams = params + compoundDrawablePadding = 8f.dip2px() + setCompoundDrawablesWithIntrinsicBounds(null, ContextCompat.getDrawable(requireContext(), itemEntity.normalIcon), null, null) + } + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val createDialog = super.onCreateDialog(savedInstanceState) + createDialog.setCanceledOnTouchOutside(true) + + val window = createDialog.window + window?.setGravity(Gravity.BOTTOM) + window?.setWindowAnimations(R.style.community_publication_animation) + return createDialog + } + + override fun onTouch(v: View, event: MotionEvent): Boolean { + if (mGestureDetector.onTouchEvent(event) && binding.root.y == 0F) { + v.performClick() + return true + } + when (event.action) { + MotionEvent.ACTION_DOWN -> { + mInitPositionY = binding.root.y - event.rawY + } + MotionEvent.ACTION_MOVE -> { + val offsetY = event.rawY + mInitPositionY + val dialogY = binding.root.y + if (dialogY + offsetY > 0) { + binding.root.animate() + .y(offsetY) + .setDuration(0) + .start() + } else { + resetDialogPosition() + } + } + MotionEvent.ACTION_CANCEL, + MotionEvent.ACTION_UP, + MotionEvent.ACTION_OUTSIDE -> { + if (binding.root.y >= binding.root.height / 2) { + dismissAllowingStateLoss() + } else { + resetDialogPosition(300) + } + } + else -> return false + } + return true + } + + private fun resetDialogPosition(duration: Long = 0) { + binding.root.animate() + .y(0F) + .setDuration(duration) + .start() + } + + override fun onStart() { + super.onStart() + val width = HaloApp.getInstance().application.resources.displayMetrics.widthPixels + val height = dialog?.window?.attributes?.height ?: ViewGroup.LayoutParams.WRAP_CONTENT + dialog?.window?.setLayout(width, height) + } + + private class SingleTapConfirm : GestureDetector.SimpleOnGestureListener() { + override fun onSingleTapUp(event: MotionEvent): Boolean { + return true + } + } + + companion object { + @JvmStatic + fun showMoreDialog(activity: AppCompatActivity, menuItems: ArrayList, title: String, shareUtils: ShareUtils, onItemClickCallback: (menuItem: MenuItemEntity) -> Unit) { + if (menuItems.isNullOrEmpty()) return + var fragment = activity.supportFragmentManager.findFragmentByTag(MoreFunctionPanelDialog::class.java.name) as? MoreFunctionPanelDialog + if (fragment == null) { + fragment = MoreFunctionPanelDialog() + fragment.menuItems = menuItems + fragment.title = title + fragment.shareUtils = shareUtils + fragment.onItemClickCallback = onItemClickCallback + fragment.show(activity.supportFragmentManager, MoreFunctionPanelDialog::class.java.name) + } else { + fragment.menuItems = menuItems + fragment.title = title + fragment.shareUtils = shareUtils + fragment.onItemClickCallback = onItemClickCallback + val transaction: FragmentTransaction = activity.supportFragmentManager.beginTransaction() + transaction.show(fragment) + transaction.commit() + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/editor/AnswerFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/AnswerFragment.kt index ed85877375..2394e6536a 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/editor/AnswerFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/AnswerFragment.kt @@ -1,14 +1,38 @@ package com.gh.gamecenter.qa.editor +import android.os.Bundle +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.RecyclerView.ItemDecoration +import com.gh.common.util.viewModelProvider +import com.gh.common.view.CustomDividerItemDecoration +import com.gh.gamecenter.R import com.gh.gamecenter.baselist.ListFragment import com.gh.gamecenter.qa.entity.AnswerEntity class AnswerFragment : ListFragment() { private var mAdapter: AnswerAdapter? = null + private var mAnswerType: InsertAnswerWrapperActivity.AnswerType = InsertAnswerWrapperActivity.AnswerType.MINE_ANSWER + + override fun onCreate(savedInstanceState: Bundle?) { + mAnswerType = arguments?.getSerializable(InsertAnswerWrapperActivity.KEY_ANSWER_TYPE) as InsertAnswerWrapperActivity.AnswerType + super.onCreate(savedInstanceState) + } + + override fun provideListViewModel(): AnswerViewModel { + return viewModelProvider(AnswerViewModel.Factory(mAnswerType)) + } override fun provideListAdapter(): AnswerAdapter { if (mAdapter == null) mAdapter = AnswerAdapter(requireContext(), mEntrance) return mAdapter!! } + + override fun getItemDecoration(): ItemDecoration? { + val insetDivider = ContextCompat.getDrawable(requireContext(), R.drawable.divider_item_line) + val itemDecoration = CustomDividerItemDecoration(requireContext(), notDecorateTheLastItem = true) + itemDecoration.setDrawable(insetDivider!!) + return itemDecoration + } + } diff --git a/app/src/main/java/com/gh/gamecenter/qa/editor/AnswerViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/AnswerViewModel.kt index d58b92526a..640d2b2139 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/editor/AnswerViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/AnswerViewModel.kt @@ -2,16 +2,29 @@ package com.gh.gamecenter.qa.editor import android.app.Application import androidx.annotation.Keep +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider import com.gh.gamecenter.baselist.ListViewModel +import com.gh.gamecenter.entity.UserEntity import com.gh.gamecenter.manager.UserManager import com.gh.gamecenter.qa.entity.AnswerEntity import com.gh.gamecenter.retrofit.RetrofitManager +import com.halo.assistant.HaloApp +import com.lightgame.utils.Utils import io.reactivex.Observable @Keep -class AnswerViewModel(application: Application) : ListViewModel(application) { +class AnswerViewModel(application: Application, private val answerType: InsertAnswerWrapperActivity.AnswerType) : ListViewModel(application) { + + override fun provideDataObservable(page: Int): Observable> { - return RetrofitManager.getInstance(getApplication()).api.getCollectionAnswer(UserManager.getInstance().userId, page) + + return if (answerType == InsertAnswerWrapperActivity.AnswerType.MINE_ANSWER) { + RetrofitManager.getInstance(getApplication()).api.getMyAnswers(UserManager.getInstance().userId, page, + HaloApp.getInstance().channel, Utils.getTime(getApplication())) + } else { + RetrofitManager.getInstance(getApplication()).api.getCollectionAnswer(UserManager.getInstance().userId, page) + } } override fun mergeResultLiveData() { @@ -28,6 +41,20 @@ class AnswerViewModel(application: Application) : ListViewModel create(modelClass: Class): T { + return AnswerViewModel(HaloApp.getInstance().application, answerType) as T + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleFragment.kt index d09f452741..db2ab8784a 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleFragment.kt @@ -1,14 +1,37 @@ package com.gh.gamecenter.qa.editor +import android.os.Bundle +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.RecyclerView +import com.gh.common.util.viewModelProvider +import com.gh.common.view.CustomDividerItemDecoration +import com.gh.gamecenter.R import com.gh.gamecenter.baselist.ListFragment import com.gh.gamecenter.qa.entity.ArticleEntity class ArticleFragment : ListFragment() { private var mAdapter: ArticleAdapter? = null + private var mArticleType: InsertArticleWrapperActivity.ArticleType = InsertArticleWrapperActivity.ArticleType.MINE_ARTICLE + + override fun onCreate(savedInstanceState: Bundle?) { + mArticleType = arguments?.getSerializable(InsertArticleWrapperActivity.KEY_ARTICLE_TYPE) as InsertArticleWrapperActivity.ArticleType + super.onCreate(savedInstanceState) + } + + override fun provideListViewModel(): ArticleViewModel { + return viewModelProvider(ArticleViewModel.Factory(mArticleType)) + } override fun provideListAdapter(): ArticleAdapter { - if (mAdapter == null) mAdapter = ArticleAdapter(context!!, mEntrance) + if (mAdapter == null) mAdapter = ArticleAdapter(requireContext(), mEntrance) return mAdapter!! } + + override fun getItemDecoration(): RecyclerView.ItemDecoration? { + val insetDivider = ContextCompat.getDrawable(requireContext(), R.drawable.divider_item_line) + val itemDecoration = CustomDividerItemDecoration(requireContext(), notDecorateTheLastItem = true) + itemDecoration.setDrawable(insetDivider!!) + return itemDecoration + } } diff --git a/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleViewModel.kt index d0346d0927..9e6b96ad31 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleViewModel.kt @@ -2,17 +2,24 @@ package com.gh.gamecenter.qa.editor import android.app.Application import androidx.annotation.Keep +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider import com.gh.gamecenter.baselist.ListViewModel import com.gh.gamecenter.manager.UserManager import com.gh.gamecenter.qa.entity.ArticleEntity import com.gh.gamecenter.retrofit.RetrofitManager +import com.halo.assistant.HaloApp import io.reactivex.Observable @Keep -class ArticleViewModel(application: Application) : ListViewModel(application) { +class ArticleViewModel(application: Application, private val articleType: InsertArticleWrapperActivity.ArticleType) : ListViewModel(application) { override fun provideDataObservable(page: Int): Observable> { - return RetrofitManager.getInstance(getApplication()).api.getCollectionCommunityArticle(UserManager.getInstance().userId, page) + return if (articleType == InsertArticleWrapperActivity.ArticleType.MINE_ARTICLE) { + RetrofitManager.getInstance(HaloApp.getInstance().application).api.getMyArticle(UserManager.getInstance().userId, page) + } else { + RetrofitManager.getInstance(getApplication()).api.getCollectionCommunityArticle(UserManager.getInstance().userId, page) + } } override fun mergeResultLiveData() { @@ -32,4 +39,10 @@ class ArticleViewModel(application: Application) : ListViewModel create(modelClass: Class): T { + return ArticleViewModel(HaloApp.getInstance().application, articleType) as T + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/editor/InsertAnswerWrapperActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/InsertAnswerWrapperActivity.kt index 34b8de4b63..05ebef7ec4 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/editor/InsertAnswerWrapperActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/InsertAnswerWrapperActivity.kt @@ -3,37 +3,35 @@ package com.gh.gamecenter.qa.editor import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import com.gh.base.BaseActivity_TabLayout +import com.gh.gamecenter.R class InsertAnswerWrapperActivity : BaseActivity_TabLayout() { - private lateinit var mFragment: LinkFragment - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setNavigationTitle("插入回答") - } + override fun getLayoutId(): Int = R.layout.activity_tablayout_no_title_viewpager override fun initFragmentList(fragments: MutableList?) { - mFragment = LinkFragment() - fragments?.add(mFragment) - fragments?.add(AnswerFragment()) + fragments?.add(AnswerFragment().with(bundleOf(KEY_ANSWER_TYPE to AnswerType.MINE_ANSWER))) + fragments?.add(AnswerFragment().with(bundleOf(KEY_ANSWER_TYPE to AnswerType.COLLECTION_ANSWER))) } override fun initTabTitleList(tabTitleList: MutableList?) { - tabTitleList?.add("输入链接") + tabTitleList?.add("我的回答") tabTitleList?.add("收藏回答") } - override fun onPageSelected(position: Int) { - super.onPageSelected(position) - mFragment.onPageChanged(position) - } - companion object { + const val KEY_ANSWER_TYPE = "AnswerType" + fun getIntent(context: Context): Intent { return Intent(context, InsertAnswerWrapperActivity::class.java) } } + + enum class AnswerType { + MINE_ANSWER, + COLLECTION_ANSWER + } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/editor/InsertArticleWrapperActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/InsertArticleWrapperActivity.kt index 6a7af842fa..44cfdce631 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/editor/InsertArticleWrapperActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/InsertArticleWrapperActivity.kt @@ -3,37 +3,36 @@ package com.gh.gamecenter.qa.editor import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import com.gh.base.BaseActivity_TabLayout +import com.gh.gamecenter.R class InsertArticleWrapperActivity : BaseActivity_TabLayout() { - private lateinit var mFragment: LinkFragment + override fun getLayoutId(): Int = R.layout.activity_tablayout_no_title_viewpager - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setNavigationTitle("插入帖子") - } - - override fun initFragmentList(fragments: MutableList?) { - mFragment = LinkFragment() - fragments?.add(mFragment) - fragments?.add(ArticleFragment()) + override fun initFragmentList(fragments: MutableList?) { + fragments?.add(ArticleFragment().with(bundleOf(KEY_ARTICLE_TYPE to ArticleType.MINE_ARTICLE))) + fragments?.add(ArticleFragment().with(bundleOf(KEY_ARTICLE_TYPE to ArticleType.COLLECTION_ARTICLE))) } override fun initTabTitleList(tabTitleList: MutableList?) { - tabTitleList?.add("输入链接") + tabTitleList?.add("我的帖子") tabTitleList?.add("收藏帖子") } - override fun onPageSelected(position: Int) { - super.onPageSelected(position) - mFragment.onPageChanged(position) - } companion object { + const val KEY_ARTICLE_TYPE = "ArticleType" + fun getIntent(context: Context): Intent { return Intent(context, InsertArticleWrapperActivity::class.java) } } + + enum class ArticleType { + MINE_ARTICLE, + COLLECTION_ARTICLE + } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/detail/AnswerViewHolder.java b/app/src/main/java/com/gh/gamecenter/qa/questions/detail/AnswerViewHolder.java index 7aa2d3edf7..fcd491ca7a 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/questions/detail/AnswerViewHolder.java +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/detail/AnswerViewHolder.java @@ -127,10 +127,10 @@ public class AnswerViewHolder extends BaseRecyclerViewHolder { mContent.setText(entity.getBrief()); mQuestionTitle.setVisibility(View.VISIBLE); mQuestionTitle.setText(entity.getQuestions().getTitle()); - mVotecount.setText(mVotecount.getContext().getString(R.string.ask_vote_count, NumberUtils.transSimpleCount(entity.getVote()))); - // 3.6.3 产品说把右下角的社区名字换成时间, 评论隐藏掉 + String commentText = String.format("%s评论 · %s点赞 · %s", NumberUtils.transSimpleCount(entity.getCommentCount()), NumberUtils.transSimpleCount(entity.getVote()), NewsUtils.getFormattedTime(entity.getTime())); + mVotecount.setText(commentText); mCommunityName.setVisibility(View.VISIBLE); - mCommunityName.setText(NewsUtils.getFormattedTime(entity.getTime())); + mCommunityName.setText(entity.getCommunityName()); mCommentCount.setVisibility(View.GONE); // mCommentCount.setText(String.format("%s 评论", NumberUtils.transSimpleCount(entity.getCommentCount()))); // mCommunityName.setText(entity.getCommunityName()); 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 index ad7cbd6075..f54168b096 100644 --- 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 @@ -4,7 +4,6 @@ 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 @@ -14,15 +13,14 @@ import android.view.View import android.view.Window import android.widget.ImageView import android.widget.LinearLayout -import android.widget.PopupWindow import android.widget.TextView +import androidx.appcompat.app.AppCompatActivity 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.ToolBarActivity import com.gh.base.fragment.BaseDialogWrapperFragment import com.gh.base.fragment.BaseFragment import com.gh.common.TimeElapsedHelper @@ -46,6 +44,7 @@ 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.dialog.MoreFunctionPanelDialog import com.gh.gamecenter.qa.entity.AnswerDraftEntity import com.gh.gamecenter.qa.entity.Questions import com.gh.gamecenter.qa.entity.QuestionsDetailEntity @@ -418,88 +417,55 @@ class QuestionsDetailFragment : private fun showMoreItemDialog() { if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) { mQuestionsDetailEntity?.let { questionEntity -> - val view = LayoutInflater.from(context).inflate(R.layout.menu_answer_detail_more_new, null) - val popupWindow = PopupWindow( - view, - LinearLayout.LayoutParams.WRAP_CONTENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ) - popupWindow.apply { - setBackgroundDrawable(ColorDrawable(0)) - isTouchable = true - isFocusable = true - isOutsideTouchable = true - } - view.measure(0, 0) - val viewWidth = view.measuredWidth - popupWindow.showAsDropDown((activity as ToolBarActivity).menu.getItem(2).actionView, -viewWidth - 10, 10) - val container = view.findViewById(R.id.container) val entities = ArrayList() - entities.add(MenuItemEntity("首页", R.drawable.menu_more_home)) if (questionEntity.user.id != UserManager.getInstance().userId) { - entities.add(MenuItemEntity("投诉", R.drawable.ic_menu_gamedetail_feedback)) + entities.add(MenuItemEntity("投诉", R.drawable.icon_gamedetail_copyright)) } if (questionEntity.me.isModerator) { - entities.add(MenuItemEntity("编辑", R.drawable.menu_more_edit)) + entities.add(MenuItemEntity("编辑", R.drawable.icon_more_panel_edit)) } - entities.add(MenuItemEntity("分享", R.drawable.icon_share_gray)) if (questionEntity.me.isModerator || questionEntity.user.id == UserManager.getInstance().userId) { - entities.add(MenuItemEntity("删除", R.drawable.menu_more_delete)) + entities.add(MenuItemEntity("删除", R.drawable.icon_more_panel_delete)) } + val shareIcon = if (questionEntity.images.isNotEmpty()) { + questionEntity.images[0] + } else { + getString(R.string.share_ghzs_logo) + } + var description = questionEntity.description + if (TextUtils.isEmpty(description)) { + description = getString(R.string.ask_share_default_summary) + } + val shareUrl = if (isPublishEnv()) { + getString(R.string.share_questions_url, questionEntity.id) + } else { + getString(R.string.share_questions_url_dev, questionEntity.id) + } + val shareUtils = ShareUtils.getInstance(activity) + shareUtils.shareParamsDetail( + activity, + shareUrl, + shareIcon, + getString(R.string.ask_share_questions_title, questionEntity.title, questionEntity.answersCount), + description, + ShareUtils.ShareEntrance.askNormal, + questionEntity.id, null) + MoreFunctionPanelDialog.showMoreDialog(requireActivity() as AppCompatActivity, entities, questionEntity.title + ?: "",shareUtils) { + when (it.text) { + "投诉" -> { + SuggestionActivity.startSuggestionActivity(context, SuggestType.normal, "report", + "问题投诉(" + questionEntity.id + "):") + } + "编辑" -> { + val intent = QuestionEditActivity.getManagerIntent(requireContext(), mQuestionsDetailEntity!!) + startActivityForResult(intent, QUESTIONS_EDIT_REQUEST) + } - entities.forEachIndexed { index, item -> - val menuItem = createMenuItem(index, item) - container.addView(menuItem) - menuItem.setOnClickListener { - popupWindow.dismiss() - when (item.text) { - "首页" -> { - DirectUtils.directToCommunity(requireContext(), questionEntity.community) - MtaHelper.onEvent("回到首页", "问题详情", questionEntity.community.name + "+" + StringUtils.combineTwoString(questionEntity.title, questionEntity.id)) - } - "投诉" -> { - SuggestionActivity.startSuggestionActivity(context, SuggestType.normal, "report", - "问题投诉(" + questionEntity.id + "):") - } - "编辑" -> { - val intent = QuestionEditActivity.getManagerIntent(requireContext(), mQuestionsDetailEntity!!) - startActivityForResult(intent, QUESTIONS_EDIT_REQUEST) - } - "分享" -> { -// GdtHelper.logAction(ActionType.SHARE, -// GdtHelper.CONTENT_TYPE, "QUESTION", -// GdtHelper.CONTENT_ID, mQuestionsId) - - popupWindow.dismiss() - val shareIcon = if (questionEntity.images.isNotEmpty()) { - questionEntity.images[0] - } else { - getString(R.string.share_ghzs_logo) - } - var description = questionEntity.description - if (TextUtils.isEmpty(description)) { - description = getString(R.string.ask_share_default_summary) - } - val shareUrl = if (isPublishEnv()) { - getString(R.string.share_questions_url, questionEntity.id) - } else { - getString(R.string.share_questions_url_dev, questionEntity.id) - } - ShareUtils.getInstance(activity).showShareWindows( - activity, - view, - shareUrl, - shareIcon, - getString(R.string.ask_share_questions_title, questionEntity.title, questionEntity.answersCount), - description, - ShareUtils.ShareEntrance.askNormal, - questionEntity.id) - } - "删除" -> { - DialogUtils.showNewAlertDialog(requireContext(), "提示", "删除问题后,其中的所有回答都将被删除", "取消", "删除", {}, { - mListViewModel.moderatorsHideQuestion() - }) - } + "删除" -> { + DialogUtils.showNewAlertDialog(requireContext(), "提示", "删除问题后,其中的所有回答都将被删除", "取消", "删除", {}, { + mListViewModel.moderatorsHideQuestion() + }) } } } diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditActivity.kt index e8a6f3a2f8..c61d2b148c 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditActivity.kt @@ -42,6 +42,7 @@ import com.gh.gamecenter.entity.Permissions import com.gh.gamecenter.mvvm.Status import com.gh.gamecenter.qa.article.edit.ArticleSelectGameAdapter import com.gh.gamecenter.qa.article.edit.ArticleTagsSelectFragment +import com.gh.gamecenter.qa.dialog.ChooseForumDialogFragment import com.gh.gamecenter.qa.editor.VideoActivity import com.gh.gamecenter.qa.entity.CommunityVideoEntity import com.gh.gamecenter.qa.entity.QuestionsDetailEntity @@ -144,7 +145,6 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { searchKey = searchKey.substring(0, QuestionEditViewModel.QUESTION_TITLE_MAX_LENGTH) if (mViewModel.title.isNullOrEmpty()) mViewModel.title = searchKey mViewModel.isFromSearch = intent.getBooleanExtra(QuestionEditViewModel.QUESTION_FORM_SEARCH, false) - if (communityEntity == null) showSelectGameDialog() } if (communityEntity != null) { @@ -229,7 +229,10 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { mBinding.suggestPicRv.addItemDecoration(SpacingItemDecoration(bottom = DisplayUtils.dip2px(10f))) mBinding.suggestPicRv.adapter = picAdapter initEditorInsertContainer() - + // 增加提问时, 如果searchKey不为空 光标跳到最后 + mBaseHandler.postDelayed({ + mBinding.questionseditTitle.setSelection(mBinding.questionseditTitle.text.toString().length) + }, 50) observeData() } @@ -327,10 +330,9 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { picAdapter.notifyDataSetChanged() }) - // 增加提问时, 如果searchKey不为空 光标跳到最后 - mBaseHandler.postDelayed({ - mBinding.questionseditTitle.setSelection(mBinding.questionseditTitle.text.toString().length) - }, 50) + mViewModel.notSelectForum.observe(this, Observer { + if (it) showSelectGameDialog() + }) } private fun changeAddLabel(isLabelContainerShow: Boolean) { @@ -457,18 +459,8 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { } private fun showSelectGameDialog() { - val selectGameDialog = Dialog(this) - val view = View.inflate(this, R.layout.dialog_article_game, null) - val recyclerView = view.findViewById(R.id.dialog_game_list) - val back = view.findViewById(R.id.dialog_back) - val loading = view.findViewById(R.id.dialog_loading) - - back.setOnClickListener { - selectGameDialog.cancel() - } - recyclerView.layoutManager = GridLayoutManager(this, 4) - recyclerView.adapter = ArticleSelectGameAdapter(this, loading) { - mViewModel.communityEntity = CommunityEntity(it.id, it.name, icon = it.game.icon, iconSubscript = it.game.iconSubscript) + ChooseForumDialogFragment.show(this) { + mViewModel.communityEntity = it if (mViewModel.questionEntity != null) { mViewModel.questionEntity?.community?.id = it.id mViewModel.questionEntity?.community?.name = it.name @@ -476,13 +468,7 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { setForumName() if (!mViewModel.isFromSearch) mViewModel.checkQuestionDraft() mBinding.vm = mViewModel - selectGameDialog.cancel() } - - selectGameDialog.requestWindowFeature(Window.FEATURE_NO_TITLE) - selectGameDialog.setCanceledOnTouchOutside(false) - selectGameDialog.setContentView(view) - selectGameDialog.show() } // Limits of EditText diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditViewModel.kt index 45160ee519..37cfee9710 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditViewModel.kt @@ -49,6 +49,7 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica val postLiveData = MediatorLiveData>() val moderatorPostLiveData = MediatorLiveData>() val videoLiveData = MutableLiveData() + val notSelectForum = MutableLiveData() var uploadImageSubscription: Disposable? = null @@ -105,11 +106,6 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica * 根据问题标题获取相应标签(问题编辑无需获取) */ fun checkTitleAndLoadTitleTag(): Boolean { - if (TextUtils.isEmpty(communityEntity?.id) || TextUtils.isEmpty(communityEntity?.name)) { - Utils.toast(getApplication(), "论坛不能为空") - return false - } - if (TextUtils.isEmpty(title)) { Utils.toast(getApplication(), "标题不能为空") return false @@ -122,6 +118,11 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica Utils.toast(getApplication(), "标题至少${QUESTION_TITLE_MIN_LENGTH}个字") return false } + if (TextUtils.isEmpty(communityEntity?.id) || TextUtils.isEmpty(communityEntity?.name)) { + Utils.toast(getApplication(), "论坛不能为空") + notSelectForum.postValue(true) + return false + } // 检查标题结尾是否存在问号,没则主动加上 if (title!!.length <= QUESTION_TITLE_MAX_LENGTH) { diff --git a/app/src/main/res/drawable-xxhdpi/ic_article_detail_star_bottom_bar.png b/app/src/main/res/drawable-xxhdpi/ic_article_detail_star_bottom_bar.png new file mode 100644 index 0000000000000000000000000000000000000000..509d7429cf4a111b8a0665042d76827bf8703984 GIT binary patch literal 2712 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

G)XsweN(Ek4Zdk}aFalTb>4{Se!4mYN! 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/icon_more_panel_close_comment_unenable.png b/app/src/main/res/drawable-xxhdpi/icon_more_panel_close_comment_unenable.png new file mode 100644 index 0000000000000000000000000000000000000000..4941b41334c3fa9428e0d74089ba96633c7fe65c GIT binary patch literal 3997 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 D!E9RD literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/icon_more_panel_delete.png b/app/src/main/res/drawable-xxhdpi/icon_more_panel_delete.png new file mode 100644 index 0000000000000000000000000000000000000000..60bdc0689da05a8819bbd9e976627779ba7688f9 GIT binary patch literal 3509 zcmV;m4NCHfP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91ke~wq1ONa40RR91kN^Mx06#wphyVZ$A4x<(RCodHUGIxj*BL%DJC4TP z*&SROHYO%o6Sp86t;Qm>MvCHa&;z)$f@5b;wB(m*g(3N4hj zY8w$rYcw$;bWMyVCT2-l+1=SSy6(>Qd2Y{H?#$e~b7$tx%sq471BY|(`T4%j`^LL;$SM38bsbYh|r7U9MT-lvn>?Kx}kv6EQBrqrvlO` zoL|TBC@>ubrkDEq`aVKlu~mwtnmy3W%*^V!xw$K#1|t9* zy@K*o*PZ~L@8kGXCX+ed-Q9gFxR-cxn?fKcwqj~(ilo_x_%zPbB#DXmwZtR6^iqNV zJdh%(Oa$KaL?;oC_V)H3$NAlo1~Ht(N+1Z{Qz#VnBYholfbw;9buAJn26?56hzJ-G z&Ckz!EkK?z#Dlq9?g-N9h}~4J77KwOYzD-64e6VR{q!)55VWcQQla?>kWBPWjIhZ# z;sFrpZKQLJj^40^F;xviu)`2!NQl#@IhxzvPb7?V8TNVwQ`^}_My;Db5GD)qyoJGE z#c>J?Ht{%(SfYh(NhEA+XfLkD4}nB);F!C+nnPU#nwXgQK1Mo*xRqXq>l_L8A;9$! zr!|BNhqJ&!ffd)2h4N+7Oz=-SYcc%Eu#c1SsQXb7{|ApN4+ znrKM^>D|^vcph)f(;@hX8W9j6iMX&v)h$cy&O+BfXw19f$Aml)(C)x0W?@YZXf6b5 z8A>31k#MW5c>-~BB2(LbtL8$W&Vf@H8VrMVXW)HOLZCq0oXOOS>IG0?XV7hr3J(P0 zWUy#Hj8w?u3{Aonr2`=sG$$&q-&7EYch%9|kX-8t2i3I_&4nS&jS}@srZ6zA2h-OL zxT}7dx=L_z{zOk@?gi)SH5R0IrHkZww2K|L6?q0|!u{0NXc8Mq@MkRKH} zj)Z`o#s;~7UKgo_R1yTr5FmHBjpxUm%8KMv5Lg-k&6!?aJmi zjp65f>xvh}IvtTacfM1fT)C>QUb~@g-=0v@Gk5rCLS1TeE8Ek(QmtB*R~y!^RZni* zpjNJYpsv1bZIr?nI2QO8hPlIPt0Gb4{^0z_>dd(h)xCRleNVFL5X+Zm)y^GHsqNb~ zSFLM%1>8vWK8@!Dfr`Zi^~XQ|U0wOlXDzYY#veSce*Mdz;z!xJw}=dZoLB?>?ey7} zk%tT=Q8}gyq2mek#g|{J^A|6-+?E`ZV|RM!cmn<7?7!P)!*-6{Dy2Jm7gm^_Q8&N( zCJ@Wj0}ra7j|{7akal&|_dA-OFRE|GzEyucbynR%S{^tyWytk(mlt)+d40%PqW+gR zga0av27O`guhb(C57bQ_LO|lN5B3#Ck}w%8fv~EW9Zewq`h&s~kFQlLRxA%Hsw(2DWAjqvvrY*rcm91agHuw&`gNfw(qsCD^2^HESR)EE!x`MBDOXv1S)$ z3!tvZX?9`OOku7V#x^~LK(<*dVe$%r5@rzF#1R77X0e3HD+EfIL2MJpnr(a#uzU)T zPXm7Y-*NTe_ximj4EdyClwf1qD0;QJjnw<3GLjMG1KbEXl5#`&!}9$Aht&zoPeNP23`sh+ zmOx1Y(PdeLKrUN92Hk}~F@WfD7eXMHtsjH#LZBExbh!&5kjvJOL3bfg3?RDPg%HSP z>&KwG5GV!^UG72%Da%}ZO^^F*T58uD^!ZUSs(Ma36225}xCp}Pt?O~m0LLlo*mMnpVK*_R)b$EbHGEf%EMA?Eum@Ywe zla^=gg+%^p*F5r2;QxW~%NxIY=S0%54wQ#FhzAOUrumsa(O+(D{z%Om!FC<2ox*6+ z#~yuHZQC-`JnJ^OXUa|;Yz|fvh`|4B_psvMY}*znGiA3uSo?vga^OEW|FJrA?n8C& z-fVeMqRy8u&#Ij}o>JSlZBCS2wF+ZCFx4>xA^>;pe5XFSa#dZuc0=91J)x#?O=w|Z zp;l~St)EJzR1f|kan-84+OU4DdUE3iwQ}VHv5wJ>&N`An?Euo%F%5yNUjw;nz@+Fc z1WJk}ER{nDWU1kjBDN4HDVDHQ4k3`GhD(arX>2o-ec>c2NQoR32#`DUK!tW+E2)r7 zG7^t~=1d`tgF@n^6#)~80J%dCG$kG=k@iWnP?|GSTmxNCw4@?jVi6#BGGNkZVkH#8 z5{rQLK%;2{Ay8t?lx)GsoiuKWU80!0IVM36h=PFO3b~VlD@spJPL6|3`L3?6DD9<= z;|R>p&(q;d^!4@ia}ixcJfr6{$DtARqaZ-8fHUutJLXo#DP{_ZqQK{N9Uo6l5ebh# znM~#nWRnocZE{4>o*W@pz?tKV1nTbYzJ-&MoZBP_0!tyFIdW2S=Kmf@H#o{vywFnc zxn1VthQ}46kus2=aK+Tr)OEP00ojciR3!ByK<@*djP>^Rt^-f*vdk=^Ij`MCJjgx1 zk7@q)a_leyZPFUj52Lw-dKN;wy&mDRRXaCu<$*&vHj?@D4wVqr1qBUX^YQ??WfJ7XcD@J4r)9x zG4UKa|2@jGvak+9$lg3NZPD{YB@eZ&i9l>nC=_jEU-QY(3=ZQbqz1j^#Z>s#pK zRUD@{rHMBpq{$ETIwTJ4#ScjGBHxyZKMrf zA&!MW1_lV)10r#||2pCT^UXqAyplnwH7QBMXx6B}e+=;;h;sz#;`2O>N)s!Aj4%+K zkH_x8`98#_anAS8ys3>TJ(Ps_5imEu4S9ey=c<#4M=@0$$GP_yYMdiCg+P7*XJ%$r zW5M<;@0!eU<61IhVoR`o&cU_aD0-l-k7&1bXn|4(+T947z%gc z4*zC&piTI-3_{UCPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91ke~wq1ONa40RR91kN^Mx06#wphyVZ$MM*?KRCodHo!xI7R~g1<*BcYb zUVDp0WGte@q0~{p7#sgO%%6`-{4MTS$F6cU8sJmJn>*Esp zD*zqc1J$ugU4)+Juzn_&%bo1&>$~G$N<4cL0SJa|Tv%8jGzYQl#demE=mo!)cv>%| zR44!s#=?d$33SqCSE_DT^U z70?hpc<{i@0eJ3WIg-!k-#~mXWHAks#R3o-n*%s6A$}Fh5IqbRG_+v@Bth~D5GHyj zF6fhaEQbNo>xfrct-a+Q#!xkdh8;sg#s!>KyCd2BUXW1JW%Snz7}_qhQft!yp)tLH z=QULRBGxmQu!+ZMr6<~$mmuN9hW*9a_)$Rg3f6gc7dbQqP_bCthMG=b*-5X%d5#40 z6yW@b!y3XxEC&jO!u6MxT z&Zpsdo&~YLAv`idQg)E&Di1YeNHs`Oc3}*;^>QmlaCrE(KJd_Og%J z*I}&-HH48$7K|k;^PRBLnwd@wXR8>}p2M8z?M7BK1c-AUx;7Lfo~MzTU2>dfXb8(V zLHc&1IZ<7J)Y;Z0cpi7o(14gLv%onJGV`wZ34tes+Fh7LPprv+ zV!_wSK!DUm!kseb@zu?WovQD5Di(Zg_8r2IVG7iphxf?{K)$+Jvr|o~*MPz2Kw3YB zuN!bzLo#$#=w$td8p`G|jBN!U>(3KacpwnQhr!(Ed8}7V1gKDeH_gcg8Sx%i_dqzv z$57`$*RXgWuSBx06;NL2F1*kvIB_43UH3qMXFnhsCTS8x0Y3$l7aArj`nZ>tgWL(S z^f8G=feHmYY`CoOpi7H-_2w1`W2nd^8=`<$0i4eBA+%MTnQi7PLoO}2@9_+VFZb0O zZ(>;&1*#RG7a}WQ#vR7AyP4(zkBh3#C)=WctAK}-Y3|69CM>%I9w8*G0%Qfu>?S+z zyXweT5P-tUC+QR`1@)bS>;xr|$+LhFRsqcl;)yIK)MH^YN;*-%s{q-_!5s-eUR7j0 zlmcoP8{-6eG*k{rBnnh1Kz4W<&yPD*9gOhSg%No0$jgw z%lY_U^UkKv3_07jZjQ0!^b{okCD0dqcKFo0zjLmB^#2cjjqiBG`R-GD6R54TMamEs zv;KtV#4q2gfQMCFzVeYnkJN2J0E)3kH9Xg@-}Eh&!&$cl0Vt*(Z3GXi;asTOf&dgl zkA{I~`y<=Baw07NwFpoccpl!i#o71tw_2O6JA=>It?^Z6 z{g`44dbU05+|Aq0m8;jBo44*b<$H_H^78#iZOHfcIpbd(bG|Y4HFR*a-xBNk@lQ@T z#Uj4~7cKPmZg5!lmdzv1j_nUSqgy@~t$-Ay#?y%I_oa;l=#zh!oL{~7dl#HIw0!LA zlg{++M?)7y&vWd}x0-^-uM&dv)RW(IKK;<3-{Dm5(*Q;L*`>ggf8743^X5?BTPIsf4#x?X4pJi2}kXFNGDB^Yxv z^~2d~zMAsvX*U4)GQ0?Zh&zOVhu3+coT~GT@z0odoxAWp&SX|=n#?mxQ_jqc0f@g$ zzd(2%hZjjABmocGNziqh&z}2JP1A#Htx1@I9mWh{{MGsedY&XgQt)`&8r1e6TfKSH zvTh7OK^F;48Mgd7JgDtKw)&OP>3zlk)Gndg;d$C+OFQZjfIKP-JRUJZt_na(D1j#= zF;&R~AP6GxR8bLO(|Ujeo(Qz~B()kKfyal4h`X!>NZ^S`NMq^dk)5*3iXp61;@VKJ0AxciCupMpl%Tja z6fFSR(8~$hC;%lWt_?*CKsNMpf;L)l8c+TBw&&mee$%-Z@P=z#8u#P1u5bzOrl3V zyU989!{_8IECJN40EoKrTRf8!I}(u4?jo(21KHih$yzS}C97}Omo5NxeHSNdpfLdP z4@&%kNgt%FZhuhQgKVwNpN4H?01EmbCBL_9Y6xn3kgaL7)0nd`{-e$OC&d~K`LS+> zq&_rWQ(+7{=y~*q#{G(;t)>KH0OJ2@U7ER4qbpxq=Eu7IKGbCWBI3S?Yt$yI@=j&8*MZx7zGgj(eL~FzSETu5gyuR(!UlG zbotB66#U#dY?=C(mqr4l`@GdZ-PPr^JC;A)ZMWi5U+NSv_D^?Hr=;Z#GHMcSd0(Z{ zd;utx-C|Co1R!(zDwQo2fKu5l<}@ms$z+zzX|A+1O$v}5dZ6;!+FF|0C2cW40mV!? zifh)?EN~L+wROspH36o#aSgrv7dkydu z2L}g-IEh}xa$b#TmP;e%hf#p6fSGe-N8idg!<_wVvb5C|;oH8NTf z9Nf6DurLSrG%ROhS`~@C3efw2le+^01Eb(%iO2LLn&a9MmLojJ_mJkzFY6X7Kqklr z8PV`ij&%>j4J7J^7rKE2L*j*~hy<;G@;>wMK3l=ZJ-vV3191lrU^y&aNXsKJ74UeU z!(MoJtil7S#5r7cn&s>`~zU{rfcbGOj#N0-zPI5@k;-rY1(aBj1iKVa@RVTnfgpIONFYEw zSSS>(<8*!>R+j}LDq=@aeZ9=SCj<4Yt_u(|=JWZp@IudHbyX(S^`z{MW2%pNWBqyd zeIu(H0>lD9;oERyhfwIMc%nv52&s?=EmbxXjxVL06c= zw!CG4SP>eQ!`$d4#IIr*5|F~m-=1_{aPZ@v$8s3M)$52`zCs)eKw1Vgv>zbxbpK^6 z!`!bY+TxY8O6`dW4HrE}h5mQ39053QAYOl-r`6WP3XpCL8qUXK_hb7Ymc7{K`)BUZ z#+V*TLi`Hoo8KB9Xw9+eG?wESs!n3teGE0uniB!Y+rY)e#SzT(pTWLq7`6*>K_4ef z4ArqdF0sD?1caeFR;i27^E}p1^VJ*u_JleXdz3gp-WJ2)9^B#o3OvvRel24#bPW4O zk!AqvdBk~a_j>cldZhx;iDygvsvJKIwt($9tn(`wv(R(~cg{b+K6jQ}nKPNK{{rPu V=N)|KIxqkL002ovPDHLkV1l>ygy;YO literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/icon_more_panel_essence.png b/app/src/main/res/drawable-xxhdpi/icon_more_panel_essence.png new file mode 100644 index 0000000000000000000000000000000000000000..a9cb83d527f99e101c2401cf03c95fadbee466ea GIT binary patch literal 3722 zcmYLMc{tR4_x{c>j6q}>Wu0fTl{IBIOc`VwYh%kYMh1~xDl}x9%GN6Dkag^ZP>h`@ zvJZKTeUD_TBtN~s>w4cm?$3SBxzBZ-|IWETWOJ+mCrl6q005`q6^!LEC;tVM<@jCF zpRGG4P@tv3WuUxIc;z_3T(>oJH#G&$9mh}r6z2&r|7|&j;4uJzi2?$cjv4f~Mgjj< zO{OsYFaF!8qXUaS9=cFrVAVguU<`fYXf(~s_N93Fpg zW6aLFnjuq`FVXK@{3qd%?>ArK7a_X%95o6X=n*8Uu`sjbrxkhV@1b$R)ZoI)j}p;x zDpUfwQYI}kGu$I0B0^zxoSb+wj*-8HF(`9a=I8SyUhSINR8a)leFt9NeQC zn&w-E-01`C^OR>szm}!ZH!#W5#PeBqD^>1jUReWYnzen`Vs~XAwUn+yQq&tf&p+=G z?d9ltP7uzkX#%z0S-Ne#r^z?f2kYoC2HiFJqTVTdgVwmM9Ft-Me_OdUl z4}L!X5PBn5_1tbQ5`As^b9D})O6%G1BSWqJ&(n*3QPuAT(~4x#d*h=}*`%69GFf|& zQw+w9lrK%GrcI99eNg6B+AjaG22SFtA*5myNg*W9+dL$kG zEoP$%72QrT2NUt(JmBPGf!9NU`hwJ|Qt?Gp4-TEK#t(#XG&K(?r9Rz|=7ic+zLai= zuwv%kq`s0Cwpo_XM)zt@QyXanIU-UW46hpNOnE2D`2Ekbd__t$5=a);ER452VSmSr85y z%mX*QFHuF=*h;q;B!jV#ZmiJ96ky(3Z!i3;ix~lR4PCMSOqYiYmWOnoFq`}7FJ<#o z_yKr;T<~~{O!a#f367`VKHk5%Zov@w4R3nmHnnL7e7`UojMWXD z3cu%8Z{0`>JQ!V2vasx7x}6K*_TjNymYtqwc#}K4C^Y(U*zx;s1Z}Y-B%OZtJT1VQQ{n!mZli**8L~t6kaD zer;NDsQv}jTVtmkUmRK!jd z1eQV{l^7Wz&N=P`I*XT5kv5V#yA7`|u76%WyY8&|rz~Q3O;re-6o~0@+>sGjl6{qS zsMuRxfci*~MOSOlbbb4&;BXQb<*R|AZG@>l*8`fQ4D3g)Jdb_wk4?(^%rX z;PS+-5NCF+bVlI$HMphNcDaT~VY(uGpdqX1hkjPf;fexrxO;g7$@x>QJ%nRg(iVCm z#QNXc6oFAOK}sKU^1kR#;3|`&j5?zz4oX943+J zECPT$Hs*Q9&rOL>C@88MK@CEDanuBkVea6tvF|8k-B+^lCV10RA{B9Sjjd^)tDCRF(2)`)sQY8vCQkU8F}?^ku=x+ct_Bv6 z^k|z<#1b>*n{r|>C)m6+PW5*m8+zu3@R}eq#g@zWMpEP`{0=itenReAKf@ETx-J zt@4L5B`j-0DuMY^N8TzGu?7{>+dmgd}QYQ^L6?DLM_K4N$Z>GQGEC zdo!V^S1cm$$BK%A0p(BPMFDvyT)HZ%faUF8iHSYh%abJQC(lvROAvd(+{MWY5~>gD zi1G>CWKsU{HS#%2u>^?9B5aoYEyt{NtOs$Ljr-^e0grD%6|DAUss}T|zv|6sP(-Jf zUswCuZsUW?IXYIZLhc##MVUQ6Z>fb-c;8qs+*g-y}JTH2=}q__>MXaG65EXVFcTLzn%1V1v--oieq=71Ikn z14_%zwxRu4@O@Z5V*N_3WugWDF!ZkW)T^fY1-Aa7)u{Gh4a60(X|G+KayY|kZl5B? z_!fU>^@AMs&0M6$2>pkvDYr`(F_GjU*F)c$rNQyXOI*&p zX;@?y`qnXR)D7b8{@rkWK7A5iJZ1hL4J(_RbB5mT{^jF*9ZQ;rt7e|peSUBfQ!q+fn=FGO3tFzlcI zwNjMFW&qMQ;R-D{HgD(Ta|Nn0YnH10yq;PT@&P;0h0SD41%t`g^ncRpP5!6KD0N@196Gwt4kzsf9Pyg@&l{o7SXJ)(n$^p_Sd~d6l^xWZL$G zkGDZ+;wIwLOXocYTaeNvmG1c1xByuPgeby7s`PWPxUB>({z3c@j6O<)jS@wE)a~zD zVB{STl5WhkZLTrZ-m_MqxLx)2=s14}yc;_iD>HP4zUf#WAaTFFrVe~-b1EN9sQW(2 zMOw@Z;Il>OD}rv`5RRsa7w%$^w%^{!IvUm zsqpH#@|of_AWClu=k5yZa86TSoq*F~_@?9DH@7GjlovKfF7*mz!Q%zTPw(ZBWZ8Mf z>|yk8ZUbxK`O`T_36QJXvGr5V=-X`B$UtNC?Ayi(sIDq0riD9>aD=-_zNK#)3>EjU zo}KlJCrYCJd#AQLe+3F37&TI%-0VP%Z}TG&bk0Lp@;O7Vo9|IRTR$tAgadU@XY1ql zdbCieLs{4n=j_CF{MY>Cdi7M#c7d#jmPsiw;hD30!D z%@FGsw=VdozgxWl3v{oPSvH7i%fpT8VS_(TEYZh@MiuR+#P~$_YQ45WqzV7IUH+&3 z&;vHCr)z?==Z;8cFPL?%qknN5Ib%%Uf8S?Sta_CxkDUc`zs@zBqpPuQGQsSZ6hvGO z+a4Cx_KtmWx-;}{?l8YQ&9ve)0v8=ygZJ6_k0<9z{@ue!4Z`}lcotNObO!C7`<+(7 zJqAI@F$qqvC5JW~A!~2OuEnSbmOLRd00@**wNXFj&l7qgkTEu`pwn-4!|L+ss~0np zx;FIY_6T2M2u=6gO?`GebJ|CoLE+mDZA@kAHk^3P#Nt)v#Ii2)HM>A*KwU^pQ}ciu z_p2Y_Eu~S*8Sx@f$|UHfbJxSoG60klco4GcxqKUbpc}TUPeb9mM*d|NK@cAf%<$K> z(N4pQxMxqBvgEc(0)8vnp6KGGFWD${=B!9> jWH?_=tueY8jX7eCPvBF!nW}vd<8MG#DgnmdFx9 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%0Dydyx`!U`!cr8 z7_Od$-|!vcSOC&8prY*niI@9NV(VhOo@k3z(kji2PiVO5IV$wOgl!AJc@BQ*d7egV z6DvTvGN?Eok6n-bN3lJCeZGI@%#rBRLWzrC0loOG;epm1tNO8R$56Es`_5yiah`cv z0PdhnJas{9hua@{#Ier*y1p7k> s^D7yH(DXD`&QBrEnI)I!oSwb^0}-@|MALyihX4Qo07*qoM6N<$g6uC%^8f$< literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/divider_item_line.xml b/app/src/main/res/drawable/divider_item_line.xml new file mode 100644 index 0000000000..321d4fc36a --- /dev/null +++ b/app/src/main/res/drawable/divider_item_line.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_tablayout_no_title_viewpager.xml b/app/src/main/res/layout/activity_tablayout_no_title_viewpager.xml new file mode 100644 index 0000000000..cbcdeaadd3 --- /dev/null +++ b/app/src/main/res/layout/activity_tablayout_no_title_viewpager.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/ask_answer_item.xml b/app/src/main/res/layout/ask_answer_item.xml index 3b1bfe88e4..d03b0d021d 100644 --- a/app/src/main/res/layout/ask_answer_item.xml +++ b/app/src/main/res/layout/ask_answer_item.xml @@ -1,25 +1,24 @@ + android:paddingLeft="16dp" + android:paddingTop="13dp" + android:paddingRight="16dp" + android:paddingBottom="16dp"> @@ -48,7 +46,9 @@ android:id="@+id/ask_answer_item_usericon" style="@style/frescoCircleStyle" android:layout_width="20dp" - android:layout_height="20dp" /> + android:layout_height="20dp" + app:roundingBorderColor="@color/black_alpha_10" + app:roundingBorderWidth="0.5dp" /> + app:layout_constraintRight_toLeftOf="@+id/sdv_user_badge" + app:layout_constraintTop_toTopOf="@id/ask_answer_item_usericon_container" /> + tools:visibility="visible" /> + tools:visibility="visible" /> + app:layout_constraintTop_toBottomOf="@id/ask_answer_item_content" /> + app:layout_constraintTop_toBottomOf="@id/ask_answer_item_content" /> + app:layout_constraintTop_toBottomOf="@id/ask_answer_item_content" /> \ No newline at end of file diff --git a/app/src/main/res/layout/collection_comunity_article_item.xml b/app/src/main/res/layout/collection_comunity_article_item.xml index 767d987475..dc58fac470 100644 --- a/app/src/main/res/layout/collection_comunity_article_item.xml +++ b/app/src/main/res/layout/collection_comunity_article_item.xml @@ -16,22 +16,20 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/reuse_listview_item_style" - android:paddingTop="5dp" - android:paddingBottom="10dp"> + android:paddingLeft="16dp" + android:paddingTop="13dp" + android:paddingRight="16dp" + android:paddingBottom="16dp"> @@ -58,6 +56,8 @@ imageIcon="@{data.user.icon}" android:layout_width="20dp" android:layout_height="20dp" + app:roundingBorderColor="@color/black_alpha_10" + app:roundingBorderWidth="0.5dp" fresco:roundAsCircle="true" /> + app:layout_constraintTop_toTopOf="@id/user_icon_container" + fresco:text="我的名字很长很长有十二字" /> + fresco:visibility="visible" /> + fresco:visibility="visible" /> + - - - - + app:layout_constraintTop_toBottomOf="@id/content" /> + app:layout_constraintTop_toBottomOf="@id/content" /> diff --git a/app/src/main/res/layout/comment_item.xml b/app/src/main/res/layout/comment_item.xml index aa70d3e99d..a3e0121653 100644 --- a/app/src/main/res/layout/comment_item.xml +++ b/app/src/main/res/layout/comment_item.xml @@ -74,7 +74,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="4dp" - android:layout_marginRight="4dp" android:background="@drawable/button_round_2496ff" android:includeFontPadding="false" android:paddingLeft="4dp" @@ -97,6 +96,7 @@ android:layout_width="16dp" android:layout_height="16dp" android:layout_marginRight="2dp" + android:layout_marginLeft="4dp" android:visibility="gone" app:layout_constrainedWidth="true" app:layout_constraintBottom_toBottomOf="@+id/comment_user_name" diff --git a/app/src/main/res/layout/dialog_choose_forum.xml b/app/src/main/res/layout/dialog_choose_forum.xml new file mode 100644 index 0000000000..30b893105c --- /dev/null +++ b/app/src/main/res/layout/dialog_choose_forum.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_game_detail_more.xml b/app/src/main/res/layout/dialog_game_detail_more.xml index 9fbbbb6b7d..445ecaba03 100644 --- a/app/src/main/res/layout/dialog_game_detail_more.xml +++ b/app/src/main/res/layout/dialog_game_detail_more.xml @@ -13,6 +13,7 @@ android:descendantFocusability="blocksDescendants"> - - - + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/handle_view"> + + + + + + app:layout_constraintTop_toBottomOf="@+id/title_container" /> + layout="@layout/piece_article_input_container" /> - - - - - - - - + android:layout_height="match_parent"> + android:layout_height="488dp" + android:layout_gravity="bottom" + android:background="@drawable/game_detail_more_dialog_background"> - + android:layout_height="48dp"> + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_comment.xml b/app/src/main/res/layout/fragment_comment.xml index 556034f6e8..094a1bb3b3 100644 --- a/app/src/main/res/layout/fragment_comment.xml +++ b/app/src/main/res/layout/fragment_comment.xml @@ -7,7 +7,7 @@ @@ -26,18 +26,16 @@ android:layout_height="wrap_content" android:layout_centerInParent="true" android:textColor="@color/text_333333" - android:textSize="14sp" - android:textStyle="bold" + android:textSize="16sp" tools:text="35条评论" /> + android:src="@drawable/ic_choose_forum_close" /> @@ -272,5 +270,14 @@ app:layout_constraintTop_toTopOf="@id/floorHintTv" tools:text="999" /> + \ No newline at end of file diff --git a/app/src/main/res/layout/item_article_detail_content.xml b/app/src/main/res/layout/item_article_detail_content.xml index 720d85df36..9e2ab44ec4 100644 --- a/app/src/main/res/layout/item_article_detail_content.xml +++ b/app/src/main/res/layout/item_article_detail_content.xml @@ -42,10 +42,10 @@ android:id="@+id/userIconIv" android:layout_width="wrap_content" android:layout_height="wrap_content" - app:avatar_width="32dp" - app:badge_width="12dp" android:layout_marginLeft="12dp" android:layout_marginTop="7dp" + app:avatar_width="32dp" + app:badge_width="12dp" app:border_color="@color/transparent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" @@ -56,8 +56,8 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="2dp" - android:layout_marginRight="16dp" android:layout_marginTop="8dp" + android:layout_marginRight="16dp" app:layout_constraintLeft_toRightOf="@id/userIconIv" app:layout_constraintRight_toLeftOf="@+id/followBtn" app:layout_constraintTop_toTopOf="@+id/userIconIv"> @@ -127,10 +127,10 @@ android:layout_marginLeft="2dp" android:layout_marginTop="53dp" android:layout_marginRight="20dp" + android:layout_marginBottom="8dp" android:includeFontPadding="false" android:textColor="@color/text_999999" android:textSize="11sp" - android:layout_marginBottom="8dp" app:layout_constraintBottom_toBottomOf="@id/userIconIv" app:layout_constraintLeft_toRightOf="@id/userIconIv" tools:text="发布于1分钟前" /> @@ -184,120 +184,5 @@ android:paddingBottom="20dp" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/new_comment_item.xml b/app/src/main/res/layout/new_comment_item.xml new file mode 100644 index 0000000000..8abaf440db --- /dev/null +++ b/app/src/main/res/layout/new_comment_item.xml @@ -0,0 +1,280 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/piece_article_input_container.xml b/app/src/main/res/layout/piece_article_input_container.xml index d14b9a809e..55373f0738 100644 --- a/app/src/main/res/layout/piece_article_input_container.xml +++ b/app/src/main/res/layout/piece_article_input_container.xml @@ -5,6 +5,7 @@ android:id="@+id/bottomContainer" android:layout_width="match_parent" android:layout_height="50dp" + android:background="@color/white" android:layout_alignParentBottom="true" tools:showIn="@layout/fragment_article_detail"> @@ -20,7 +21,7 @@ android:maxLines="1" android:paddingLeft="16dp" android:paddingRight="16dp" - android:textColor="@color/AAAAAA" + android:textColor="@color/text_cccccc" android:textSize="14sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" @@ -40,8 +41,8 @@ @@ -52,25 +53,54 @@ android:gravity="center" android:text="赞同" android:textColor="@color/text_666666" - android:textSize="11sp" /> + android:textSize="10sp" /> + + + + + + + + @@ -81,7 +111,7 @@ android:gravity="center" android:text="评论" android:textColor="@color/text_666666" - android:textSize="11sp" /> + android:textSize="10sp" /> \ No newline at end of file diff --git a/app/src/main/res/layout/piece_comment_typing_container.xml b/app/src/main/res/layout/piece_comment_typing_container.xml index 77063d4886..065dc5b25c 100644 --- a/app/src/main/res/layout/piece_comment_typing_container.xml +++ b/app/src/main/res/layout/piece_comment_typing_container.xml @@ -41,7 +41,7 @@ android:layout_height="wrap_content" android:background="@android:color/transparent" android:drawablePadding="4dp" - android:hint="写评论" + android:hint="说点什么吧" android:lineSpacingExtra="4dp" android:textColor="@color/text_333333" android:textColorHint="@color/theme_font" diff --git a/app/src/main/res/layout/piece_comment_typing_container_dark.xml b/app/src/main/res/layout/piece_comment_typing_container_dark.xml index c15ea66e8e..daeed3f1b7 100644 --- a/app/src/main/res/layout/piece_comment_typing_container_dark.xml +++ b/app/src/main/res/layout/piece_comment_typing_container_dark.xml @@ -40,7 +40,7 @@ android:layout_height="wrap_content" android:background="@android:color/transparent" android:drawablePadding="4dp" - android:hint="写评论" + android:hint="说点什么吧" android:lineSpacingExtra="4dp" android:textColor="@color/white" android:textColorHint="@color/text_666666" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fb64bb146d..590fe3cc92 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -119,7 +119,7 @@ 资讯 首页 我的光环 - 写评论 + 说点什么吧 发送 发表评论... 发表评论... From 120ea26455073f2006050642f131d91882c862db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=8E=89=E4=B9=85?= <1484288157@qq.com> Date: Wed, 13 Jan 2021 11:22:40 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=B8=96=E5=AD=90/?= =?UTF-8?q?=E5=9B=9E=E7=AD=94=E4=B8=8A=E4=BC=A0=E5=9B=BE=E7=89=87=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E5=8A=A0=E8=BD=BD=E5=BC=B9=E7=AA=97=EF=BC=8C=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E5=8D=A0=E4=BD=8D=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/gh/common/util/UploadImageUtils.kt | 4 +- .../java/com/gh/common/view/RichEditor.java | 15 +- .../com/gh/gamecenter/SuggestionActivity.java | 5 + .../detail/ForumArticleAskListFragment.kt | 11 +- .../forum/detail/ForumDetailFragment.kt | 41 +- .../qa/answer/edit/AnswerEditActivity.kt | 42 +- .../qa/answer/edit/AnswerEditViewModel.kt | 36 +- .../qa/article/edit/ArticleEditActivity.kt | 57 +- .../qa/article/edit/ArticleEditViewModel.kt | 35 +- .../main/res/layout/fragment_forum_detail.xml | 601 +++++++++--------- .../piece_community_vote_and_comment.xml | 4 +- 11 files changed, 474 insertions(+), 377 deletions(-) diff --git a/app/src/main/java/com/gh/common/util/UploadImageUtils.kt b/app/src/main/java/com/gh/common/util/UploadImageUtils.kt index 6672758ea4..aeb0934522 100644 --- a/app/src/main/java/com/gh/common/util/UploadImageUtils.kt +++ b/app/src/main/java/com/gh/common/util/UploadImageUtils.kt @@ -116,6 +116,7 @@ object UploadImageUtils { Observable.create(ObservableOnSubscribe> { val compressList = compressImageList(imgs, compressGif) + listener.onCompressSuccess(compressList.map { file -> file.absolutePath }.toList()) var listTotal = 0L // 总大小 var listProgress = 0L // 已上传的大小 for (img in compressList) { @@ -274,7 +275,7 @@ object UploadImageUtils { } // 防止GIF图片文件后缀不是GIF,这个FileName只是告诉服务端后缀格式,没有其他用处 - fun getFileName(file: File): String { + fun getFileName(file: File): String { val options = BitmapFactory.Options() options.inJustDecodeBounds = true BitmapFactory.decodeFile(file.absolutePath, options) @@ -292,6 +293,7 @@ object UploadImageUtils { interface OnUploadImageListListener { fun onSuccess(imageUrl: LinkedHashMap, errorMap: Map) // key:sourceImage value:compressImage + fun onCompressSuccess(imageUrls: List) {} fun onError(errorMap: Map) // 全部上传失败时回调 fun onProgress(total: Long, progress: Long) } diff --git a/app/src/main/java/com/gh/common/view/RichEditor.java b/app/src/main/java/com/gh/common/view/RichEditor.java index b9236033f6..b9fbe2bcc4 100644 --- a/app/src/main/java/com/gh/common/view/RichEditor.java +++ b/app/src/main/java/com/gh/common/view/RichEditor.java @@ -321,6 +321,10 @@ public class RichEditor extends WebView { exec("javascript:RE.setBaseFontSize('" + px + "px');"); } + public boolean hasPlaceholderImage() { + return getHtml().contains("placeholder-image-container"); + } + @Override public void setPadding(int left, int top, int right, int bottom) { super.setPadding(left, top, right, bottom); @@ -444,6 +448,15 @@ public class RichEditor extends WebView { exec("javascript:RE.setTextColor('" + hex + "');"); } + public void insertPlaceholderImage(String id) { + exec("javascript:RE.prepareInsert();"); + exec("javascript:RE.insertPlaceholderImage('" + id + "');"); + } + + public void replacePlaceholderImage(String list) { + exec("javascript:RE.replacePlaceholderImage('" + list + "');"); + } + public void removeFormat() { exec("javascript:RE.removeFormat();"); } @@ -737,7 +750,7 @@ public class RichEditor extends WebView { public void invalidate() { super.invalidate(); - if (mInitialLayoutCallback != null &&getHeight() > 0) { + if (mInitialLayoutCallback != null && getHeight() > 0) { // 仅初次 layout 完成会有回调 mInitialLayoutCallback.onCallback(); mInitialLayoutCallback = null; diff --git a/app/src/main/java/com/gh/gamecenter/SuggestionActivity.java b/app/src/main/java/com/gh/gamecenter/SuggestionActivity.java index 2ba84ab6cb..276dba7368 100644 --- a/app/src/main/java/com/gh/gamecenter/SuggestionActivity.java +++ b/app/src/main/java/com/gh/gamecenter/SuggestionActivity.java @@ -967,6 +967,11 @@ public class SuggestionActivity extends ToolBarActivity implements OnRequestCall private void postPic(final String email) { UploadImageUtils.INSTANCE.compressAndUploadImageList(UploadImageUtils.UploadType.suggestion , mAdapter.getFileList(), false, new UploadImageUtils.OnUploadImageListListener() { + @Override + public void onCompressSuccess(@NotNull List imageUrls) { + + } + @Override public void onProgress(long total, long progress) { int percent = (int) (100 * (progress / (float) total)); diff --git a/app/src/main/java/com/gh/gamecenter/forum/detail/ForumArticleAskListFragment.kt b/app/src/main/java/com/gh/gamecenter/forum/detail/ForumArticleAskListFragment.kt index f413a275ab..8ce88b45c4 100644 --- a/app/src/main/java/com/gh/gamecenter/forum/detail/ForumArticleAskListFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/forum/detail/ForumArticleAskListFragment.kt @@ -31,6 +31,7 @@ class ForumArticleAskListFragment : ListFragment(R.id.reuse_ll_loading) - private val mReuseNoConnection by bindView(R.id.reuse_no_connection) - private val mReuseNoData by bindView(R.id.reuse_none_data) - private val mReuseNoDataTv by bindView(R.id.reuse_tv_none_data) - private var mAllForumArticleAskListFragment: ForumArticleAskListFragment? = null private var mEssenceForumArticleAskListFragment: ForumArticleAskListFragment? = null private var mAskForumArticleAskListFragment: ForumArticleAskListFragment? = null @@ -96,11 +90,11 @@ class ForumDetailFragment : BaseLazyTabFragment() { val factory = ForumDetailViewModel.Factory(bbsId) mViewModel = viewModelProvider(factory) mViewModel?.forumDetail?.observe(this, Observer { - mReuseLoading.visibility = View.GONE + mBinding.reuseLoading.reuseLlLoading.visibility = View.GONE if (it.status == Status.SUCCESS) { mBinding.communityEdit.visibility = View.VISIBLE mBinding.forumContainer.visibility = View.VISIBLE - mReuseNoConnection.visibility = View.GONE + mBinding.reuseNoConnection.reuseNoConnection.visibility = View.GONE if (it.data != null) { mForumDetail = it.data initUI() @@ -109,16 +103,20 @@ class ForumDetailFragment : BaseLazyTabFragment() { mBinding.communityEdit.visibility = View.GONE mBinding.forumContainer.visibility = View.GONE if (it.exception != null && it.exception.code() == 404) { - mReuseNoDataTv.text = "页面为空" - mReuseNoData.visibility = View.VISIBLE - mReuseNoConnection.visibility = View.GONE + mBinding.reuseNoneData.reuseTvNoneData.text = "页面为空" + mBinding.reuseNoneData.reuseNoneData.visibility = View.VISIBLE + mBinding.reuseNoConnection.reuseNoConnection.visibility = View.GONE ToastUtils.showToast("内容可能已被删除") } else { - mReuseNoData.visibility = View.GONE - mReuseNoConnection.visibility = View.VISIBLE + mBinding.reuseNoneData.reuseNoneData.visibility = View.GONE + mBinding.reuseNoConnection.reuseNoConnection.visibility = View.VISIBLE } } }) + mBinding.refreshLayout.setProgressViewOffset(false, 0, DisplayUtils.dip2px(40f) + DisplayUtils.getStatusBarHeight(requireContext().getResources())); + mBinding.appbar.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { _, verticalOffset -> + mBinding.refreshLayout.isEnabled = abs(verticalOffset) <= 2 + }) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -163,9 +161,24 @@ class ForumDetailFragment : BaseLazyTabFragment() { MtaHelper.onEvent("论坛详情", getKeyValue(mLastPosition), getKeyValue(it)) mLastPosition = it } + mBinding.refreshLayout.setOnRefreshListener { + if (mAllForumArticleAskListFragment != null && mViewPager.currentItem == 0) { + mAllForumArticleAskListFragment?.refresh() + } + if (mEssenceForumArticleAskListFragment != null && mViewPager.currentItem == 1) { + mEssenceForumArticleAskListFragment?.refresh() + } + if (mAskForumArticleAskListFragment != null && mViewPager.currentItem == 2) { + mAskForumArticleAskListFragment?.refresh() + } + } LogUtils.uploadAccessToBbs(bbsId, "论坛详情") } + fun hideRefreshingLayout() { + mBinding.refreshLayout.isRefreshing = false + } + private fun getKeyValue(position: Int): String { return when (position) { 0 -> "全部Tab" @@ -242,7 +255,7 @@ class ForumDetailFragment : BaseLazyTabFragment() { ?: "", mEntrance, "论坛详情")) } R.id.reuse_no_connection -> { - mReuseLoading.visibility = View.VISIBLE + mBinding.reuseLoading.reuseLlLoading.visibility = View.VISIBLE mViewModel?.getForumDetail() } R.id.gameZoneTv -> { diff --git a/app/src/main/java/com/gh/gamecenter/qa/answer/edit/AnswerEditActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/answer/edit/AnswerEditActivity.kt index 26b3bea91b..55a83b1203 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/answer/edit/AnswerEditActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/answer/edit/AnswerEditActivity.kt @@ -31,8 +31,11 @@ import com.gh.gamecenter.qa.entity.Questions import com.gh.gamecenter.video.VideoVerifyItemViewHolder import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel import com.halo.assistant.HaloApp +import com.lightgame.utils.Util_System_Keyboard +import com.lightgame.utils.Utils import com.zhihu.matisse.Matisse import com.zhihu.matisse.MimeType +import org.json.JSONArray import org.json.JSONObject /** @@ -245,15 +248,24 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { } } - mViewModel.postImageLiveData.observeNonNull(this) { - if (it.status == Status.SUCCESS) { - val imageUrl = it.data!! - for (sourceImage in imageUrl.keys) { - mViewModel.mapImages.set(TextUtils.htmlEncode(sourceImage).decodeURI(), imageUrl[sourceImage]!!) - mRichEditor.insertImage(FILE_HOST + sourceImage.decodeURI()) - } + mViewModel.chooseImagesUpload.observe(this, Observer { + for (key in it.keys) { + mRichEditor.focusEditor() + mRichEditor.insertPlaceholderImage(key) } - } + }) + + mViewModel.chooseImagesUploadSuccess.observe(this, Observer { + val jsonArray = JSONArray() + mRichEditor.focusEditor() + for (key in it.keys) { + val jsonObject = JSONObject() + jsonObject.put("id", key) + jsonObject.put("url", it[key]) + jsonArray.put(jsonObject) + } + mRichEditor.replacePlaceholderImage(jsonArray.toString()) + }) mViewModel.deleteDraftLiveDate.observe(this, Observer { if (it == true) { @@ -362,21 +374,16 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { mRichEditor.postDelayed({ val answerContent = getReplaceRealContent() mRichEditor.showLinkStyle() + if (mRichEditor.hasPlaceholderImage()) { + ToastUtils.showToast("图片正在上传中") + return@postDelayed + } // filter rule val answerLength = HtmlUtils.stripHtml(answerContent).length if (answerLength < MIN_ANSWER_TEXT_LENGTH) { -// toast(R.string.answer_beneath_length_limit) ToastUtils.showToast(getString(R.string.answer_beneath_length_limit), if (mIsKeyBoardShow) Gravity.CENTER else -1) return@postDelayed } else if (answerLength > MAX_ANSWER_TEXT_LENGTH) { - /* DialogUtils.showAlertDialog(this, - getString(R.string.answer_post_failed), - getString(R.string.answer_exceed_length_limit, - MAX_ANSWER_TEXT_LENGTH, - answerLength - MAX_ANSWER_TEXT_LENGTH), - getString(R.string.answer_resume_edit), "", { - // do nothing - }, null)*/ ToastUtils.showToast("回答最多输入10000个字", if (mIsKeyBoardShow) Gravity.CENTER else -1) return@postDelayed } @@ -458,6 +465,7 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { */ private fun saveDraft(forcedExit: Boolean) { val editContent = getReplaceRealContent() + if (mRichEditor.hasPlaceholderImage()) return if (TextUtils.isEmpty(UserManager.getInstance().token)) { return } else if (forcedExit && TextUtils.isEmpty(editContent)) { diff --git a/app/src/main/java/com/gh/gamecenter/qa/answer/edit/AnswerEditViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/answer/edit/AnswerEditViewModel.kt index 8444ca5df3..bdef40f421 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/answer/edit/AnswerEditViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/answer/edit/AnswerEditViewModel.kt @@ -1,12 +1,9 @@ package com.gh.gamecenter.qa.answer.edit import android.app.Application -import androidx.lifecycle.AndroidViewModel -import androidx.lifecycle.MediatorLiveData -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider import android.content.Intent import android.text.TextUtils +import androidx.lifecycle.* import com.gh.base.fragment.WaitingDialogFragment import com.gh.common.syncpage.SyncDataEntity import com.gh.common.syncpage.SyncFieldConstants @@ -56,6 +53,10 @@ class AnswerEditViewModel(application: Application, val draftsLiveData = MediatorLiveData() val saveDraftsLiveData = MediatorLiveData() // 自动保存不会回调 + val uploadingImage = ArrayList>() + val chooseImagesUpload = MutableLiveData>() + val chooseImagesUploadSuccess = MutableLiveData>() + var uploadImageSubscription: Disposable? = null val mapImages = HashMap() @@ -156,19 +157,30 @@ class AnswerEditViewModel(application: Application, } if (pictureList.size == 0) return - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传中...", true)) - uploadImageSubscription = UploadImageUtils.compressAndUploadImageList(UploadImageUtils.UploadType.answer, pictureList , false, object : UploadImageUtils.OnUploadImageListListener { override fun onProgress(total: Long, progress: Long) { - var percent = (100 * (progress / total.toFloat())).toInt() - if (percent >= 100) percent = 99 - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("图片上传中 $percent%", true)) } + override fun onCompressSuccess(imageUrls: List) { + val chooseImageMd5Map = HashMap() + imageUrls.forEach { + chooseImageMd5Map[MD5Utils.getUrlMD5(it)] = "" + } + uploadingImage.add(chooseImageMd5Map) + chooseImagesUpload.postValue(chooseImageMd5Map) + + } override fun onSuccess(imageUrl: LinkedHashMap, errorMap: Map) { - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传中...", false)) - postImageLiveData.postValue(Resource.success(imageUrl)) + val uploadMap = uploadingImage.find { it.containsKey(MD5Utils.getUrlMD5(imageUrl.entries.iterator().next().key)) } + uploadMap?.let { + for (key in imageUrl.keys) { + uploadMap[MD5Utils.getUrlMD5(key)] = AnswerEditActivity.FILE_HOST + key.decodeURI() + mapImages[TextUtils.htmlEncode(key).decodeURI()] = imageUrl[key] ?: "" + } + chooseImagesUploadSuccess.postValue(uploadMap) + uploadingImage.remove(uploadMap) + } val errorSize = pictureList.size - imageUrl.size if (errorSize > 0) { for (error in errorMap.values) { @@ -182,8 +194,6 @@ class AnswerEditViewModel(application: Application, } override fun onError(errorMap: Map) { - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传中...", false)) - postImageLiveData.postValue(Resource.error(null)) val errorSize = pictureList.size for (error in errorMap.values) { diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditActivity.kt index 4d5c587799..015d7b27c6 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditActivity.kt @@ -9,19 +9,14 @@ import android.os.Bundle import android.os.Message import android.text.InputFilter import android.text.TextUtils -import android.view.Gravity import android.view.MenuItem import android.view.View -import android.view.Window import android.view.inputmethod.InputMethodManager import android.widget.* import androidx.core.content.ContextCompat -import androidx.core.widget.NestedScrollView import androidx.core.widget.doOnTextChanged import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders -import androidx.recyclerview.widget.GridLayoutManager -import androidx.recyclerview.widget.RecyclerView import butterknife.OnClick import com.gh.base.BaseRichEditorActivity import com.gh.base.fragment.WaitingDialogFragment @@ -32,7 +27,6 @@ import com.gh.gamecenter.R import com.gh.gamecenter.entity.CommunityEntity import com.gh.gamecenter.eventbus.EBReuse import com.gh.gamecenter.manager.UserManager -import com.gh.gamecenter.mvvm.Status import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity import com.gh.gamecenter.qa.article.draft.ArticleDraftActivity import com.gh.gamecenter.qa.dialog.ChooseForumDialogFragment @@ -45,6 +39,8 @@ import com.zhihu.matisse.Matisse import com.zhihu.matisse.MimeType import kotterknife.bindView import org.greenrobot.eventbus.EventBus +import org.json.JSONArray +import org.json.JSONObject class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { @@ -82,7 +78,8 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { if (mViewModel.mSelectCommunityData != null && !TextUtils.isEmpty(mEditTitle.text.trim()) && (!TextUtils.isEmpty(mRichEditor.text) - || mRichEditor.html.contains(" @@ -431,6 +434,7 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { private fun checkDraft(saveType: SaveDraftType): Boolean { if (mViewModel.detailEntity != null) return true + if (mRichEditor.hasPlaceholderImage()) return true val draftEntity = mViewModel.draftEntity @@ -492,6 +496,7 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { } private fun showPatchBackDialog() { + if (mRichEditor.hasPlaceholderImage()) return DialogUtils.showCancelAlertDialog(this, "提示", "即将退出修改,是否需要将此次编辑保存到草稿箱?", "保存草稿", @@ -537,6 +542,10 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { mViewModel.title = mEditTitle.text.toString() mViewModel.content = getReplaceRealContent() mRichEditor.showLinkStyle() + if (mRichEditor.hasPlaceholderImage()) { + ToastUtils.showToast("图片正在上传中") + return@postDelayed + } if (mViewModel.checkDataAndLoadTitleTag(mIsKeyBoardShow)) { mArticleTagsSelectFragment?.publishArticle() } diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditViewModel.kt index cbdbb2aa13..f316a73b95 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditViewModel.kt @@ -14,6 +14,7 @@ import com.gh.gamecenter.entity.CommunityEntity import com.gh.gamecenter.eventbus.EBReuse import com.gh.gamecenter.manager.UserManager import com.gh.gamecenter.mvvm.Resource +import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity import com.gh.gamecenter.qa.entity.ArticleDetailEntity import com.gh.gamecenter.qa.entity.ArticleDraftEntity import com.gh.gamecenter.qa.questions.edit.QuestionEditViewModel @@ -34,6 +35,8 @@ import org.json.JSONObject import retrofit2.HttpException import java.io.File import java.util.* +import kotlin.collections.ArrayList +import kotlin.collections.HashMap class ArticleEditViewModel(application: Application) : AndroidViewModel(application) { @@ -43,13 +46,16 @@ class ArticleEditViewModel(application: Application) : AndroidViewModel(applicat val MAX_ARTICLE_TEXT_LENGTH = 10000 val processDialog = MediatorLiveData() - val postImageLiveData = MediatorLiveData>>() val postArticle = MediatorLiveData() val postArticleDrafts = MediatorLiveData>() val articleDraftsContent = MediatorLiveData() val error = MutableLiveData() val notSelectForum = MutableLiveData() + val uploadingImage = ArrayList>() + val chooseImagesUpload = MutableLiveData>() + val chooseImagesUploadSuccess = MutableLiveData>() + var uploadImageSubscription: Disposable? = null var mSelectCommunityData: CommunityEntity? = null @@ -175,19 +181,32 @@ class ArticleEditViewModel(application: Application) : AndroidViewModel(applicat } if (pictureList.size == 0) return - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传中...", true)) uploadImageSubscription = UploadImageUtils.compressAndUploadImageList(UploadImageUtils.UploadType.answer, pictureList , false, object : UploadImageUtils.OnUploadImageListListener { override fun onProgress(total: Long, progress: Long) { - var percent = (100 * (progress / total.toFloat())).toInt() - if (percent >= 100) percent = 99 - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("图片上传中 $percent%", true)) + } + + override fun onCompressSuccess(imageUrls: List) { + val chooseImageMd5Map = HashMap() + imageUrls.forEach { + chooseImageMd5Map[MD5Utils.getUrlMD5(it)] = "" + } + uploadingImage.add(chooseImageMd5Map) + chooseImagesUpload.postValue(chooseImageMd5Map) + } override fun onSuccess(imageUrl: LinkedHashMap, errorMap: Map) { - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传中...", false)) - postImageLiveData.postValue(Resource.success(imageUrl)) + val uploadMap = uploadingImage.find { it.containsKey(MD5Utils.getUrlMD5(imageUrl.entries.iterator().next().key)) } + uploadMap?.let { + for (key in imageUrl.keys) { + uploadMap[MD5Utils.getUrlMD5(key)] = AnswerEditActivity.FILE_HOST + key.decodeURI() + mapImg[TextUtils.htmlEncode(key).decodeURI()] = imageUrl[key] ?: "" + } + chooseImagesUploadSuccess.postValue(uploadMap) + uploadingImage.remove(uploadMap) + } val errorSize = pictureList.size - imageUrl.size if (errorSize > 0) { for (error in errorMap.values) { @@ -201,7 +220,6 @@ class ArticleEditViewModel(application: Application) : AndroidViewModel(applicat } override fun onError(errorMap: Map) { - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传中...", false)) val errorSize = pictureList.size for (error in errorMap.values) { @@ -215,7 +233,6 @@ class ArticleEditViewModel(application: Application) : AndroidViewModel(applicat } else { Utils.toast(getApplication(), errorSize.toString() + "张图片上传失败") } - postImageLiveData.postValue(Resource.error(null)) } }) } diff --git a/app/src/main/res/layout/fragment_forum_detail.xml b/app/src/main/res/layout/fragment_forum_detail.xml index 4ebcabb9b5..621247d934 100644 --- a/app/src/main/res/layout/fragment_forum_detail.xml +++ b/app/src/main/res/layout/fragment_forum_detail.xml @@ -16,324 +16,330 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - + android:layout_height="match_parent"> - - + android:orientation="vertical" + android:visibility="gone" + tools:visibility="visible"> - + android:gravity="center" + app:layout_behavior="com.gh.common.view.FixAppBarLayoutBehavior"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:fitsSystemWindows="true" + app:contentScrim="@color/white" + app:layout_scrollFlags="scroll|exitUntilCollapsed" + app:scrimAnimationDuration="0" + app:scrimVisibleHeightTrigger="80dp" + app:titleEnabled="false"> + android:layout_height="wrap_content" + android:gravity="center_horizontal" + android:orientation="vertical" + app:layout_collapseMode="pin"> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + android:layout_marginRight="4dp" + android:includeFontPadding="false" + android:text="最新回复" + android:textColor="@color/text_999999" + android:textSize="12sp" /> + android:id="@+id/filterArrow" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@drawable/ic_filter_down" /> - + + - - - + android:layout_height="match_parent" + android:overScrollMode="never" + app:layout_behavior="@string/appbar_scrolling_view_behavior" /> - - - - - - - - - - - - - - - - - - + + - - - + + + @@ -37,7 +37,7 @@ android:layout_width="0dp" android:layout_height="0dp" android:layout_gravity="center" - android:background="@drawable/reuse_listview_item_style" + android:background="@color/white" android:gravity="center" app:layout_constraintBottom_toBottomOf="@id/comment_count_container" app:layout_constraintLeft_toRightOf="@id/comment_count_container" From a42bcbd1600fdc3efcc629a24247fd7e0a3ca8f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=8E=89=E4=B9=85?= <1484288157@qq.com> Date: Fri, 15 Jan 2021 16:30:06 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E8=8D=89=E7=A8=BF=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 4 + .../simulator/SimulatorDownloadManager.kt | 2 +- .../java/com/gh/common/util/DialogUtils.java | 16 +- .../java/com/gh/common/view/RichEditor.java | 11 + .../forum/follow/ForumMyFollowAdapter.kt | 2 +- .../gamecenter/forum/select/ForumAdapter.kt | 2 +- .../qa/answer/edit/AnswerEditActivity.kt | 73 ++--- .../article/detail/ArticleDetailFragment.kt | 4 + .../detail/BaseArticleDetailCommentAdapter.kt | 6 +- .../qa/article/draft/ArticleDraftFragment.kt | 19 +- .../qa/article/edit/ArticleEditActivity.kt | 138 ++++----- .../qa/article/edit/ArticleEditViewModel.kt | 25 +- .../qa/draft/CommunityDraftWrapperActivity.kt | 5 +- .../gamecenter/qa/editor/ArticleViewModel.kt | 9 + .../gh/gamecenter/qa/entity/AnswerEntity.kt | 5 + .../qa/entity/QuestionDraftEntity.kt | 20 ++ .../qa/entity/QuestionsDetailEntity.kt | 6 +- .../questions/draft/QuestionDraftActivity.kt | 17 ++ .../questions/draft/QuestionDraftAdapter.kt | 71 +++++ .../questions/draft/QuestionDraftFragment.kt | 94 +++++++ .../questions/draft/QuestionDraftViewModel.kt | 46 +++ .../qa/questions/edit/QuestionEditActivity.kt | 265 ++++++++++++++---- .../questions/edit/QuestionEditViewModel.kt | 146 +++++----- .../qa/questions/edit/TagsSelectFragment.kt | 33 +-- .../retrofit/service/ApiService.java | 32 +++ .../drawable-xxhdpi/ic_alert_dialog_close.png | Bin 0 -> 775 bytes .../drawable/divider_item_line_space_16.xml | 18 ++ .../main/res/layout/community_answer_item.xml | 72 +++++ .../layout/community_article_draft_item.xml | 74 +++-- .../layout/community_question_draft_item.xml | 78 ++++++ app/src/main/res/layout/dialog_new_alert.xml | 13 +- app/src/main/res/menu/menu_answer_post.xml | 7 +- app/src/main/res/menu/menu_question_post.xml | 6 +- 33 files changed, 973 insertions(+), 346 deletions(-) create mode 100644 app/src/main/java/com/gh/gamecenter/qa/entity/QuestionDraftEntity.kt create mode 100644 app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftActivity.kt create mode 100644 app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftAdapter.kt create mode 100644 app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftFragment.kt create mode 100644 app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftViewModel.kt create mode 100644 app/src/main/res/drawable-xxhdpi/ic_alert_dialog_close.png create mode 100644 app/src/main/res/drawable/divider_item_line_space_16.xml create mode 100644 app/src/main/res/layout/community_question_draft_item.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a93d3af35e..47b6c37bc0 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -615,6 +615,10 @@ android:name=".personal.NewPersonalActivity" android:screenOrientation="portrait" /> + + diff --git a/app/src/main/java/com/gh/common/simulator/SimulatorDownloadManager.kt b/app/src/main/java/com/gh/common/simulator/SimulatorDownloadManager.kt index 5daca02c94..fc42fb695c 100644 --- a/app/src/main/java/com/gh/common/simulator/SimulatorDownloadManager.kt +++ b/app/src/main/java/com/gh/common/simulator/SimulatorDownloadManager.kt @@ -118,7 +118,7 @@ class SimulatorDownloadManager private constructor() { key = if (shouldShowUpdate && isInstalled) "更新弹窗" else "下载弹窗", logShowEvent = true ) - DialogUtils.showNewAlertDialog(context, title, message, negativeText, positiveText, trackableEntity, Gravity.LEFT, { + DialogUtils.showNewAlertDialog(context, title, message, negativeText, positiveText, trackableEntity, Gravity.LEFT, false, { if (shouldShowUpdate && isInstalled) { cancelCallback?.invoke() MtaHelper.onEvent(trackableEntity.event, trackableEntity.key, "点击下次再说") diff --git a/app/src/main/java/com/gh/common/util/DialogUtils.java b/app/src/main/java/com/gh/common/util/DialogUtils.java index 43fcfcb809..dc0d50621a 100644 --- a/app/src/main/java/com/gh/common/util/DialogUtils.java +++ b/app/src/main/java/com/gh/common/util/DialogUtils.java @@ -350,7 +350,7 @@ public class DialogUtils { * @param cmListener 确认按钮监听 */ public static Dialog showNewAlertDialog(Context context, String title, CharSequence message - , String negative, String positive, TrackableEntity trackableEntity, int gravity, final CancelListener clListener, final ConfirmListener cmListener) { + , String negative, String positive, TrackableEntity trackableEntity, int gravity, boolean shouldShowCloseBtn, final CancelListener clListener, final ConfirmListener cmListener) { context = checkDialogContext(context); final Dialog dialog; if (trackableEntity != null) { @@ -373,6 +373,7 @@ public class DialogUtils { TextView cancelBtn = contentView.findViewById(R.id.cancel); TextView confirmBtn = contentView.findViewById(R.id.confirm); View middleLine = contentView.findViewById(R.id.middle_line); + View closeIv = contentView.findViewById(R.id.closeIv); titleTv.setGravity(gravity); contentTv.setGravity(gravity); @@ -389,6 +390,8 @@ public class DialogUtils { confirmBtn.setVisibility(View.GONE); middleLine.setVisibility(View.GONE); } + closeIv.setVisibility(shouldShowCloseBtn ? View.VISIBLE : View.GONE); + closeIv.setOnClickListener(v -> dialog.dismiss()); cancelBtn.setOnClickListener(v -> { if (clListener != null) clListener.onCancel(); @@ -413,7 +416,12 @@ public class DialogUtils { public static Dialog showNewAlertDialog(Context context, String title, CharSequence message , String negative, String positive, final CancelListener clListener, final ConfirmListener cmListener) { - return showNewAlertDialog(context, title, message, negative, positive, null, Gravity.LEFT, clListener, cmListener); + return showNewAlertDialog(context, title, message, negative, positive, null, Gravity.LEFT, false, clListener, cmListener); + } + + public static Dialog showNewAlertDialog(Context context, String title, CharSequence message + , String negative, String positive, int gravity, boolean shouldShowCloseBtn, final CancelListener clListener, final ConfirmListener cmListener) { + return showNewAlertDialog(context, title, message, negative, positive, null, gravity, shouldShowCloseBtn, clListener, cmListener); } /** @@ -1951,8 +1959,8 @@ public class DialogUtils { final Dialog dialog = new Dialog(context, R.style.DialogWindowTransparent); View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_energy, null); - ((TextView)contentView.findViewById(R.id.userName)).setText("\"" + userName + "\""); - ((TextView)contentView.findViewById(R.id.energy)).setText(energy + ""); + ((TextView) contentView.findViewById(R.id.userName)).setText("\"" + userName + "\""); + ((TextView) contentView.findViewById(R.id.energy)).setText(energy + ""); contentView.findViewById(R.id.dialog_positive).setOnClickListener(v -> { dialog.dismiss(); diff --git a/app/src/main/java/com/gh/common/view/RichEditor.java b/app/src/main/java/com/gh/common/view/RichEditor.java index b9fbe2bcc4..c48ec0265d 100644 --- a/app/src/main/java/com/gh/common/view/RichEditor.java +++ b/app/src/main/java/com/gh/common/view/RichEditor.java @@ -24,6 +24,7 @@ import com.gh.common.util.HtmlUtils; import com.gh.common.util.ImageUtils; import com.gh.common.util.MtaHelper; import com.gh.common.util.NetworkUtils; +import com.gh.common.util.PackageUtils; import com.gh.common.util.RichEditorUtils; import com.gh.common.util.SPUtils; import com.gh.gamecenter.BuildConfig; @@ -662,6 +663,16 @@ public class RichEditor extends WebView { return DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()); } + @JavascriptInterface + public String getAppVersion() { + return BuildConfig.VERSION_NAME; + } + + @JavascriptInterface + public int getAppVersionCode() { + return PackageUtils.getVersionCode(); + } + /** * 显示toast * diff --git a/app/src/main/java/com/gh/gamecenter/forum/follow/ForumMyFollowAdapter.kt b/app/src/main/java/com/gh/gamecenter/forum/follow/ForumMyFollowAdapter.kt index f5f9a4ea8b..6949f5edc5 100644 --- a/app/src/main/java/com/gh/gamecenter/forum/follow/ForumMyFollowAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/forum/follow/ForumMyFollowAdapter.kt @@ -69,7 +69,7 @@ class ForumMyFollowAdapter(context: Context, val mViewModel: ForumMyFollowViewMo popupWindow.dismiss() when (text) { "取消关注" -> { - DialogUtils.showNewAlertDialog(mContext, "提示", "确定取消关注", "暂不", "确定", null, Gravity.CENTER, {}, { + DialogUtils.showNewAlertDialog(mContext, "提示", "确定取消关注", "暂不", "确定", null, Gravity.CENTER, false, {}, { MtaHelper.onEvent("论坛首页", "我关注的论坛", "取消关注") mViewModel.unFollowForum(entity.id) { EventBus.getDefault().post(EBForumFollowChange(entity, false)) diff --git a/app/src/main/java/com/gh/gamecenter/forum/select/ForumAdapter.kt b/app/src/main/java/com/gh/gamecenter/forum/select/ForumAdapter.kt index 8dc6b38389..84e44ab883 100644 --- a/app/src/main/java/com/gh/gamecenter/forum/select/ForumAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/forum/select/ForumAdapter.kt @@ -54,7 +54,7 @@ class ForumAdapter(val context: Context, val mViewModel: ForumSelectViewModel?, mContext.ifLogin("论坛-选择论坛") { debounceActionWithInterval(it.id) { if (forumEntity.isFollow) { - DialogUtils.showNewAlertDialog(mContext, "提示", "确定取消关注", "暂不", "确定", null, Gravity.CENTER, {}, { + DialogUtils.showNewAlertDialog(mContext, "提示", "确定取消关注", "暂不", "确定", null, Gravity.CENTER, false, {}, { mViewModel?.unFollowForum(forumEntity.id) { MtaHelper.onEvent("论坛首页", "选择论坛", "关注") forumEntity.isFollow = false diff --git a/app/src/main/java/com/gh/gamecenter/qa/answer/edit/AnswerEditActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/answer/edit/AnswerEditActivity.kt index 55a83b1203..0bd6ab2efa 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/answer/edit/AnswerEditActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/answer/edit/AnswerEditActivity.kt @@ -31,8 +31,6 @@ import com.gh.gamecenter.qa.entity.Questions import com.gh.gamecenter.video.VideoVerifyItemViewHolder import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel import com.halo.assistant.HaloApp -import com.lightgame.utils.Util_System_Keyboard -import com.lightgame.utils.Utils import com.zhihu.matisse.Matisse import com.zhihu.matisse.MimeType import org.json.JSONArray @@ -44,6 +42,7 @@ import org.json.JSONObject class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { private lateinit var mMenuDraft: MenuItem + private lateinit var mMenuPost: MenuItem private lateinit var mBinding: FragmentAnswerEditBinding private lateinit var mViewModel: AnswerEditViewModel @@ -84,6 +83,7 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { super.onCreate(savedInstanceState) setToolbarMenu(R.menu.menu_answer_post) mMenuDraft = mToolbar.menu.findItem(R.id.menu_draft) + mMenuPost = mToolbar.menu.findItem(R.id.menu_answer_post) mCommunityName = intent?.getStringExtra(EntranceUtils.KEY_COMMUNITY_NAME) mOpenAnswerInNewPage = intent?.getBooleanExtra(EntranceUtils.KEY_ANSWER_OPEN_IN_NEW_PAGE, false)!! mBinding = FragmentAnswerEditBinding.bind(mContentView) @@ -108,6 +108,7 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { mBinding.answerPlaceholder.visibility = if (t.contains(" @@ -134,6 +135,7 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { mKeyboardHeightProvider = KeyboardHeightProvider(this) mBinding.root.post { mKeyboardHeightProvider?.start() } + checkPostButtonEnable() } override fun getLayoutId(): Int { @@ -277,6 +279,7 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { mViewModel.draftsLiveData.observe(this, Observer { mRichEditor.setHtml(it, false) requestFocusAndMoveCursorToEnd() + checkPostButtonEnable() }) mViewModel.saveDraftsLiveData.observeNonNull(this) { @@ -375,23 +378,32 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { val answerContent = getReplaceRealContent() mRichEditor.showLinkStyle() if (mRichEditor.hasPlaceholderImage()) { - ToastUtils.showToast("图片正在上传中") + ToastUtils.showToast("图片上传ing") return@postDelayed } - // filter rule - val answerLength = HtmlUtils.stripHtml(answerContent).length - if (answerLength < MIN_ANSWER_TEXT_LENGTH) { - ToastUtils.showToast(getString(R.string.answer_beneath_length_limit), if (mIsKeyBoardShow) Gravity.CENTER else -1) - return@postDelayed - } else if (answerLength > MAX_ANSWER_TEXT_LENGTH) { - ToastUtils.showToast("回答最多输入10000个字", if (mIsKeyBoardShow) Gravity.CENTER else -1) - return@postDelayed + if (checkData(answerContent)) { + mViewModel.postAnswer(answerContent) } - mViewModel.postAnswer(answerContent) }, 100) } } + private fun checkData(answerContent: String, isShowToast: Boolean = true): Boolean { + val answerLength = HtmlUtils.stripHtml(answerContent).length + if (answerLength < MIN_ANSWER_TEXT_LENGTH) { + if (isShowToast) ToastUtils.showToast(getString(R.string.answer_beneath_length_limit), if (mIsKeyBoardShow) Gravity.CENTER else -1) + return false + } else if (answerLength > MAX_ANSWER_TEXT_LENGTH) { + if (isShowToast) ToastUtils.showToast("回答最多输入10000个字", if (mIsKeyBoardShow) Gravity.CENTER else -1) + return false + } + val draftValue = mViewModel.draftsLiveData.value + if (!draftValue.isNullOrEmpty()) { + return draftValue != answerContent + } + return true + } + private fun getReplaceRealContent(): String { var answerContent = mRichEditor.html for (s in mViewModel.mapImages.keys) { @@ -403,6 +415,12 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { return answerContent } + private fun checkPostButtonEnable() { + val answerContent = getReplaceRealContent() + val isEnabled = checkData(answerContent, false) + mMenuPost.actionView.alpha = if (isEnabled) 1f else 0.6f + } + override fun handleBackPressed(): Boolean { return if (TextUtils.isEmpty(UserManager.getInstance().token)) { false @@ -417,14 +435,9 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { && !mRichEditor.html.contains(" { - DialogUtils.showNewAlertDialog(binding.root.context, "提示", "是否将此条评论置顶?", "取消", "确认", null, Gravity.CENTER, {}, { + DialogUtils.showNewAlertDialog(binding.root.context, "提示", "是否将此条评论置顶?", "取消", "确认", null, Gravity.CENTER, false, {}, { commentTop(binding.root.context, viewModel, comment, false) }) } "取消置顶" -> { - DialogUtils.showNewAlertDialog(binding.root.context, "提示", "是否将此条评论取消置顶?", "取消", "确认", null, Gravity.CENTER, {}, { + DialogUtils.showNewAlertDialog(binding.root.context, "提示", "是否将此条评论取消置顶?", "取消", "确认", null, Gravity.CENTER, false, {}, { viewModel.updateCommentTop(comment.id ?: "", top = false, isAgain = false) { isSuccess, errorCode -> if (isSuccess) { @@ -433,7 +433,7 @@ abstract class BaseArticleDetailCommentAdapter(context: Context, viewModel.load(LoadType.REFRESH) } else { if (errorCode == 403095) { - DialogUtils.showNewAlertDialog(context, "提示", "当前已有置顶评论,\n是否将此条评论覆盖展示?", "取消", "确认", null, Gravity.CENTER, {}, { + DialogUtils.showNewAlertDialog(context, "提示", "当前已有置顶评论,\n是否将此条评论覆盖展示?", "取消", "确认", null, Gravity.CENTER, false, {}, { commentTop(context, viewModel, comment, true) }) } diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/draft/ArticleDraftFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/article/draft/ArticleDraftFragment.kt index 6245086e2e..fd2187c7f2 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/draft/ArticleDraftFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/draft/ArticleDraftFragment.kt @@ -3,10 +3,13 @@ package com.gh.gamecenter.qa.article.draft import android.app.Activity import android.content.Intent import android.os.Bundle +import androidx.core.content.ContextCompat import androidx.lifecycle.ViewModelProviders +import androidx.recyclerview.widget.RecyclerView import com.gh.common.util.EntranceUtils import com.gh.common.util.UrlFilterUtils import com.gh.common.util.checkStoragePermissionBeforeAction +import com.gh.common.view.CustomDividerItemDecoration import com.gh.gamecenter.R import com.gh.gamecenter.baselist.ListFragment import com.gh.gamecenter.baselist.LoadType @@ -89,6 +92,12 @@ class ArticleDraftFragment : ListFragment() { override fun onResponse(response: ResponseBody?) { - mListViewModel.load(LoadType.REFRESH) + val index = mAdapter?.entityList?.indexOf(entity) ?: -1 + if (index >= 0) { + mAdapter?.entityList?.remove(entity) + if (mAdapter?.entityList.isNullOrEmpty()) { + mListViewModel.load(LoadType.REFRESH) + } else { + mAdapter?.notifyItemRemoved(index) + } + } } override fun onFailure(e: HttpException?) { diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditActivity.kt index 015d7b27c6..0369558ed5 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditActivity.kt @@ -9,9 +9,9 @@ import android.os.Bundle import android.os.Message import android.text.InputFilter import android.text.TextUtils +import android.view.Gravity import android.view.MenuItem import android.view.View -import android.view.inputmethod.InputMethodManager import android.widget.* import androidx.core.content.ContextCompat import androidx.core.widget.doOnTextChanged @@ -138,8 +138,6 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { //setEditTextInputSpace() mEditTitle.filters = arrayOf(TextHelper.getFilter(50, "标题最多50个字")) - mEditTitle.requestFocus() - mEditTitle.doOnTextChanged { text, start, count, after -> if (text?.contains("\n") == true) { mEditTitle.setText(text.toString().replace("\n", "")) @@ -194,7 +192,7 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { EventBus.getDefault().post(EBReuse(ARTICLE_DRAFT_CHANGE_TAG)) finish() } else { - showDraftFailureDialog() + //showDraftFailureDialog() } } SaveDraftType.AUTO -> { @@ -288,6 +286,7 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { mGameName.isEnabled = false mGameName.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null) } + mEditTitle.requestFocus() } mViewModel.notSelectForum.observe(this, Observer { if (it) showSelectGameDialog() @@ -361,7 +360,6 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { mViewModel.mSelectCommunityData?.icon = mViewModel.draftEntity?.community?.game?.getIcon() mViewModel.mSelectCommunityData?.iconSubscript = mViewModel.draftEntity?.community?.game?.iconSubscript mEditTitle.setText(mViewModel.draftEntity?.title) - mMenuDraft.isVisible = false mGameName.isEnabled = true setGameName() mViewModel.getArticleDraftsContent(mViewModel.draftEntity?.id!!) @@ -373,7 +371,8 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { mViewModel.mSelectCommunityData?.iconSubscript = mViewModel.detailEntity?.community?.game?.iconSubscript setGameName() - mMenuDraft.isVisible = true + //编辑帖子草稿箱入口不存在 + mMenuDraft.isVisible = false mGameName.isEnabled = false mGameName.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null) @@ -391,9 +390,6 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { mRichEditor.setHtml(html, false) try { mRichEditor.scrollTo(0, 10000000) - val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - imm.showSoftInput(mRichEditor, InputMethodManager.SHOW_IMPLICIT) - mRichEditor.postDelayed({ mRichEditor.focusEditor() }, 800) } catch (e: Exception) { e.printStackTrace() } @@ -418,70 +414,57 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { return false } - if (mViewModel.detailEntity != null) { - return if (!TextUtils.isEmpty(mEditTitle.text) - || mRichEditor.html.contains(" MAX_ARTICLE_TEXT_LENGTH) return false + if (detailEntity != null && detailEntity?.title == title && HtmlUtils.stripHtml(detailEntity?.content) == HtmlUtils.stripHtml(content)) return false return true } - /** - * 根据问题标题获取相应标签(标签默认选中) - */ - fun loadTitleTags() { - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true)) - mApi - .getQuestionTagsByTitle(mSelectCommunityData?.id, UrlFilterUtils.getFilterQuery("title", title)) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(object : Response>() { - override fun onResponse(response: List?) { - titleTags.postValue(response) - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", false)) - } - - override fun onFailure(e: HttpException?) { - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", false)) - Utils.toast(getApplication(), R.string.request_failure_normal_hint) - } - }) - } - - /** * 检查图片是否符合规则并上传图片 * @param picPath 图片本地路径 diff --git a/app/src/main/java/com/gh/gamecenter/qa/draft/CommunityDraftWrapperActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/draft/CommunityDraftWrapperActivity.kt index b4dc0764e1..d6c483307c 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/draft/CommunityDraftWrapperActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/draft/CommunityDraftWrapperActivity.kt @@ -7,6 +7,7 @@ import androidx.fragment.app.Fragment import com.gh.base.BaseActivity_TabLayout import com.gh.gamecenter.qa.article.draft.ArticleDraftFragment import com.gh.gamecenter.qa.answer.draft.AnswerDraftFragment +import com.gh.gamecenter.qa.questions.draft.QuestionDraftFragment class CommunityDraftWrapperActivity : BaseActivity_TabLayout() { @@ -16,13 +17,13 @@ class CommunityDraftWrapperActivity : BaseActivity_TabLayout() { } override fun initFragmentList(fragments: MutableList) { - fragments.add(AnswerDraftFragment()) fragments.add(ArticleDraftFragment()) + fragments.add(QuestionDraftFragment()) } override fun initTabTitleList(tabTitleList: MutableList) { - tabTitleList.add("回答草稿") tabTitleList.add("帖子草稿") + tabTitleList.add("问题草稿") } companion object { diff --git a/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleViewModel.kt index 9e6b96ad31..e6bd143144 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleViewModel.kt @@ -5,6 +5,7 @@ import androidx.annotation.Keep import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import com.gh.gamecenter.baselist.ListViewModel +import com.gh.gamecenter.entity.UserEntity import com.gh.gamecenter.manager.UserManager import com.gh.gamecenter.qa.entity.ArticleEntity import com.gh.gamecenter.retrofit.RetrofitManager @@ -36,6 +37,14 @@ class ArticleViewModel(application: Application, private val articleType: Insert } i++ } + + if (articleType == InsertArticleWrapperActivity.ArticleType.MINE_ARTICLE) { + val userInfoEntity = UserManager.getInstance().userInfoEntity + list.forEach { + it.user = UserEntity(userInfoEntity?.icon, userInfoEntity?.name, userInfoEntity?.userId, + auth = userInfoEntity?.auth, badge = userInfoEntity?.badge) + } + } return list } diff --git a/app/src/main/java/com/gh/gamecenter/qa/entity/AnswerEntity.kt b/app/src/main/java/com/gh/gamecenter/qa/entity/AnswerEntity.kt index 07528712e4..09361c5e1a 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/entity/AnswerEntity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/entity/AnswerEntity.kt @@ -40,6 +40,7 @@ class AnswerEntity() : Parcelable { @SerializedName("sequence_id") var sequenceId: String? = null + @SerializedName("brief", alternate = ["content"]) var brief: String? = null @SerializedName("title") @@ -108,6 +109,10 @@ class AnswerEntity() : Parcelable { @Ignore var description: String? = "" + @Ignore + @SerializedName("popular_answer") + var popularAnswer: AnswerEntity? = null + fun getPassVideos(): List { val passVideos = arrayListOf() for (video in videos) { diff --git a/app/src/main/java/com/gh/gamecenter/qa/entity/QuestionDraftEntity.kt b/app/src/main/java/com/gh/gamecenter/qa/entity/QuestionDraftEntity.kt new file mode 100644 index 0000000000..12c7439724 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/entity/QuestionDraftEntity.kt @@ -0,0 +1,20 @@ +package com.gh.gamecenter.qa.entity + +import android.os.Parcelable +import com.gh.gamecenter.entity.CommunityEntity +import com.google.gson.annotations.SerializedName +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class QuestionDraftEntity( + @SerializedName("_id") + var id: String = "", + @SerializedName("community_id") + var communityId:String="", + var bbs: CommunityEntity? = null, + var title: String = "", + var description: String = "", + var images: ArrayList = arrayListOf(), + var videos: ArrayList = arrayListOf(), + var tags: List = arrayListOf() +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/entity/QuestionsDetailEntity.kt b/app/src/main/java/com/gh/gamecenter/qa/entity/QuestionsDetailEntity.kt index 4cbceaa194..9964c94d11 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/entity/QuestionsDetailEntity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/entity/QuestionsDetailEntity.kt @@ -29,7 +29,11 @@ data class QuestionsDetailEntity(var id: String? = null, var me: MeEntity = MeEntity(), @SerializedName("follow_count") private var followCount: Int = 0, - var user: UserEntity = UserEntity()) : Parcelable { + var user: UserEntity = UserEntity(), + //提交问题用 + @SerializedName("draft_id") + var draftId: String = "" +) : Parcelable { fun getFollowCount(): Int { return if (followCount == 0) 1 else { diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftActivity.kt new file mode 100644 index 0000000000..349eee17ab --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftActivity.kt @@ -0,0 +1,17 @@ +package com.gh.gamecenter.qa.questions.draft + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.gh.common.util.EntranceUtils +import com.gh.gamecenter.NormalActivity + +class QuestionDraftActivity : NormalActivity() { + + companion object { + fun getIntent(context: Context): Intent { + val bundle = Bundle() + return getTargetIntent(context, QuestionDraftActivity::class.java, QuestionDraftFragment::class.java, bundle) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftAdapter.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftAdapter.kt new file mode 100644 index 0000000000..7cd8821a95 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftAdapter.kt @@ -0,0 +1,71 @@ +package com.gh.gamecenter.qa.questions.draft + +import android.content.Context +import android.text.TextUtils +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.gh.base.BaseRecyclerViewHolder +import com.gh.common.constant.ItemViewType +import com.gh.common.util.DialogUtils +import com.gh.gamecenter.R +import com.gh.gamecenter.adapter.viewholder.FooterViewHolder +import com.gh.gamecenter.baselist.ListAdapter +import com.gh.gamecenter.databinding.CommunityQuestionDraftItemBinding +import com.gh.gamecenter.qa.entity.QuestionDraftEntity + +class QuestionDraftAdapter(val context: Context, val mViewModel: QuestionDraftViewModel?,private val selectCallback: (QuestionDraftEntity) -> Unit) : ListAdapter(context) { + + override fun areItemsTheSame(oldItem: QuestionDraftEntity, newItem: QuestionDraftEntity): Boolean { + return !TextUtils.isEmpty(oldItem.id) && oldItem.id == newItem.id + } + + override fun areContentsTheSame(oldItem: QuestionDraftEntity, newItem: QuestionDraftEntity): Boolean { + return oldItem == newItem + } + + override fun getItemViewType(position: Int): Int { + return if (position == itemCount - 1) { + ItemViewType.ITEM_FOOTER + } else ItemViewType.ITEM_BODY + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + val view: View + return when (viewType) { + ItemViewType.ITEM_FOOTER -> { + view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false) + FooterViewHolder(view) + } + else -> { + view = mLayoutInflater.inflate(R.layout.community_question_draft_item, parent, false) + QuestionDraftViewHolder(CommunityQuestionDraftItemBinding.bind(view)) + } + } + } + + override fun getItemCount(): Int { + return if (mEntityList == null || mEntityList.isEmpty()) 0 else mEntityList.size + FOOTER_ITEM_COUNT + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is QuestionDraftViewHolder) { + val entity = mEntityList[position] + holder.binding.data = entity + holder.binding.articleDraftDelete.setOnClickListener { + DialogUtils.showAlertDialog(mContext, "警告", "确定要删除问题草稿吗?删除之后不可恢复", + "确定", "取消", DialogUtils.ConfirmListener { + mViewModel?.deleteDraft(entity.id) + }, null) + } + holder.itemView.setOnClickListener { + selectCallback.invoke(entity) + } + } else if (holder is FooterViewHolder) { + holder.initItemPadding() + holder.initFooterViewHolder(mIsLoading, isNetworkError, mIsOver, R.string.ask_loadover_hint) + } + } + + class QuestionDraftViewHolder(val binding: CommunityQuestionDraftItemBinding) : BaseRecyclerViewHolder(binding.root) +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftFragment.kt new file mode 100644 index 0000000000..1921561f7a --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftFragment.kt @@ -0,0 +1,94 @@ +package com.gh.gamecenter.qa.questions.draft + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import androidx.core.content.ContextCompat +import androidx.lifecycle.Observer +import androidx.recyclerview.widget.RecyclerView +import com.gh.common.util.ToastUtils +import com.gh.common.util.checkStoragePermissionBeforeAction +import com.gh.common.util.viewModelProvider +import com.gh.common.view.CustomDividerItemDecoration +import com.gh.gamecenter.R +import com.gh.gamecenter.baselist.ListAdapter +import com.gh.gamecenter.baselist.ListFragment +import com.gh.gamecenter.baselist.LoadType +import com.gh.gamecenter.eventbus.EBReuse +import com.gh.gamecenter.qa.article.edit.ArticleEditActivity +import com.gh.gamecenter.qa.draft.CommunityDraftWrapperActivity +import com.gh.gamecenter.qa.entity.ArticleDetailEntity +import com.gh.gamecenter.qa.entity.ArticleDraftEntity +import com.gh.gamecenter.qa.entity.QuestionDraftEntity +import com.gh.gamecenter.qa.questions.edit.QuestionEditActivity +import org.greenrobot.eventbus.Subscribe +import org.greenrobot.eventbus.ThreadMode + +class QuestionDraftFragment : ListFragment() { + + var mAdapter: QuestionDraftAdapter? = null + lateinit var mViewModel: QuestionDraftViewModel + + override fun provideListAdapter(): ListAdapter<*> { + return mAdapter ?: QuestionDraftAdapter(requireContext(), mViewModel) { + if (activity is CommunityDraftWrapperActivity) { + checkStoragePermissionBeforeAction { + val intent = QuestionEditActivity.getDraftIntent(requireContext(), it) + startActivity(intent) + } + } else { + checkStoragePermissionBeforeAction { + val intent = Intent() + intent.putExtra(QuestionDraftEntity::class.java.simpleName, it) + requireActivity().setResult(Activity.RESULT_OK, intent) + requireActivity().finish() + } + } + }.apply { + mAdapter = this + } + } + + override fun provideListViewModel(): QuestionDraftViewModel { + mViewModel = viewModelProvider() + return mViewModel + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (activity is QuestionDraftActivity) { + setNavigationTitle("问题草稿") + } + mViewModel.deleteDraftSuccess.observe(this, Observer { pair -> + if (pair.second) { + val draftId = pair.first + val index = mAdapter?.entityList?.indexOfFirst { it.id == draftId } ?: -1 + if (index >= 0) { + mAdapter?.entityList?.removeAt(index) + if (mAdapter?.entityList.isNullOrEmpty()) { + mListViewModel.load(LoadType.REFRESH) + } else { + mAdapter?.notifyItemRemoved(index) + } + + ToastUtils.showToast("删除成功") + } + + } + }) + } + + override fun getItemDecoration(): RecyclerView.ItemDecoration? { + val insetDivider = ContextCompat.getDrawable(requireContext(), R.drawable.divider_item_line_space_16) + val itemDecoration = CustomDividerItemDecoration(requireContext(), notDecorateTheLastItem = true) + itemDecoration.setDrawable(insetDivider!!) + return itemDecoration + } + + @Subscribe(threadMode = ThreadMode.MAIN) + fun onEventMainThread(reuse: EBReuse) { + if (QuestionEditActivity.QUESTION_DRAFT_CHANGE_TAG == reuse.type) { + mBaseHandler.postDelayed({ mListViewModel.load(LoadType.REFRESH) }, 100) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftViewModel.kt new file mode 100644 index 0000000000..6b720870cf --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftViewModel.kt @@ -0,0 +1,46 @@ +package com.gh.gamecenter.qa.questions.draft + +import android.annotation.SuppressLint +import android.app.Application +import androidx.lifecycle.MutableLiveData +import com.gh.common.util.observableToMain +import com.gh.gamecenter.baselist.ListViewModel +import com.gh.gamecenter.manager.UserManager +import com.gh.gamecenter.qa.entity.QuestionDraftEntity +import com.gh.gamecenter.retrofit.Response +import com.gh.gamecenter.retrofit.RetrofitManager +import com.halo.assistant.HaloApp +import io.reactivex.Observable +import okhttp3.ResponseBody +import retrofit2.HttpException + +class QuestionDraftViewModel(application: Application) : ListViewModel(application) { + val deleteDraftSuccess = MutableLiveData>() + private val api = RetrofitManager.getInstance(HaloApp.getInstance().application).api + + override fun provideDataObservable(page: Int): Observable> { + return api.getQuestionDrafts(UserManager.getInstance().userId) + } + + override fun mergeResultLiveData() { + mResultLiveData.addSource(mListLiveData) { mResultLiveData.postValue(it) } + } + + @SuppressLint("CheckResult") + fun deleteDraft(draftId: String) { + api.deleteQuestionDraft(UserManager.getInstance().userId, draftId) + .compose(observableToMain()) + .subscribe(object :Response(){ + override fun onResponse(response: ResponseBody?) { + super.onResponse(response) + deleteDraftSuccess.postValue(Pair(draftId, true)) + } + + override fun onFailure(e: HttpException?) { + super.onFailure(e) + deleteDraftSuccess.postValue(Pair(draftId, false)) + } + }) + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditActivity.kt index c61d2b148c..9d56d6a714 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditActivity.kt @@ -9,24 +9,18 @@ import android.graphics.Color import android.graphics.LinearGradient import android.graphics.Shader import android.os.Bundle +import android.os.Message import android.text.Editable +import android.text.TextUtils import android.text.TextWatcher -import android.view.KeyEvent -import android.view.MenuItem -import android.view.View -import android.view.Window +import android.view.* import android.widget.EditText -import android.widget.ProgressBar -import android.widget.RelativeLayout import androidx.core.content.ContextCompat import androidx.core.widget.addTextChangedListener import androidx.databinding.DataBindingUtil import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders -import androidx.recyclerview.widget.GridLayoutManager -import androidx.recyclerview.widget.RecyclerView import com.gh.base.ToolBarActivity -import com.gh.base.fragment.BaseDialogWrapperFragment import com.gh.base.fragment.WaitingDialogFragment import com.gh.common.AppExecutor import com.gh.common.util.* @@ -39,17 +33,23 @@ import com.gh.gamecenter.entity.CommunityEntity import com.gh.gamecenter.entity.MyVideoEntity import com.gh.gamecenter.entity.NotificationUgc import com.gh.gamecenter.entity.Permissions +import com.gh.gamecenter.eventbus.EBReuse import com.gh.gamecenter.mvvm.Status -import com.gh.gamecenter.qa.article.edit.ArticleSelectGameAdapter -import com.gh.gamecenter.qa.article.edit.ArticleTagsSelectFragment +import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity +import com.gh.gamecenter.qa.article.draft.ArticleDraftActivity +import com.gh.gamecenter.qa.article.edit.ArticleEditActivity import com.gh.gamecenter.qa.dialog.ChooseForumDialogFragment import com.gh.gamecenter.qa.editor.VideoActivity import com.gh.gamecenter.qa.entity.CommunityVideoEntity +import com.gh.gamecenter.qa.entity.QuestionDraftEntity import com.gh.gamecenter.qa.entity.QuestionsDetailEntity +import com.gh.gamecenter.qa.questions.draft.QuestionDraftActivity import com.gh.gamecenter.qa.questions.edit.pic.QuestionsEditPicAdapter import com.gh.gamecenter.qa.questions.edit.tip.QuestionTitleTipAdapter import com.lightgame.utils.Util_System_Keyboard +import com.lightgame.utils.Utils import com.zhihu.matisse.Matisse +import org.greenrobot.eventbus.EventBus import org.json.JSONObject import kotlin.math.abs @@ -66,10 +66,12 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { private var mUploadImageCancelDialog: Dialog? = null private var mKeyboardHeightProvider: KeyboardHeightProvider? = null private lateinit var picAdapter: QuestionsEditPicAdapter + private lateinit var mMenuDraft: MenuItem private lateinit var mMenuPost: MenuItem private var mIsExtendedKeyboardShow = false private var mOffset = 0 private var mTagsSelectFragment: TagsSelectFragment? = null + private var mPostDraftsCount: Int = 0 private val mSaveTitleKey = "title" private val mSaveContentKey = "content" @@ -96,6 +98,25 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { duration = RichEditor.formatVideoDuration(videoEntity.length), status = videoEntity.status)) } + } else if (requestCode == QUESTION_DRAFT_REQUEST_CODE && resultCode == RESULT_OK) { + val draftEntity = data?.getParcelableExtra(QuestionDraftEntity::class.java.simpleName) + if (draftEntity != null) { + mViewModel.questionDraftEntity = draftEntity + setQuestionDraft(draftEntity) + mViewModel.getQuestionDraftContent(draftEntity.id) + } + } + } + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + if (msg.what == 1) { + if (mViewModel.communityEntity != null + && !mViewModel.title.isNullOrEmpty() + && !mViewModel.content.isNullOrEmpty()) { + mViewModel.saveQuestionDraft(SaveDraftType.AUTO) + } + mBaseHandler.sendEmptyMessageDelayed(1, SAVE_DRAFTS_INTERVAL_TIME.toLong()) } } @@ -104,6 +125,7 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { setToolbarMenu(R.menu.menu_question_post) mToolbar.navigationIcon = null + mMenuDraft = mToolbar.menu.findItem(R.id.menu_draft) mMenuPost = mToolbar.menu.findItem(R.id.menu_question_post) mViewModel = ViewModelProviders.of(this).get(QuestionEditViewModel::class.java) if (savedInstanceState != null) { @@ -127,24 +149,25 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { if (intent != null) { val communityEntity = intent.getParcelableExtra(CommunityEntity::class.java.simpleName) val detailEntity = intent.getParcelableExtra(QuestionsDetailEntity::class.java.simpleName) - if (detailEntity != null) { // 问题编辑 - mViewModel.questionEntity = detailEntity - mViewModel.communityEntity = detailEntity.community - mViewModel.communityEntity?.icon = detailEntity.community.game?.getIcon() - mViewModel.communityEntity?.iconSubscript = detailEntity.community.game?.iconSubscript - setForumName() - mViewModel.content = detailEntity.description - mViewModel.picList.postValue(ArrayList(detailEntity.images)) - mViewModel.isModeratorPatch = intent.getBooleanExtra(EntranceUtils.KEY_QUESTION_MODERATOR_PATCH, false) - val videos = detailEntity.videos - if (videos.isNotEmpty()) mViewModel.videoLiveData.postValue(detailEntity.videos[0]) - if (mViewModel.title.isNullOrEmpty()) mViewModel.title = detailEntity.title - } else { // 新增问题 - var searchKey = intent.getStringExtra(EntranceUtils.KEY_QUESTIONS_SEARCH_KEY) - if (!searchKey.isNullOrEmpty() && searchKey.length > QuestionEditViewModel.QUESTION_TITLE_MAX_LENGTH) - searchKey = searchKey.substring(0, QuestionEditViewModel.QUESTION_TITLE_MAX_LENGTH) - if (mViewModel.title.isNullOrEmpty()) mViewModel.title = searchKey - mViewModel.isFromSearch = intent.getBooleanExtra(QuestionEditViewModel.QUESTION_FORM_SEARCH, false) + val draftEntity = intent.getParcelableExtra(QuestionDraftEntity::class.java.simpleName) + when { + detailEntity != null -> { // 问题编辑 + setPatchContent(detailEntity) + } + draftEntity != null -> { //草稿编辑 + mViewModel.questionDraftEntity = draftEntity + setQuestionDraft(draftEntity) + mViewModel.getQuestionDraftContent(draftEntity.id) + mBaseHandler.sendEmptyMessageDelayed(1, SAVE_DRAFTS_INTERVAL_TIME.toLong()) + } + else -> { // 新增问题 + var searchKey = intent.getStringExtra(EntranceUtils.KEY_QUESTIONS_SEARCH_KEY) + if (!searchKey.isNullOrEmpty() && searchKey.length > QuestionEditViewModel.QUESTION_TITLE_MAX_LENGTH) + searchKey = searchKey.substring(0, QuestionEditViewModel.QUESTION_TITLE_MAX_LENGTH) + if (mViewModel.title.isNullOrEmpty()) mViewModel.title = searchKey + mViewModel.isFromSearch = intent.getBooleanExtra(QuestionEditViewModel.QUESTION_FORM_SEARCH, false) + mBaseHandler.sendEmptyMessageDelayed(1, SAVE_DRAFTS_INTERVAL_TIME.toLong()) + } } if (communityEntity != null) { @@ -152,7 +175,6 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { setForumName() mBinding.chooseForumTv.isEnabled = false mBinding.chooseForumTv.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null) - if (!mViewModel.isFromSearch) mViewModel.checkQuestionDraft() } } @@ -195,6 +217,7 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { mBinding.questionseditContent.filters = arrayOf(TextHelper.getFilter(300, "内容最多300个字")) mBinding.questionseditContent.addTextChangedListener { mBinding.editorTextNumTv.text = "${mBinding.questionseditContent.text.length}/300" + checkPostButtonEnable() } mBinding.questionseditContent.setOnTouchListener { v, event -> closeExtendedKeyboard() @@ -236,6 +259,35 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { observeData() } + private fun setPatchContent(detailEntity: QuestionsDetailEntity) { + mMenuDraft.isVisible = false + mViewModel.questionEntity = detailEntity + mViewModel.communityEntity = detailEntity.community + mViewModel.communityEntity?.icon = detailEntity.community.game?.getIcon() + mViewModel.communityEntity?.iconSubscript = detailEntity.community.game?.iconSubscript + mViewModel.content = detailEntity.description + mViewModel.picList.postValue(ArrayList(detailEntity.images)) + mViewModel.isModeratorPatch = intent.getBooleanExtra(EntranceUtils.KEY_QUESTION_MODERATOR_PATCH, false) + val videos = detailEntity.videos + if (videos.isNotEmpty()) mViewModel.videoLiveData.postValue(detailEntity.videos[0]) + if (mViewModel.title.isNullOrEmpty()) mViewModel.title = detailEntity.title + setForumName() + } + + private fun setQuestionDraft(draftEntity: QuestionDraftEntity) { + mViewModel.communityEntity = draftEntity.bbs + mViewModel.communityEntity?.icon = draftEntity.bbs?.game?.getIcon() + mViewModel.communityEntity?.iconSubscript = draftEntity.bbs?.game?.iconSubscript + mViewModel.title = draftEntity.title + mViewModel.content = draftEntity.description + mViewModel.picList.postValue(draftEntity.images) + val videos = draftEntity.videos + if (videos.isNotEmpty()) mViewModel.videoLiveData.postValue(videos[0]) + mBinding.questionseditTitle.setText(mViewModel.title) + mBinding.questionseditContent.setText(mViewModel.content) + setForumName() + } + private fun observeData() { mViewModel.moderatorPostLiveData.observe(this, Observer { if (it?.status == Status.SUCCESS) { @@ -269,6 +321,41 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { toast(R.string.post_failure_hint) } }) + mViewModel.postQuestionDrafts.observe(this, Observer { pair -> + if (pair != null) { + when (pair.first) { + SaveDraftType.EXIT -> { + if (pair.second) { + Utils.toast(this, "问题已保存到草稿箱") + EventBus.getDefault().post(EBReuse(ArticleEditActivity.ARTICLE_DRAFT_CHANGE_TAG)) + finish() + } + } + SaveDraftType.AUTO -> { + if (pair.second) { + if (mPostDraftsCount >= AnswerEditActivity.SAVE_DRAFTS_TOAST_COUNT) { + mPostDraftsCount = 0 + Utils.toast(this, "问题已保存到草稿箱") + } else { + mPostDraftsCount++ + } + } + } + SaveDraftType.SKIP -> { + if (pair.second) { + Utils.toast(this, "问题已保存到草稿箱") + startActivityForResult(ArticleDraftActivity.getIntent(this), ArticleEditActivity.ARTICLE_DRAFT_REQUEST_CODE) + } else { + Utils.toast(this, "问题草稿保存失败") + } + } + } + } + }) + mViewModel.questionDraftsContent.observe(this, Observer { + mViewModel.questionDraftEntity = it + setQuestionDraft(it) + }) // Process dialog mViewModel.processDialog.observe(this, Observer { it -> @@ -419,23 +506,30 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { } override fun onMenuItemClick(menuItem: MenuItem?): Boolean { - if (mViewModel.isModeratorPatch) { - if (checkSameFromQuestionData()) { - toast("内容没有变化") + if (menuItem?.itemId == R.id.menu_question_post) { + if (mViewModel.isModeratorPatch) { + if (checkSameFromQuestionData()) { + toast("内容没有变化") + } else { + mViewModel.selectedTags.addAll(mViewModel.questionEntity?.tags!!) + DialogUtils.showAlertDialog(this, "修改问题", + if (mViewModel.questionEntity!!.me.moderatorPermissions.updateQuestion == Permissions.REPORTER) + "你的操作将提交给小编审核,确定提交吗?" else "你的操作将立即生效,确定提交吗?(你的管理权限为:高级)", + "确定", "取消", DialogUtils.ConfirmListener { + mViewModel.uploadPicAndPatchQuestion(false) + }, null) + } } else { - mViewModel.selectedTags.addAll(mViewModel.questionEntity?.tags!!) - DialogUtils.showAlertDialog(this, "修改问题", - if (mViewModel.questionEntity!!.me.moderatorPermissions.updateQuestion == Permissions.REPORTER) - "你的操作将提交给小编审核,确定提交吗?" else "你的操作将立即生效,确定提交吗?(你的管理权限为:高级)", - "确定", "取消", DialogUtils.ConfirmListener { - mViewModel.uploadPicAndPatchQuestion(false) - }, null) + if (mViewModel.checkTitleAndLoadTitleTag()) { + mTagsSelectFragment?.postQuestion() + } } - } else { - if (mViewModel.checkTitleAndLoadTitleTag()) { - mTagsSelectFragment?.postQuestion() + } else if (menuItem?.itemId == R.id.menu_draft) { + if (checkDraft(SaveDraftType.SKIP)) { + startActivityForResult(QuestionDraftActivity.getIntent(this), QUESTION_DRAFT_REQUEST_CODE) } } + return false } @@ -466,7 +560,6 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { mViewModel.questionEntity?.community?.name = it.name } setForumName() - if (!mViewModel.isFromSearch) mViewModel.checkQuestionDraft() mBinding.vm = mViewModel } } @@ -513,8 +606,6 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { } // 需要检查的内容,其中任意一个不为空都要打开提示弹窗 val imgList = mViewModel.picList.value - val title = mBinding.questionseditTitle.text.toString().trim() - val content = mBinding.questionseditContent.text.toString().trim() if (mViewModel.isModeratorPatch) { if (checkSameFromQuestionData()) { @@ -524,21 +615,62 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { , "确定退出修改?已编辑的内容将丢失" , "继续编辑", " 退出", null) { finish() } return true - } else if (imgList != null && imgList.size > 0 || title.isNotEmpty() || content.isNotEmpty()) { - if (mViewModel.questionEntity == null && !mViewModel.isFromSearch) { - mViewModel.saveQuestionDraft() - toast("问题草稿已保存") + } + + //问题发布 + if (mViewModel.questionEntity == null && mViewModel.questionDraftEntity == null) { + if (mViewModel.communityEntity != null && (!imgList.isNullOrEmpty() || !mViewModel.title.isNullOrEmpty() || !mViewModel.content.isNullOrEmpty())) { + DialogUtils.showNewAlertDialog(this, "提示", "是否保存内容再退出?", "不保存", "保存并退出", Gravity.CENTER, true, { + finish() + }, { + mViewModel.saveQuestionDraft(SaveDraftType.EXIT) + }) + return true + } + } + + //问题编辑,需要判断是否修改过 + if (mViewModel.questionEntity != null) { + return if (mViewModel.questionEntity?.community?.id != mViewModel.communityEntity?.id + || mViewModel.questionEntity?.title != mViewModel.title + || mViewModel.questionEntity?.description != mViewModel.content) { + showBackDialog() + true + } else false + } + + return !checkDraft(SaveDraftType.EXIT) + } + + private fun checkDraft(saveType: SaveDraftType): Boolean { + val draftEntity = mViewModel.questionDraftEntity ?: return true + if (draftEntity.title.isEmpty() && draftEntity.description.isEmpty()) return true + if (saveType == SaveDraftType.SKIP) { + //判断是否修改了草稿,修改了需自动保存无需提示 + if (draftEntity.bbs?.id != mViewModel.communityEntity?.id + || draftEntity.title != mViewModel.title + || draftEntity.description != mViewModel.content) { + mViewModel.saveQuestionDraft(SaveDraftType.AUTO) + return true + } + } else if (saveType == SaveDraftType.EXIT) { + //退出页面需判断是否修改了草稿,修改了需弹窗提示 + if (draftEntity.bbs?.id != mViewModel.communityEntity?.id + || draftEntity.title != mViewModel.title + || draftEntity.description != mViewModel.content) { + showBackDialog() return false } - - DialogUtils.showCancelAlertDialog(this, "提示" - , if (mViewModel.questionEntity == null) "确定放弃提问吗?" else "确定放弃修改吗?" - , "再想想", " 放弃", null) { finish() } - return true - } else if (mViewModel.questionEntity == null && !mViewModel.isFromSearch) { - mViewModel.cleanCurrentCommunityDraft() } - return false + return true + } + + private fun showBackDialog() { + DialogUtils.showNewAlertDialog(this, "提示", "是否保存修改内容用于下次编辑?", "不保存", "保存并退出", Gravity.CENTER, true,{ + finish() + }, { + mViewModel.saveQuestionDraft(SaveDraftType.EXIT) + }) } private fun checkSameFromQuestionData(): Boolean { @@ -594,6 +726,9 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { companion object { const val QUESTION_POSTED_TAG = "QUESTION_POSTED_TAG" + const val QUESTION_DRAFT_REQUEST_CODE = 105 + const val QUESTION_DRAFT_CHANGE_TAG = "ANSWER_DRAFT_CHANGE_TAG" + const val SAVE_DRAFTS_INTERVAL_TIME = 15000 // searchKey 补充到标题(新增问题) fun getIntent(context: Context, searchKey: String?): Intent { @@ -630,5 +765,19 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { return intent } + //编辑草稿 + @JvmStatic + fun getDraftIntent(context: Context, questionDraftEntity: QuestionDraftEntity): Intent { + val intent = Intent(context, QuestionEditActivity::class.java) + intent.putExtra(QuestionDraftEntity::class.java.simpleName, questionDraftEntity) + return intent + } + + } + + enum class SaveDraftType { + EXIT, // 退出时保存 + AUTO, // 自动保存 + SKIP // 跳转至草稿箱时保存 } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditViewModel.kt index 37cfee9710..34bae5b4d1 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditViewModel.kt @@ -1,5 +1,6 @@ package com.gh.gamecenter.qa.questions.edit +import android.annotation.SuppressLint import android.app.Application import android.net.Uri import android.provider.MediaStore @@ -12,11 +13,16 @@ import com.gh.common.util.* import com.gh.gamecenter.R import com.gh.gamecenter.entity.CommunityEntity import com.gh.gamecenter.entity.Permissions +import com.gh.gamecenter.entity.User import com.gh.gamecenter.eventbus.EBReuse import com.gh.gamecenter.manager.UserManager import com.gh.gamecenter.mvvm.Resource +import com.gh.gamecenter.qa.article.edit.ArticleEditActivity +import com.gh.gamecenter.qa.entity.ArticleDraftEntity import com.gh.gamecenter.qa.entity.CommunityVideoEntity +import com.gh.gamecenter.qa.entity.QuestionDraftEntity 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.gh.gamecenter.retrofit.service.ApiService @@ -50,6 +56,8 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica val moderatorPostLiveData = MediatorLiveData>() val videoLiveData = MutableLiveData() val notSelectForum = MutableLiveData() + val postQuestionDrafts = MediatorLiveData>() + val questionDraftsContent = MutableLiveData() var uploadImageSubscription: Disposable? = null @@ -58,9 +66,10 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica var content: String? = "" // picList 纯粹用于展示,可以包含本地和网络地址的图片 - val picList = MediatorLiveData>() + val picList = MediatorLiveData>() var defaultTags: MutableList = ArrayList() var questionEntity: QuestionsDetailEntity? = null + var questionDraftEntity: QuestionDraftEntity? = null val selectedTags: MutableList = ArrayList() val selectedTagsChange = MediatorLiveData() @@ -118,6 +127,8 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica Utils.toast(getApplication(), "标题至少${QUESTION_TITLE_MIN_LENGTH}个字") return false } + if (questionEntity != null && questionEntity?.title == title && questionEntity?.description == content) return false + if (TextUtils.isEmpty(communityEntity?.id) || TextUtils.isEmpty(communityEntity?.name)) { Utils.toast(getApplication(), "论坛不能为空") notSelectForum.postValue(true) @@ -140,31 +151,10 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica // 检查标题长度限制 title?.trim() if (title!!.length < QUESTION_TITLE_MIN_LENGTH) return false + if (questionEntity != null && questionEntity?.title == title && questionEntity?.description == content) return false return true } - /** - * 根据问题标题获取相应标签(标签默认选中) - */ - private fun loadTitleTags() { - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true)) - mApiService - .getQuestionTagsByTitle(communityEntity?.id, UrlFilterUtils.getFilterQuery("title", title)) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(object : Response>() { - override fun onResponse(response: List?) { - titleTags.postValue(response) - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", false)) - } - - override fun onFailure(e: HttpException?) { - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", false)) - Utils.toast(getApplication(), R.string.request_failure_normal_hint) - } - }) - } - /** * 选择动作(选中标签/移除已选中的标签) */ @@ -353,7 +343,9 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica entity.images = successfullyUploadedPicList val video: CommunityVideoEntity? = videoLiveData.value if (video != null) entity.videos = arrayListOf(video) - + if (!questionDraftEntity?.id.isNullOrEmpty()) { + entity.draftId = questionDraftEntity?.id ?: "" + } val observable = if (questionEntity != null) { if (!isModeratorPatch) { questionEntity?.images = entity.images @@ -384,16 +376,18 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica override fun onResponse(response: ResponseBody?) { processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", false)) MtaHelper.onEvent("发表问题", "提交成功", communityEntity?.name) - val data = response?.string() + val data = response?.string() ?: "" postLiveData.postValue(Resource.success(data)) EventBus.getDefault().post(EBReuse(QuestionEditActivity.QUESTION_POSTED_TAG)) - if (questionEntity == null && !isFromSearch) cleanCurrentCommunityDraft() if (questionEntity == null) { tryWithDefaultCatch { EnergyTaskHelper.postEnergyTask("post_question", JSONObject(data).optString("_id")) } } + if (!questionDraftEntity?.id.isNullOrEmpty()) { + EventBus.getDefault().post(EBReuse(QuestionEditActivity.QUESTION_DRAFT_CHANGE_TAG)) + } } override fun onFailure(e: HttpException?) { @@ -440,65 +434,63 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica }) } - fun cleanCurrentCommunityDraft() { - val draftKey = getDraftKey() - if (draftKey.isNullOrEmpty()) { - //Utils.toast(getApplication(), "删除草稿失败") - return + @SuppressLint("CheckResult") + fun saveQuestionDraft(saveType: QuestionEditActivity.SaveDraftType) { + val body = getQuestionBody() + val observable = if (!questionDraftEntity?.id.isNullOrEmpty()) { + mApiService.updateQuestionDraft(UserManager.getInstance().userId, questionDraftEntity?.id, body) + } else { + mApiService.addQuestionDraft(UserManager.getInstance().userId, body) } - SPUtils.remove(draftKey) + observable + .compose(singleToMain()) + .subscribe(object : BiResponse() { + override fun onSuccess(data: ResponseBody) { + val string = data.string() + if (!string.isNullOrEmpty() && questionDraftEntity?.id.isNullOrEmpty()) { + if (questionDraftEntity == null) questionDraftEntity = QuestionDraftEntity() + questionDraftEntity?.id = JSONObject(string).getString("_id") + } + postQuestionDrafts.postValue(Pair(saveType, true)) + } + + override fun onFailure(exception: Exception) { + super.onFailure(exception) + postQuestionDrafts.postValue(Pair(saveType, false)) + } + }) } - fun saveQuestionDraft() { - val draftKey = getDraftKey() - if (draftKey.isNullOrEmpty()) { - Utils.toast(getApplication(), "保存草稿失败") - return - } - - val draftJson = JSONObject() - draftJson.put("title", title) - draftJson.put("content", content) - draftJson.put("images", JSONArray(picList.value)) - SPUtils.setString(draftKey, draftJson.toString()) + private fun getQuestionBody(): RequestBody { + val draftEntity = QuestionDraftEntity( + communityId = communityEntity?.id ?: "", + tags = selectedTags.toList(), + images = picList.value ?: arrayListOf(), + videos = if (videoLiveData.value != null) arrayListOf(videoLiveData.value!!) else arrayListOf(), + title = title ?: "", + description = content ?: "" + ) + return draftEntity.toRequestBody() } - fun checkQuestionDraft() { - val draftKey = getDraftKey() - if (draftKey.isNullOrEmpty()) { - Utils.toast(getApplication(), "获取草稿失败") - return - } + @SuppressLint("CheckResult") + fun getQuestionDraftContent(draftId: String) { + processDialog.postValue(WaitingDialogFragment.WaitingDialogData("加载中...", true)) + mApiService.getQuestionDraft(UserManager.getInstance().userId, draftId) + .compose(singleToMain()) + .subscribe(object : BiResponse() { + override fun onSuccess(data: QuestionDraftEntity) { + questionDraftsContent.postValue(data) + processDialog.postValue(WaitingDialogFragment.WaitingDialogData("加载中...", false)) + } - val draft = SPUtils.getString(draftKey, "") - if (draft.isNullOrEmpty()) return - val draftJson = JSONObject(draft) - - val draftTitle = draftJson.optString("title") - if (draftTitle.isNotEmpty()) title = draftTitle - - val draftContent = draftJson.optString("content") - if (draftContent.isNotEmpty()) content = draftContent - - val draftImages = draftJson.optJSONArray("images") - if (draftImages != null) { - val images = ArrayList() - for (i in 0 until draftImages.length()) { - val img = draftImages.getString(i) - if (img.isNotEmpty() && File(img).exists()) { - images.add(img) - } - } - if (images.isNotEmpty()) picList.postValue(images) - } + override fun onFailure(exception: Exception) { + super.onFailure(exception) + processDialog.postValue(WaitingDialogFragment.WaitingDialogData("加载中...", false)) + } + }) } - private fun getDraftKey(): String? { - if (communityEntity?.id.isNullOrEmpty()) return null - return QUESTION_DRAFT_KEY + communityEntity?.id - } - - companion object { const val QUESTION_TAG_MAX_COUNT = 5 const val PIC_MAX_AMOUNT = 30 diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/TagsSelectFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/TagsSelectFragment.kt index 710c57be20..b6429d9921 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/TagsSelectFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/TagsSelectFragment.kt @@ -223,28 +223,25 @@ class TagsSelectFragment : BaseFragment() { // 添加标签 val mDefaultTag = mViewModel?.defaultTags ?: ArrayList() - if (mViewModel?.questionEntity == null) { - val mTitleTag = (mViewModel?.titleTags?.value ?: ArrayList()) as MutableList - // 添加默认标签(如果标题标签与默认标签重复则选中) - for (s in mDefaultTag.reversed()) { - val contains = mTitleTag.contains(s) - addTag(s, contains) - if (contains) mTitleTag.remove(s) + val tags = when { + mViewModel?.questionEntity != null -> { + mViewModel?.questionEntity?.tags ?: arrayListOf() } - // 未匹配到默认标签的默认选中在前排 - for (s in mTitleTag) { - addTag(s, true) + mViewModel?.questionDraftEntity != null -> { + mViewModel?.questionDraftEntity?.tags ?: arrayListOf() } - } else { - val tags = mViewModel?.questionEntity?.tags ?: ArrayList() - for (s in mDefaultTag) { - if (!tags.contains(s)) - addTag(s, false) - } - for (s in tags.reversed()) { - addTag(s, true) + else -> { + arrayListOf() } } + + for (s in mDefaultTag) { + if (!tags.contains(s)) + addTag(s, false) + } + for (s in tags.reversed()) { + addTag(s, true) + } } private fun showAddTagDialog() { 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 24c20a1bac..88c1c5bddd 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 @@ -100,6 +100,7 @@ import com.gh.gamecenter.qa.entity.CommunitySelectEntity; import com.gh.gamecenter.qa.entity.CommunitySelectOpenEntity; import com.gh.gamecenter.qa.entity.EditorInsertDefaultEntity; import com.gh.gamecenter.qa.entity.InviteEntity; +import com.gh.gamecenter.qa.entity.QuestionDraftEntity; import com.gh.gamecenter.qa.entity.QuestionHistoryDetailEntity; import com.gh.gamecenter.qa.entity.QuestionHistoryEntity; import com.gh.gamecenter.qa.entity.Questions; @@ -108,6 +109,7 @@ import com.gh.gamecenter.qa.entity.QuestionsIndexEntity; import com.gh.gamecenter.qa.entity.SearchHottestEntity; import com.gh.gamecenter.qa.entity.SearchNewestEntity; import com.gh.gamecenter.qa.entity.SuggestedFollowEntity; +import com.gh.gamecenter.retrofit.Response; import com.google.gson.JsonObject; import java.util.ArrayList; @@ -2808,4 +2810,34 @@ public interface ApiService { */ @GET("shop/orders/roll_notices") Single> getRollNotices(); + + /** + * 新增一个问题草稿 + */ + @POST("users/{user_id}/question_drafts") + Single addQuestionDraft(@Path("user_id") String userId, @Body RequestBody body); + + /** + * 获取单个问题草稿 + */ + @GET("users/{user_id}/question_drafts/{draft_id}") + Single getQuestionDraft(@Path("user_id") String userId, @Path("draft_id") String draftId); + + /** + * 修改一个问题草稿 + */ + @POST("users/{user_id}/question_drafts/{draft_id}") + Single updateQuestionDraft(@Path("user_id") String userId, @Path("draft_id") String draftId, @Body RequestBody body); + + /** + * 获取问题草稿列表 + */ + @GET("users/{user_id}/question_drafts") + Observable> getQuestionDrafts(@Path("user_id") String userId); + + /** + * 删除单个问题草稿 + */ + @DELETE("users/{user_id}/question_drafts/{draft_id}") + Observable deleteQuestionDraft(@Path("user_id") String userId, @Path("draft_id") String draftId); } \ No newline at end of file diff --git a/app/src/main/res/drawable-xxhdpi/ic_alert_dialog_close.png b/app/src/main/res/drawable-xxhdpi/ic_alert_dialog_close.png new file mode 100644 index 0000000000000000000000000000000000000000..8a4adefd490fd6f789b8977d6be0406f4f908c77 GIT binary patch literal 775 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyy~ySip>6gB0F2&*5QUU@G)P12xnsd@tU_XPEvnmLWk61MGarqd@}ebHBaK*;aFxg!ljJ^K+ z_uqf5NBn)~Hy=#Ua{O|(^I7HO%Fki^eS!>)`)mVtOgM7*>&FTgQ44;-hE26EH=SU- zs3s?+u`HN-UMItsoL0_t&cchlYlP#kC^7Z8Emps>hnwNMi9*eh$!$_+oi8aeEx4U< z@LAIbk^W_c*RTCNqIcv7W8 zW0F0#7v6jvC&VCg#3`dAoUxWHIXR%6WO*65tI#MXVE91hnIXm8y7ubS&3N4tBT`c;UxljaR%CUH^ZnxNZA?Ww}d7#l5=5 z-t65i-kiyAW^q(88$OCm(c{Q(5cz1SxJS$|y}w1JHgwUFE#_QS_Zhm~k3aCam7MW6 z>sJoz1)db=?4M%Z9J`O~v|>+iI>j0FhULRnjte=3tEcj^o4Ch!oK5?jaBJpsB?jMJ zhU&APFEq`+b?dpEK#FpfAY;Zwxi<+ru8Exgw_5=e>Tg^bjG_t{-xFY^D6rZ7)^J*g1{=bt^GzUftNXjLpj87L8Yy85}Sb4q9e08ywvS^xk5 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/divider_item_line_space_16.xml b/app/src/main/res/drawable/divider_item_line_space_16.xml new file mode 100644 index 0000000000..3343904cb8 --- /dev/null +++ b/app/src/main/res/drawable/divider_item_line_space_16.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/community_answer_item.xml b/app/src/main/res/layout/community_answer_item.xml index b549164a28..2edbf2bd19 100644 --- a/app/src/main/res/layout/community_answer_item.xml +++ b/app/src/main/res/layout/community_answer_item.xml @@ -194,6 +194,78 @@ app:layout_constraintTop_toBottomOf="@+id/content" app:offset="40dp" /> + + + + + + + + + + + - + @@ -15,67 +16,62 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/reuse_listview_item_style" - android:paddingLeft="20dp" - android:paddingBottom="14dp"> + android:paddingLeft="16dp" + android:paddingTop="20dp" + android:paddingRight="16dp" + android:paddingBottom="16dp"> - - - + android:textSize="11sp" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/article_draft_title" + tools:text="地下城与勇士" /> - - + app:layout_constraintTop_toBottomOf="@+id/article_draft_title" /> \ No newline at end of file diff --git a/app/src/main/res/layout/community_question_draft_item.xml b/app/src/main/res/layout/community_question_draft_item.xml new file mode 100644 index 0000000000..8b46456535 --- /dev/null +++ b/app/src/main/res/layout/community_question_draft_item.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_new_alert.xml b/app/src/main/res/layout/dialog_new_alert.xml index 1010100ca1..2246d2b545 100644 --- a/app/src/main/res/layout/dialog_new_alert.xml +++ b/app/src/main/res/layout/dialog_new_alert.xml @@ -40,7 +40,7 @@ app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/title" - tools:text="内容内容内容内容内容内容"/> + tools:text="内容内容内容内容内容内容" /> + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_answer_post.xml b/app/src/main/res/menu/menu_answer_post.xml index c4792fb7e9..bf5a8a317b 100644 --- a/app/src/main/res/menu/menu_answer_post.xml +++ b/app/src/main/res/menu/menu_answer_post.xml @@ -3,11 +3,10 @@ xmlns:app = "http://schemas.android.com/apk/res-auto" > + android:title="草稿" + app:showAsAction="always" />

- +