Skip to content

Commit

Permalink
MBL-586: Unify rewards selection viewModels (#2133)
Browse files Browse the repository at this point in the history
  • Loading branch information
Arkariang authored Sep 24, 2024
1 parent 37f062f commit 12923ee
Show file tree
Hide file tree
Showing 5 changed files with 201 additions and 994 deletions.
169 changes: 59 additions & 110 deletions app/src/main/java/com/kickstarter/ui/fragments/RewardsFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,72 +6,49 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.rxjava2.subscribeAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.kickstarter.R
import com.kickstarter.databinding.FragmentRewardsBinding
import com.kickstarter.libs.Environment
import com.kickstarter.libs.utils.extensions.addToDisposable
import com.kickstarter.libs.utils.extensions.getEnvironment
import com.kickstarter.libs.utils.extensions.reduce
import com.kickstarter.libs.utils.extensions.selectPledgeFragment
import com.kickstarter.ui.activities.compose.projectpage.RewardCarouselScreen
import com.kickstarter.ui.compose.designsystem.KSTheme
import com.kickstarter.ui.compose.designsystem.KickstarterApp
import com.kickstarter.ui.data.PledgeData
import com.kickstarter.ui.data.PledgeReason
import com.kickstarter.ui.data.ProjectData
import com.kickstarter.viewmodels.RewardsFragmentViewModel.Factory
import com.kickstarter.viewmodels.RewardsFragmentViewModel.RewardsFragmentViewModel
import com.kickstarter.viewmodels.usecases.ShippingRulesState
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import com.kickstarter.viewmodels.projectpage.RewardsSelectionViewModel

class RewardsFragment : Fragment() {

private lateinit var dialog: AlertDialog
private var binding: FragmentRewardsBinding? = null

private lateinit var viewModelFactory: Factory
private val viewModel: RewardsFragmentViewModel by viewModels {
viewModelFactory
}
private lateinit var rewardsSelectionViewModelFactory: RewardsSelectionViewModel.Factory
private val viewModel: RewardsSelectionViewModel by viewModels { rewardsSelectionViewModelFactory }

private lateinit var environment: Environment
private val disposables = CompositeDisposable()

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)

this.context?.getEnvironment()?.let { env ->
viewModelFactory = Factory(env)
environment = env
rewardsSelectionViewModelFactory = RewardsSelectionViewModel.Factory(env)
}

super.onCreateView(inflater, container, savedInstanceState)
binding = FragmentRewardsBinding.inflate(inflater, container, false)
return binding?.root
}

@Composable
private fun ScrollToPosition(
scrollToPosition: State<Int>,
listState: LazyListState
) {
LaunchedEffect(scrollToPosition) {
// Animate scroll to the scrollToPosition item
listState.animateScrollToItem(index = scrollToPosition.value)
}
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
createDialog()
Expand All @@ -86,69 +63,53 @@ class RewardsFragment : Fragment() {
) {
KSTheme {

val projectData: State<ProjectData> = viewModel.projectData().subscribeAsState(initial = ProjectData.builder().build())
val backing = projectData.value.backing() ?: projectData.value.project().backing()
val project = projectData.value.project()

val rules = viewModel.countrySelectorRules().collectAsStateWithLifecycle(
initialValue = ShippingRulesState()
).value
val rewardSelectionUIState by viewModel.rewardSelectionUIState.collectAsStateWithLifecycle()
val shippingUIState by viewModel.shippingUIState.collectAsStateWithLifecycle()
val projectData = rewardSelectionUIState.project
val indexOfBackedReward = rewardSelectionUIState.initialRewardIndex
val rewards = shippingUIState.filteredRw
val project = projectData.project()
val backing = projectData.backing()

val rewards = rules.filteredRw
val listState = rememberLazyListState()
val rewardLoading = shippingUIState.loading
val currentUserShippingRule = shippingUIState.selectedShippingRule
val shippingRules = shippingUIState.shippingRules

val listState = rememberLazyListState(
initialFirstVisibleItemIndex = indexOfBackedReward
)
RewardCarouselScreen(
lazyRowState = listState,
environment = requireNotNull(environment),
environment = environment,
rewards = rewards,
project = project,
backing = backing,
onRewardSelected = {
viewModel.inputs.rewardClicked(it)
viewModel.onUserRewardSelection(it)
},
countryList = rules.shippingRules,
onShippingRuleSelected = {
viewModel.inputs.selectedShippingRule(it)
countryList = shippingRules,
onShippingRuleSelected = { shippingRule ->
viewModel.selectedShippingRule(shippingRule)
},
currentShippingRule = rules.selectedShippingRule,
isLoading = rules.loading
currentShippingRule = currentUserShippingRule,
isLoading = rewardLoading
)

ScrollToPosition(viewModel.outputs.backedRewardPosition().subscribeAsState(initial = 0), listState)
LaunchedEffect(Unit) {
viewModel.flowUIRequest.collect {
viewModel.getPledgeData()?.let {
if (viewModel.shouldShowAlert()) {
showDialog()
} else {
showAddonsFragment(it)
}
}
}
}
}
}
}
}

this.viewModel.outputs.showPledgeFragment()
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
dialog.dismiss()
// showPledgeFragment(it.first, it.second)
showAddonsFragment(Pair(it.first, it.second))
}
.addToDisposable(disposables)

this.viewModel.outputs.showAddOnsFragment()
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
dialog.dismiss()
showAddonsFragment(it)
}
.addToDisposable(disposables)

this.viewModel.outputs.showAlert()
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
showAlert()
}
.addToDisposable(disposables)
}

fun setState(state: Boolean?) {
state?.let {
viewModel.isExpanded(state)
}
}

private fun createDialog() {
Expand All @@ -159,54 +120,32 @@ class RewardsFragment : Fragment() {
.setMessage(getString(R.string.It_may_not_offer_some_or_all_of_your_add_ons))
.setNegativeButton(getString(R.string.No_go_back)) { _, _ -> {} }
.setPositiveButton(getString(R.string.Yes_continue)) { _, _ ->
this.viewModel.inputs.alertButtonPressed()
viewModel.getPledgeData()?.let { showAddonsFragment(it) }
}.create()
}
}

private fun showAlert() {
private fun showDialog() {
if (this.isVisible)
dialog.show()
}

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

fun configureWith(projectData: ProjectData) {
this.viewModel.inputs.configureWith(projectData)
}

private fun showPledgeFragment(
pledgeData: PledgeData,
pledgeReason: PledgeReason
) {
val fragment = this.selectPledgeFragment(pledgeData, pledgeReason)

if (this.isVisible && this.parentFragmentManager.findFragmentByTag(fragment::class.java.simpleName) == null) {
this.parentFragmentManager
.beginTransaction()
.setCustomAnimations(R.anim.slide_in_right, 0, 0, R.anim.slide_out_right)
.add(
R.id.fragment_container,
fragment,
fragment::class.java.simpleName
)
.addToBackStack(fragment::class.java.simpleName)
.commit()
}
}

private fun showAddonsFragment(pledgeDataAndReason: Pair<PledgeData, PledgeReason>) {
private fun showAddonsFragment(pledgeDataAndReason: kotlin.Pair<PledgeData, PledgeReason>) {
if (this.isVisible && this.parentFragmentManager.findFragmentByTag(BackingAddOnsFragment::class.java.simpleName) == null) {

val reducedProject = pledgeDataAndReason.first.projectData().project().reduce()

val reducedProjectData = pledgeDataAndReason.first.projectData().toBuilder().project(reducedProject).build()
val reducedPledgeData = pledgeDataAndReason.first.toBuilder().projectData(reducedProjectData).build()
val reducedProjectData =
pledgeDataAndReason.first.projectData().toBuilder().project(reducedProject).build()
val reducedPledgeData =
pledgeDataAndReason.first.toBuilder().projectData(reducedProjectData).build()

val addOnsFragment = BackingAddOnsFragment.newInstance(Pair(reducedPledgeData, pledgeDataAndReason.second))
val addOnsFragment = BackingAddOnsFragment.newInstance(
Pair(
reducedPledgeData,
pledgeDataAndReason.second
)
)

this.parentFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.slide_in_right, 0, 0, R.anim.slide_out_right)
Expand All @@ -219,4 +158,14 @@ class RewardsFragment : Fragment() {
.commit()
}
}

fun setState(state: Boolean?) {
state?.let {
viewModel.sendEvent(expanded = it)
}
}

fun configureWith(projectData: ProjectData) {
this.viewModel.provideProjectData(projectData)
}
}
Loading

0 comments on commit 12923ee

Please sign in to comment.