Skip to content

Commit

Permalink
[🔜] Prelaunch project MVP (#587)
Browse files Browse the repository at this point in the history
* Prelaunch activated projects open in the browser and tests.
  • Loading branch information
eoji authored Aug 21, 2019
1 parent c9b432d commit 061d64c
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -285,4 +285,19 @@ public static Project staffPick() {
.staffPick(true)
.build();
}

public static Project prelaunchProject(final String projectUrl) {

final Project.Urls.Web web = Project.Urls.Web.builder()
.project(projectUrl)
.rewards(projectUrl + "/rewards")
.updates(projectUrl + "/posts")
.build();

return project()
.toBuilder()
.prelaunchActivated(true)
.urls(Project.Urls.builder().web(web).build())
.build();
}
}
2 changes: 2 additions & 0 deletions app/src/main/java/com/kickstarter/models/Project.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public abstract class Project implements Parcelable, Relay {
public abstract @Nullable List<Permission> permissions();
public abstract double pledged();
public abstract @Nullable Photo photo();
public abstract @Nullable Boolean prelaunchActivated();
public abstract @Nullable List<Reward> rewards();
public abstract @Nullable String slug();
public abstract @Nullable Boolean staffPick();
Expand Down Expand Up @@ -92,6 +93,7 @@ public abstract static class Builder {
public abstract Builder permissions(List<Permission> __);
public abstract Builder pledged(double __);
public abstract Builder photo(Photo __);
public abstract Builder prelaunchActivated(Boolean __);
public abstract Builder rewards(List<Reward> __);
public abstract Builder slug(String __);
public abstract Builder staffPick(Boolean __);
Expand Down
32 changes: 32 additions & 0 deletions app/src/main/java/com/kickstarter/ui/activities/ProjectActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.content.Intent
import android.graphics.Rect
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.util.Pair
Expand Down Expand Up @@ -294,6 +295,11 @@ class ProjectActivity : BaseActivity<ProjectViewModel.ViewModel>(), CancelPledge
.observeOn(AndroidSchedulers.mainThread())
.subscribe { startMessagesActivity(it) }

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

this.heartIcon.setOnClickListener {
this.viewModel.inputs.heartButtonClicked()
}
Expand Down Expand Up @@ -432,6 +438,32 @@ class ProjectActivity : BaseActivity<ProjectViewModel.ViewModel>(), CancelPledge
}
}

private fun openProjectAndFinish(url: String) {
val uri = Uri.parse(url)

val fakeUri = Uri.parse("http://www.kickstarter.com")
val browserIntent = Intent(Intent.ACTION_VIEW, fakeUri)
val queryIntentActivities = packageManager.queryIntentActivities(browserIntent, 0)
val targetIntents = queryIntentActivities
.filter { !it.activityInfo.packageName.contains("com.kickstarter") }
.map { resolveInfo ->
val intent = Intent(Intent.ACTION_VIEW, uri)
intent.setPackage(resolveInfo.activityInfo.packageName)
intent
}
.toMutableList()

if (targetIntents.isNotEmpty()) {
/* We need to remove the first intent so it's not duplicated
when we add the EXTRA_INITIAL_INTENTS intents. */
val chooserIntent = Intent.createChooser(targetIntents.removeAt(0), "")
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toTypedArray())
startActivity(chooserIntent)
}

finish()
}

private fun renderProject(projectAndCountry: Pair<Project, String>) {
val project = projectAndCountry.first
val country = projectAndCountry.second
Expand Down
18 changes: 17 additions & 1 deletion app/src/main/java/com/kickstarter/viewmodels/ProjectViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ interface ProjectViewModel {
/** Emits a boolean that determines if the manage pledge menu should be visible. */
fun managePledgeMenuIsVisible(): Observable<Boolean>

/** Emits the url of a prelaunch activated project to open in the browser. */
fun prelaunchUrl(): Observable<String>

/** Emits a project and country when a new value is available. If the view model is created with a full project
* model, this observable will emit that project immediately, and then again when it has updated from the api. */
fun projectAndUserCountry(): Observable<Pair<Project, String>>
Expand Down Expand Up @@ -214,6 +217,7 @@ interface ProjectViewModel {
private val expandPledgeSheet = BehaviorSubject.create<Boolean>()
private val heartDrawableId = BehaviorSubject.create<Int>()
private val managePledgeMenuIsVisible = BehaviorSubject.create<Boolean>()
private val prelaunchUrl = PublishSubject.create<String>()
private val projectAndUserCountry = BehaviorSubject.create<Pair<Project, String>>()
private val revealRewardsFragment = PublishSubject.create<Void>()
private val rewardsButtonColor = BehaviorSubject.create<Int>()
Expand Down Expand Up @@ -244,10 +248,19 @@ interface ProjectViewModel {

init {

val initialProject = intent()
val mappedProject = intent()
.flatMap { i -> ProjectIntentMapper.project(i, this.client) }
.share()

mappedProject
.filter { BooleanUtils.isTrue(it.prelaunchActivated()) }
.map { it.webProjectUrl() }
.compose(bindToLifecycle())
.subscribe(this.prelaunchUrl)

val initialProject = mappedProject
.filter { BooleanUtils.isFalse(it.prelaunchActivated()) }

// An observable of the ref tag stored in the cookie for the project. Can emit `null`.
val cookieRefTag = initialProject
.take(1)
Expand Down Expand Up @@ -651,6 +664,9 @@ interface ProjectViewModel {
@NonNull
override fun managePledgeMenuIsVisible(): Observable<Boolean> = this.managePledgeMenuIsVisible

@NonNull
override fun prelaunchUrl(): Observable<String> = this.prelaunchUrl

@NonNull
override fun projectAndUserCountry(): Observable<Pair<Project, String>> = this.projectAndUserCountry

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.kickstarter.viewmodels

import android.content.Intent
import android.net.Uri
import android.util.Pair
import com.kickstarter.KSRobolectricTestCase
import com.kickstarter.R
Expand All @@ -11,12 +12,14 @@ import com.kickstarter.libs.preferences.BooleanPreferenceType
import com.kickstarter.libs.preferences.MockBooleanPreference
import com.kickstarter.mock.MockCurrentConfig
import com.kickstarter.mock.factories.*
import com.kickstarter.mock.services.MockApiClient
import com.kickstarter.models.Project
import com.kickstarter.models.User
import com.kickstarter.ui.IntentKey
import com.kickstarter.ui.data.PledgeData
import com.kickstarter.ui.data.PledgeReason
import org.junit.Test
import rx.Observable
import rx.observers.TestSubscriber

class ProjectViewModelTest : KSRobolectricTestCase() {
Expand All @@ -26,6 +29,7 @@ class ProjectViewModelTest : KSRobolectricTestCase() {
private val expandPledgeSheet = TestSubscriber<Boolean>()
private val heartDrawableId = TestSubscriber<Int>()
private val managePledgeMenuIsVisible = TestSubscriber<Boolean>()
private val prelaunchUrl = TestSubscriber<String>()
private val projectTest = TestSubscriber<Project>()
private val revealRewardsFragment = TestSubscriber<Void>()
private val rewardsButtonColor = TestSubscriber<Int>()
Expand Down Expand Up @@ -56,6 +60,7 @@ class ProjectViewModelTest : KSRobolectricTestCase() {
this.vm.outputs.expandPledgeSheet().subscribe(this.expandPledgeSheet)
this.vm.outputs.heartDrawableId().subscribe(this.heartDrawableId)
this.vm.outputs.managePledgeMenuIsVisible().subscribe(this.managePledgeMenuIsVisible)
this.vm.outputs.prelaunchUrl().subscribe(this.prelaunchUrl)
this.vm.outputs.projectAndUserCountry().map { pc -> pc.first }.subscribe(this.projectTest)
this.vm.outputs.revealRewardsFragment().subscribe(this.revealRewardsFragment)
this.vm.outputs.rewardsButtonColor().subscribe(this.rewardsButtonColor)
Expand Down Expand Up @@ -93,6 +98,55 @@ class ProjectViewModelTest : KSRobolectricTestCase() {
this.koalaTest.assertValues(KoalaEvent.PROJECT_PAGE, KoalaEvent.VIEWED_PROJECT_PAGE)
}

@Test
fun testEmitsProjectWithDeepLink() {
val project = ProjectFactory.project()
val currentConfig = MockCurrentConfig()
currentConfig.config(ConfigFactory.config())

val environment = environment().toBuilder()
.currentConfig(currentConfig)
.apiClient(object : MockApiClient(){
override fun fetchProject(param: String): Observable<Project> {
return Observable.just(project)
}
})
.build()

setUpEnvironment(environment)
val uri = Uri.parse("https://www.kickstarter.com/projects/1186238668/skull-graphic-tee")
this.vm.intent(Intent(Intent.ACTION_VIEW, uri))

this.projectTest.assertValues(project)
this.prelaunchUrl.assertNoValues()
this.koalaTest.assertValues(KoalaEvent.PROJECT_PAGE, KoalaEvent.VIEWED_PROJECT_PAGE)
}

@Test
fun testEmitsProjectWithDeepLink_preLaunchActivated() {
val url = "https://www.kickstarter.com/projects/1186238668/skull-graphic-tee"
val project = ProjectFactory.prelaunchProject(url)
val currentConfig = MockCurrentConfig()
currentConfig.config(ConfigFactory.config())

val environment = environment().toBuilder()
.currentConfig(currentConfig)
.apiClient(object : MockApiClient(){
override fun fetchProject(param: String): Observable<Project> {
return Observable.just(project)
}
})
.build()

setUpEnvironment(environment)
val uri = Uri.parse(url)
this.vm.intent(Intent(Intent.ACTION_VIEW, uri))

this.projectTest.assertNoValues()
this.prelaunchUrl.assertValue(url)
this.koalaTest.assertNoValues()
}

@Test
fun testLoggedOutStarProjectFlow() {
val currentUser = MockCurrentUser()
Expand Down

0 comments on commit 061d64c

Please sign in to comment.