Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev

# Conflicts:
#	app/src/main/java/com/gh/gamecenter/qa/answer/detail/AnswerDetailFragment.kt
#	app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java
This commit is contained in:
kehaoyuan
2019-03-25 18:25:41 +08:00
19 changed files with 845 additions and 479 deletions

View File

@ -21,78 +21,41 @@ import retrofit2.HttpException
object CommentHelper {
// TODO 合并这两个方法的共同部分
@JvmStatic
fun showCommunityArticleCommentOptions(
context: Context,
commentEntity: CommentEntity,
showConversation: Boolean,
articleId: String,
communityId: String,
listener: OnCommentCallBackListener?) {
val dialogOptions = ArrayList<String>()
if (commentEntity.me == null || !commentEntity.me?.isAnswerCommented!!) {
dialogOptions.add("回复")
}
dialogOptions.add("复制")
dialogOptions.add("举报")
if (commentEntity.parentUser != null && showConversation) {
dialogOptions.add("查看对话")
}
DialogUtils.showListDialog(context, dialogOptions, null) {
when (it) {
"回复" -> {
context.ifLogin("社区文章详情-评论-回复") {
if (listener != null) {
listener.onCommentCallback(commentEntity)
} else if (!TextUtils.isEmpty(commentEntity.id)) {
context.startActivity(MessageDetailActivity.getMessageDetailIntent(context, commentEntity, commentEntity.id))
} else {
Utils.toast(context, "缺少关键属性")
}
}
}
"复制" -> copyText(commentEntity.content, context)
"举报" -> context.ifLogin("社区文章详情-评论-举报") {
showReportTypeDialog(context) { reportType ->
PostCommentUtils.reportCommunityArticleComment(context, communityId, articleId, commentEntity.id, reportType,
object : PostCommentUtils.PostCommentListener {
override fun postSuccess(response: JSONObject?) {
Utils.toast(context, "感谢您的举报")
}
override fun postFailed(error: Throwable?) {
if (error == null) {
Utils.toast(context, "举报失败,请稍后重试")
} else {
Utils.toast(context, "举报失败,${error.message}")
}
}
})
}
}
"查看对话" -> {
context.startActivity(CommentDetailActivity
.getCommunityArticleCommentIntent(context, articleId, commentEntity.id, communityId, null))
}
}
}
fun showCommunityArticleCommentOptions(context: Context,
commentEntity: CommentEntity,
showConversation: Boolean,
articleId: String,
communityId: String,
listener: OnCommentCallBackListener?) {
showCommentOptions(context = context,
commentEntity = commentEntity,
showConversation = showConversation,
articleId = articleId,
communityId = communityId,
listener = listener)
}
@JvmStatic
fun showAnswerCommentOptions(
context: Context,
commentEntity: CommentEntity,
showConversation: Boolean,
answerId: String,
listener: OnCommentCallBackListener?) {
fun showAnswerCommentOptions(context: Context,
commentEntity: CommentEntity,
showConversation: Boolean,
answerId: String,
listener: OnCommentCallBackListener?) {
showCommentOptions(context = context,
commentEntity = commentEntity,
showConversation = showConversation,
answerId = answerId,
listener = listener)
}
private fun showCommentOptions(context: Context,
commentEntity: CommentEntity,
showConversation: Boolean,
articleId: String? = null,
communityId: String? = null,
answerId: String? = null,
listener: OnCommentCallBackListener? = null) {
val dialogOptions = ArrayList<String>()
if (commentEntity.me == null || !commentEntity.me?.isAnswerCommented!!) {
@ -103,9 +66,10 @@ object CommentHelper {
dialogOptions.add("举报")
commentEntity.me?.let {
if (it.isModerator && (
it.moderatorPermissions.contains(MeEntity.HIDE_ANSWER_COMMENT)
|| it.moderatorPermissions.contains(MeEntity.TOP_ANSWER_COMMENT))) {
if (it.isModerator || (it.moderatorPermissions.contains(MeEntity.HIDE_ANSWER_COMMENT)
|| it.moderatorPermissions.contains(MeEntity.TOP_ANSWER_COMMENT)
|| it.moderatorPermissions.contains(MeEntity.HIDE_COMMUNITY_ARTICLE)
|| it.moderatorPermissions.contains(MeEntity.TOP_COMMUNITY_ARTICLE_COMMENT))) {
dialogOptions.add("管理")
}
}
@ -116,7 +80,7 @@ object CommentHelper {
DialogUtils.showListDialog(context, dialogOptions, null) {
when (it) {
"管理" -> showControlDialog(context, answerId, commentEntity, commentEntity.me!!)
"管理" -> showControlDialog(context, answerId, articleId, communityId, commentEntity, commentEntity.me!!)
"回复" -> {
context.ifLogin("回答详情-评论-回复") {
@ -132,43 +96,63 @@ object CommentHelper {
"复制" -> copyText(commentEntity.content, context)
"举报" -> context.ifLogin("回答详情-评论-举报") {
showReportTypeDialog(context) { reportType ->
PostCommentUtils.postAnswerReportData(context, commentEntity.id, answerId, reportType,
object : PostCommentUtils.PostCommentListener {
override fun postSuccess(response: JSONObject?) {
Utils.toast(context, "感谢您的举报")
}
"举报" -> {
context.ifLogin("回答详情-评论-举报") {
showReportTypeDialog(context) { reportType ->
override fun postFailed(error: Throwable?) {
if (error == null) {
Utils.toast(context, "举报失败,请稍后重试")
} else {
Utils.toast(context, "举报失败,${error.message}")
}
val commentListener = object : PostCommentUtils.PostCommentListener {
override fun postSuccess(response: JSONObject?) {
Utils.toast(context, "感谢您的举报")
}
override fun postFailed(error: Throwable?) {
if (error == null) {
Utils.toast(context, "举报失败,请稍后重试")
} else {
Utils.toast(context, "举报失败,${error.message}")
}
})
}
}
if (answerId != null) {
PostCommentUtils.postAnswerReportData(context, commentEntity.id, answerId, reportType, commentListener)
} else {
PostCommentUtils.reportCommunityArticleComment(context, communityId, articleId, commentEntity.id, reportType, commentListener)
}
}
}
}
"查看对话" -> {
context.startActivity(CommentDetailActivity
.getAnswerCommentIntent(context, commentEntity.id, answerId, null))
if (answerId != null) {
context.startActivity(CommentDetailActivity
.getAnswerCommentIntent(context, commentEntity.id, answerId, null))
} else {
context.startActivity(CommentDetailActivity
.getCommunityArticleCommentIntent(context, articleId, commentEntity.id, communityId, null))
}
}
}
}
}
private fun showControlDialog(context: Context, answerId: String, comment: CommentEntity, me: MeEntity) {
private fun showControlDialog(context: Context,
answerId: String? = null,
articleId: String? = null,
communityId: String? = null,
comment: CommentEntity,
me: MeEntity) {
val dialogOptions = arrayListOf<String>()
val highlight = "置顶评论"
val hide = "隐藏评论"
if (me.moderatorPermissions.contains(MeEntity.TOP_ANSWER_COMMENT)) {
if (me.moderatorPermissions.contains(MeEntity.TOP_ANSWER_COMMENT)
|| me.moderatorPermissions.contains(MeEntity.TOP_COMMUNITY_ARTICLE_COMMENT)) {
dialogOptions.add(highlight)
}
if (me.moderatorPermissions.contains(MeEntity.HIDE_ANSWER_COMMENT)) {
if (me.moderatorPermissions.contains(MeEntity.HIDE_ANSWER_COMMENT)
|| me.moderatorPermissions.contains(MeEntity.HIDE_COMMUNITY_ARTICLE_COMMENT)) {
dialogOptions.add(hide)
}
@ -179,9 +163,11 @@ object CommentHelper {
}
val disabledOptions = arrayListOf<String>()
if (comment.priority != 0) {
disabledOptions.add(highlight)
}
comment.me?.let {
if (it.isAnswerCommented) {
disabledOptions.add(highlight)
@ -191,7 +177,6 @@ object CommentHelper {
DialogUtils.showListDialog(context, dialogOptions, disabledOptions) {
when (it) {
highlight -> {
if (comment.priority != 0) {
Utils.toast(context, "评论已经置顶")
return@showListDialog
@ -204,77 +189,101 @@ object CommentHelper {
}
}
DialogUtils.showAlertDialog(context, highlight, content,
"确定", "取消",
{
RetrofitManager.getInstance(context).api
.highlightAnswerComment(answerId, comment.id)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
if (me.moderatorLevel == MeEntity.MODERATOR_LEVEL_PRIMARY) {
Utils.toast(context, "提交成功")
} else {
Utils.toast(context, "置顶成功,请刷新列表")
}
}
val highlightObserver = object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
if (me.moderatorLevel == MeEntity.MODERATOR_LEVEL_PRIMARY) {
Utils.toast(context, "提交成功")
} else {
Utils.toast(context, "置顶成功,请刷新列表")
}
}
override fun onFailure(e: HttpException?) {
super.onFailure(e)
e?.let { httpException ->
if (httpException.code() == 403) {
val string = e.response().errorBody()?.string()
val errorJson = JSONObject(string)
val errorCode = errorJson.getInt("code")
if (errorCode == 403059) {
Utils.toast(getApplication(), "权限错误,请刷新后重试")
return
} else {
Utils.toast(getApplication(), e.message())
}
}
}
}
})
}, null)
override fun onFailure(e: HttpException?) {
super.onFailure(e)
e?.let { httpException ->
if (httpException.code() == 403) {
val string = e.response().errorBody()?.string()
val errorJson = JSONObject(string)
val errorCode = errorJson.getInt("code")
if (errorCode == 403059) {
Utils.toast(getApplication(), "权限错误,请刷新后重试")
return
} else {
Utils.toast(getApplication(), e.message())
}
}
}
}
}
if (answerId == null) {
DialogUtils.showAlertDialog(context, highlight, content,
"确定", "取消", {
RetrofitManager.getInstance(context).api
.highlightAnswerComment(answerId, comment.id)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(highlightObserver)
}, null)
} else {
DialogUtils.showAlertDialog(context, highlight, content,
"确定", "取消", {
RetrofitManager.getInstance(context).api
.highlightCommunityArticleComment(communityId, articleId, comment.id)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(highlightObserver)
}, null)
}
}
hide -> {
DialogUtils.showAlertDialog(context, hide, content,
"确定", "取消",
{
RetrofitManager.getInstance(context).api
.hideAnswerComment(answerId, comment.id)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
if (me.moderatorLevel == MeEntity.MODERATOR_LEVEL_PRIMARY) {
Utils.toast(context, "提交成功")
} else {
Utils.toast(context, "隐藏成功,请刷新列表")
}
}
val hideObserver = object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
if (me.moderatorLevel == MeEntity.MODERATOR_LEVEL_PRIMARY) {
Utils.toast(context, "提交成功")
} else {
Utils.toast(context, "隐藏成功,请刷新列表")
}
}
override fun onFailure(e: HttpException?) {
super.onFailure(e)
e?.let { httpException ->
if (httpException.code() == 403) {
val string = e.response().errorBody()?.string()
val errorJson = JSONObject(string)
val errorCode = errorJson.getInt("code")
if (errorCode == 403059) {
Utils.toast(getApplication(), "权限错误,请刷新后重试")
return
} else {
Utils.toast(getApplication(), e.message())
}
}
}
}
})
}, null)
override fun onFailure(e: HttpException?) {
super.onFailure(e)
e?.let { httpException ->
if (httpException.code() == 403) {
val string = e.response().errorBody()?.string()
val errorJson = JSONObject(string)
val errorCode = errorJson.getInt("code")
if (errorCode == 403059) {
Utils.toast(getApplication(), "权限错误,请刷新后重试")
return
} else {
Utils.toast(getApplication(), e.message())
}
}
}
}
}
if (answerId != null) {
DialogUtils.showAlertDialog(context, hide, content,
"确定", "取消", {
RetrofitManager.getInstance(context).api
.hideAnswerComment(answerId, comment.id)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(hideObserver)
}, null)
} else {
DialogUtils.showAlertDialog(context, hide, content,
"确定", "取消", {
RetrofitManager.getInstance(context).api
.hideCommunityArticleComment(communityId, articleId, comment.id)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(hideObserver)
}, null)
}
}
}
}

View File

@ -39,12 +39,12 @@ public class CommentDetailActivity extends NormalActivity {
public static Intent getCommunityArticleCommentIntent(Context context,
String articleId,
String articleCommentId,
String articleCommunityId,
String communityId,
LinkEntity linkEntity) {
Bundle args = new Bundle();
args.putString(CommentActivity.ARTICLE_ID, articleId);
args.putString(EntranceUtils.KEY_ARTICLE_COMMENT_ID, articleCommentId);
args.putString(CommentActivity.ARTICLE_COMMUNITY_ID, articleCommunityId);
args.putString(CommentActivity.COMMUNITY_ID, communityId);
args.putParcelable(EntranceUtils.KEY_LINK, linkEntity);
return getTargetIntent(context, CommentDetailActivity.class, CommentConversationFragment.class, args);
}

View File

@ -90,15 +90,24 @@ class MeEntity(@SerializedName("is_community_voted")
const val MODERATOR_LEVEL_SUPPER = "super"
// moderator permissions
// 问题权限
const val PATCH_QUESTION_TAG = "update-question-tag" // 修改问题标签:只修改标签
const val PATCH_QUESTION = "update-question" // 修改问题:除标签以外的字段
const val HIDE_QUESTION = "hide-question" // 隐藏问题
const val GET_MODIFIED_VERSIONS = "get-modified-versions" // 查看问题的修改历史
// 回答权限
const val CHOICENESS_ANSWER = "choiceness-answer" // 将回答加入精选列表
const val FOLD_ANSWER = "fold-answer" // 折叠回答
const val HIDE_ANSWER = "hide-answer" // 隐藏回答
const val TOP_ANSWER_COMMENT = "top-answer-comment" // 置顶回答的评论
const val HIDE_ANSWER_COMMENT = "hide-answer-comment" // 隐藏回答的评论
// 文章权限
const val UPDATE_COMMUNITY_ARTICLE = "update-community-article" // 修改文章
const val CHOICENESS_COMMUNITY_ARTICLE = "choiceness-community-article" // 加精文章
const val HIDE_COMMUNITY_ARTICLE = "hide-community-article" // 隐藏文章
const val TOP_COMMUNITY_ARTICLE_COMMENT = "top-community-article-comment" // 置顶文章评论
const val HIDE_COMMUNITY_ARTICLE_COMMENT = "hide-community-article-comment" // 隐藏文章评论
}
}

View File

@ -21,16 +21,14 @@ import android.view.MenuItem
import android.view.View
import android.view.animation.*
import android.webkit.JavascriptInterface
import android.widget.ImageView
import android.widget.RelativeLayout
import android.widget.TextView
import android.widget.*
import butterknife.BindView
import butterknife.OnClick
import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.drawee.controller.ControllerListener
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.drawee.view.SimpleDraweeView
import com.facebook.fresco.animation.drawable.AnimatedDrawable2
import com.facebook.fresco.animation.drawable.AnimationListener
import com.facebook.fresco.animation.drawable.BaseAnimationListener
import com.facebook.imagepipeline.image.ImageInfo
import com.gh.base.fragment.BaseFragment
import com.gh.common.TimeElapsedHelper
@ -42,7 +40,6 @@ import com.gh.gamecenter.databinding.FragmentAnswerDetailBinding
import com.gh.gamecenter.entity.MeEntity
import com.gh.gamecenter.entity.SpecialColumn
import com.gh.gamecenter.eventbus.EBReuse
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.normal.NormalFragment
import com.gh.gamecenter.personal.PersonalFragment.LOGIN_TAG
import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity
@ -60,6 +57,7 @@ import org.greenrobot.eventbus.ThreadMode
import org.json.JSONObject
import java.io.IOException
import java.util.*
import kotlin.collections.ArrayList
class AnswerDetailFragment : NormalFragment() {
@ -80,7 +78,7 @@ class AnswerDetailFragment : NormalFragment() {
@BindView(R.id.answer_detail_loading)
lateinit var mLoading: View
@BindView(R.id.answer_detail_content)
lateinit var mContent: View
lateinit var mContent: ScrollView
@BindView(R.id.answer_detail_title_container)
lateinit var mAnswerDetailTitleContainer: View
@BindView(R.id.reuse_none_data)
@ -113,6 +111,20 @@ class AnswerDetailFragment : NormalFragment() {
lateinit var mRefreshLayout: SmartRefreshLayout
@BindView(R.id.answer_container)
lateinit var mContainerView: View
@BindView(R.id.questionsdetail_item_pic1)
lateinit var mPic1: SimpleDraweeView
@BindView(R.id.questionsdetail_item_pic2)
lateinit var mPic2: SimpleDraweeView
@BindView(R.id.questionsdetail_item_pic3)
lateinit var mPic3: SimpleDraweeView
@BindView(R.id.questionsdetail_item_picll)
lateinit var mImgLl: LinearLayout
@BindView(R.id.questionsdetail_item_des)
lateinit var mQuestionsDescTv: TextView
@BindView(R.id.questiondetail_item_pic3_mask)
lateinit var mPic3Mask: View
@BindView(R.id.questiondetail_item_pic3_desc)
lateinit var mPic3Desc: TextView
private var mPath: String? = ""
private var mAnswerId: String? = ""
@ -241,7 +253,6 @@ class AnswerDetailFragment : NormalFragment() {
apiResponse?.let {
if (apiResponse.data != null) {
mDetailEntity = apiResponse.data
mBinding.detail = mDetailEntity
if (mAnswerIdList.size == 0) mAnswerIdList.add(mAnswerId!!)
@ -258,16 +269,17 @@ class AnswerDetailFragment : NormalFragment() {
showCompensateAnimation(scrollUp = false)
}
GdtHelper.logAction(ActionType.PAGE_VIEW,
GdtHelper.CONTENT_TYPE, "ANSWER",
GdtHelper.CONTENT_ID, mAnswerId)
GdtHelper.logAction(ActionType.PAGE_VIEW, GdtHelper.CONTENT_TYPE, "ANSWER", GdtHelper.CONTENT_ID, mAnswerId)
mBinding.detail = mDetailEntity
updateView()
// 没点赞过作者不是自己正文长度不少于20个字。 开启停留一定时长(字数/10 + 5秒)后的动画
if (!mDetailEntity!!.me.isAnswerOwn && !mDetailEntity!!.me.isAnswerVoted) {
if (mDetailEntity!!.content.length > 20) {
startTimeElapsedCount((mDetailEntity!!.content.length / 10f + 5).toInt())
}
}
updateView()
} else if (apiResponse.httpException != null) {
val e = apiResponse.httpException
try {
@ -318,6 +330,11 @@ class AnswerDetailFragment : NormalFragment() {
}
})
mViewModel.commentable.observeNonNull(this) { commentable ->
mDetailEntity?.commentable = commentable
toggleComment(commentable)
}
mViewModel.voteLiveData.observe(this, Observer { apiResponse ->
apiResponse?.let {
if (apiResponse.data != null) {
@ -370,52 +387,54 @@ class AnswerDetailFragment : NormalFragment() {
}
})
mViewModel.fold.observe(this, Observer { isFold ->
isFold?.let {
if (isFold) {
if (MeEntity.MODERATOR_LEVEL_PRIMARY == mDetailEntity!!.me.moderatorLevel) {
toast("提交成功")
} else {
toast("操作成功")
requireActivity().setResult(BaseFragment.RESULT_REFRESH, null)
requireActivity().finish()
}
mViewModel.fold.observeNonNull(this) { isFold ->
if (isFold) {
if (MeEntity.MODERATOR_LEVEL_PRIMARY == mDetailEntity!!.me.moderatorLevel) {
toast("提交成功")
} else {
toast("权限错误,请刷新后重试")
toast("操作成功")
requireActivity().setResult(BaseFragment.RESULT_REFRESH, null)
requireActivity().finish()
}
} else {
toast("权限错误,请刷新后重试")
}
})
}
mViewModel.hide.observe(this, Observer { isHidden ->
isHidden?.let {
if (isHidden) {
if (MeEntity.MODERATOR_LEVEL_PRIMARY == mDetailEntity!!.me.moderatorLevel) {
toast("提交成功")
} else {
toast("操作成功")
mViewModel.getAnswerDetail(mAnswerId!!, mEntrance)
requireActivity().setResult(BaseFragment.RESULT_REFRESH, null)
}
mViewModel.hide.observeNonNull(this) { isHidden ->
if (isHidden) {
if (MeEntity.MODERATOR_LEVEL_PRIMARY == mDetailEntity!!.me.moderatorLevel) {
toast("提交成功")
} else {
toast("权限错误,请刷新后重试")
toast("操作成功")
mViewModel.getAnswerDetail(mAnswerId!!, mEntrance)
requireActivity().setResult(BaseFragment.RESULT_REFRESH, null)
}
} else {
toast("权限错误,请刷新后重试")
}
})
}
mViewModel.highlight.observe(this, Observer { isHighlighted ->
isHighlighted?.let {
if (isHighlighted) {
if (MeEntity.MODERATOR_LEVEL_PRIMARY == mDetailEntity!!.me.moderatorLevel) {
toast("提交成功")
} else {
toast("操作成功")
requireActivity().finish()
}
mViewModel.highlight.observeNonNull(this) { isHighlighted ->
if (isHighlighted) {
if (MeEntity.MODERATOR_LEVEL_PRIMARY == mDetailEntity!!.me.moderatorLevel) {
toast("提交成功")
} else {
toast("权限错误,请刷新后重试")
toast("操作成功")
requireActivity().finish()
}
} else {
toast("权限错误,请刷新后重试")
}
})
}
}
private fun toggleComment(enable: Boolean) {
if (enable) {
mAnswerCommentCountTv.text = String.format("%d 评论", mDetailEntity!!.commentCount)
} else {
mAnswerCommentCountTv.text = "评论已关闭"
}
}
/**
@ -476,30 +495,11 @@ class AnswerDetailFragment : NormalFragment() {
}
private fun trackReadEvent() {
MtaHelper.onEventWithTime(
"答案阅读量_按社区",
mElapsedHelper!!.elapsedTime,
mDetailEntity!!.community.name,
StringUtils.combineTwoString(mDetailEntity!!.content, mAnswerId))
MtaHelper.onEventWithTime(
"答案阅读量_按位置",
mElapsedHelper!!.elapsedTime,
mPath,
StringUtils.combineTwoString(mDetailEntity!!.content, mAnswerId))
MtaHelper.onEventWithTime(
"答案阅读量_社区加位置",
mElapsedHelper!!.elapsedTime,
mDetailEntity!!.community.name,
mPath)
LogUtils.uploadAnswerReadTime(mEntrance,
mElapsedHelper!!.elapsedTime,
mAnswerId,
mDetailEntity!!.question,
mDetailEntity!!.community.id,
mDetailEntity!!.community.name,
mViewModel.trackReadEvent(mAnswerId!!,
mDetailEntity!!,
mElapsedHelper?.elapsedTime!!,
mEntrance,
mPath!!,
mSpecialColumn)
mElapsedHelper?.resetCounting()
@ -523,33 +523,15 @@ class AnswerDetailFragment : NormalFragment() {
val controller = Fresco.newDraweeControllerBuilder()
.setUri(uri)
.setAutoPlayAnimations(true)
.setControllerListener(object : ControllerListener<ImageInfo> {
override fun onFailure(id: String?, throwable: Throwable?) {}
override fun onRelease(id: String?) {}
override fun onSubmit(id: String?, callerContext: Any?) {}
override fun onIntermediateImageSet(id: String?, imageInfo: ImageInfo?) {}
override fun onIntermediateImageFailed(id: String?, throwable: Throwable?) {}
.setControllerListener(object : BaseControllerListener<ImageInfo>() {
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
if (animatable != null) {
val animatedDrawable = animatable as AnimatedDrawable2?
animatedDrawable?.setAnimationListener(object : AnimationListener {
override fun onAnimationStart(drawable: AnimatedDrawable2) {}
animatedDrawable?.setAnimationListener(object : BaseAnimationListener() {
override fun onAnimationStop(drawable: AnimatedDrawable2) {
mAnswerDetailLikeAnimationIv.visibility = View.GONE
updateVote()
}
override fun onAnimationReset(drawable: AnimatedDrawable2) {}
override fun onAnimationRepeat(drawable: AnimatedDrawable2) {}
override fun onAnimationFrame(drawable: AnimatedDrawable2, frameNumber: Int) {}
})
}
}
@ -560,9 +542,9 @@ class AnswerDetailFragment : NormalFragment() {
}
}
private fun showControlDialog() {
val permissionList = mDetailEntity!!.me.moderatorPermissions
val moderatorLevel = mDetailEntity!!.me.moderatorLevel
private fun showControlDialog(answer: AnswerDetailEntity) {
val permissionList = answer.me.moderatorPermissions
val moderatorLevel = answer.me.moderatorLevel
val highlight = "加精回答"
val fold = "折叠回答"
@ -570,8 +552,8 @@ class AnswerDetailFragment : NormalFragment() {
val displayablePermissionList = ArrayList<String>()
if (permissionList.contains(MeEntity.CHOICENESS_ANSWER) && !mDetailEntity!!.me.isAnswerOwn) {
// 将答案加入精选的权限
if (permissionList.contains(MeEntity.CHOICENESS_ANSWER) && !answer.me.isAnswerOwn) {
// 将答案加的权限
displayablePermissionList.add(highlight)
}
if (permissionList.contains(MeEntity.FOLD_ANSWER)) {
@ -582,23 +564,22 @@ class AnswerDetailFragment : NormalFragment() {
}
val disabledOptions = ArrayList<String>()
if (mDetailEntity!!.fold!!) {
if (answer.fold!!) {
disabledOptions.add(fold)
}
DialogUtils.showListDialog(requireContext(), displayablePermissionList, disabledOptions) { text ->
val content: String
if (MeEntity.MODERATOR_LEVEL_PRIMARY == moderatorLevel) {
content = "你的操作将提交给小编审核,确定提交吗?"
val content: String = if (MeEntity.MODERATOR_LEVEL_PRIMARY == moderatorLevel) {
"你的操作将提交给小编审核,确定提交吗?"
} else {
content = "你的操作将立即生效,确定提交吗?(你的管理权限为:高级)"
"你的操作将立即生效,确定提交吗?(你的管理权限为:高级)"
}
when (text) {
highlight -> DialogUtils.showAlertDialog(requireContext(), highlight, content,
"确定", "取消",
{ mViewModel.doHighlightThisAnswer(mAnswerId!!) }, null)
fold -> if (mDetailEntity!!.fold!!) {
fold -> if (answer.fold!!) {
Utils.toast(requireContext(), "回答已经折叠")
} else {
DialogUtils.showAlertDialog(requireContext(), fold, content,
@ -614,11 +595,8 @@ class AnswerDetailFragment : NormalFragment() {
override fun onMenuItemClick(menuItem: MenuItem) {
when (menuItem.itemId) {
R.id.menu_more -> {
mDetailEntity?.let {
showMoreItemDialog()
}
}
R.id.menu_more -> mDetailEntity?.let { showMoreItemDialog(it) }
R.id.menu_collect -> {
if (mDetailEntity == null) return
CheckLoginUtils.checkLogin(context, "回答详情-收藏") {
@ -668,7 +646,7 @@ class AnswerDetailFragment : NormalFragment() {
}
}
private fun showMoreItemDialog() {
private fun showMoreItemDialog(answer: AnswerDetailEntity) {
if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
val view = LayoutInflater.from(context).inflate(R.layout.menu_answer_detail_more, null)
val dialog = Dialog(activity!!)
@ -684,29 +662,45 @@ class AnswerDetailFragment : NormalFragment() {
window.attributes = lp
}
dialog.show()
val item1 = view.findViewById<View>(R.id.more_item1)
val item2 = view.findViewById<View>(R.id.more_item2)
if (mDetailEntity!!.me.isModerator) {
val reportContainer = view.findViewById<View>(R.id.container_report)
val shareContainer = view.findViewById<View>(R.id.container_share)
val commentControlContainer = view.findViewById<View>(R.id.container_comment_control)
if (answer.me.isModerator) {
val controlView = view.findViewById<View>(R.id.container_control)
controlView.visibility = View.VISIBLE
controlView.setOnClickListener {
showControlDialog()
showControlDialog(answer)
dialog.dismiss()
}
}
item1.setOnClickListener {
if (answer.me.isAnswerOwn) {
commentControlContainer.visibility = View.VISIBLE
val commentControlTv = commentControlContainer.findViewById<TextView>(R.id.tv_comment_control)
if (answer.commentable == true) {
commentControlTv.text = "关闭评论"
} else {
commentControlTv.text = "恢复评论"
}
commentControlContainer.setOnClickListener {
mViewModel.toggleComment(mAnswerId!!, !mDetailEntity?.commentable!!)
dialog.dismiss()
}
}
reportContainer.setOnClickListener {
dialog.dismiss()
// 跳转意见反馈
SuggestionActivity.startSuggestionActivity(context, SuggestType.normal, "report",
"回答举报($mAnswerId")
}
item2.setOnClickListener {
shareContainer.setOnClickListener {
GdtHelper.logAction(ActionType.SHARE,
GdtHelper.CONTENT_TYPE, "ANSWER",
GdtHelper.CONTENT_ID, mAnswerId)
dialog.dismiss()
if (mDetailEntity == null) return@setOnClickListener
val shareIcon: String = if (mAnswersImgs!!.size > 0) {
mAnswersImgs[0]
} else {
@ -719,9 +713,9 @@ class AnswerDetailFragment : NormalFragment() {
ShareUtils.getInstance(context).showShareWindows(activity,
getView(),
getString(R.string.share_answers_url, mDetailEntity!!.question.id, mAnswerId),
getString(R.string.share_answers_url, answer.question.id, mAnswerId),
shareIcon,
getString(R.string.ask_share_answers_title, mDetailEntity!!.user.name, mDetailEntity!!.question.title, mDetailEntity!!.vote),
getString(R.string.ask_share_answers_title, answer.user.name, answer.question.title, answer.vote),
shareSummary,
ShareUtils.ShareType.askNormal)
}
@ -736,7 +730,10 @@ class AnswerDetailFragment : NormalFragment() {
R.id.answer_detail_comment_count_container,
R.id.answer_detail_follow,
R.id.answer_detail_usericon,
R.id.answer_detail_username)
R.id.answer_detail_username,
R.id.questionsdetail_item_pic1,
R.id.questionsdetail_item_pic2,
R.id.questionsdetail_item_pic3)
override fun onClick(view: View) {
when (view.id) {
R.id.reuse_no_connection -> {
@ -744,78 +741,103 @@ class AnswerDetailFragment : NormalFragment() {
mLoading.visibility = View.VISIBLE
mViewModel.getAnswerDetail(mAnswerId!!, mEntrance)
}
R.id.answer_detail_title_answer_count_container, R.id.answer_detail_title -> if (mDetailEntity != null) {
startActivity(QuestionsDetailActivity.getIntent(context, mDetailEntity!!.question.id, mEntrance, "回答详情"))
}
R.id.answer_detail_like_container -> CheckLoginUtils.checkLogin(context, "回答详情-赞同") {
if (mDetailEntity != null && !mDetailEntity!!.me.isAnswerVoted) {
mViewModel.postVote(mAnswerId!!)
DataUtils.onMtaEvent(context,
"答案点赞量_社区加位置",
UserManager.getInstance().community.name,
mDetailEntity?.community?.name,
mPath)
} else {
toast(R.string.ask_vote_hint)
}
}
R.id.answer_detail_comment_count_container -> if (mDetailEntity != null) {
val content = if (mDetailEntity != null) mDetailEntity!!.content else ""
val uploadCount = if (content.length > 30) {
content.substring(0, 30)
R.id.answer_detail_comment_count_container -> {
if (mDetailEntity != null && mDetailEntity?.commentable == true) {
val content = if (mDetailEntity != null) mDetailEntity!!.content else ""
val uploadCount = if (content.length > 30) {
content.substring(0, 30)
} else {
content
}
DataUtils.onMtaEvent(context, "详情页面", "答案评论详情", uploadCount)
showCommentDialog(mDetailEntity!!.commentCount == 0)
} else {
content
toast("评论已关闭")
}
DataUtils.onMtaEvent(context, "详情页面", "答案评论详情", uploadCount)
showCommentDialog(mDetailEntity!!.commentCount == 0)
}
R.id.answer_detail_title_status_tv -> if (mDetailEntity != null) {
when (mAnswerStatus) {
ANSWER_STATUS_UNKNOWN -> {
}
ANSWERED_MY_ANSWER -> {
// 跳转编辑问题页面
editContent()
}
ANSWERED_NOT_MY_ANSWER -> {
startActivityForResult(AnswerDetailActivity.getIntent(context, mDetailEntity!!.me.myAnswerId, mEntrance, "答案详情"), ANSWER_PATCH_REQUEST)
}
NOT_ANSWERED_YET -> CheckLoginUtils.checkLogin(context, "回答详情-[我来回答]") {
val question = mDetailEntity!!.question
startActivity(AnswerEditActivity.getIntent(context!!, question.id, question.title, true, question.communityName))
R.id.answer_detail_title_status_tv -> {
mDetailEntity?.let {
when (mAnswerStatus) {
ANSWER_STATUS_UNKNOWN -> {
}
ANSWERED_MY_ANSWER -> {
// 跳转编辑问题页面
editContent(it)
}
ANSWERED_NOT_MY_ANSWER -> {
startActivityForResult(AnswerDetailActivity.getIntent(context, mDetailEntity!!.me.myAnswerId, mEntrance, "答案详情"), ANSWER_PATCH_REQUEST)
}
NOT_ANSWERED_YET -> CheckLoginUtils.checkLogin(context, "回答详情-[我来回答]") {
val question = mDetailEntity!!.question
startActivity(AnswerEditActivity.getIntent(context, question.id, question.title, true, question.communityName))
}
}
}
}
R.id.answer_detail_usericon,
R.id.answer_detail_username -> PersonalHomeActivity.startTargetActivity(context!!, mDetailEntity!!.user.id, mEntrance, "回答详情")
R.id.answer_detail_follow -> CheckLoginUtils.checkLogin(context, "回答详情-[关注]用户") {
if (mBinding.answerDetailFollow.text == "关注") {
mViewModel.follow(mDetailEntity!!.user.id!!)
R.id.answer_detail_follow -> {
CheckLoginUtils.checkLogin(context, "回答详情-[关注]用户") {
if (mBinding.answerDetailFollow.text == "关注") {
mViewModel.follow(mDetailEntity!!.user.id!!)
}
}
}
R.id.questionsdetail_item_pic1 -> showQuestionImageDetail(0)
R.id.questionsdetail_item_pic2 -> showQuestionImageDetail(1)
R.id.questionsdetail_item_pic3 -> showQuestionImageDetail(2)
}
}
private fun showQuestionImageDetail(position: Int) {
val images = ArrayList(mDetailEntity?.question?.images)
if (position > images.size) {
return
} else {
val intent = ViewImageActivity.getViewImageIntent(context, images, position, "$mEntrance+(回答详情)")
startActivity(intent)
}
}
private fun showCommentDialog(showKeyBoard: Boolean) {
var commentCount = 0
if (mDetailEntity != null) {
commentCount = mDetailEntity!!.commentCount
}
val intent = CommentActivity.getIntent(context!!, mAnswerId!!, commentCount, mCacheCommentDraft, showKeyBoard)
val intent = CommentActivity.getIntent(context!!,
mAnswerId!!,
mDetailEntity?.commentCount ?: 0,
mCacheCommentDraft, showKeyBoard)
startActivityForResult(intent, CommentActivity.REQUEST_CODE)
}
private fun editContent() {
if (mDetailEntity != null) {
startActivityForResult(
AnswerEditActivity.getIntent(context!!,
mAnswerId,
mDetailEntity!!.question.title,
mDetailEntity!!.content,
UserManager.getInstance().community.name),
ANSWER_PATCH_REQUEST)
}
private fun editContent(answer: AnswerDetailEntity) {
startActivityForResult(
AnswerEditActivity.getIntent(context,
mAnswerId,
answer.question.title,
answer.content,
answer.community.name),
ANSWER_PATCH_REQUEST)
}
@SuppressLint("DefaultLocale")
@ -838,6 +860,29 @@ class AnswerDetailFragment : NormalFragment() {
}
mAnswerCountTv.text = String.format("查看全部%d个回答", mDetailEntity!!.question.answerCount)
mQuestionsDescTv.text = mDetailEntity?.question?.description
val images = mDetailEntity?.question?.images ?: arrayListOf()
for (i in images.indices) {
when (i) {
0 -> ImageUtils.display(mPic1, images[i])
1 -> ImageUtils.display(mPic2, images[i])
2 -> {
ImageUtils.display(mPic3, images[i])
if (images.size > 3) {
mPic3Mask.visibility = View.VISIBLE
mPic3Desc.visibility = View.VISIBLE
mPic3Desc.text = "+" + (images.size - 3)
}
}
}
}
if (images.isNotEmpty()) {
mImgLl.visibility = View.VISIBLE
} else {
mImgLl.visibility = View.GONE
}
// 是否已回答
if (!TextUtils.isEmpty(mDetailEntity!!.me.myAnswerId)) {
@ -865,7 +910,7 @@ class AnswerDetailFragment : NormalFragment() {
mTime.text = String.format("编辑于 %s", NewsUtils.getFormattedTime(mDetailEntity!!.updateTime))
}
mAnswerCommentCountTv.text = String.format("%d 评论", NumberUtils.transSimpleCount(mDetailEntity!!.commentCount))
toggleComment(mDetailEntity?.commentable ?: true)
mNoConn.visibility = View.GONE
mLoading.visibility = View.GONE
@ -912,11 +957,7 @@ class AnswerDetailFragment : NormalFragment() {
mBinding.answerDetailFollow.animate()
.alpha(0f)
.setInterpolator(LinearInterpolator())
.doOnEnd {
if (context != null) {
mBinding.answerDetailFollow.visibility = View.GONE
}
}
.doOnEnd { context?.let { mBinding.answerDetailFollow.visibility = View.GONE } }
.setDuration(500L)
.start()
}, 2000L)
@ -956,7 +997,9 @@ class AnswerDetailFragment : NormalFragment() {
TranslateAnimation.RELATIVE_TO_PARENT, 0f,
TranslateAnimation.RELATIVE_TO_PARENT, fromY,
TranslateAnimation.RELATIVE_TO_PARENT, 0f)
translateAnimation.duration = 300
mContent.scrollTo(0, 0)
translateAnimation.duration = SCROLL_ANIMATION_DURATION
translateAnimation.interpolator = DecelerateInterpolator()
mContainerView.startAnimation(translateAnimation)
}
@ -971,7 +1014,7 @@ class AnswerDetailFragment : NormalFragment() {
TranslateAnimation.RELATIVE_TO_PARENT, 0f,
TranslateAnimation.RELATIVE_TO_PARENT, 0f,
TranslateAnimation.RELATIVE_TO_PARENT, toY)
translateAnimation.duration = 300
translateAnimation.duration = SCROLL_ANIMATION_DURATION
translateAnimation.interpolator = AccelerateInterpolator()
translateAnimation.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationRepeat(animation: Animation?) {}
@ -1062,6 +1105,7 @@ class AnswerDetailFragment : NormalFragment() {
private const val ANSWERED_NOT_MY_ANSWER = 2
private const val NOT_ANSWERED_YET = 3
private const val SCROLL_ANIMATION_DURATION = 500L
private const val ANSWER_PATCH_REQUEST = 100
const val TAG = "ask.AnswerDetailFragment"
}

View File

@ -6,8 +6,11 @@ import android.arch.lifecycle.LiveData
import android.arch.lifecycle.MutableLiveData
import android.text.Html
import com.gh.common.util.DataUtils
import com.gh.common.util.LogUtils
import com.gh.common.util.MtaHelper
import com.gh.common.util.StringUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.entity.SpecialColumn
import com.gh.gamecenter.entity.VoteEntity
import com.gh.gamecenter.qa.entity.AnswerDetailEntity
import com.gh.gamecenter.retrofit.Response
@ -16,9 +19,12 @@ import com.gh.gamecenter.user.ApiResponse
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.RequestBody
import okhttp3.ResponseBody
import org.json.JSONObject
import retrofit2.HttpException
import java.util.*
class AnswerDetailViewModel(application: Application) : AndroidViewModel(application) {
@ -29,6 +35,7 @@ class AnswerDetailViewModel(application: Application) : AndroidViewModel(applica
val highlight = MutableLiveData<Boolean>()
val hide = MutableLiveData<Boolean>()
val fold = MutableLiveData<Boolean>()
val commentable = MutableLiveData<Boolean>()
val answerLiveData: LiveData<ApiResponse<AnswerDetailEntity>>
get() = mAnswerLiveData
@ -119,6 +126,27 @@ class AnswerDetailViewModel(application: Application) : AndroidViewModel(applica
})
}
fun toggleComment(answerId: String, isCommentable: Boolean) {
val params = HashMap<String, Boolean>()
params["commentable"] = isCommentable
val body = RequestBody.create(MediaType.parse("application/json"),
JSONObject(params).toString())
RetrofitManager.getInstance(getApplication())
.api
.postAnswerCommentable(answerId, body)
.subscribeOn(Schedulers.io())
.subscribe(object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
commentable.postValue(isCommentable)
}
override fun onFailure(e: HttpException?) {
Utils.toast(getApplication(), e?.message())
}
})
}
fun doHighlightThisAnswer(answerId: String) {
RetrofitManager.getInstance(getApplication()).api
.highlightAnswer(answerId)
@ -197,4 +225,37 @@ class AnswerDetailViewModel(application: Application) : AndroidViewModel(applica
})
}
fun trackReadEvent(answerId: String,
answerDetailEntity: AnswerDetailEntity,
elapsedTime: Int,
entrance: String,
path: String,
specialColumn: SpecialColumn?) {
MtaHelper.onEventWithTime(
"答案阅读量_按社区",
elapsedTime,
answerDetailEntity.community.name,
StringUtils.combineTwoString(answerDetailEntity.content, answerId))
MtaHelper.onEventWithTime(
"答案阅读量_按位置",
elapsedTime,
path,
StringUtils.combineTwoString(answerDetailEntity.content, answerId))
MtaHelper.onEventWithTime(
"答案阅读量_社区加位置",
elapsedTime,
answerDetailEntity.community.name,
path)
LogUtils.uploadAnswerReadTime(entrance,
elapsedTime,
answerId,
answerDetailEntity.question,
answerDetailEntity.community.id,
answerDetailEntity.community.name,
specialColumn)
}
}

View File

@ -1,6 +1,5 @@
package com.gh.gamecenter.qa.article.detail
import android.animation.Animator
import android.app.Activity
import android.app.Dialog
import android.arch.lifecycle.Lifecycle
@ -25,7 +24,7 @@ import butterknife.OnClick
import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.fresco.animation.drawable.AnimatedDrawable2
import com.facebook.fresco.animation.drawable.AnimationListener
import com.facebook.fresco.animation.drawable.BaseAnimationListener
import com.gh.base.BaseActivity
import com.gh.common.TimeElapsedHelper
import com.gh.common.TimeoutCallback
@ -37,11 +36,13 @@ import com.gh.gamecenter.SuggestionActivity
import com.gh.gamecenter.ViewImageActivity
import com.gh.gamecenter.databinding.ActivityArticleDetailBinding
import com.gh.gamecenter.entity.CommunityEntity
import com.gh.gamecenter.entity.MeEntity
import com.gh.gamecenter.entity.SpecialColumn
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.mvvm.Status
import com.gh.gamecenter.qa.article.edit.ArticleEditActivity
import com.gh.gamecenter.qa.comment.CommentActivity
import com.gh.gamecenter.qa.entity.ArticleDetailEntity
import com.gh.gamecenter.suggest.SuggestType
import com.google.android.flexbox.FlexboxLayout
import com.qq.gdt.action.ActionType
@ -179,6 +180,37 @@ class ArticleDetailActivity : BaseActivity() {
}
}
mViewModel.highlight.observeNonNull(this) { isHighlighted ->
if (isHighlighted) {
if (MeEntity.MODERATOR_LEVEL_PRIMARY == mViewModel.detailEntity!!.me.moderatorLevel) {
toast("提交成功")
} else {
toast("操作成功")
finish()
}
} else {
toast("权限错误,请刷新后重试")
}
}
mViewModel.hide.observeNonNull(this) { isHidden ->
if (isHidden) {
if (MeEntity.MODERATOR_LEVEL_PRIMARY == mViewModel.detailEntity!!.me.moderatorLevel) {
toast("提交成功")
} else {
toast("操作成功")
mViewModel.getArticleDetail()
}
} else {
toast("权限错误,请刷新后重试")
}
}
mViewModel.commentable.observeNonNull(this) { enable ->
mViewModel.detailEntity?.commentable = enable
updateCommentable(enable)
}
mBinding.articleDetailRd.addJavascriptInterface(JsInterface(), "imagelistener")
if (mIsShowCommentManager) {
@ -188,6 +220,15 @@ class ArticleDetailActivity : BaseActivity() {
mElapsedHelper = TimeElapsedHelper(this)
}
private fun updateCommentable(commentable: Boolean) {
if (commentable) {
mBinding.articleDetailCommentCountTv.text = String.format("%d 评论",
mViewModel.detailEntity?.count?.comment ?: 0)
} else {
mBinding.articleDetailCommentCountTv.text = "评论已关闭"
}
}
/**
* 开启点赞引导动画倒计时
*/
@ -209,32 +250,14 @@ class ArticleDetailActivity : BaseActivity() {
.setUri(uri)
.setAutoPlayAnimations(true)
.setControllerListener(object : BaseControllerListener<Any>() {
override fun onFinalImageSet(id: String?,
imageInfo: Any?,
animatable: Animatable?) {
override fun onFinalImageSet(id: String?, imageInfo: Any?, animatable: Animatable?) {
if (animatable != null) {
val animatedDrawable = animatable as AnimatedDrawable2?
animatedDrawable!!.setAnimationListener(object : AnimationListener {
override fun onAnimationStart(drawable: AnimatedDrawable2) {
}
animatedDrawable!!.setAnimationListener(object : BaseAnimationListener() {
override fun onAnimationStop(drawable: AnimatedDrawable2) {
mBinding.articleDetailCommentLikeAnimationIv.visibility = View.GONE
updateVote()
}
override fun onAnimationReset(drawable: AnimatedDrawable2) {
}
override fun onAnimationRepeat(drawable: AnimatedDrawable2) {
}
override fun onAnimationFrame(drawable: AnimatedDrawable2, frameNumber: Int) {
}
})
}
}
@ -278,12 +301,14 @@ class ArticleDetailActivity : BaseActivity() {
fun onClick(v: View) {
when (v.id) {
R.id.article_detail_comment_count_container -> {
if (mViewModel.detailEntity != null) {
if (mViewModel.detailEntity != null == mViewModel.detailEntity!!.commentable) {
val intent = CommentActivity.getArticleCommentIntent(this, mViewModel.articleId!!
, mViewModel.detailEntity?.count?.comment, ""
, mViewModel.detailEntity?.count?.comment == 0
, mViewModel.detailEntity?.community?.id!!)
startActivityForResult(intent, CommentActivity.REQUEST_CODE)
} else {
toast("评论已关闭")
}
}
R.id.article_detail_like_container -> {
@ -320,7 +345,8 @@ class ArticleDetailActivity : BaseActivity() {
}
}
}
R.id.article_detail_usericon_container, R.id.article_detail_username -> {
R.id.article_detail_usericon_container,
R.id.article_detail_username -> {
if (mViewModel.detailEntity != null) {
PersonalHomeActivity.startTargetActivity(this,
mViewModel.detailEntity?.user?.id, mEntrance, "社区文章详情")
@ -340,23 +366,11 @@ class ArticleDetailActivity : BaseActivity() {
mBinding.articleDetailFollow.animate()
.alpha(0f)
.setInterpolator(LinearInterpolator())
.setListener(object : Animator.AnimatorListener {
override fun onAnimationStart(animation: Animator) {
}
override fun onAnimationEnd(animation: Animator) {
.doOnEnd {
if (this != null && !this.isFinishing) {
mBinding.articleDetailFollow.visibility = View.GONE
}
override fun onAnimationCancel(animation: Animator) {
}
override fun onAnimationRepeat(animation: Animator) {
}
})
}
.setDuration(500L)
.start()
}, 2000L)
@ -372,10 +386,10 @@ class ArticleDetailActivity : BaseActivity() {
&& mViewModel.detailEntity != null
&& !mViewModel.detailEntity!!.me.isAnswerOwn) {
mBinding.tvFollowHint.visibility = View.VISIBLE
mBinding.tvFollowHint.animate()
.alpha(0f)
.setDuration(750)
.start()
mBinding.tvFollowHint.animate()
.alpha(0f)
.setDuration(750)
.start()
}
}
@ -427,27 +441,54 @@ class ArticleDetailActivity : BaseActivity() {
window.attributes = lp
}
dialog.show()
val itemName1 = view.findViewById<TextView>(R.id.more_item_title1)
val itemIcon1 = view.findViewById<ImageView>(R.id.more_item_icon1)
val item1 = view.findViewById<View>(R.id.more_item1)
val item2 = view.findViewById<View>(R.id.more_item2)
if (mViewModel.detailEntity?.user?.id == UserManager.getInstance().userId) {
itemName1.text = "编辑文章"
itemIcon1.setImageResource(R.drawable.menu_more_edit)
val reportContainer = view.findViewById<View>(R.id.container_report)
val reportTv = view.findViewById<TextView>(R.id.tv_report)
val reportIv = view.findViewById<ImageView>(R.id.iv_report)
val shareContainer = view.findViewById<View>(R.id.container_share)
val commentControlContainer = view.findViewById<View>(R.id.container_comment_control)
if (mViewModel.detailEntity?.me!!.isModerator) {
val controlView = view.findViewById<View>(R.id.container_control)
controlView.visibility = View.VISIBLE
controlView.setOnClickListener {
showControlDialog(mViewModel.detailEntity!!)
dialog.dismiss()
}
}
item1.setOnClickListener { _ ->
if (mViewModel.detailEntity?.user?.id == UserManager.getInstance().userId) {
reportTv.text = "编辑文章"
reportIv.setImageResource(R.drawable.menu_more_edit)
}
if (mViewModel.detailEntity?.me!!.isAnswerOwn) {
commentControlContainer.visibility = View.VISIBLE
val commentControlTv = commentControlContainer.findViewById<TextView>(R.id.tv_comment_control)
if (mViewModel.detailEntity?.commentable!!) {
commentControlTv.text = "关闭评论"
} else {
commentControlTv.text = "恢复评论"
}
commentControlContainer.setOnClickListener {
mViewModel.toggleComment(
mViewModel.detailEntity?.community!!.id,
mViewModel.articleId!!,
!mViewModel.detailEntity?.commentable!!)
dialog.dismiss()
}
}
reportContainer.setOnClickListener {
dialog.dismiss()
if (mViewModel.detailEntity?.user?.id == UserManager.getInstance().userId) {
startActivityForResult(ArticleEditActivity.getPatchIntent(this, mViewModel.detailEntity!!), ARTICLE_PATCH_REQUEST)
} else {
// 跳转意见反馈
SuggestionActivity.startSuggestionActivity(this, SuggestType.normal, "report",
"文章举报(" + mViewModel.articleId + "")
}
}
item2.setOnClickListener { _ ->
shareContainer.setOnClickListener {
dialog.dismiss()
GdtHelper.logAction(ActionType.SHARE,
@ -471,6 +512,45 @@ class ArticleDetailActivity : BaseActivity() {
}
}
private fun showControlDialog(article: ArticleDetailEntity) {
val permissionList = article.me.moderatorPermissions
val moderatorLevel = article.me.moderatorLevel
val highlight = "加精文章"
val hide = "隐藏文章"
val displayablePermissionList = ArrayList<String>()
if (permissionList.contains(MeEntity.CHOICENESS_COMMUNITY_ARTICLE)) {
displayablePermissionList.add(highlight)
}
if (permissionList.contains(MeEntity.HIDE_COMMUNITY_ARTICLE)) {
displayablePermissionList.add(hide)
}
DialogUtils.showListDialog(this, displayablePermissionList, null) { text ->
val content: String = if (MeEntity.MODERATOR_LEVEL_PRIMARY == moderatorLevel) {
"你的操作将提交给小编审核,确定提交吗?"
} else {
"你的操作将立即生效,确定提交吗?(你的管理权限为:高级)"
}
when (text) {
highlight -> {
DialogUtils.showAlertDialog(this, highlight, content,
"确定", "取消",
{ mViewModel.doHighlightThisArticle(mViewModel.detailEntity!!.community.id, mViewModel.articleId) }, null)
}
hide -> {
DialogUtils.showAlertDialog(this, hide, content,
"确定", "取消",
{ mViewModel.doHideThisArticle(mViewModel.detailEntity!!.community.id, mViewModel.articleId) }, null)
}
}
}
}
private fun updateView() {
if (mViewModel.detailEntity == null) return
mCollectMenuItem = getMenuItem(R.id.menu_collect)
@ -539,6 +619,7 @@ class ArticleDetailActivity : BaseActivity() {
}
}
updateCommentable(mViewModel.detailEntity?.commentable!!)
updateVote()
}
@ -573,7 +654,6 @@ class ArticleDetailActivity : BaseActivity() {
override fun onDestroy() {
super.onDestroy()
if (mViewModel.detailEntity != null) {
MtaHelper.onEventWithTime(
"文章阅读量_社区加位置",
mElapsedHelper?.elapsedTime!!,
@ -584,7 +664,8 @@ class ArticleDetailActivity : BaseActivity() {
mViewModel.articleId,
mViewModel.detailEntity?.title,
mElapsedHelper?.elapsedTime!!,
mViewModel.detailEntity?.community, mSpecialColumn)
mViewModel.detailEntity?.community,
mSpecialColumn)
}
}

View File

@ -17,24 +17,31 @@ import com.gh.gamecenter.retrofit.RetrofitManager
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.RequestBody
import okhttp3.ResponseBody
import org.greenrobot.eventbus.EventBus
import org.json.JSONObject
import retrofit2.HttpException
import java.util.*
class ArticleDetailViewModel(application: Application) : AndroidViewModel(application) {
private val mApi = RetrofitManager.getInstance(getApplication()).api
var detailEntity: ArticleDetailEntity? = null
val articleLiveData = MutableLiveData<Resource<ArticleDetailEntity>>()
private val mFollowLiveData = MutableLiveData<Boolean>()
private var community: CommunityEntity? = null // 社区名称可能为空
val hide = MutableLiveData<Boolean>()
val vote = MutableLiveData<VoteEntity>()
val highlight = MutableLiveData<Boolean>()
val commentable = MutableLiveData<Boolean>()
val articleLiveData = MutableLiveData<Resource<ArticleDetailEntity>>()
val followLiveData: LiveData<Boolean>
get() = mFollowLiveData
val vote = MutableLiveData<VoteEntity>()
private var community: CommunityEntity? = null // 社区名称可能为空
var articleId: String? = null
@ -143,4 +150,57 @@ class ArticleDetailViewModel(application: Application) : AndroidViewModel(applic
}
})
}
fun doHighlightThisArticle(communityId: String, articleId: String?) {
mApi.highlightCommunityArticle(communityId, articleId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
super.onResponse(response)
highlight.postValue(true)
}
override fun onFailure(e: HttpException?) {
super.onFailure(e)
highlight.postValue(false)
}
})
}
fun doHideThisArticle(communityId: String, articleId: String?) {
mApi.hideCommunityArticle(communityId, articleId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
super.onResponse(response)
hide.postValue(true)
}
override fun onFailure(e: HttpException?) {
super.onFailure(e)
hide.postValue(false)
}
})
}
fun toggleComment(communityId: String, articleId: String, isCommentable: Boolean) {
val params = HashMap<String, Boolean>()
params["commentable"] = isCommentable
val body = RequestBody.create(MediaType.parse("application/json"),
JSONObject(params).toString())
mApi.postCommunityArticleCommentable(communityId, articleId, body)
.subscribeOn(Schedulers.io())
.subscribe(object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
commentable.postValue(isCommentable)
}
override fun onFailure(e: HttpException?) {
Utils.toast(getApplication(), e?.message())
}
})
}
}

View File

@ -19,7 +19,7 @@ class CommentActivity : AppCompatActivity() {
const val SHOW_KEYBOARD = "show_keyboard"
const val ARTICLE_ID = "article_id"
const val ARTICLE_COMMUNITY_ID = "article_community_id"
const val COMMUNITY_ID = "community_id"
const val REQUEST_CODE = 8123
@ -36,13 +36,13 @@ class CommentActivity : AppCompatActivity() {
@JvmStatic
fun getArticleCommentIntent(context: Context, articleId: String, commentCount: Int? = 0,
commentDraft: String? = null, showKeyboard: Boolean,
articleCommunityId: String): Intent {
communityId: String): Intent {
val intent = Intent(context, CommentActivity::class.java)
intent.putExtra(ARTICLE_ID, articleId)
intent.putExtra(COMMENT_COUNT, commentCount)
intent.putExtra(COMMENT_DRAFT, commentDraft)
intent.putExtra(SHOW_KEYBOARD, showKeyboard)
intent.putExtra(ARTICLE_COMMUNITY_ID, articleCommunityId)
intent.putExtra(COMMUNITY_ID, communityId)
return intent
}
}
@ -58,7 +58,7 @@ class CommentActivity : AppCompatActivity() {
val showKeyboard = intent.getBooleanExtra(SHOW_KEYBOARD, false)
val articleId = intent.getStringExtra(ARTICLE_ID)
val articleCommunityId = intent.getStringExtra(ARTICLE_COMMUNITY_ID)
val communityId = intent.getStringExtra(COMMUNITY_ID)
val value = object : AnswerDetailFragment.CommentListener {
override fun onCountChange(count: Int) {
@ -82,7 +82,7 @@ class CommentActivity : AppCompatActivity() {
} else {
CommentFragment.getArticleInstance(
articleId,
articleCommunityId,
communityId,
showKeyboard,
commentCount,
commentDraft,

View File

@ -39,7 +39,7 @@ public class CommentConversationFragment extends CommentFragment {
} else {
mEntrance = "(文章-评论详情-查看对话)";
}
mAdapter = new CommentAdapter(getContext(), mArticleId, mArticleCommunityId,
mAdapter = new CommentAdapter(getContext(), mArticleId, mCommunityId,
mAnswerId, false, this, mEntrance);
}
return mAdapter;
@ -52,7 +52,7 @@ public class CommentConversationFragment extends CommentFragment {
mArticleId = getArguments().getString(CommentActivity.ARTICLE_ID);
mArticleCommentId = getArguments().getString(EntranceUtils.KEY_ARTICLE_COMMENT_ID);
mArticleCommunityId = getArguments().getString(CommentActivity.ARTICLE_COMMUNITY_ID);
mCommunityId = getArguments().getString(CommentActivity.COMMUNITY_ID);
mLinkEntity = getArguments().getParcelable(EntranceUtils.KEY_LINK);
super.onCreate(savedInstanceState);
}
@ -88,7 +88,7 @@ public class CommentConversationFragment extends CommentFragment {
@Override
protected CommentViewModel provideListViewModel() {
return ViewModelProviders.of(this, new CommentViewModel.Factory((Application) getContext().getApplicationContext()
, mAnswerId, mCommentId, mArticleId, mArticleCommunityId, mArticleCommentId)).get(CommentViewModel.class);
, mAnswerId, mCommentId, mArticleId, mCommunityId, mArticleCommentId)).get(CommentViewModel.class);
}
@Override

View File

@ -69,7 +69,7 @@ public class CommentFragment extends ListFragment<CommentEntity, CommentViewMode
protected String mAnswerId;
protected String mArticleId;
private String mCommentDraft;
protected String mArticleCommunityId;
protected String mCommunityId;
protected boolean mShowSoftKeyboardOnStartUp;
@ -196,7 +196,7 @@ public class CommentFragment extends ListFragment<CommentEntity, CommentViewMode
@Override
protected CommentViewModel provideListViewModel() {
return ViewModelProviders.of(this, new CommentViewModel.Factory((Application) getContext().getApplicationContext(),
mAnswerId, null, mArticleId, mArticleCommunityId, null)).get(CommentViewModel.class);
mAnswerId, null, mArticleId, mCommunityId, null)).get(CommentViewModel.class);
}
@Override
@ -208,7 +208,7 @@ public class CommentFragment extends ListFragment<CommentEntity, CommentViewMode
} else {
entrance = "(文章详情-评论列表)";
}
mAdapter = new CommentAdapter(getContext(), mArticleId, mArticleCommunityId,
mAdapter = new CommentAdapter(getContext(), mArticleId, mCommunityId,
mAnswerId, true, this, entrance);
}
return mAdapter;
@ -239,7 +239,7 @@ public class CommentFragment extends ListFragment<CommentEntity, CommentViewMode
fragment.mCommentCount = commentCount;
fragment.mCommentListener = listener;
fragment.mCommentDraft = commentDraft;
fragment.mArticleCommunityId = articleCommunityId;
fragment.mCommunityId = articleCommunityId;
return fragment;
}

View File

@ -24,7 +24,7 @@ data class AnswerDetailEntity(var content: String = "",
var community: CommunityEntity = CommunityEntity(),
@SerializedName("comment_count")
var commentCount: Int = 0,
var commentable: Boolean? = false,
var commentable: Boolean? = true,
@SerializedName("next_id")
var nextId: String? = "",
var fold: Boolean? = false) : Parcelable

View File

@ -17,7 +17,8 @@ data class ArticleDetailEntity(@SerializedName("_id")
var user: UserEntity = UserEntity(),
var me: MeEntity = MeEntity(),
val time: ArticleDetailTime = ArticleDetailTime(),
var community: CommunityEntity = CommunityEntity()) : Parcelable
var community: CommunityEntity = CommunityEntity(),
var commentable: Boolean? = true) : Parcelable
@Parcelize
data class ArticleDetailTime(var create: Long = 0, var edit: Long = 0) : Parcelable

View File

@ -15,4 +15,6 @@ data class Questions(@SerializedName("_id")
var communityName: String = "",
@SerializedName("answerCount")
var answerCount: Int = 0,
var description: String? = null,
var images: List<String> = ArrayList(),
val time: Long = 0) : Parcelable

View File

@ -1520,6 +1520,44 @@ public interface ApiService {
@GET("communities/{community_id}")
Observable<AskGameSelectEntity> getCommunityDesc(@Path("community_id") String community_id);
/**
* 设置回答详情的的评论区域是否开启
*/
@POST("answers/{answer_id}:commentable")
Observable<ResponseBody> postAnswerCommentable(@Path("answer_id") String answerId, @Body RequestBody body);
/**
* 加精社区文章
*/
@POST("communities/{community_id}/articles/{article_id}:choiceness")
Observable<ResponseBody> highlightCommunityArticle(@Path("community_id") String communityId, @Path("article_id") String articleId);
/**
* 隐藏社区文章
*/
@POST("communities/{community_id}/articles/{article_id}:hide")
Observable<ResponseBody> hideCommunityArticle(@Path("community_id") String communityId, @Path("article_id") String articleId);
/**
* 置顶社区文章评论
*/
@POST("communities/{community_id}/articles/{article_id}/comments/{comment_id}:set-top")
Observable<ResponseBody> highlightCommunityArticleComment(@Path("community_id") String communityId, @Path("article_id") String articleId, @Path("comment_id") String commendId);
/**
* 隐藏社区文章评论
*/
@POST("communities/{community_id}/articles/{article_id}/comments/{comment_id}:hide")
Observable<ResponseBody> hideCommunityArticleComment(@Path("community_id") String communityId, @Path("article_id") String articleId, @Path("comment_id") String commendId);
/**
* 设置回答详情的的评论区域是否开启
*/
@POST("communities/{community_id}/articles/{article_id}:commentable")
Observable<ResponseBody> postCommunityArticleCommentable(@Path("community_id") String communityId, @Path("article_id") String articleId, @Body RequestBody body);
/**
* 获取社区默认搜索文案
*/