From ee65993c018968a8b3f9adc70c9c319da0343128 Mon Sep 17 00:00:00 2001 From: jlplks Date: Wed, 4 Dec 2024 15:00:30 -0700 Subject: [PATCH] Remove "Update Pledge" option on Manage Your Pledge menu (#2180) * Created plot selected menu for ProjectPageViewModel * added isPledgeOverTimeAllowed to project * Added incremental to Backing object, Created a project with plot selected on ProjectFactory, added test * fix ktlint --------- Co-authored-by: Isabel Martin --- .../mock/factories/ProjectFactory.kt | 1 + .../java/com/kickstarter/models/Backing.kt | 7 + .../projectpage/ProjectPageViewModel.kt | 310 +++++++++++++----- .../res/menu/manage_pledge_plot_selected.xml | 17 + .../viewmodels/ProjectPageViewModelTest.kt | 15 + 5 files changed, 263 insertions(+), 87 deletions(-) create mode 100644 app/src/main/res/menu/manage_pledge_plot_selected.xml diff --git a/app/src/main/java/com/kickstarter/mock/factories/ProjectFactory.kt b/app/src/main/java/com/kickstarter/mock/factories/ProjectFactory.kt index 688e8fffc3..5a9ec0a505 100644 --- a/app/src/main/java/com/kickstarter/mock/factories/ProjectFactory.kt +++ b/app/src/main/java/com/kickstarter/mock/factories/ProjectFactory.kt @@ -141,6 +141,7 @@ object ProjectFactory { .backerId(IdFactory.id().toLong()) .cancelable(true) .id(IdFactory.id().toLong()) + .incremental(true) .sequence(1) .reward(reward) .rewardId(reward.id()) diff --git a/app/src/main/java/com/kickstarter/models/Backing.kt b/app/src/main/java/com/kickstarter/models/Backing.kt index 41d289b730..d1d78e5a35 100644 --- a/app/src/main/java/com/kickstarter/models/Backing.kt +++ b/app/src/main/java/com/kickstarter/models/Backing.kt @@ -19,6 +19,7 @@ class Backing private constructor( private val completedAt: DateTime?, private val completedByBacker: Boolean, private val id: Long, + private val incremental: Boolean?, private val location: Location?, private val locationId: Long?, private val locationName: String?, @@ -47,6 +48,7 @@ class Backing private constructor( fun completedAt() = this.completedAt fun completedByBacker() = this.completedByBacker override fun id() = this.id + fun incremental() = this.incremental fun location() = this.location fun locationId() = this.locationId fun locationName() = this.locationName @@ -77,6 +79,7 @@ class Backing private constructor( private var completedAt: DateTime? = null, private var completedByBacker: Boolean = false, private var id: Long = 0L, + private var incremental: Boolean? = null, private var location: Location? = null, private var locationId: Long? = null, private var locationName: String? = null, @@ -105,6 +108,7 @@ class Backing private constructor( fun completedAt(completedAt: DateTime?) = apply { this.completedAt = completedAt } fun completedByBacker(completedByBacker: Boolean?) = apply { this.completedByBacker = completedByBacker ?: false } fun id(id: Long?) = apply { this.id = id ?: 0L } + fun incremental(incremental: Boolean?) = apply { this.incremental = incremental } fun location(location: Location?) = apply { this.location = location } fun locationId(locationId: Long?) = apply { this.locationId = locationId } fun locationName(locationName: String?) = apply { this.locationName = locationName } @@ -132,6 +136,7 @@ class Backing private constructor( completedAt = completedAt, completedByBacker = completedByBacker, id = id, + incremental = incremental, location = location, locationId = locationId, locationName = locationName, @@ -162,6 +167,7 @@ class Backing private constructor( completedAt = completedAt, completedByBacker = completedByBacker, id = id, + incremental = incremental, location = location, locationId = locationId, locationName = locationName, @@ -183,6 +189,7 @@ class Backing private constructor( var equals = super.equals(other) if (other is Backing) { equals = id() == other.id() && + incremental() == other.incremental() && amount() == other.amount() && backer() == other.backer() && backerNote() == other.backerNote() && diff --git a/app/src/main/java/com/kickstarter/viewmodels/projectpage/ProjectPageViewModel.kt b/app/src/main/java/com/kickstarter/viewmodels/projectpage/ProjectPageViewModel.kt index 2ec6fdac45..95c5897dbb 100644 --- a/app/src/main/java/com/kickstarter/viewmodels/projectpage/ProjectPageViewModel.kt +++ b/app/src/main/java/com/kickstarter/viewmodels/projectpage/ProjectPageViewModel.kt @@ -296,10 +296,12 @@ interface ProjectPageViewModel { private val heartButtonClicked = PublishSubject.create() private val nativeProjectActionButtonClicked = PublishSubject.create() private val onGlobalLayout = PublishSubject.create() - private val fullScreenVideoButtonClicked = PublishSubject.create>() + private val fullScreenVideoButtonClicked = + PublishSubject.create>() private val pledgePaymentSuccessfullyUpdated = PublishSubject.create() private val pledgeSuccessfullyCancelled = PublishSubject.create() - private val pledgeSuccessfullyCreated = PublishSubject.create>() + private val pledgeSuccessfullyCreated = + PublishSubject.create>() private val pledgeSuccessfullyUpdated = PublishSubject.create() private val pledgeToolbarNavigationClicked = PublishSubject.create() private val refreshProject = PublishSubject.create() @@ -338,11 +340,14 @@ interface ProjectPageViewModel { private val showUpdatePledge = PublishSubject.create>() private val showUpdatePledgeSuccess = PublishSubject.create() private val startRootCommentsActivity = PublishSubject.create() - private val startRootCommentsForCommentsThreadActivity = PublishSubject.create>() + private val startRootCommentsForCommentsThreadActivity = + PublishSubject.create>() private val startLoginToutActivity = PublishSubject.create() private val startMessagesActivity = PublishSubject.create() - private val startProjectUpdateActivity = PublishSubject.create, Pair>>() - private val startProjectUpdateToRepliesDeepLinkActivity = PublishSubject.create, Pair>>() + private val startProjectUpdateActivity = + PublishSubject.create, Pair>>() + private val startProjectUpdateToRepliesDeepLinkActivity = + PublishSubject.create, Pair>>() private val startThanksActivity = PublishSubject.create>() private val updateFragments = BehaviorSubject.create() private val hideVideoPlayer = BehaviorSubject.create() @@ -384,7 +389,10 @@ interface ProjectPageViewModel { .doAfterTerminate { progressBarIsGone.onNext(true) } - .withLatestFrom(currentConfig.observable(), currentUser.observable()) { project, config, user -> + .withLatestFrom( + currentConfig.observable(), + currentUser.observable() + ) { project, config, user -> return@withLatestFrom project.updateProjectWith(config, user.getValue()) } .materialize() @@ -420,7 +428,8 @@ interface ProjectPageViewModel { mappedProjectValues .subscribe { if (it.showLatePledgeFlow()) { - val isFFEnabled = featureFlagClient.getBoolean(FlagKey.ANDROID_POST_CAMPAIGN_PLEDGES) + val isFFEnabled = + featureFlagClient.getBoolean(FlagKey.ANDROID_POST_CAMPAIGN_PLEDGES) this.showLatePledgeFlow.onNext(it.showLatePledgeFlow() && isFFEnabled) } @@ -438,9 +447,14 @@ interface ProjectPageViewModel { // An observable of the ref tag stored in the cookie for the project. Emits an optional since this value can be null. val cookieRefTag = initialProject .take(1) - .map { - p -> - KsOptional.of(RefTagUtils.storedCookieRefTagForProject(p, this.cookieManager, this.sharedPreferences)) + .map { p -> + KsOptional.of( + RefTagUtils.storedCookieRefTagForProject( + p, + this.cookieManager, + this.sharedPreferences + ) + ) } val refTag = intent @@ -451,7 +465,11 @@ interface ProjectPageViewModel { val saveProjectFromDeepLinkActivity = intent .take(1) - .delay(3, TimeUnit.SECONDS, environment.schedulerV2()) // add delay to wait until activity subscribed to viewmodel + .delay( + 3, + TimeUnit.SECONDS, + environment.schedulerV2() + ) // add delay to wait until activity subscribed to viewmodel .filter { it.getBooleanExtra(IntentKey.DEEP_LINK_SCREEN_PROJECT_SAVE, false) } @@ -459,7 +477,11 @@ interface ProjectPageViewModel { val saveProjectFromDeepUrl = intent .take(1) - .delay(3, TimeUnit.SECONDS, environment.schedulerV2()) // add delay to wait until activity subscribed to viewmodel + .delay( + 3, + TimeUnit.SECONDS, + environment.schedulerV2() + ) // add delay to wait until activity subscribed to viewmodel .filter { it.data.isNotNull() } .map { requireNotNull(it.data) } .filter { @@ -511,8 +533,14 @@ interface ProjectPageViewModel { .doAfterTerminate { progressBarIsGone.onNext(true) } - .withLatestFrom(currentConfig.observable(), currentUser.observable()) { project, config, user -> - return@withLatestFrom project.updateProjectWith(config, user.getValue()) + .withLatestFrom( + currentConfig.observable(), + currentUser.observable() + ) { project, config, user -> + return@withLatestFrom project.updateProjectWith( + config, + user.getValue() + ) } .materialize() } @@ -534,22 +562,23 @@ interface ProjectPageViewModel { } .share() - val projectOnDeepLinkChangeSave = Observable.merge(saveProjectFromDeepLinkActivity, saveProjectFromDeepUrl) - .compose(combineLatestPair(this.currentUser.observable())) - .filter { it.second.isPresent() } - .withLatestFrom(initialProject) { userAndFlag, p -> - Pair(userAndFlag, p) - } - .take(1) - .filter { - it.second.isStarred() != it.first.first - }.switchMap { - if (it.first.first) { - this.saveProject(it.second) - } else { - this.unSaveProject(it.second) + val projectOnDeepLinkChangeSave = + Observable.merge(saveProjectFromDeepLinkActivity, saveProjectFromDeepUrl) + .compose(combineLatestPair(this.currentUser.observable())) + .filter { it.second.isPresent() } + .withLatestFrom(initialProject) { userAndFlag, p -> + Pair(userAndFlag, p) } - }.share() + .take(1) + .filter { + it.second.isStarred() != it.first.first + }.switchMap { + if (it.first.first) { + this.saveProject(it.second) + } else { + this.unSaveProject(it.second) + } + }.share() val currentProject = Observable.mergeArray( initialProject, @@ -579,7 +608,11 @@ interface ProjectPageViewModel { } .addToDisposable(disposables) - val projectSavedStatus = Observable.merge(projectOnUserChangeSave, savedProjectOnLoginSuccess, projectOnDeepLinkChangeSave) + val projectSavedStatus = Observable.merge( + projectOnUserChangeSave, + savedProjectOnLoginSuccess, + projectOnDeepLinkChangeSave + ) projectSavedStatus .subscribe { this.analyticEvents.trackWatchProjectCTA(it, PROJECT) } @@ -591,23 +624,28 @@ interface ProjectPageViewModel { .subscribe { this.showSavedPrompt.onNext(it) } .addToDisposable(disposables) - val currentProjectData = Observable.combineLatest, KsOptional, KsOptional, Project, ProjectData>( - refTag, - cookieRefTag, - fullDeeplink, - currentProject - ) { refTagFromIntent, refTagFromCookie, fullDeeplink, project -> - projectData(refTagFromIntent, refTagFromCookie, fullDeeplink, project) - } + val currentProjectData = + Observable.combineLatest, KsOptional, KsOptional, Project, ProjectData>( + refTag, + cookieRefTag, + fullDeeplink, + currentProject + ) { refTagFromIntent, refTagFromCookie, fullDeeplink, project -> + projectData(refTagFromIntent, refTagFromCookie, fullDeeplink, project) + } currentProjectData .distinctUntilChanged() .subscribe { this.projectData.onNext(it) val showEnvironmentalTab = it.project().envCommitments()?.isNotEmpty() ?: false - val tabConfigEnv = PagerTabConfig(ProjectPagerTabs.ENVIRONMENTAL_COMMITMENT, showEnvironmentalTab) + val tabConfigEnv = PagerTabConfig( + ProjectPagerTabs.ENVIRONMENTAL_COMMITMENT, + showEnvironmentalTab + ) - val showAiTab = it.project().aiDisclosure()?.let { disclosure -> !disclosure.isUIEmptyValues() } ?: false + val showAiTab = it.project().aiDisclosure() + ?.let { disclosure -> !disclosure.isUIEmptyValues() } ?: false val tabConfigAi = PagerTabConfig(ProjectPagerTabs.USE_OF_AI, showAiTab) this.updateTabs.onNext(listOf(tabConfigAi, tabConfigEnv)) @@ -616,18 +654,27 @@ interface ProjectPageViewModel { currentProject .compose(takeWhenV2(this.shareButtonClicked)) - .map { Pair(it.name(), UrlUtils.appendRefTag(it.webProjectUrl(), RefTag.projectShare().tag())) } + .map { + Pair( + it.name(), + UrlUtils.appendRefTag(it.webProjectUrl(), RefTag.projectShare().tag()) + ) + } .subscribe { this.showShareSheet.onNext(it) } .addToDisposable(disposables) - val latestProjectAndProjectData = currentProject.compose>(combineLatestPair(projectData)) + val latestProjectAndProjectData = + currentProject.compose>(combineLatestPair(projectData)) intent .take(1) - .delay(3, TimeUnit.SECONDS, environment.schedulerV2()) // add delay to wait until activity subscribed to viewmodel + .delay( + 3, + TimeUnit.SECONDS, + environment.schedulerV2() + ) // add delay to wait until activity subscribed to viewmodel .filter { - it.getBooleanExtra(IntentKey.DEEP_LINK_SCREEN_PROJECT_COMMENT, false) && - it.getStringExtra(IntentKey.COMMENT)?.isEmpty() ?: true + it.getBooleanExtra(IntentKey.DEEP_LINK_SCREEN_PROJECT_COMMENT, false) && it.getStringExtra(IntentKey.COMMENT)?.isEmpty() ?: true } .withLatestFrom(latestProjectAndProjectData) { _, project -> project @@ -639,7 +686,11 @@ interface ProjectPageViewModel { intent .take(1) - .delay(3, TimeUnit.SECONDS, environment.schedulerV2()) // add delay to wait until activity subscribed to viewmodel + .delay( + 3, + TimeUnit.SECONDS, + environment.schedulerV2() + ) // add delay to wait until activity subscribed to viewmodel .filter { it.getBooleanExtra(IntentKey.DEEP_LINK_SCREEN_PROJECT_COMMENT, false) && it.getStringExtra(IntentKey.COMMENT)?.isNotEmpty() ?: false @@ -655,9 +706,14 @@ interface ProjectPageViewModel { intent .take(1) - .delay(3, TimeUnit.SECONDS, environment.schedulerV2()) // add delay to wait until activity subscribed to viewmodel + .delay( + 3, + TimeUnit.SECONDS, + environment.schedulerV2() + ) // add delay to wait until activity subscribed to viewmodel .filter { - it.getStringExtra(IntentKey.DEEP_LINK_SCREEN_PROJECT_UPDATE)?.isNotEmpty() ?: false && + it.getStringExtra(IntentKey.DEEP_LINK_SCREEN_PROJECT_UPDATE) + ?.isNotEmpty() ?: false && it.getStringExtra(IntentKey.COMMENT)?.isEmpty() ?: true }.map { Pair( @@ -674,9 +730,14 @@ interface ProjectPageViewModel { intent .take(1) - .delay(3, TimeUnit.SECONDS, environment.schedulerV2()) // add delay to wait until activity subscribed to viewmodel + .delay( + 3, + TimeUnit.SECONDS, + environment.schedulerV2() + ) // add delay to wait until activity subscribed to viewmodel .filter { - it.getStringExtra(IntentKey.DEEP_LINK_SCREEN_PROJECT_UPDATE)?.isNotEmpty() ?: false && + it.getStringExtra(IntentKey.DEEP_LINK_SCREEN_PROJECT_UPDATE) + ?.isNotEmpty() ?: false && it.getStringExtra(IntentKey.COMMENT)?.isNotEmpty() ?: false }.map { Pair( @@ -819,7 +880,12 @@ interface ProjectPageViewModel { it.first.project().toBuilder().backing(it.second).build() } else it.first.project() - projectData(KsOptional.of(it.first.refTagFromIntent()), KsOptional.of(it.first.refTagFromCookie()), KsOptional.of(it.first.fullDeeplink()), updatedProject) + projectData( + KsOptional.of(it.first.refTagFromIntent()), + KsOptional.of(it.first.refTagFromCookie()), + KsOptional.of(it.first.fullDeeplink()), + updatedProject + ) } .subscribe { this.updateFragments.onNext(it) } .addToDisposable(disposables) @@ -845,7 +911,9 @@ interface ProjectPageViewModel { val projectDataAndBackedReward = currentProjectData .compose>(combineLatestPair(backing)) .filter { it.first.project().backing().isNotNull() } - .filter { it.first.project().backing()?.backedReward(it.first.project()).isNotNull() } + .filter { + it.first.project().backing()?.backedReward(it.first.project()).isNotNull() + } .map { pD -> pD.first.project().backing()?.backedReward(pD.first.project())?.let { Pair(pD.first.toBuilder().backing(pD.second).build(), it) @@ -854,13 +922,23 @@ interface ProjectPageViewModel { projectDataAndBackedReward .compose(takeWhenV2(this.fixPaymentMethodButtonClicked)) - .map { Pair(pledgeData(it.second, it.first, PledgeFlowContext.FIX_ERRORED_PLEDGE), PledgeReason.FIX_PLEDGE) } + .map { + Pair( + pledgeData(it.second, it.first, PledgeFlowContext.FIX_ERRORED_PLEDGE), + PledgeReason.FIX_PLEDGE + ) + } .subscribe { this.updatePledgeData.onNext(it) } .addToDisposable(disposables) projectDataAndBackedReward .compose(takeWhenV2, Unit>(this.updatePaymentClicked)) - .map { Pair(pledgeData(it.second, it.first, PledgeFlowContext.MANAGE_REWARD), PledgeReason.UPDATE_PAYMENT) } + .map { + Pair( + pledgeData(it.second, it.first, PledgeFlowContext.MANAGE_REWARD), + PledgeReason.UPDATE_PAYMENT + ) + } .subscribe { this.updatePledgeData.onNext(it) this.analyticEvents.trackChangePaymentMethod(it.first) @@ -878,7 +956,11 @@ interface ProjectPageViewModel { currentProject .filter { it.isBacking() } - .map { if (it.backing()?.isErrored() == true) R.string.Payment_failure else R.string.Youre_a_backer } + .map { + if (it.backing() + ?.isErrored() == true + ) R.string.Payment_failure else R.string.Youre_a_backer + } .distinctUntilChanged() .subscribe { this.backingDetailsTitle.onNext(it) } .addToDisposable(disposables) @@ -896,7 +978,10 @@ interface ProjectPageViewModel { val currentProjectAndUser = currentProject .compose>>(combineLatestPair(this.currentUser.observable())) - Observable.combineLatest(currentProjectData, this.currentUser.observable()) { data, user -> + Observable.combineLatest( + currentProjectData, + this.currentUser.observable() + ) { data, user -> ProjectViewUtils.pledgeActionButtonText( data.project(), user.getValue(), @@ -994,12 +1079,22 @@ interface ProjectPageViewModel { val pledgeFlowContext = projectDataAndPledgeFlowContext.second // If a cookie hasn't been set for this ref+project then do so. if (data.refTagFromCookie() == null) { - data.refTagFromIntent()?.let { RefTagUtils.storeCookie(it, data.project(), this.cookieManager, this.sharedPreferences) } + data.refTagFromIntent()?.let { + RefTagUtils.storeCookie( + it, + data.project(), + this.cookieManager, + this.sharedPreferences + ) + } } val dataWithStoredCookieRefTag = storeCurrentCookieRefTag(data) // Send event to segment - this.analyticEvents.trackProjectScreenViewed(dataWithStoredCookieRefTag, OVERVIEW.contextName) + this.analyticEvents.trackProjectScreenViewed( + dataWithStoredCookieRefTag, + OVERVIEW.contextName + ) // Send event to backend event attribution this.attributionEvents.trackProjectPageViewed(dataWithStoredCookieRefTag) }.addToDisposable(disposables) @@ -1010,7 +1105,10 @@ interface ProjectPageViewModel { .compose(takePairWhenV2(this.tabSelected)) .distinctUntilChanged() .subscribe { - this.analyticEvents.trackProjectPageTabChanged(it.first, getSelectedTabContextName(it.second)) + this.analyticEvents.trackProjectPageTabChanged( + it.first, + getSelectedTabContextName(it.second) + ) }.addToDisposable(disposables) fullProjectDataAndPledgeFlowContext @@ -1045,30 +1143,41 @@ interface ProjectPageViewModel { super.onCleared() } - private fun getSelectedTabContextName(selectedTabIndex: Int): String = when (selectedTabIndex) { - ProjectPagerTabs.OVERVIEW.ordinal -> OVERVIEW.contextName - ProjectPagerTabs.CAMPAIGN.ordinal -> CAMPAIGN.contextName - ProjectPagerTabs.FAQS.ordinal -> FAQS.contextName - ProjectPagerTabs.RISKS.ordinal -> RISKS.contextName - ProjectPagerTabs.USE_OF_AI.ordinal -> AI.contextName - ProjectPagerTabs.ENVIRONMENTAL_COMMITMENT.ordinal -> ENVIRONMENT.contextName - else -> OVERVIEW.contextName - } + private fun getSelectedTabContextName(selectedTabIndex: Int): String = + when (selectedTabIndex) { + ProjectPagerTabs.OVERVIEW.ordinal -> OVERVIEW.contextName + ProjectPagerTabs.CAMPAIGN.ordinal -> CAMPAIGN.contextName + ProjectPagerTabs.FAQS.ordinal -> FAQS.contextName + ProjectPagerTabs.RISKS.ordinal -> RISKS.contextName + ProjectPagerTabs.USE_OF_AI.ordinal -> AI.contextName + ProjectPagerTabs.ENVIRONMENTAL_COMMITMENT.ordinal -> ENVIRONMENT.contextName + else -> OVERVIEW.contextName + } private fun managePledgeMenu(projectAndFragmentStackCount: Pair): Int { val project = projectAndFragmentStackCount.first val count = projectAndFragmentStackCount.second + val isPledgeOverTimeEnabled = + featureFlagClient.getBoolean(FlagKey.ANDROID_PLEDGE_OVER_TIME) && project.isPledgeOverTimeAllowed() == true && project.backing()?.incremental() == true return when { !project.isBacking() || count.isNonZero() -> 0 project.isLive -> when { - project.backing()?.status() == Backing.STATUS_PREAUTH -> R.menu.manage_pledge_preauth + isPledgeOverTimeEnabled -> R.menu.manage_pledge_plot_selected + project.backing() + ?.status() == Backing.STATUS_PREAUTH -> R.menu.manage_pledge_preauth + else -> R.menu.manage_pledge_live } + else -> R.menu.manage_pledge_ended } } - private fun pledgeData(reward: Reward, projectData: ProjectData, pledgeFlowContext: PledgeFlowContext): PledgeData { + private fun pledgeData( + reward: Reward, + projectData: ProjectData, + pledgeFlowContext: PledgeFlowContext + ): PledgeData { return PledgeData.with(pledgeFlowContext, projectData, reward) } @@ -1076,12 +1185,19 @@ interface ProjectPageViewModel { return when { project.userIsCreator(currentUser) -> null project.isLive && !project.isBacking() -> PledgeFlowContext.NEW_PLEDGE - !project.isLive && project.backing()?.isErrored() ?: false -> PledgeFlowContext.FIX_ERRORED_PLEDGE + !project.isLive && project.backing() + ?.isErrored() ?: false -> PledgeFlowContext.FIX_ERRORED_PLEDGE + else -> null } } - private fun projectData(refTagFromIntent: KsOptional, refTagFromCookie: KsOptional, fullDeeplink: KsOptional, project: Project): ProjectData { + private fun projectData( + refTagFromIntent: KsOptional, + refTagFromCookie: KsOptional, + fullDeeplink: KsOptional, + project: Project + ): ProjectData { return ProjectData .builder() .refTagFromIntent(refTagFromIntent.getValue()) @@ -1094,7 +1210,13 @@ interface ProjectPageViewModel { private fun storeCurrentCookieRefTag(data: ProjectData): ProjectData { return data .toBuilder() - .refTagFromCookie(RefTagUtils.storedCookieRefTagForProject(data.project(), cookieManager, sharedPreferences)) + .refTagFromCookie( + RefTagUtils.storedCookieRefTagForProject( + data.project(), + cookieManager, + sharedPreferences + ) + ) .build() } @@ -1195,13 +1317,15 @@ interface ProjectPageViewModel { override fun activityResult(result: ActivityResult) = this.activityResult.onNext(result) - override fun backingDetailsSubtitle(): Observable?> = this.backingDetailsSubtitle + override fun backingDetailsSubtitle(): Observable?> = + this.backingDetailsSubtitle override fun backingDetailsTitle(): Observable = this.backingDetailsTitle override fun backingDetailsIsVisible(): Observable = this.backingDetailsIsVisible - override fun expandPledgeSheet(): Observable> = this.expandPledgeSheet + override fun expandPledgeSheet(): Observable> = + this.expandPledgeSheet override fun goBack(): Observable = this.goBack @@ -1211,11 +1335,13 @@ interface ProjectPageViewModel { override fun pledgeActionButtonColor(): Observable = this.pledgeActionButtonColor - override fun pledgeActionButtonContainerIsGone(): Observable = this.pledgeActionButtonContainerIsGone + override fun pledgeActionButtonContainerIsGone(): Observable = + this.pledgeActionButtonContainerIsGone override fun pledgeActionButtonText(): Observable = this.pledgeActionButtonText - override fun pledgeToolbarNavigationIcon(): Observable = this.pledgeToolbarNavigationIcon + override fun pledgeToolbarNavigationIcon(): Observable = + this.pledgeToolbarNavigationIcon override fun pledgeToolbarTitle(): Observable = this.pledgeToolbarTitle @@ -1223,7 +1349,8 @@ interface ProjectPageViewModel { override fun projectData(): Observable = this.projectData - override fun reloadProjectContainerIsGone(): Observable = this.reloadProjectContainerIsGone + override fun reloadProjectContainerIsGone(): Observable = + this.reloadProjectContainerIsGone override fun reloadProgressBarIsGone(): Observable = this.retryProgressBarIsGone @@ -1237,17 +1364,20 @@ interface ProjectPageViewModel { override fun showCancelPledgeSuccess(): Observable = this.showCancelPledgeSuccess - override fun showPledgeNotCancelableDialog(): Observable = this.showPledgeNotCancelableDialog + override fun showPledgeNotCancelableDialog(): Observable = + this.showPledgeNotCancelableDialog override fun showSavedPrompt(): Observable = this.showSavedPrompt override fun showShareSheet(): Observable> = this.showShareSheet - override fun showUpdatePledge(): Observable> = this.showUpdatePledge + override fun showUpdatePledge(): Observable> = + this.showUpdatePledge override fun showUpdatePledgeSuccess(): Observable = this.showUpdatePledgeSuccess - override fun startRootCommentsActivity(): Observable = this.startRootCommentsActivity + override fun startRootCommentsActivity(): Observable = + this.startRootCommentsActivity override fun startRootCommentsForCommentsThreadActivity(): Observable> = this.startRootCommentsForCommentsThreadActivity @@ -1256,14 +1386,17 @@ interface ProjectPageViewModel { override fun startMessagesActivity(): Observable = this.startMessagesActivity - override fun startThanksActivity(): Observable> = this.startThanksActivity + override fun startThanksActivity(): Observable> = + this.startThanksActivity - override fun startProjectUpdateActivity(): Observable, Pair>> = this.startProjectUpdateActivity + override fun startProjectUpdateActivity(): Observable, Pair>> = + this.startProjectUpdateActivity override fun startProjectUpdateToRepliesDeepLinkActivity(): Observable, Pair>> = this.startProjectUpdateToRepliesDeepLinkActivity - override fun onOpenVideoInFullScreen(): Observable> = this.onOpenVideoInFullScreen + override fun onOpenVideoInFullScreen(): Observable> = + this.onOpenVideoInFullScreen override fun updateTabs(): Observable> = this.updateTabs @@ -1275,11 +1408,13 @@ interface ProjectPageViewModel { override fun playButtonIsVisible(): Observable = this.playButtonIsVisible - override fun backingViewGroupIsVisible(): Observable = this.backingViewGroupIsVisible + override fun backingViewGroupIsVisible(): Observable = + this.backingViewGroupIsVisible override fun showLatePledgeFlow(): Observable = this.showLatePledgeFlow - override fun showPledgeRedemptionScreen(): Observable> = this.showPledgeRedemptionScreen + override fun showPledgeRedemptionScreen(): Observable> = + this.showPledgeRedemptionScreen private fun backingDetailsSubtitle(project: Project): Either? { return project.backing()?.let { backing -> @@ -1291,7 +1426,8 @@ interface ProjectPageViewModel { val backingAmount = backing.amount() - val formattedAmount = this.ksCurrency.format(backingAmount, project, RoundingMode.HALF_UP) + val formattedAmount = + this.ksCurrency.format(backingAmount, project, RoundingMode.HALF_UP) Either.Left("$formattedAmount $title".trim()) } diff --git a/app/src/main/res/menu/manage_pledge_plot_selected.xml b/app/src/main/res/menu/manage_pledge_plot_selected.xml new file mode 100644 index 0000000000..dab035b05c --- /dev/null +++ b/app/src/main/res/menu/manage_pledge_plot_selected.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/app/src/test/java/com/kickstarter/viewmodels/ProjectPageViewModelTest.kt b/app/src/test/java/com/kickstarter/viewmodels/ProjectPageViewModelTest.kt index 04782923a2..58112cb034 100644 --- a/app/src/test/java/com/kickstarter/viewmodels/ProjectPageViewModelTest.kt +++ b/app/src/test/java/com/kickstarter/viewmodels/ProjectPageViewModelTest.kt @@ -1738,6 +1738,21 @@ class ProjectPageViewModelTest : KSRobolectricTestCase() { this.managePledgeMenu.assertValue(0) } + @Test + fun testManagePledgeMenu_whenProjectBacked_Live_And_PLOTSelected() { + val mockFeatureFlagClient = object : MockFeatureFlagClient() { + override fun getBoolean(FlagKey: FlagKey): Boolean { + return true + } + } + setUpEnvironment(environment().toBuilder().featureFlagClient(mockFeatureFlagClient).apolloClientV2(apolloClientSuccessfulGetProject()).build()) + + // Start the view model with a PLOT selected project + this.vm.configureWith(Intent().putExtra(IntentKey.PROJECT, ProjectFactory.backedProjectWithPlotSelected())) + + this.managePledgeMenu.assertValue(R.menu.manage_pledge_plot_selected) + } + @Test fun testManagePledgeMenu_whenManaging() { setUpEnvironment(environment().toBuilder().apolloClientV2(apolloClientSuccessfulGetProject()).build())