Skip to content

Commit

Permalink
Merge branch 'master' into sunday-nt-1914-ux-post-comment
Browse files Browse the repository at this point in the history
  • Loading branch information
Arkariang committed Jun 4, 2021
2 parents c9307ab + 615c324 commit 1382960
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.kickstarter.libs.models
class OptimizelyFeature {
enum class Key(val key: String) {
LIGHTS_ON("android_lights_on"),
COMMENT_THREADING("android_comment_threading")
COMMENT_THREADING("android_comment_threading"),
COMMENT_ENABLE_THREADS("android_comment_enable_threads"),
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class ThreadActivity : BaseActivity<ThreadViewModel.ViewModel>() {
private fun configureRootCommentView(comment: Comment) {
binding.commentsCardView.setCommentUserName(comment.author().name())
binding.commentsCardView.setCommentBody(comment.body())
binding.commentsCardView.hideReplyViewGroup()
binding.commentsCardView.hideReplyButton()
binding.commentsCardView.setCommentPostTime(DateTimeUtils.relative(this, ksString, comment.createdAt()))
binding.commentsCardView.setCommentUserName(comment.author().name())
binding.commentsCardView.setAvatarUrl(comment.author().avatar().medium())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,21 @@ class CommentCardViewHolder(
.compose(Transformers.observeForUI())
.subscribe { binding.commentsCardView.setCommentCardStatus(it) }

this.vm.outputs.isCommentActionGroupVisible()
this.vm.outputs.isReplyButtonVisible()
.compose(bindToLifecycle())
.compose(Transformers.observeForUI())
.subscribe { binding.commentsCardView.setCommentActionGroupVisibility(it) }
.subscribe { binding.commentsCardView.setReplyButtonVisibility(it) }

this.vm.outputs.commentPostTime()
.compose(bindToLifecycle())
.compose(Transformers.observeForUI())
.subscribe { binding.commentsCardView.setCommentPostTime(DateTimeUtils.relative(context(), ksString, it)) }

this.vm.outputs.isCommentEnableThreads()
.compose(bindToLifecycle())
.compose(Transformers.observeForUI())
.subscribe { binding.commentsCardView.setCommentEnabledThreads(it) }

this.vm.outputs.openCommentGuideLines()
.compose(bindToLifecycle())
.compose(Transformers.observeForUI())
Expand Down
41 changes: 27 additions & 14 deletions app/src/main/java/com/kickstarter/ui/views/CommentCard.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class CommentCard @JvmOverloads constructor(

private var onCommentCardClickedListener: OnCommentCardClickedListener? = null

private var isCommentEnabledThreads: Boolean = false

init {
obtainStyledAttributes(context, attrs, defStyleAttr)

Expand All @@ -33,10 +35,6 @@ class CommentCard @JvmOverloads constructor(
onCommentCardClickedListener?.onRetryViewClicked(it)
}

binding.flagButton.setOnClickListener {
onCommentCardClickedListener?.onFlagButtonClicked(it)
}

binding.replies.setOnClickListener {
onCommentCardClickedListener?.onViewRepliesButtonClicked(it)
}
Expand Down Expand Up @@ -87,8 +85,8 @@ class CommentCard @JvmOverloads constructor(
setCommentUserName(it)
}

getBoolean(R.styleable.CommentCardView_is_comment_action_group_visible, true)?.also {
setCommentActionGroupVisibility(it)
getBoolean(R.styleable.CommentCardView_is_comment_reply_button_visible, true)?.also {
setReplyButtonVisibility(it)
}

getInt(R.styleable.CommentCardView_comment_card_status, 0).also { attrValue ->
Expand All @@ -101,8 +99,12 @@ class CommentCard @JvmOverloads constructor(
}
}

fun setCommentActionGroupVisibility(isGroupVisble: Boolean) {
binding.commentActionGroup.isVisible = isGroupVisble
fun setCommentEnabledThreads(isActiveFeatureFlag: Boolean) {
this.isCommentEnabledThreads = isActiveFeatureFlag
}

fun setReplyButtonVisibility(isGroupVisible: Boolean) {
binding.replyButton.isVisible = isGroupVisible && this.isCommentEnabledThreads
}

fun setCommentCardStatus(cardCommentStatus: CommentCardStatus) {
Expand All @@ -113,9 +115,11 @@ class CommentCard @JvmOverloads constructor(
cardCommentStatus == CommentCardStatus.COMMENT_WITHOUT_REPLIES ||
cardCommentStatus != CommentCardStatus.DELETED_COMMENT

binding.commentActionGroup.isVisible = cardCommentStatus == CommentCardStatus.COMMENT_WITH_REPLIES ||
cardCommentStatus == CommentCardStatus.COMMENT_WITHOUT_REPLIES ||
cardCommentStatus == CommentCardStatus.FAILED_TO_SEND_COMMENT
if (shouldShowReplyButton(cardCommentStatus)) {
setReplyButtonVisibility(true)
} else {
hideReplyButton()
}

binding.retryButton.isVisible =
cardCommentStatus == CommentCardStatus.FAILED_TO_SEND_COMMENT
Expand All @@ -129,20 +133,29 @@ class CommentCard @JvmOverloads constructor(
binding.commentBody.setTextColor(ContextCompat.getColor(context, commentBodyTextColor))
}

private fun shouldShowReplyButton(cardCommentStatus: CommentCardStatus) =
cardCommentStatus == CommentCardStatus.COMMENT_WITH_REPLIES ||
cardCommentStatus == CommentCardStatus.COMMENT_WITHOUT_REPLIES ||
cardCommentStatus == CommentCardStatus.FAILED_TO_SEND_COMMENT

/*
* To display replies count
* binding.replies.text = String.format("%s (%d)",resources.getString(R.string.view_replies), replies)
*/
fun setCommentReplies(replies: Int) {
binding.replies.isVisible = replies > 0
setViewRepliesVisibility(replies > 0)
}

fun setViewRepliesVisibility(isViewRepliesVisible: Boolean) {
binding.replies.isVisible = isViewRepliesVisible && isCommentEnabledThreads
}

fun setCommentUserName(username: String) {
binding.commentUserName.text = username
}

fun hideReplyViewGroup() {
binding.commentActionGroup.isVisible = false
fun hideReplyButton() {
binding.replyButton.isVisible = false
}

fun setCommentPostTime(time: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.kickstarter.viewmodels

import com.kickstarter.libs.ActivityViewModel
import com.kickstarter.libs.Environment
import com.kickstarter.libs.ExperimentsClientType
import com.kickstarter.libs.models.OptimizelyFeature
import com.kickstarter.libs.rx.transformers.Transformers
import com.kickstarter.libs.rx.transformers.Transformers.takeWhen
import com.kickstarter.libs.utils.ObjectUtils
Expand Down Expand Up @@ -57,7 +59,7 @@ interface CommentsViewHolderViewModel {
fun commentPostTime(): Observable<DateTime>

/** Emits the visibility of the comment card action group */
fun isCommentActionGroupVisible(): Observable<Boolean>
fun isReplyButtonVisible(): Observable<Boolean>

/** Emits the current [Comment] when Comment GuideLines clicked.. */
fun openCommentGuideLines(): Observable<Comment>
Expand All @@ -73,6 +75,9 @@ interface CommentsViewHolderViewModel {

/** Emits the current [Comment] when view replies clicked.. */
fun viewCommentReplies(): Observable<Comment>

/** Emits the current [OptimizelyFeature.Key.COMMENT_ENABLE_THREADS] status to the CommentCard UI*/
fun isCommentEnableThreads(): Observable<Boolean>
}

class ViewModel(environment: Environment) : ActivityViewModel<CommentCardViewHolder>(environment), Inputs, Outputs {
Expand All @@ -84,7 +89,7 @@ interface CommentsViewHolderViewModel {
private val onViewCommentRepliesButtonClicked = PublishSubject.create<Void>()

private val commentCardStatus = BehaviorSubject.create<CommentCardStatus>()
private val isCommentActionGroupVisible = BehaviorSubject.create<Boolean>()
private val isReplyButtonVisible = BehaviorSubject.create<Boolean>()
private val commentAuthorName = BehaviorSubject.create<String>()
private val commentAuthorAvatarUrl = BehaviorSubject.create<String>()
private val commentMessageBody = BehaviorSubject.create<String>()
Expand All @@ -95,21 +100,30 @@ interface CommentsViewHolderViewModel {
private val replyToComment = PublishSubject.create<Comment>()
private val flagComment = PublishSubject.create<Comment>()
private val viewCommentReplies = PublishSubject.create<Comment>()
private val isCommentEnableThreads = PublishSubject.create<Boolean>()

val inputs: Inputs = this
val outputs: Outputs = this

private val optimizely: ExperimentsClientType = environment.optimizely()

init {
this.commentInput
.map { it.comment }
.filter { ObjectUtils.isNotNull(it) }
.compose(bindToLifecycle())
.subscribe { this.commentCardStatus.onNext(cardStatus(it)) }
.subscribe {
this.commentCardStatus.onNext(cardStatus(it))
}

this.commentInput
.compose(Transformers.combineLatestPair(environment.currentUser().observable()))
.compose(bindToLifecycle())
.subscribe { this.isCommentActionGroupVisible.onNext(isActionGroupVisible(it.first, it.second)) }
.subscribe {
this.isReplyButtonVisible.onNext(
shouldReplyButtonBeVisible(it.first, it.second, optimizely.isFeatureEnabled(OptimizelyFeature.Key.COMMENT_ENABLE_THREADS))
)
}

val comment = this.commentInput
.map { it.comment }
Expand Down Expand Up @@ -171,15 +185,35 @@ interface CommentsViewHolderViewModel {
.subscribe(this.flagComment)
}

private fun isActionGroupVisible(commentCardData: CommentCardData, user: User?) =
commentCardData.project?.let {
it.isBacking || ProjectUtils.userIsCreator(it, user)
} ?: false

/**
* Checks if the current user is backing the current project,
* or the current user is the creator of the project
* @param commentCardData
* @param featureFlagActive
* @param user
*
* @return
* true -> if current user is backer and the feature flag is active
* false -> any of the previous conditions fails
*/
private fun shouldReplyButtonBeVisible(
commentCardData: CommentCardData,
user: User?,
featureFlagActive: Boolean
) =
commentCardData.project?.let { (it.isBacking || ProjectUtils.userIsCreator(it, user)) && featureFlagActive } ?: false

/**
* Updates the status of the current comment card.
* Also updates the current state of the [OptimizelyFeature.Key.COMMENT_ENABLE_THREADS]
* everytime the state changes.
*/
private fun cardStatus(comment: Comment?) = when {
comment?.deleted() ?: false -> CommentCardStatus.DELETED_COMMENT
(comment?.repliesCount() ?: false != 0) -> CommentCardStatus.COMMENT_WITH_REPLIES
else -> CommentCardStatus.COMMENT_WITHOUT_REPLIES
}.also {
this.isCommentEnableThreads.onNext(optimizely.isFeatureEnabled(OptimizelyFeature.Key.COMMENT_ENABLE_THREADS))
}

override fun configureWith(commentCardData: CommentCardData) = this.commentInput.onNext(commentCardData)
Expand All @@ -206,7 +240,7 @@ interface CommentsViewHolderViewModel {

override fun commentPostTime(): Observable<DateTime> = this.commentPostTime

override fun isCommentActionGroupVisible(): Observable<Boolean> = this.isCommentActionGroupVisible
override fun isReplyButtonVisible(): Observable<Boolean> = this.isReplyButtonVisible

override fun openCommentGuideLines(): Observable<Comment> = openCommentGuideLines

Expand All @@ -217,5 +251,7 @@ interface CommentsViewHolderViewModel {
override fun flagComment(): Observable<Comment> = flagComment

override fun viewCommentReplies(): Observable<Comment> = this.viewCommentReplies

override fun isCommentEnableThreads(): Observable<Boolean> = this.isCommentEnableThreads
}
}
20 changes: 2 additions & 18 deletions app/src/main/res/layout/comment_card.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"/>


<androidx.appcompat.widget.AppCompatButton
android:id="@+id/reply_button"
style="@style/CommentsReplayButton"
Expand All @@ -67,16 +66,6 @@
app:layout_constraintStart_toStartOf="@id/avatar"
app:layout_constraintTop_toBottomOf="@id/replies" />

<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/flag_button"
style="@style/CommentsReplayButton"
android:src="@drawable/ic_flag"
android:layout_marginTop="@dimen/grid_3"
app:layout_goneMarginTop="0dp"
app:layout_constraintBottom_toTopOf="@+id/separtor"
app:layout_constraintEnd_toEndOf="@id/comment_body"
app:layout_constraintTop_toBottomOf="@id/replies"/>

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/retry_button"
style="@style/CommentsRetryButton"
Expand Down Expand Up @@ -112,24 +101,19 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />

<androidx.constraintlayout.widget.Group
android:id="@+id/comment_action_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:constraint_referenced_ids="reply_button,flag_button" />

<androidx.constraintlayout.widget.Group
android:id="@+id/reply_message_group"
android:layout_width="wrap_content"
android:visibility="gone"
android:layout_height="wrap_content"
tools:visibility="visible"
app:constraint_referenced_ids="flagged_message,info_button" />

<androidx.constraintlayout.widget.Group
android:id="@+id/comment_deleted_message_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
tools:visibility="visible"
app:constraint_referenced_ids="flagged_message,info_button" />
</androidx.constraintlayout.widget.ConstraintLayout>
2 changes: 1 addition & 1 deletion app/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
<attr name="comment_card_message" format="string" />
<attr name="comment_card_replies" format="integer" />
<attr name="comment_card_avatar_url" format="string" />
<attr name="is_comment_action_group_visible" format="boolean" />
<attr name="is_comment_reply_button_visible" format="boolean" />
</declare-styleable>
</resources>
Loading

0 comments on commit 1382960

Please sign in to comment.