Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[🆕] Manage pledge menu #588

Merged
merged 5 commits into from Aug 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
159 changes: 143 additions & 16 deletions app/src/main/java/com/kickstarter/ui/activities/ProjectActivity.kt
Expand Up @@ -25,6 +25,7 @@ import com.kickstarter.extensions.showSnackbar
import com.kickstarter.libs.ActivityRequestCodes
import com.kickstarter.libs.BaseActivity
import com.kickstarter.libs.KSString
import com.kickstarter.libs.KoalaContext
import com.kickstarter.libs.qualifiers.RequiresActivityViewModel
import com.kickstarter.libs.rx.transformers.Transformers
import com.kickstarter.libs.utils.ProjectViewUtils
Expand All @@ -35,10 +36,9 @@ import com.kickstarter.models.User
import com.kickstarter.ui.IntentKey
import com.kickstarter.ui.adapters.ProjectAdapter
import com.kickstarter.ui.data.LoginReason
import com.kickstarter.ui.fragments.CancelPledgeFragment
import com.kickstarter.ui.fragments.NewCardFragment
import com.kickstarter.ui.fragments.PledgeFragment
import com.kickstarter.ui.fragments.RewardsFragment
import com.kickstarter.ui.data.PledgeData
import com.kickstarter.ui.data.PledgeReason
import com.kickstarter.ui.fragments.*
import com.kickstarter.viewmodels.ProjectViewModel
import com.stripe.android.view.StripeEditText
import kotlinx.android.synthetic.main.activity_project.*
Expand Down Expand Up @@ -91,12 +91,39 @@ class ProjectActivity : BaseActivity<ProjectViewModel.ViewModel>(), CancelPledge
}

rewards_toolbar.setNavigationOnClickListener {
this.viewModel.inputs.hideRewardsSheetClicked()
this.viewModel.inputs.collapsePledgeSheet()
}

rewards_toolbar.setOnMenuItemClickListener {
when {
it.itemId == R.id.update_pledge -> {
this.viewModel.inputs.updatePledgeClicked()
true
}
it.itemId == R.id.rewards -> {
this.viewModel.inputs.viewRewardsClicked()
true
}
it.itemId == R.id.update_payment -> {
this.viewModel.inputs.updatePaymentClicked()
true
}
it.itemId == R.id.cancel_pledge -> {
this.viewModel.inputs.cancelPledgeClicked()
true
}
it.itemId == R.id.contact_creator -> {
this.viewModel.inputs.contactCreatorClicked()
true
}
else -> false
}
}

this.supportFragmentManager.addOnBackStackChangedListener {
this.viewModel.inputs.fragmentStackCount(this.supportFragmentManager.backStackEntryCount)
}

}
else -> {
project_action_buttons.visibility = when {
Expand Down Expand Up @@ -162,7 +189,7 @@ class ProjectActivity : BaseActivity<ProjectViewModel.ViewModel>(), CancelPledge
.observeOn(AndroidSchedulers.mainThread())
.subscribe { setInitialRewardsContainerY() }

this.viewModel.outputs.showRewardsFragment()
this.viewModel.outputs.expandPledgeSheet()
.compose(bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { animateRewards(it) }
Expand Down Expand Up @@ -232,6 +259,41 @@ class ProjectActivity : BaseActivity<ProjectViewModel.ViewModel>(), CancelPledge
.observeOn(AndroidSchedulers.mainThread())
.subscribe { showCancelPledgeSuccess() }

this.viewModel.outputs.showRewardsFragment()
.compose(bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { showRewardsFragment(it) }

this.viewModel.outputs.showBackingFragment()
.compose(bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { showBackingFragment(it) }

this.viewModel.outputs.managePledgeMenuIsVisible()
.compose(bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { toggleManagePledgeVisibility(it) }

this.viewModel.outputs.showCancelPledgeFragment()
.compose(bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { showCancelPledgeFragment(it) }

this.viewModel.outputs.revealRewardsFragment()
.compose(bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { revealRewardsFragment() }

this.viewModel.outputs.showUpdatePledge()
.compose(bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { showPledgeFragment(it) }

this.viewModel.outputs.startMessagesActivity()
.compose(bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { startMessagesActivity(it) }

this.heartIcon.setOnClickListener {
this.viewModel.inputs.heartButtonClicked()
}
Expand Down Expand Up @@ -362,7 +424,7 @@ class ProjectActivity : BaseActivity<ProjectViewModel.ViewModel>(), CancelPledge
val rewardsSheetIsExpanded = pledge_container.alpha == 1f
when {
supportFragmentManager.backStackEntryCount > 0 && rewardsSheetIsExpanded -> supportFragmentManager.popBackStack()
rewardsSheetIsExpanded -> this.viewModel.inputs.hideRewardsSheetClicked()
rewardsSheetIsExpanded -> this.viewModel.inputs.collapsePledgeSheet()
else -> {
clearFragmentBackStack()
super.back()
Expand All @@ -376,11 +438,24 @@ class ProjectActivity : BaseActivity<ProjectViewModel.ViewModel>(), CancelPledge
this.adapter.takeProject(project, country, environment().nativeCheckoutPreference().get())
if (!environment().nativeCheckoutPreference().get()) {
ProjectViewUtils.setActionButton(project, this.back_project_button, this.manage_pledge_button, this.view_pledge_button, null)
} else {
setupRewardsFragment(project)
}
}

private fun renderProject(backingFragment: BackingFragment, rewardsFragment: RewardsFragment, project: Project) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens when we have two methods with the same name? I see that we have another renderProject above with a different function signature. Is it able to detect which one to invoke based on the arguments?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep! I was considering naming it renderProjectInFragments but it's kinda long and redundant.

Copy link

@roblum roblum Aug 15, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I'm still learning how the files in this codebase are structured and what the purpose of each of these functions are. It looks like the one above renders an action button for the project? Could it be something like renderProjectActionButton or is that too specific? (disregard if I misunderstood)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ooh it's doing more than that. It's loading the project into the ProjectAdapter, loading the old style rewards if the native checkout flag is off, and configuring the button

rewardsFragment.takeProject(project)
backingFragment.takeProject(project)
}

private fun revealRewardsFragment() {
val rewardsFragment = supportFragmentManager.findFragmentById(R.id.fragment_rewards) as RewardsFragment
supportFragmentManager
.beginTransaction()
.setCustomAnimations(R.anim.slide_in_right, 0, 0, R.anim.slide_out_right)
.show(rewardsFragment)
.addToBackStack(RewardsFragment::class.java.simpleName)
.commit()
}

private fun rewardsSheetGuideline(): Int = when {
ViewUtils.isLandscape(this) -> 0
else -> resources.getDimensionPixelSize(R.dimen.reward_fragment_guideline_constraint_end)
Expand All @@ -392,9 +467,27 @@ class ProjectActivity : BaseActivity<ProjectViewModel.ViewModel>(), CancelPledge
this.projectRecyclerView.setPadding(0, 0, 0, guideline)
}

private fun setupRewardsFragment(project: Project) {
val rewardsFragment = supportFragmentManager.findFragmentById(R.id.fragment_rewards) as RewardsFragment?
rewardsFragment?.takeProject(project)
private fun showBackingFragment(project: Project) {
val (rewardsFragment, backingFragment) = supportFragmentManager.findFragmentById(R.id.fragment_rewards) as RewardsFragment to
supportFragmentManager.findFragmentById(R.id.fragment_backing) as BackingFragment
if(!rewardsFragment.isHidden && supportFragmentManager.backStackEntryCount == 0) {
supportFragmentManager.beginTransaction()
.show(backingFragment)
.hide(rewardsFragment)
.commit()
}
renderProject(backingFragment, rewardsFragment, project)
}

private fun showCancelPledgeFragment(project: Project) {
eoji marked this conversation as resolved.
Show resolved Hide resolved
val cancelPledgeFragment = CancelPledgeFragment.newInstance(project)
val tag = CancelPledgeFragment::class.java.simpleName
supportFragmentManager
.beginTransaction()
.setCustomAnimations(R.anim.slide_up, 0, 0, R.anim.slide_down)
.add(R.id.fragment_container, cancelPledgeFragment, tag)
.addToBackStack(tag)
.commit()
}

private fun showCancelPledgeSuccess() {
Expand All @@ -404,6 +497,33 @@ class ProjectActivity : BaseActivity<ProjectViewModel.ViewModel>(), CancelPledge
}, this.animDuration)
}

private fun showPledgeFragment(pledgeDataAndPledgeReason: Pair<PledgeData, PledgeReason>) {
val pledgeFragment = PledgeFragment.newInstance(pledgeDataAndPledgeReason.first)
val tag = PledgeFragment::class.java.simpleName
supportFragmentManager
.beginTransaction()
.setCustomAnimations(R.anim.slide_up, 0, 0, R.anim.slide_down)
.add(R.id.fragment_container, pledgeFragment, tag)
.addToBackStack(tag)
.commit()
}

private fun showRewardsFragment(project: Project) {
val (rewardsFragment, backingFragment) = supportFragmentManager.findFragmentById(R.id.fragment_rewards) as RewardsFragment to
supportFragmentManager.findFragmentById(R.id.fragment_backing) as BackingFragment
if(!backingFragment.isHidden && supportFragmentManager.backStackEntryCount == 0) {
supportFragmentManager.beginTransaction()
.show(rewardsFragment)
.hide(backingFragment)
.commit()
}
renderProject(backingFragment, rewardsFragment, project)
}

private fun showStarToast() {
ViewUtils.showToastFromTop(this, getString(this.projectStarConfirmationString), 0, resources.getDimensionPixelSize(R.dimen.grid_8))
}

private fun startCampaignWebViewActivity(project: Project) {
startWebViewActivity(getString(this.campaignString), project.descriptionUrl())
}
Expand All @@ -421,10 +541,6 @@ class ProjectActivity : BaseActivity<ProjectViewModel.ViewModel>(), CancelPledge
startActivityWithTransition(intent, R.anim.slide_in_right, R.anim.fade_out_slide_out_left)
}

private fun showStarToast() {
ViewUtils.showToastFromTop(this, getString(this.projectStarConfirmationString), 0, resources.getDimensionPixelSize(R.dimen.grid_8))
}

private fun startCheckoutActivity(project: Project) {
val intent = Intent(this, CheckoutActivity::class.java)
.putExtra(IntentKey.PROJECT, project)
Expand Down Expand Up @@ -477,6 +593,13 @@ class ProjectActivity : BaseActivity<ProjectViewModel.ViewModel>(), CancelPledge
startActivityWithTransition(intent, R.anim.slide_in_right, R.anim.fade_out_slide_out_left)
}

private fun startMessagesActivity(project: Project) {
startActivity(Intent(this, MessagesActivity::class.java)
.putExtra(IntentKey.KOALA_CONTEXT, KoalaContext.Message.PROJECT_PAGE)
.putExtra(IntentKey.PROJECT, project)
.putExtra(IntentKey.BACKING, project.backing()))
}

private fun startVideoActivity(project: Project) {
val intent = Intent(this, VideoActivity::class.java)
.putExtra(IntentKey.PROJECT, project)
Expand All @@ -499,4 +622,8 @@ class ProjectActivity : BaseActivity<ProjectViewModel.ViewModel>(), CancelPledge
}
project_action_button.layoutParams = buttonParams
}

private fun toggleManagePledgeVisibility(visible: Boolean) {
if (visible) rewards_toolbar.inflateMenu(R.menu.manage_pledge) else rewards_toolbar.menu.clear()
}
}
4 changes: 3 additions & 1 deletion app/src/main/java/com/kickstarter/ui/data/PledgeData.kt
Expand Up @@ -3,4 +3,6 @@ package com.kickstarter.ui.data
import com.kickstarter.models.Project
import com.kickstarter.models.Reward

data class PledgeData(val rewardScreenLocation: ScreenLocation, val reward: Reward, val project: Project)
data class PledgeData(val rewardScreenLocation: ScreenLocation?, val reward: Reward, val project: Project) {
constructor(reward: Reward, project: Project) : this(null, reward, project)
}
5 changes: 5 additions & 0 deletions app/src/main/java/com/kickstarter/ui/data/PledgeReason.kt
@@ -0,0 +1,5 @@
package com.kickstarter.ui.data

enum class PledgeReason {
PLEDGE, UPDATE_PAYMENT, UPDATE_PLEDGE
}
24 changes: 24 additions & 0 deletions app/src/main/java/com/kickstarter/ui/fragments/BackingFragment.kt
@@ -0,0 +1,24 @@
package com.kickstarter.ui.fragments

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.kickstarter.R
import com.kickstarter.libs.BaseFragment
import com.kickstarter.libs.qualifiers.RequiresFragmentViewModel
import com.kickstarter.models.Project
import com.kickstarter.viewmodels.BackingFragmentViewModel

@RequiresFragmentViewModel(BackingFragmentViewModel.ViewModel::class)
class BackingFragment: BaseFragment<BackingFragmentViewModel.ViewModel>() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_backing, container, false)
}

fun takeProject(project: Project) {
this.viewModel.inputs.project(project)
}

}
22 changes: 14 additions & 8 deletions app/src/main/java/com/kickstarter/ui/fragments/PledgeFragment.kt
Expand Up @@ -39,6 +39,7 @@ import com.kickstarter.libs.utils.ObjectUtils
import com.kickstarter.libs.utils.UrlUtils
import com.kickstarter.libs.utils.ViewUtils
import com.kickstarter.models.Project
import com.kickstarter.models.Reward
import com.kickstarter.models.ShippingRule
import com.kickstarter.models.StoredCard
import com.kickstarter.models.chrome.ChromeTabsHelperActivity
Expand All @@ -61,6 +62,7 @@ import kotlinx.android.synthetic.main.fragment_pledge_section_payment.*
import kotlinx.android.synthetic.main.fragment_pledge_section_pledge_amount.*
import kotlinx.android.synthetic.main.fragment_pledge_section_shipping.*
import kotlinx.android.synthetic.main.fragment_pledge_section_total.*
import kotlin.math.min

@RequiresFragmentViewModel(PledgeFragmentViewModel.ViewModel::class)
class PledgeFragment : BaseFragment<PledgeFragmentViewModel.ViewModel>(), RewardCardAdapter.Delegate, ShippingRulesAdapter.Delegate {
Expand Down Expand Up @@ -537,8 +539,15 @@ class PledgeFragment : BaseFragment<PledgeFragmentViewModel.ViewModel>(), Reward

//Reward card animation helper methods
private fun showPledgeSection(pledgeData: PledgeData) {
setInitialViewStates(pledgeData)
startPledgeAnimatorSet(true, pledgeData.rewardScreenLocation)
pledgeData.rewardScreenLocation?.let {
setInitialViewStates(pledgeData)
startPledgeAnimatorSet(true, it)
}?: run {
reward_to_copy.visibility = View.GONE
reward_snapshot.visibility = View.GONE
expand_icon_container.visibility = View.GONE
pledge_root.visibility = View.VISIBLE
}
}

private fun startPledgeAnimatorSet(reveal: Boolean, location: ScreenLocation) {
Expand Down Expand Up @@ -654,7 +663,7 @@ class PledgeFragment : BaseFragment<PledgeFragmentViewModel.ViewModel>(), Reward
private fun getMiniRewardHeight(miniRewardWidth: Float, location: ScreenLocation): Float {
val scale = miniRewardWidth / location.width
val scaledHeight = (location.height * scale).toInt()
return Math.min(resources.getDimensionPixelSize(R.dimen.mini_reward_height), scaledHeight).toFloat()
return min(resources.getDimensionPixelSize(R.dimen.mini_reward_height), scaledHeight).toFloat()
}

private fun getWidthAnimator(initialValue: Float, finalValue: Float) =
Expand All @@ -676,10 +685,7 @@ class PledgeFragment : BaseFragment<PledgeFragmentViewModel.ViewModel>(), Reward
}
}

private fun positionRewardSnapshot(pledgeData: PledgeData) {
val location = pledgeData.rewardScreenLocation
val reward = pledgeData.reward
val project = pledgeData.project
private fun positionRewardSnapshot(location: ScreenLocation, reward: Reward, project: Project) {
val rewardParams = reward_snapshot.layoutParams as CoordinatorLayout.LayoutParams
rewardParams.leftMargin = location.x.toInt()
rewardParams.topMargin = location.y.toInt()
Expand Down Expand Up @@ -708,7 +714,7 @@ class PledgeFragment : BaseFragment<PledgeFragmentViewModel.ViewModel>(), Reward
}

private fun setInitialViewStates(pledgeData: PledgeData) {
positionRewardSnapshot(pledgeData)
pledgeData.rewardScreenLocation?.let { positionRewardSnapshot(it, pledgeData.reward, pledgeData.project) }
pledge_details.y = pledge_root.height.toFloat()
}

Expand Down
Expand Up @@ -16,11 +16,11 @@ import com.kickstarter.models.Reward
import com.kickstarter.ui.adapters.NativeCheckoutRewardsAdapter
import com.kickstarter.ui.data.PledgeData
import com.kickstarter.ui.data.ScreenLocation
import com.kickstarter.viewmodels.RewardFragmentViewModel
import com.kickstarter.viewmodels.RewardsFragmentViewModel
import kotlinx.android.synthetic.main.fragment_rewards.*

@RequiresFragmentViewModel(RewardFragmentViewModel.ViewModel::class)
class RewardsFragment : BaseFragment<RewardFragmentViewModel.ViewModel>(), NativeCheckoutRewardsAdapter.Delegate {
@RequiresFragmentViewModel(RewardsFragmentViewModel.ViewModel::class)
class RewardsFragment : BaseFragment<RewardsFragmentViewModel.ViewModel>(), NativeCheckoutRewardsAdapter.Delegate {

private var rewardsAdapter = NativeCheckoutRewardsAdapter(this)

Expand Down