Skip to content

Commit

Permalink
[MBL-797] Update root comment viewholder to rx2 (#1918)
Browse files Browse the repository at this point in the history
* update root comment viewholder to rx2

* lint
  • Loading branch information
mtgriego committed Dec 13, 2023
1 parent 303cad2 commit f478b47
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,90 +3,107 @@ package com.kickstarter.ui.viewholders
import android.view.View
import com.kickstarter.R
import com.kickstarter.databinding.ItemRootCommentCardBinding
import com.kickstarter.libs.rx.transformers.Transformers
import com.kickstarter.libs.utils.DateTimeUtils
import com.kickstarter.libs.utils.extensions.addToDisposable
import com.kickstarter.ui.data.CommentCardData
import com.kickstarter.ui.views.CommentCardStatus
import com.kickstarter.ui.views.OnCommentCardClickedListener
import com.kickstarter.viewmodels.RootCommentViewHolderViewModel
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable

@Suppress("UNCHECKED_CAST")
class RootCommentViewHolder(
val binding: ItemRootCommentCardBinding
) : KSViewHolder(binding.root) {

private val vm: RootCommentViewHolderViewModel.ViewModel = RootCommentViewHolderViewModel.ViewModel(environment())
private val vm: RootCommentViewHolderViewModel.ViewModel =
RootCommentViewHolderViewModel.ViewModel(environment())
private val ksString = requireNotNull(environment().ksString())
private val disposables = CompositeDisposable()

init {

binding.commentsCardView.setFlaggedMessage(
context().getString(R.string.This_comment_is_under_review_for_potentially_violating_kickstarters_community_guidelines)
)

this.vm.outputs.bindRootComment()
.compose(bindToLifecycle())
.compose(Transformers.observeForUI())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { commentCardData ->
CommentCardStatus.values().firstOrNull { commentCardData.commentCardState == it.commentCardStatus }?.let {
if (it == CommentCardStatus.CANCELED_PLEDGE_MESSAGE || it == CommentCardStatus.FLAGGED_COMMENT) {
binding.commentsCardView.setCommentCardStatus(it)

context().getString(R.string.This_person_canceled_their_pledge).also {
binding.commentsCardView.setCancelPledgeMessage(it)
}

binding.commentsCardView.setCommentCardClickedListener(object :
OnCommentCardClickedListener {
override fun onRetryViewClicked(view: View) {
CommentCardStatus.values()
.firstOrNull { commentCardData.commentCardState == it.commentCardStatus }?.let {
if (it == CommentCardStatus.CANCELED_PLEDGE_MESSAGE || it == CommentCardStatus.FLAGGED_COMMENT) {
binding.commentsCardView.setCommentCardStatus(it)

context().getString(R.string.This_person_canceled_their_pledge)
.also { message ->
binding.commentsCardView.setCancelPledgeMessage(message)
}

override fun onReplyButtonClicked(view: View) {
}
binding.commentsCardView.setCommentCardClickedListener(object :
OnCommentCardClickedListener {
override fun onRetryViewClicked(view: View) {
}

override fun onFlagButtonClicked(view: View) {
}
override fun onReplyButtonClicked(view: View) {
}

override fun onViewRepliesButtonClicked(view: View) {
}
override fun onFlagButtonClicked(view: View) {
}

override fun onCommentGuideLinesClicked(view: View) {
}
override fun onViewRepliesButtonClicked(view: View) {
}

override fun onShowCommentClicked(view: View) {
vm.inputs.onShowCanceledPledgeRootCommentClicked()
}
})
override fun onCommentGuideLinesClicked(view: View) {
}

override fun onShowCommentClicked(view: View) {
vm.inputs.onShowCanceledPledgeRootCommentClicked()
}
})
}
}
}

commentCardData?.comment?.let { comment ->
binding.commentsCardView.setCommentUserName(comment.author().name())
binding.commentsCardView.setCommentBody(comment.body())
binding.commentsCardView.hideReplyButton()
comment.createdAt()?.let { createdAt ->
binding.commentsCardView.setCommentPostTime(DateTimeUtils.relative(context(), ksString, createdAt))
binding.commentsCardView.setCommentPostTime(
DateTimeUtils.relative(
context(),
ksString,
createdAt
)
)
}
binding.commentsCardView.setCommentUserName(comment.author().name())
binding.commentsCardView.setAvatarUrl(comment.author().avatar().medium())
}
}
}.addToDisposable(disposables)

this.vm.outputs.showCanceledPledgeRootComment()
.compose(bindToLifecycle())
.compose(Transformers.observeForUI())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
binding.commentsCardView.setCommentCardStatus(it)
}
.addToDisposable(disposables)

this.vm.outputs.authorBadge()
.compose(bindToLifecycle())
.compose(Transformers.observeForUI())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { binding.commentsCardView.setCommentBadge(it) }
.addToDisposable(disposables)
}

override fun bindData(data: Any?) {
if (data is CommentCardData) {
this.vm.inputs.configureWith(data)
}
}

override fun destroy() {
disposables.clear()
vm.clear()
super.destroy()
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
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.libs.utils.extensions.addToDisposable
import com.kickstarter.libs.utils.extensions.isNotNull
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
import rx.subjects.PublishSubject
import io.reactivex.Observable
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.subjects.BehaviorSubject
import io.reactivex.subjects.PublishSubject

interface RootCommentViewHolderViewModel {
interface Inputs {
Expand All @@ -25,45 +26,53 @@ interface RootCommentViewHolderViewModel {
fun authorBadge(): Observable<CommentCardBadge>
}

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

private val currentUser = requireNotNull(environment.currentUser())
private val currentUser = requireNotNull(environment.currentUserV2())

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

val inputs = this
val outputs = this

private val disposables = CompositeDisposable()

init {
val commentCardData = this.initCellConfig
commentCardData.compose(bindToLifecycle())
commentCardData
.subscribe {
this.bindRootComment.onNext(it)
}
.addToDisposable(disposables)

commentCardData
.map { requireNotNull(it.comment) }
.compose(Transformers.takeWhen(this.onShowCanceledPledgeRootCommentClicked))
.compose(bindToLifecycle())
.compose(Transformers.takeWhenV2(this.onShowCanceledPledgeRootCommentClicked))
.subscribe { this.showCanceledPledgeRootComment.onNext(CommentCardStatus.CANCELED_PLEDGE_COMMENT) }
.addToDisposable(disposables)

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

// - Inputs
override fun configureWith(comment: CommentCardData) = this.initCellConfig.onNext(comment)
override fun onShowCanceledPledgeRootCommentClicked() = this.onShowCanceledPledgeRootCommentClicked.onNext(null)
override fun onShowCanceledPledgeRootCommentClicked() = this.onShowCanceledPledgeRootCommentClicked.onNext(Unit)
// - Outputs
override fun bindRootComment(): Observable<CommentCardData> = this.bindRootComment
override fun showCanceledPledgeRootComment(): Observable<CommentCardStatus> = this.showCanceledPledgeRootComment
override fun authorBadge(): Observable<CommentCardBadge> = this.authorBadge

fun clear() {
disposables.clear()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ package com.kickstarter.viewmodels
import com.kickstarter.KSRobolectricTestCase
import com.kickstarter.libs.Environment
import com.kickstarter.libs.MockCurrentUser
import com.kickstarter.libs.utils.extensions.addToDisposable
import com.kickstarter.mock.factories.CommentFactory
import com.kickstarter.mock.factories.UserFactory
import com.kickstarter.ui.data.CommentCardData
import com.kickstarter.ui.views.CommentCardBadge
import com.kickstarter.ui.views.CommentCardStatus
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.subscribers.TestSubscriber
import org.junit.After
import org.junit.Test
import rx.observers.TestSubscriber
import type.CommentBadge

class RootCommentViewHolderViewModelTest : KSRobolectricTestCase() {
Expand All @@ -18,12 +21,17 @@ class RootCommentViewHolderViewModelTest : KSRobolectricTestCase() {
private val bindRootComment = TestSubscriber<CommentCardData>()
private val showCanceledPledgeRootCommentClicked = TestSubscriber<CommentCardStatus>()
private val authorBadge = TestSubscriber<CommentCardBadge>()
private val disposables = CompositeDisposable()

private fun setupEnvironment(environment: Environment) {
this.vm = RootCommentViewHolderViewModel.ViewModel(environment)
this.vm.outputs.bindRootComment().subscribe(bindRootComment)
this.vm.outputs.authorBadge().subscribe(authorBadge)
this.vm.outputs.showCanceledPledgeRootComment().subscribe(showCanceledPledgeRootCommentClicked)
this.vm.outputs.bindRootComment().subscribe { bindRootComment.onNext(it) }
.addToDisposable(disposables)
this.vm.outputs.authorBadge().subscribe { authorBadge.onNext(it) }
.addToDisposable(disposables)
this.vm.outputs.showCanceledPledgeRootComment()
.subscribe { showCanceledPledgeRootCommentClicked.onNext(it) }
.addToDisposable(disposables)
}

@Test
Expand All @@ -41,7 +49,7 @@ class RootCommentViewHolderViewModelTest : KSRobolectricTestCase() {
assertTrue(it.comment?.body() == commentCardData.comment?.body())
assertTrue(it.comment?.authorCanceledPledge() == commentCardData.comment?.authorCanceledPledge())
assertTrue(it.commentCardState == commentCardData.commentCardState)
}
}.addToDisposable(disposables)
}

@Test
Expand All @@ -52,7 +60,8 @@ class RootCommentViewHolderViewModelTest : KSRobolectricTestCase() {
.id(1)
.build()

val comment = CommentFactory.commentWithCanceledPledgeAuthor(currentUser).toBuilder().id(1).body("comment1").build()
val comment = CommentFactory.commentWithCanceledPledgeAuthor(currentUser).toBuilder().id(1)
.body("comment1").build()
val commentCardData1 = CommentCardData.builder()
.comment(comment)
.commentCardState(CommentCardStatus.CANCELED_PLEDGE_MESSAGE.commentCardStatus)
Expand All @@ -63,7 +72,7 @@ class RootCommentViewHolderViewModelTest : KSRobolectricTestCase() {
vm.outputs.bindRootComment().take(0).subscribe {
assertTrue(it.comment?.body() == commentCardData1.comment?.body())
assertTrue(it.commentCardState == commentCardData1.commentCardState)
}
}.addToDisposable(disposables)

this.vm.inputs.onShowCanceledPledgeRootCommentClicked()

Expand Down Expand Up @@ -120,7 +129,10 @@ class RootCommentViewHolderViewModelTest : KSRobolectricTestCase() {
.build()

setupEnvironment(environment)
val authorBadges = listOf<String>(CommentBadge.SUPERBACKER.rawValue(), CommentBadge.COLLABORATOR.rawValue())
val authorBadges = listOf<String>(
CommentBadge.SUPERBACKER.rawValue(),
CommentBadge.COLLABORATOR.rawValue()
)
val author = UserFactory.user().toBuilder().id(2).build()
val comment = CommentFactory.commentFromCurrentUser(author, authorBadges)
val commentCardData = CommentCardData.builder()
Expand Down Expand Up @@ -157,7 +169,8 @@ class RootCommentViewHolderViewModelTest : KSRobolectricTestCase() {
@Test
fun commentBadge_whenNotLoggedInAndCommentIsFromCreator_shouldEmitCreator() {
setupEnvironment(environment())
val authorBadges = listOf<String>(CommentBadge.SUPERBACKER.rawValue(), CommentBadge.CREATOR.rawValue())
val authorBadges =
listOf<String>(CommentBadge.SUPERBACKER.rawValue(), CommentBadge.CREATOR.rawValue())
val author = UserFactory.user().toBuilder().id(2).build()
val comment = CommentFactory.commentFromCurrentUser(author, authorBadges)
val commentCardData = CommentCardData.builder()
Expand All @@ -169,4 +182,9 @@ class RootCommentViewHolderViewModelTest : KSRobolectricTestCase() {

this.authorBadge.assertValue(CommentCardBadge.CREATOR)
}

@After
fun clear() {
disposables.clear()
}
}

0 comments on commit f478b47

Please sign in to comment.