Skip to content

Commit

Permalink
update project notifications settings to RX2 (#2115)
Browse files Browse the repository at this point in the history
Co-authored-by: Isabel Martin <arkariang@gmail.com>
  • Loading branch information
mtgriego and Arkariang authored Aug 29, 2024
1 parent b62d902 commit 36b994c
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 35 deletions.
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
package com.kickstarter.ui.activities

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import com.kickstarter.R
import com.kickstarter.databinding.ProjectNotificationSettingsLayoutBinding
import com.kickstarter.libs.BaseActivity
import com.kickstarter.libs.qualifiers.RequiresActivityViewModel
import com.kickstarter.libs.utils.extensions.addToDisposable
import com.kickstarter.libs.utils.extensions.getEnvironment
import com.kickstarter.ui.adapters.ProjectNotificationSettingsAdapter
import com.kickstarter.ui.extensions.showSnackbar
import com.kickstarter.viewmodels.ProjectNotificationSettingsViewModel
import rx.android.schedulers.AndroidSchedulers
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable

@RequiresActivityViewModel(ProjectNotificationSettingsViewModel.ViewModel::class)
class ProjectNotificationSettingsActivity : BaseActivity<ProjectNotificationSettingsViewModel.ViewModel>() {
class ProjectNotificationSettingsActivity : ComponentActivity() {
private lateinit var binding: ProjectNotificationSettingsLayoutBinding
private lateinit var viewModelFactory: ProjectNotificationSettingsViewModel.Factory
private val viewModel: ProjectNotificationSettingsViewModel.ProjectNotificationSettingsViewModel by viewModels {
viewModelFactory
}

private val disposables = CompositeDisposable()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
getEnvironment()?.let { env ->
viewModelFactory = ProjectNotificationSettingsViewModel.Factory(env)
}
binding = ProjectNotificationSettingsLayoutBinding.inflate(layoutInflater)
setContentView(binding.root)

Expand All @@ -26,23 +37,24 @@ class ProjectNotificationSettingsActivity : BaseActivity<ProjectNotificationSett
binding.projectNotificationSettingsRecyclerView.layoutManager = LinearLayoutManager(this)

viewModel.outputs.projectNotifications()
.compose(bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { adapter.projectNotifications(it) }
.addToDisposable(disposables)

viewModel.outputs.unableToFetchProjectNotificationsError()
.compose(bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
showSnackbar(
binding.projectNotificationSettingsRecyclerView,
getString(R.string.general_error_something_wrong)
)
}
.addToDisposable(disposables)
}

override fun onDestroy() {
super.onDestroy()
disposables.clear()
binding.projectNotificationSettingsRecyclerView.adapter = null
}
}
Original file line number Diff line number Diff line change
@@ -1,50 +1,62 @@
package com.kickstarter.viewmodels

import com.kickstarter.libs.ActivityViewModel
import androidx.lifecycle.ViewModelProvider
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.ProjectNotification
import com.kickstarter.services.ApiClientType
import com.kickstarter.ui.activities.ProjectNotificationSettingsActivity
import rx.Observable
import rx.subjects.BehaviorSubject
import com.kickstarter.services.ApiClientTypeV2
import io.reactivex.Observable
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.subjects.BehaviorSubject

interface ProjectNotificationSettingsViewModel {
interface Outputs {
fun projectNotifications(): Observable<List<ProjectNotification>>
fun unableToFetchProjectNotificationsError(): Observable<Void>
fun unableToFetchProjectNotificationsError(): Observable<Unit>
}

class ViewModel(environment: Environment) :
ActivityViewModel<ProjectNotificationSettingsActivity>(environment), Outputs {
private val client: ApiClientType
class ProjectNotificationSettingsViewModel(environment: Environment) : androidx.lifecycle.ViewModel(), Outputs {
private val client: ApiClientTypeV2 = requireNotNull(environment.apiClientV2())
private val projectNotifications = BehaviorSubject.create<List<ProjectNotification>>()
private val unableToFetchProjectNotificationsError = BehaviorSubject.create<Void>()
private val unableToFetchProjectNotificationsError = BehaviorSubject.create<Unit>()
private val disposables = CompositeDisposable()

val outputs: Outputs = this

override fun projectNotifications(): Observable<List<ProjectNotification>> = projectNotifications

override fun unableToFetchProjectNotificationsError(): Observable<Void> = unableToFetchProjectNotificationsError
override fun unableToFetchProjectNotificationsError(): Observable<Unit> = unableToFetchProjectNotificationsError

init {
client = requireNotNull(environment.apiClient())

val projectNotificationsNotification = client
.fetchProjectNotifications()
.materialize()

projectNotificationsNotification
.compose(Transformers.values())
.compose(bindToLifecycle())
.compose(Transformers.valuesV2())
.filter { it.isNotNull() }
.subscribe {
projectNotifications.onNext(it)
}
.addToDisposable(disposables)

projectNotificationsNotification
.compose(Transformers.errors())
.compose(bindToLifecycle())
.subscribe { unableToFetchProjectNotificationsError.onNext(null) }
.compose(Transformers.errorsV2())
.subscribe { unableToFetchProjectNotificationsError.onNext(Unit) }
.addToDisposable(disposables)
}

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

class Factory(private val environment: Environment) : ViewModelProvider.Factory {
override fun <T : androidx.lifecycle.ViewModel> create(modelClass: Class<T>): T {
return ProjectNotificationSettingsViewModel(environment) as T
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,41 @@ package com.kickstarter.viewmodels

import com.kickstarter.KSRobolectricTestCase
import com.kickstarter.libs.Environment
import com.kickstarter.libs.utils.extensions.addToDisposable
import com.kickstarter.mock.factories.ProjectNotificationFactory
import com.kickstarter.mock.services.MockApiClient
import com.kickstarter.mock.services.MockApiClientV2
import com.kickstarter.models.ProjectNotification
import io.reactivex.Observable
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.subscribers.TestSubscriber
import org.junit.After
import org.junit.Test
import rx.Observable
import rx.observers.TestSubscriber
import java.util.Collections

class ProjectNotificationSettingsViewModelTest : KSRobolectricTestCase() {

private lateinit var vm: ProjectNotificationSettingsViewModel.ViewModel
private lateinit var vm: ProjectNotificationSettingsViewModel.ProjectNotificationSettingsViewModel

private val projectNotifications = TestSubscriber<List<ProjectNotification>>()
private val unableToFetchProjectNotificationsError = TestSubscriber<Void>()
private val unableToFetchProjectNotificationsError = TestSubscriber<Unit>()
private val disposables = CompositeDisposable()

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

this.vm.outputs.projectNotifications().subscribe(this.projectNotifications)
this.vm.outputs.unableToFetchProjectNotificationsError().subscribe(this.unableToFetchProjectNotificationsError)
this.vm.outputs.projectNotifications().subscribe { this.projectNotifications.onNext(it) }
.addToDisposable(disposables)
this.vm.outputs.unableToFetchProjectNotificationsError()
.subscribe { this.unableToFetchProjectNotificationsError.onNext(it) }
.addToDisposable(disposables)
}

@Test
fun testProjectNotifications() {
val projectNotifications = Collections.singletonList(ProjectNotificationFactory.disabled())
setUpEnvironment(
environment().toBuilder().apiClient(object : MockApiClient() {
environment().toBuilder().apiClientV2(object : MockApiClientV2() {
override fun fetchProjectNotifications(): Observable<List<ProjectNotification>> {
return Observable.just(projectNotifications)
}
Expand All @@ -41,7 +49,7 @@ class ProjectNotificationSettingsViewModelTest : KSRobolectricTestCase() {
@Test
fun testUnableToFetchProjectNotificationsError() {
setUpEnvironment(
environment().toBuilder().apiClient(object : MockApiClient() {
environment().toBuilder().apiClientV2(object : MockApiClientV2() {
override fun fetchProjectNotifications(): Observable<List<ProjectNotification>> {
return Observable.error(Throwable("error"))
}
Expand All @@ -50,4 +58,9 @@ class ProjectNotificationSettingsViewModelTest : KSRobolectricTestCase() {

this.unableToFetchProjectNotificationsError.assertValueCount(1)
}

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

0 comments on commit 36b994c

Please sign in to comment.