Skip to content

Commit

Permalink
NT-1948: UI User badges (#1337)
Browse files Browse the repository at this point in the history
* Create badges for comments card

* linter

* Kotlin linter

* Update to use current user stream and fix tests

Co-authored-by: Isabel Martin <arkariang@gmail.com>
  • Loading branch information
leighdouglas and Arkariang committed Jul 29, 2021
1 parent f0f0f4d commit 6866c2d
Show file tree
Hide file tree
Showing 14 changed files with 402 additions and 4 deletions.
15 changes: 15 additions & 0 deletions app/src/main/java/com/kickstarter/mock/factories/CommentFactory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,21 @@ class CommentFactory {
.build()
}

fun commentFromCurrentUser(user: User, authorBadges: List<String>): Comment {
return Comment.builder()
.id(1)
.author(user)
.body("Some text here")
.parentId(1)
.repliesCount(0)
.cursor("")
.authorBadges(authorBadges)
.authorCanceledPledge(false)
.deleted(false)
.createdAt(DateTime.now())
.build()
}

fun comment(
avatar: Avatar = AvatarFactory.avatar(),
name: String = "joe",
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/kickstarter/models/Comment.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,10 @@ public boolean equals(final @Nullable Object obj) {
equals = Objects.equals(this.id(), other.id()) &&
Objects.equals(this.body(), other.body()) &&
Objects.equals(this.author(), other.author()) &&
Objects.equals(this.authorBadges(), other.authorBadges()) &&
Objects.equals(this.cursor(), other.cursor()) &&
Objects.equals(this.deleted(), other.deleted()) &&
Objects.equals(this.repliesCount(), other.repliesCount()) &&
Objects.equals(this.authorCanceledPledge(), other.authorCanceledPledge()) &&
Objects.equals(this.createdAt(), other.createdAt()) &&
Objects.equals(this.parentId(), other.parentId());
Expand Down
11 changes: 11 additions & 0 deletions app/src/main/java/com/kickstarter/models/extensions/CommentExt.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.kickstarter.models.extensions

import com.kickstarter.models.Comment
import com.kickstarter.models.User
import com.kickstarter.ui.data.CommentCardData
import com.kickstarter.ui.views.CommentCardBadge
import com.kickstarter.ui.views.CommentCardStatus
import type.CommentBadge

/**
* Update the internal persisted list of comments with the successful response
Expand Down Expand Up @@ -59,6 +62,14 @@ fun Comment.updateCommentFailedToPost(
return listOfComments
}

fun Comment.assignAuthorBadge(user: User? = null): CommentCardBadge {
if (this.author().id() == user?.id()) return CommentCardBadge.YOU
if (this.authorBadges()?.contains(CommentBadge.CREATOR.rawValue()) == true) return CommentCardBadge.CREATOR
if (this.authorBadges()?.contains(CommentBadge.COLLABORATOR.rawValue()) == true) return CommentCardBadge.COLLABORATOR
if (this.authorBadges()?.contains(CommentBadge.SUPERBACKER.rawValue()) == true) return CommentCardBadge.SUPERBACKER
return CommentCardBadge.NO_BADGE
}

/**
* Update the internal persisted list of comments with the failed response
* from calling the Post Mutation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ class CommentCardViewHolder(
.compose(Transformers.observeForUI())
.subscribe { this.delegate.onCommentPostedFailed(it) }

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

binding.commentsCardView.setCommentCardClickedListener(object : OnCommentCardClickedListener {
override fun onRetryViewClicked(view: View) {
vm.inputs.onRetryViewClicked()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ class RootCommentViewHolder(
.subscribe {
binding.commentsCardView.setCommentCardStatus(it)
}

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

override fun bindData(data: Any?) {
Expand Down
42 changes: 42 additions & 0 deletions app/src/main/java/com/kickstarter/ui/views/CommentCard.kt
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,18 @@ class CommentCard @JvmOverloads constructor(
setReplyButtonVisibility(it)
}

getInt(R.styleable.CommentCardView_is_comment_you_badge_visible, 0).also {
setCommentBadge(CommentCardBadge.NO_BADGE)
}

getInt(R.styleable.CommentCardView_is_comment_reply_button_visible, 0).also {
setCommentBadge(CommentCardBadge.NO_BADGE)
}

getInt(R.styleable.CommentCardView_is_comment_reply_button_visible, 0).also {
setCommentBadge(CommentCardBadge.NO_BADGE)
}

getInt(R.styleable.CommentCardView_comment_card_status, 0).also { attrValue ->
CommentCardStatus.values().firstOrNull {
it.commentCardStatus == attrValue
Expand Down Expand Up @@ -229,6 +241,28 @@ class CommentCard @JvmOverloads constructor(
fun setAvatarUrl(url: String?) {
binding.avatar.loadCircleImage(url)
}

fun setCommentBadge(badge: CommentCardBadge?) {
when (badge) {
CommentCardBadge.NO_BADGE -> setBadgesVisibility(false, false, false)
CommentCardBadge.YOU -> setBadgesVisibility(true, false, false)
CommentCardBadge.SUPERBACKER -> setBadgesVisibility(false, true, false)
CommentCardBadge.CREATOR -> setBadgesVisibility(false, false, true, context.getString(R.string.Creator))
CommentCardBadge.COLLABORATOR -> setBadgesVisibility(false, false, true, context.getString(R.string.Collaborator))
}
}

private fun setBadgesVisibility(
isYouBadgeVisible: Boolean,
isSuperBackerBadgeVisible: Boolean,
isCreatorBadgeVisible: Boolean,
creatorBadgeText: String? = null
) {
binding.youBadge.isVisible = isYouBadgeVisible
binding.superbackerBadge.isVisible = isSuperBackerBadgeVisible
binding.ownerBadge.isVisible = isCreatorBadgeVisible
binding.ownerBadge.text = creatorBadgeText ?: ""
}
}

interface OnCommentCardClickedListener {
Expand All @@ -240,6 +274,14 @@ interface OnCommentCardClickedListener {
fun onShowCommentClicked(view: View)
}

enum class CommentCardBadge(val commentCardBadge: Int) {
NO_BADGE(0),
YOU(1),
CREATOR(2),
SUPERBACKER(3),
COLLABORATOR(4),
}

enum class CommentCardStatus(val commentCardStatus: Int) {
COMMENT_FOR_LOGIN_BACKED_USERS(0), // comments without reply view
COMMENT_WITH_REPLIES(1), // comments with reply view
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import com.kickstarter.libs.utils.extensions.isReply
import com.kickstarter.models.Comment
import com.kickstarter.models.Project
import com.kickstarter.models.User
import com.kickstarter.models.extensions.assignAuthorBadge
import com.kickstarter.services.ApolloClientType
import com.kickstarter.services.mutations.PostCommentData
import com.kickstarter.ui.data.CommentCardData
import com.kickstarter.ui.viewholders.CommentCardViewHolder
import com.kickstarter.ui.views.CommentCardBadge
import com.kickstarter.ui.views.CommentCardStatus
import org.joda.time.DateTime
import rx.Observable
Expand Down Expand Up @@ -99,6 +101,8 @@ interface CommentsViewHolderViewModel {

/** Emits the current [Comment] when show comment for canceled pledge. */
fun showCanceledComment(): Observable<Comment>

fun authorBadge(): Observable<CommentCardBadge>
}

class ViewModel(environment: Environment) :
Expand All @@ -112,6 +116,7 @@ interface CommentsViewHolderViewModel {
private val onShowCommentClicked = PublishSubject.create<Void>()

private val commentCardStatus = BehaviorSubject.create<CommentCardStatus>()
private val authorBadge = BehaviorSubject.create<CommentCardBadge>()
private val isReplyButtonVisible = BehaviorSubject.create<Boolean>()
private val commentAuthorName = BehaviorSubject.create<String>()
private val commentAuthorAvatarUrl = BehaviorSubject.create<String>()
Expand Down Expand Up @@ -174,6 +179,12 @@ interface CommentsViewHolderViewModel {
this.commentCardStatus.onNext(CommentCardStatus.FAILED_TO_SEND_COMMENT)
this.failedToPosted.onNext(it.second.first.comment)
}

comment
.withLatestFrom(currentUser.observable()) { comment, user -> Pair(comment, user) }
.map { it.first.assignAuthorBadge(it.second) }
.compose(bindToLifecycle())
.subscribe { this.authorBadge.onNext(it) }
}

/**
Expand Down Expand Up @@ -471,5 +482,7 @@ interface CommentsViewHolderViewModel {
override fun isFailedToPost(): Observable<Comment> = this.failedToPosted

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

override fun authorBadge(): Observable<CommentCardBadge> = this.authorBadge
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.kickstarter.viewmodels

import android.util.Pair
import com.kickstarter.libs.ActivityViewModel
import com.kickstarter.libs.Environment
import com.kickstarter.libs.rx.transformers.Transformers
import com.kickstarter.models.extensions.assignAuthorBadge
import com.kickstarter.ui.data.CommentCardData
import com.kickstarter.ui.viewholders.RootCommentViewHolder
import com.kickstarter.ui.views.CommentCardBadge
import com.kickstarter.ui.views.CommentCardStatus
import rx.Observable
import rx.subjects.BehaviorSubject
Expand All @@ -19,14 +22,19 @@ interface RootCommentViewHolderViewModel {
interface Outputs {
fun bindRootComment(): Observable<CommentCardData>
fun showCanceledPledgeRootComment(): Observable<CommentCardStatus>
fun authorBadge(): Observable<CommentCardBadge>
}

class ViewModel(environment: Environment) : ActivityViewModel<RootCommentViewHolder>(environment), Inputs, Outputs {
private val initCellConfig = BehaviorSubject.create<CommentCardData>()
private val onShowCanceledPledgeRootCommentClicked = PublishSubject.create<Void>()
private val authorBadge = BehaviorSubject.create<CommentCardBadge>()

private val currentUser = environment.currentUser()

private val bindRootComment = BehaviorSubject.create<CommentCardData>()
private val showCanceledPledgeRootComment = PublishSubject.create<CommentCardStatus>()

val inputs = this
val outputs = this

Expand All @@ -42,6 +50,12 @@ interface RootCommentViewHolderViewModel {
.compose(Transformers.takeWhen(this.onShowCanceledPledgeRootCommentClicked))
.compose(bindToLifecycle())
.subscribe { this.showCanceledPledgeRootComment.onNext(CommentCardStatus.CANCELED_PLEDGE_COMMENT) }

commentCardData
.withLatestFrom(currentUser.observable()) { comment, user -> Pair(comment, user) }
.map { it.first.comment?.assignAuthorBadge(it.second) }
.compose(bindToLifecycle())
.subscribe { this.authorBadge.onNext(it) }
}

// - Inputs
Expand All @@ -50,5 +64,6 @@ interface RootCommentViewHolderViewModel {
// - Outputs
override fun bindRootComment(): Observable<CommentCardData> = this.bindRootComment
override fun showCanceledPledgeRootComment(): Observable<CommentCardStatus> = this.showCanceledPledgeRootComment
override fun authorBadge(): Observable<CommentCardBadge> = this.authorBadge
}
}
51 changes: 51 additions & 0 deletions app/src/main/res/layout/comment_card.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,57 @@
app:layout_constraintStart_toEndOf="@+id/avatar"
app:layout_constraintTop_toTopOf="@+id/avatar" />

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/owner_badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/rounded_layout"
android:backgroundTint="@color/green_alpha_6"
android:layout_marginStart="@dimen/grid_1"
android:padding="@dimen/grid_1"
android:textColor="@color/kds_create_700"
android:textStyle="bold"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/comment_user_name"
app:layout_constraintStart_toEndOf="@+id/comment_user_name"
app:layout_constraintTop_toTopOf="@+id/comment_user_name" />

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/you_badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/grid_1"
android:background="@drawable/rounded_layout"
android:backgroundTint="@color/blue_alpha_6"
android:paddingStart="@dimen/grid_3_half"
android:paddingEnd="@dimen/grid_3_half"
android:paddingBottom="@dimen/grid_1"
android:paddingTop="@dimen/grid_1"
android:text="@string/you"
android:textColor="@color/blue_darken_10"
android:textStyle="bold"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/comment_user_name"
app:layout_constraintStart_toEndOf="@+id/comment_user_name"
app:layout_constraintTop_toTopOf="@+id/comment_user_name" />

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/superbacker_badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="@color/green_alpha_6"
android:layout_marginStart="@dimen/grid_1"
android:textColor="@color/kds_celebrate_500"
android:textSize="@dimen/badge_superbacker"
android:letterSpacing="0.05"
android:textStyle="bold"
android:text="@string/Superbacker"
android:textAllCaps="true"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/comment_user_name"
app:layout_constraintStart_toEndOf="@+id/comment_user_name"
app:layout_constraintTop_toTopOf="@+id/comment_user_name" />

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/comment_post_time"
style="@style/FootnotePrimary"
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,8 @@
<attr name="comment_card_replies" format="integer" />
<attr name="comment_card_avatar_url" format="string" />
<attr name="is_comment_reply_button_visible" format="boolean" />
<attr name="is_comment_you_badge_visible" format="integer" />
<attr name="is_comment_owner_badge_visible" format="integer" />
<attr name="is_comment_superbacker_badge_visible" format="integer"/>
</declare-styleable>
</resources>
1 change: 1 addition & 0 deletions app/src/main/res/values/dimens.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
<dimen name="grid_57">342dp</dimen>

<!-- Typography-->
<dimen name="badge_superbacker">10sp</dimen>
<dimen name="caption_2">11sp</dimen>
<dimen name="caption_1">12sp</dimen>
<dimen name="footnote">13sp</dimen>
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings_i18n.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1795,4 +1795,6 @@ saved</string>
<string name="via_custom" formatted="false">via custom</string>
<string name="via_external" formatted="false">via external</string>
<string name="via_kickstarter" formatted="false">via Kickstarter</string>
<string name="you" formatted="false">You</string>

</resources>
Loading

0 comments on commit 6866c2d

Please sign in to comment.