Skip to content

Commit

Permalink
MBL-1053: Identify if https links in messages are KSR links (#1917)
Browse files Browse the repository at this point in the history
* migrate to rxjava2

* migrate to rxjava 2, open deeplink activity to validate links, update tests, linter

---------

Co-authored-by: mtgriego <matthew.t.griego@gmail.com>
  • Loading branch information
leighdouglas and mtgriego committed Dec 14, 2023
1 parent f478b47 commit d09017f
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -1,51 +1,94 @@
package com.kickstarter.ui.viewholders

import android.content.Intent
import android.net.Uri
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.style.ClickableSpan
import android.text.style.URLSpan
import android.view.View
import androidx.core.content.ContextCompat.startActivity
import androidx.core.view.isGone
import com.kickstarter.databinding.MessageViewBinding
import com.kickstarter.libs.rx.transformers.Transformers
import com.kickstarter.libs.transformations.CircleTransformation
import com.kickstarter.libs.utils.ViewUtils
import com.kickstarter.libs.utils.extensions.addToDisposable
import com.kickstarter.models.Message
import com.kickstarter.ui.activities.DeepLinkActivity
import com.kickstarter.viewmodels.MessageHolderViewModel
import com.squareup.picasso.Picasso
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable

class MessageViewHolder(private val binding: MessageViewBinding) : KSViewHolder(binding.root) {
private val viewModel = MessageHolderViewModel.ViewModel(environment())
private val disposables = CompositeDisposable()

init {
viewModel.outputs.deliveryStatusTextViewIsGone()
.compose(bindToLifecycle())
.compose(Transformers.observeForUI())
.subscribe(ViewUtils.setGone(binding.messageDeliveryStatusTextView))
.observeOn(AndroidSchedulers.mainThread())
.subscribe { binding.messageDeliveryStatusTextView.isGone = it }
.addToDisposable(disposables)

viewModel.outputs.messageBodyRecipientCardViewIsGone()
.compose(bindToLifecycle())
.compose(Transformers.observeForUI())
.subscribe(ViewUtils.setGone(binding.messageBodyRecipientCardView))
.observeOn(AndroidSchedulers.mainThread())
.subscribe { binding.messageBodyRecipientCardView.isGone = it }
.addToDisposable(disposables)

viewModel.outputs.messageBodyRecipientTextViewText()
.compose(bindToLifecycle())
.compose(Transformers.observeForUI())
.subscribe { binding.messageBodyRecipientTextView.text = it }
.observeOn(AndroidSchedulers.mainThread())
.subscribe { setText(it) }
.addToDisposable(disposables)

viewModel.outputs.messageBodySenderCardViewIsGone()
.compose(bindToLifecycle())
.compose(Transformers.observeForUI())
.subscribe(ViewUtils.setGone(binding.messageBodySenderCardView))
.observeOn(AndroidSchedulers.mainThread())
.subscribe { binding.messageBodySenderCardView.isGone = it }
.addToDisposable(disposables)

viewModel.outputs.messageBodySenderTextViewText()
.compose(bindToLifecycle())
.compose(Transformers.observeForUI())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { binding.messageBodySenderTextView.text = it }
.addToDisposable(disposables)

viewModel.outputs.participantAvatarImageHidden()
.compose(bindToLifecycle())
.compose(Transformers.observeForUI())
.subscribe(ViewUtils.setGone(binding.messageSenderAvatarImageView))
.observeOn(AndroidSchedulers.mainThread())
.subscribe { binding.messageSenderAvatarImageView.isGone = it }
.addToDisposable(disposables)

viewModel.outputs.participantAvatarImageUrl()
.compose(bindToLifecycle())
.compose(Transformers.observeForUI())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { setParticipantAvatarImageView(it) }
.addToDisposable(disposables)
}

override fun destroy() {
disposables.clear()
super.destroy()
}

private fun setText(text: String) {
binding.messageBodyRecipientTextView.text = text
val tvText: CharSequence = binding.messageBodyRecipientTextView.text
if (tvText is Spannable) {
val end = tvText.length
val urls = tvText.getSpans(0, end, URLSpan::class.java)
val style = SpannableStringBuilder(tvText)
style.clearSpans()
for (urlSpan in urls) {
val clickableSpan = object : ClickableSpan() {
override fun onClick(view: View) {
val intent = Intent(view.context, DeepLinkActivity::class.java)
intent.data = Uri.parse(urlSpan.url)
startActivity(view.context, intent, null)
}
}
style.setSpan(
clickableSpan, tvText.getSpanStart(urlSpan),
tvText.getSpanEnd(urlSpan),
Spannable.SPAN_EXCLUSIVE_INCLUSIVE
)
}
binding.messageBodyRecipientTextView.text = style
}
}

@Throws(Exception::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ package com.kickstarter.viewmodels

import android.util.Pair
import com.kickstarter.libs.ActivityViewModel
import com.kickstarter.libs.CurrentUserType
import com.kickstarter.libs.CurrentUserTypeV2
import com.kickstarter.libs.Environment
import com.kickstarter.libs.utils.PairUtils
import com.kickstarter.libs.utils.extensions.negate
import com.kickstarter.models.Message
import com.kickstarter.models.User
import com.kickstarter.ui.viewholders.MessageViewHolder
import rx.Observable
import rx.subjects.PublishSubject
import io.reactivex.Observable
import io.reactivex.subjects.PublishSubject

interface MessageHolderViewModel {
interface Inputs {
Expand Down Expand Up @@ -48,7 +48,7 @@ interface MessageHolderViewModel {
ActivityViewModel<MessageViewHolder?>(environment),
Inputs,
Outputs {
private val currentUser: CurrentUserType?
private val currentUser: CurrentUserTypeV2?
private val isLastPosition = PublishSubject.create<Boolean>()
private val message = PublishSubject.create<Message>()
private val deliveryStatusTextViewIsGone: Observable<Boolean>
Expand All @@ -63,7 +63,7 @@ interface MessageHolderViewModel {
val outputs: Outputs = this

init {
currentUser = requireNotNull(environment.currentUser())
currentUser = requireNotNull(environment.currentUserV2())

val messageAndCurrentUserIsSender =
Observable.combineLatest<Message, User, Pair<Message, User>>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ package com.kickstarter.viewmodels

import com.kickstarter.KSRobolectricTestCase
import com.kickstarter.libs.Environment
import com.kickstarter.libs.MockCurrentUser
import com.kickstarter.libs.MockCurrentUserV2
import com.kickstarter.libs.utils.extensions.addToDisposable
import com.kickstarter.mock.factories.MessageFactory.message
import com.kickstarter.mock.factories.UserFactory.user
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.subscribers.TestSubscriber
import org.junit.After
import org.junit.Test
import rx.observers.TestSubscriber

class MessageHolderViewModelTest : KSRobolectricTestCase() {
private lateinit var vm: MessageHolderViewModel.ViewModel
Expand All @@ -17,19 +20,23 @@ class MessageHolderViewModelTest : KSRobolectricTestCase() {
private val participantAvatarImageHidden = TestSubscriber<Boolean>()
private val participantAvatarImageUrl = TestSubscriber<String>()
private val deliveryStatusTextViewIsGone = TestSubscriber<Boolean>()
private val disposables = CompositeDisposable()

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

private fun setUpEnvironment(environment: Environment) {
vm = MessageHolderViewModel.ViewModel(environment)

vm.outputs.messageBodyRecipientCardViewIsGone().subscribe(
messageBodyRecipientCardViewIsGone
)
vm.outputs.messageBodyRecipientTextViewText().subscribe(messageBodyRecipientTextViewText)
vm.outputs.messageBodySenderCardViewIsGone().subscribe(messageBodySenderCardViewIsGone)
vm.outputs.messageBodySenderTextViewText().subscribe(messageBodySenderTextViewText)
vm.outputs.participantAvatarImageHidden().subscribe(participantAvatarImageHidden)
vm.outputs.participantAvatarImageUrl().subscribe(participantAvatarImageUrl)
vm.outputs.deliveryStatusTextViewIsGone().subscribe(deliveryStatusTextViewIsGone)
vm.outputs.messageBodyRecipientCardViewIsGone().subscribe { messageBodyRecipientCardViewIsGone.onNext(it) }.addToDisposable(disposables)
vm.outputs.messageBodyRecipientTextViewText().subscribe { messageBodyRecipientTextViewText.onNext(it) }.addToDisposable(disposables)
vm.outputs.messageBodySenderCardViewIsGone().subscribe { messageBodySenderCardViewIsGone.onNext(it) }.addToDisposable(disposables)
vm.outputs.messageBodySenderTextViewText().subscribe { messageBodySenderTextViewText.onNext(it) }.addToDisposable(disposables)
vm.outputs.participantAvatarImageHidden().subscribe { participantAvatarImageHidden.onNext(it) }.addToDisposable(disposables)
vm.outputs.participantAvatarImageUrl().subscribe { participantAvatarImageUrl.onNext(it) }.addToDisposable(disposables)
vm.outputs.deliveryStatusTextViewIsGone().subscribe { deliveryStatusTextViewIsGone.onNext(it) }.addToDisposable(disposables)
}

@Test
Expand All @@ -41,9 +48,9 @@ class MessageHolderViewModelTest : KSRobolectricTestCase() {
.sender(sender)
.build()

val currentUser = MockCurrentUser(recipient)
val currentUser = MockCurrentUserV2(recipient)

setUpEnvironment(environment().toBuilder().currentUser(currentUser).build())
setUpEnvironment(environment().toBuilder().currentUserV2(currentUser).build())

vm.inputs.configureWith(message)

Expand All @@ -69,9 +76,9 @@ class MessageHolderViewModelTest : KSRobolectricTestCase() {
.sender(sender)
.build()

val currentUser = MockCurrentUser(sender)
val currentUser = MockCurrentUserV2(sender)

setUpEnvironment(environment().toBuilder().currentUser(currentUser).build())
setUpEnvironment(environment().toBuilder().currentUserV2(currentUser).build())

vm.inputs.configureWith(message)

Expand All @@ -96,8 +103,8 @@ class MessageHolderViewModelTest : KSRobolectricTestCase() {
.recipient(recipient)
.sender(sender)
.build()
val currentUser = MockCurrentUser(recipient)
setUpEnvironment(environment().toBuilder().currentUser(currentUser).build())
val currentUser = MockCurrentUserV2(recipient)
setUpEnvironment(environment().toBuilder().currentUserV2(currentUser).build())
vm.inputs.configureWith(message)

// Avatar shown for sender who is the creator.
Expand All @@ -113,8 +120,8 @@ class MessageHolderViewModelTest : KSRobolectricTestCase() {
.recipient(recipient)
.sender(sender)
.build()
val currentUser = MockCurrentUser(sender)
setUpEnvironment(environment().toBuilder().currentUser(currentUser).build())
val currentUser = MockCurrentUserV2(sender)
setUpEnvironment(environment().toBuilder().currentUserV2(currentUser).build())
vm.inputs.configureWith(message)

// Avatar hidden for sender who is the backer.
Expand Down

0 comments on commit d09017f

Please sign in to comment.