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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creator tools project switcher #209

Merged
merged 3 commits into from
Feb 6, 2018
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;

import static com.kickstarter.libs.rx.transformers.Transformers.observeForUI;

Expand Down Expand Up @@ -82,6 +83,11 @@ public void back() {
}
}

@OnClick(R.id.creator_dashboard_bottom_sheet_scrim)
protected void bottomSheetScrimClicked() {
hideBottomSheet();
}

@Override
protected void onDestroy() {
super.onDestroy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@
import android.view.View;

import com.kickstarter.R;
import com.kickstarter.models.Empty;
import com.kickstarter.models.Project;
import com.kickstarter.ui.viewholders.CreatorDashboardBottomSheetViewHolder;
import com.kickstarter.ui.viewholders.EmptyViewHolder;
import com.kickstarter.ui.viewholders.KSViewHolder;

import java.util.Collections;
import java.util.List;

public final class CreatorDashboardBottomSheetAdapter extends KSAdapter {
private static final int SECTION_PROJECTS_HEADER = 0;
private static final int SECTION_PROJECTS = 1;

private Delegate delegate;

Expand All @@ -24,17 +29,30 @@ public CreatorDashboardBottomSheetAdapter(final @Nullable Delegate delegate) {

@Override
protected int layout(final @NonNull SectionRow sectionRow) {
return R.layout.creator_dashboard_project_switcher_view;
switch (sectionRow.section()) {
case SECTION_PROJECTS_HEADER:
return R.layout.creator_dashboard_project_switcher_header;
case SECTION_PROJECTS:
return R.layout.creator_dashboard_project_switcher_view;
}
return R.layout.empty_view;
}

@Override
protected @NonNull KSViewHolder viewHolder(final @LayoutRes int layout, final @NonNull View view) {
return new CreatorDashboardBottomSheetViewHolder(view, this.delegate);
switch (layout) {
case R.layout.creator_dashboard_project_switcher_view:
return new CreatorDashboardBottomSheetViewHolder(view, this.delegate);
case R.layout.creator_dashboard_project_switcher_header:
default:
return new EmptyViewHolder(view);
}
}

public void takeProjects(final @NonNull List<Project> projects) {
clearSections();
addSection(projects);
insertSection(SECTION_PROJECTS_HEADER, Collections.singletonList(Empty.get()));
insertSection(SECTION_PROJECTS, projects);
notifyDataSetChanged();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import android.support.v4.content.ContextCompat;
import android.util.Pair;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
Expand Down Expand Up @@ -43,6 +44,7 @@ public final class CreatorDashboardHeaderViewHolder extends KSViewHolder {
protected @Bind(R.id.creator_dashboard_funding_text) TextView fundingTextTextView;
protected @Bind(R.id.creator_dashboard_messages) RelativeLayout messagesButton;
protected @Bind(R.id.creator_dashboard_percent) TextView percentTextView;
protected @Bind(R.id.creator_dashboard_project_selector) Button projectsButton;
protected @Bind(R.id.creator_dashboard_time_remaining) TextView timeRemainingTextView;
protected @Bind(R.id.creator_dashboard_time_remaining_text) TextView timeRemainingTextTextView;

Expand Down Expand Up @@ -82,6 +84,11 @@ public CreatorDashboardHeaderViewHolder(final @NonNull View view, final @Nullabl
.compose(observeForUI())
.subscribe(ViewUtils.setGone(this.messagesButton));

this.viewModel.outputs.otherProjectsButtonIsGone()
.compose(bindToLifecycle())
.compose(observeForUI())
.subscribe(ViewUtils.setGone(this.projectsButton));

this.viewModel.outputs.percentageFunded()
.compose(bindToLifecycle())
.compose(observeForUI())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
import com.kickstarter.libs.Environment;
import com.kickstarter.libs.RefTag;
import com.kickstarter.libs.utils.NumberUtils;
import com.kickstarter.libs.utils.ObjectUtils;
import com.kickstarter.libs.utils.PairUtils;
import com.kickstarter.libs.utils.ProgressBarUtils;
import com.kickstarter.libs.utils.ProjectUtils;
import com.kickstarter.models.Project;
import com.kickstarter.models.User;
import com.kickstarter.services.apiresponses.ProjectStatsEnvelope;
import com.kickstarter.ui.viewholders.CreatorDashboardHeaderViewHolder;

Expand Down Expand Up @@ -42,6 +44,9 @@ interface Outputs {
/** Emits when the messages button should be gone. */
Observable<Boolean> messagesButtonIsGone();

/** Emits when the other projects button should be gone. */
Observable<Boolean> otherProjectsButtonIsGone();

/** string number with the percentage of a projects funding */
Observable<String> percentageFunded();

Expand Down Expand Up @@ -75,10 +80,18 @@ public ViewModel(final @NonNull Environment environment) {

this.currentUser = environment.currentUser();

final Observable<User> user = this.currentUser.observable();

this.otherProjectsButtonIsGone = user
.map(User::createdProjectsCount)
.filter(ObjectUtils::isNotNull)
.map(count -> count <= 1)
.compose(bindToLifecycle());

this.currentProject = this.projectAndStats
.map(PairUtils::first);

this.messagesButtonIsGone = Observable.zip(this.currentProject, this.currentUser.observable(), Pair::create)
this.messagesButtonIsGone = Observable.zip(this.currentProject, user, Pair::create)
.map(projectAndUser -> projectAndUser.first.creator().id() != projectAndUser.second.id());

this.percentageFunded = this.currentProject
Expand Down Expand Up @@ -123,6 +136,7 @@ public ViewModel(final @NonNull Environment environment) {

private final Observable<Project> currentProject;
private final Observable<Boolean> messagesButtonIsGone;
private final Observable<Boolean> otherProjectsButtonIsGone;
private final Observable<String> percentageFunded;
private final Observable<Integer> percentageFundedProgress;
private final Observable<Integer> progressBarBackground;
Expand All @@ -148,6 +162,9 @@ public ViewModel(final @NonNull Environment environment) {
@Override public @NonNull Observable<Boolean> messagesButtonIsGone() {
return this.messagesButtonIsGone;
}
@Override public @NonNull Observable<Boolean> otherProjectsButtonIsGone() {
return this.otherProjectsButtonIsGone;
}
@Override public @NonNull Observable<String> percentageFunded() {
return this.percentageFunded;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,14 @@ public ViewModel(final @NonNull Environment environment) {
final Observable<ProjectStatsEnvelope> projectStatsEnvelope = projectStatsEnvelopeNotification
.compose(values());

this.projectsForBottomSheet = projects;
this.projectsForBottomSheet = Observable.combineLatest(
projects.filter(projectList -> projectList.size() > 1),
this.projectSelected,
(projectList, project) -> Observable
.from(projectList)
.filter(p -> p.id() != project.id())
.toList())
.flatMap(listObservable -> listObservable);

this.projectSelected
.compose(combineLatestPair(projectStatsEnvelope))
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/layout/creator_dashboard_layout.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black_alpha_17"
android:clickable="true"
android:fitsSystemWindows="true"
android:visibility="gone" />

<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_marginTop="?attr/actionBarSize"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView
style="@style/CalloutSecondary"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/grid_1"
android:paddingEnd="@dimen/grid_3"
android:paddingStart="@dimen/grid_3"
android:paddingTop="@dimen/grid_3"
android:text="@string/Select_another_project" />
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/click_indicator_light"
android:background="@drawable/click_indicator_light_masked"
android:orientation="vertical"
android:padding="@dimen/grid_3">

Expand Down
5 changes: 5 additions & 0 deletions app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,11 @@
<item name="android:fontFamily">@string/font_family_sans_serif_medium</item>
</style>

<style name="CalloutSecondary" parent="TextSecondary">
<item name="android:textSize">@dimen/callout</item>
<item name="android:lineSpacingExtra">@dimen/callout_line_spacing_extra</item>
</style>

<style name="CalloutSecondaryMedium" parent="TextSecondary">
<item name="android:textSize">@dimen/callout</item>
<item name="android:lineSpacingExtra">@dimen/callout_line_spacing_extra</item>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class CreatorDashboardHeaderHolderViewModelTest extends KSRobolectricTest
private CreatorDashboardHeaderHolderViewModel.ViewModel vm;

private final TestSubscriber<Boolean> messagesButtonIsGone = new TestSubscriber<>();
private final TestSubscriber<Boolean> otherProjectsButtonIsGone = new TestSubscriber<>();
private final TestSubscriber<String> percentageFunded = new TestSubscriber<>();
private final TestSubscriber<Integer> percentageFundedProgress = new TestSubscriber<>();
private final TestSubscriber<String> projectBackersCountText = new TestSubscriber<>();
Expand All @@ -40,6 +41,7 @@ public class CreatorDashboardHeaderHolderViewModelTest extends KSRobolectricTest
protected void setUpEnvironment(final @NonNull Environment environment) {
this.vm = new CreatorDashboardHeaderHolderViewModel.ViewModel(environment);
this.vm.outputs.messagesButtonIsGone().subscribe(this.messagesButtonIsGone);
this.vm.outputs.otherProjectsButtonIsGone().subscribe(this.otherProjectsButtonIsGone);
this.vm.outputs.projectBackersCountText().subscribe(this.projectBackersCountText);
this.vm.outputs.projectNameTextViewText().subscribe(this.projectNameTextViewText);
this.vm.outputs.percentageFunded().subscribe(this.percentageFunded);
Expand All @@ -65,6 +67,27 @@ public void testMessagesButtonIsGone() {
this.messagesButtonIsGone.assertValues(true);
}

@Test
public void testOtherProjectsButtonIsGone_WhenCreatorHas1Project() {
final User creatorWith1Project = UserFactory.creator().toBuilder().createdProjectsCount(1).build();
final CurrentUserType creator = new MockCurrentUser(creatorWith1Project);

setUpEnvironment(environment().toBuilder().currentUser(creator).build());
this.vm.inputs.projectAndStats(Pair.create(ProjectFactory.project(), ProjectStatsEnvelopeFactory.projectStatsEnvelope()));

this.otherProjectsButtonIsGone.assertValues(true);
}

@Test
public void testOtherProjectsButtonIsGone_WhenCreatorHasManyProjects() {
final CurrentUserType creator = new MockCurrentUser(UserFactory.creator());

setUpEnvironment(environment().toBuilder().currentUser(creator).build());
this.vm.inputs.projectAndStats(Pair.create(ProjectFactory.project(), ProjectStatsEnvelopeFactory.projectStatsEnvelope()));

this.otherProjectsButtonIsGone.assertValues(false);
}

@Test
public void testProjectBackersCountText() {
final Project project = ProjectFactory.project().toBuilder().backersCount(10).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@
import com.kickstarter.libs.RefTag;
import com.kickstarter.libs.utils.ListUtils;
import com.kickstarter.models.Project;
import com.kickstarter.services.apiresponses.ProjectStatsEnvelope;
import com.kickstarter.services.MockApiClient;
import com.kickstarter.services.apiresponses.ProjectStatsEnvelope;
import com.kickstarter.services.apiresponses.ProjectsEnvelope;

import org.junit.Test;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import rx.Observable;
Expand All @@ -42,9 +43,7 @@ protected void setUpEnvironment(final @NonNull Environment environment) {

@Test
public void testStartProjectActivity() {
final List<Project> projects = Arrays.asList(
ProjectFactory.project()
);
final List<Project> projects = Collections.singletonList(ProjectFactory.project());

final MockApiClient apiClient = new MockApiClient() {
@Override public @NonNull
Expand All @@ -54,35 +53,49 @@ Observable<ProjectsEnvelope> fetchProjects(final boolean member) {
};
setUpEnvironment(environment().toBuilder().apiClient(apiClient).build());
this.vm.inputs.projectViewClicked();
this.startProjectActivity.assertValues(Pair.create(ListUtils.first(projects), RefTag.dashboard()));
this.startProjectActivity.assertValue(Pair.create(ListUtils.first(projects), RefTag.dashboard()));
}

@Test
public void testProjectAndStats() {
final List<Project> projects = Arrays.asList(
ProjectFactory.project()
);
final List<Project> projects = Collections.singletonList(ProjectFactory.project());

final ProjectStatsEnvelope ProjectStatsEnvelope = ProjectStatsEnvelopeFactory.projectStatsEnvelope();
final MockApiClient apiClient = new MockApiClient() {
@Override public @NonNull Observable<ProjectsEnvelope> fetchProjects(final boolean member) {
return Observable.just(ProjectsEnvelopeFactory.projectsEnvelope(projects));
}
@Override public @NonNull
Observable<ProjectStatsEnvelope> fetchProjectStats(final Project project) {
Observable<ProjectStatsEnvelope> fetchProjectStats(final @NonNull Project project) {
return Observable.just(ProjectStatsEnvelope);
}
};

setUpEnvironment(environment().toBuilder().apiClient(apiClient).build());
final Pair<Project, ProjectStatsEnvelope> outputPair = Pair.create(ListUtils.first(projects), ProjectStatsEnvelope);
this.projectAndStats.assertValues(outputPair);
this.projectAndStats.assertValue(outputPair);
}

@Test
public void testProjectsForBottomSheet_With1Project() {
final List<Project> projects = Collections.singletonList(ProjectFactory.project());
final MockApiClient apiClient = new MockApiClient() {
@Override public @NonNull
Observable<ProjectsEnvelope> fetchProjects(final boolean member) {
return Observable.just(ProjectsEnvelopeFactory.projectsEnvelope(projects));
}
};
setUpEnvironment(environment().toBuilder().apiClient(apiClient).build());
this.projectsForBottomSheet.assertNoValues();
}

@Test
public void testProjectsForBottomSheet() {
public void testProjectsForBottomSheet_WithManyProjects() {
final Project project1 = ProjectFactory.project();
final Project project2 = ProjectFactory.project();
final List<Project> projects = Arrays.asList(
ProjectFactory.project()
project1,
project2
);
final MockApiClient apiClient = new MockApiClient() {
@Override public @NonNull
Expand All @@ -91,15 +104,13 @@ Observable<ProjectsEnvelope> fetchProjects(final boolean member) {
}
};
setUpEnvironment(environment().toBuilder().apiClient(apiClient).build());
this.projectsForBottomSheet.assertValues(projects);
this.projectsForBottomSheet.assertValue(Collections.singletonList(project2));
}

@Test
public void testProjectSwitcherProjectClickOutput() {
final Project project = ProjectFactory.project();
final List<Project> projects = Arrays.asList(
ProjectFactory.project()
);
final List<Project> projects = Collections.singletonList(ProjectFactory.project());
final MockApiClient apiClient = new MockApiClient() {
@Override public @NonNull
Observable<ProjectsEnvelope> fetchProjects(final boolean member) {
Expand Down