diff --git a/art/icons/ic_launcher/web_hi_res.svg b/art/icons/ic_launcher/web_hi_res.svg new file mode 100644 index 00000000..be6b5b9a --- /dev/null +++ b/art/icons/ic_launcher/web_hi_res.svg @@ -0,0 +1,37 @@ + + + + +Created by potrace 1.15, written by Peter Selinger 2001-2017 + + + + + + + + + + + diff --git a/build.gradle b/build.gradle index 3a5cba21..33abb31b 100644 --- a/build.gradle +++ b/build.gradle @@ -87,13 +87,19 @@ android { } } } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } } dependencies { + implementation 'com.android.support:support-v4:26.0.2' + //implementation 'com.android.support:appcompat-v7:26.0.2' + implementation 'com.android.support:design:26.0.2' + implementation 'com.google.zxing:android-integration:3.3.0' + implementation 'com.google.code.gson:gson:2.8.1' + implementation 'com.google.dagger:dagger:2.11' + + annotationProcessor 'com.google.dagger:dagger-compiler:2.11' + androidTestAnnotationProcessor 'com.google.dagger:dagger-compiler:2.11' + testImplementation 'junit:junit:4.12' testImplementation 'org.hamcrest:hamcrest-all:1.3' testImplementation 'org.mockito:mockito-all:1.10.19' @@ -103,17 +109,17 @@ dependencies { exclude module: 'commons-logging' exclude module: 'httpclient' } - androidTestImplementation 'com.android.support:support-annotations:26.0.1' + androidTestImplementation 'com.android.support:support-annotations:26.0.2' androidTestImplementation 'com.android.support.test:runner:1.0.1' androidTestImplementation 'com.android.support.test:rules:1.0.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' + androidTestImplementation('com.android.support.test.espresso:espresso-contrib:3.0.1') { + exclude module: 'support-v4' + exclude module: 'recyclerview-v7' + exclude module: 'appcompat-v7' + exclude module: 'design' + } androidTestUtil 'com.android.support.test:orchestrator:1.0.1' - implementation 'com.google.code.gson:gson:2.8.1' - implementation 'com.android.support:support-v4:26.0.1' - implementation 'com.google.zxing:android-integration:3.3.0' - implementation 'com.google.dagger:dagger:2.11' - annotationProcessor 'com.google.dagger:dagger-compiler:2.11' - androidTestAnnotationProcessor 'com.google.dagger:dagger-compiler:2.11' } versioneye { diff --git a/src/androidTest/java/de/avalax/fitbuddy/MainActivityTest.java b/src/androidTest/java/de/avalax/fitbuddy/FitbuddyAcceptanceTest.java similarity index 70% rename from src/androidTest/java/de/avalax/fitbuddy/MainActivityTest.java rename to src/androidTest/java/de/avalax/fitbuddy/FitbuddyAcceptanceTest.java index bcf4c905..eea40ad6 100644 --- a/src/androidTest/java/de/avalax/fitbuddy/MainActivityTest.java +++ b/src/androidTest/java/de/avalax/fitbuddy/FitbuddyAcceptanceTest.java @@ -4,6 +4,7 @@ import android.support.test.filters.LargeTest; import android.support.test.runner.AndroidJUnit4; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -19,11 +20,13 @@ import static android.support.test.espresso.matcher.ViewMatchers.isEnabled; import static android.support.test.espresso.matcher.ViewMatchers.withId; import static android.support.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.CoreMatchers.not; +import static de.avalax.fitbuddy.runner.BottomNavigationMatcher.bottomNavItemIsChecked; +import static de.avalax.fitbuddy.runner.BottomNavigationMatcher.bottomNavItemIsNotChecked; @RunWith(AndroidJUnit4.class) @LargeTest -public class MainActivityTest { +public class FitbuddyAcceptanceTest { + private int actionBarTitleId() { Resources resources = activityRule.getActivity().getResources(); return resources.getIdentifier("action_bar_title", "id", "android"); @@ -34,6 +37,16 @@ private int actionBarTitleId() { MainActivity.class); @Test + public void initialStart_shouldShowStartFragmentOnly() throws Exception { + activityRule.launchActivity(); + + onView(withId(R.id.navigation_start_item)).check(matches(bottomNavItemIsChecked())); + onView(withId(R.id.navigation_workout_item)).check(matches(bottomNavItemIsNotChecked())); + onView(withId(R.id.navigation_statistics_item)).check(matches(bottomNavItemIsNotChecked())); + } + + @Test + @Ignore public void switchedToWorkout_shouldShowWorkoutActivity() throws Exception { BasicWorkout workout = new BasicWorkout(); Exercise exercise = workout.getExercises().createExercise(); @@ -43,18 +56,9 @@ public void switchedToWorkout_shouldShowWorkoutActivity() throws Exception { activityRule.launchActivity(); - onView(withId(R.id.continue_workout_button)).check(matches(isEnabled())); - onView(withId(R.id.continue_workout_button)).perform(click()); + onView(withId(R.id.navigation_start_item)).check(matches(isEnabled())); + onView(withId(R.id.navigation_start_item)).perform(click()); onView(withId(actionBarTitleId())).check(matches(withText("first_exercise"))); } - - @Test - public void noWorkoutCreated_shouldShowMainActivity() throws Exception { - activityRule.getWorkoutSession().switchWorkout(null); - - activityRule.launchActivity(); - - onView(withId(R.id.continue_workout_button)).check(matches(not(isEnabled()))); - } } diff --git a/src/androidTest/java/de/avalax/fitbuddy/runner/BottomNavigationMatcher.java b/src/androidTest/java/de/avalax/fitbuddy/runner/BottomNavigationMatcher.java new file mode 100644 index 00000000..4b1f47e7 --- /dev/null +++ b/src/androidTest/java/de/avalax/fitbuddy/runner/BottomNavigationMatcher.java @@ -0,0 +1,40 @@ +package de.avalax.fitbuddy.runner; + +import android.annotation.SuppressLint; +import android.support.design.internal.BottomNavigationItemView; +import android.support.test.espresso.matcher.BoundedMatcher; +import android.view.View; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; + +public class BottomNavigationMatcher { + public static Matcher bottomNavItemIsChecked() { + return withBottomNavItemCheckedStatus(true); + } + + public static Matcher bottomNavItemIsNotChecked() { + return withBottomNavItemCheckedStatus(false); + } + + private static Matcher withBottomNavItemCheckedStatus(final boolean isChecked) { + return new BoundedMatcher(BottomNavigationItemView.class) { + boolean triedMatching; + + @Override + public void describeTo(Description description) { + if (triedMatching) { + description.appendText("with BottomNavigationItem check status: " + String.valueOf(isChecked)); + description.appendText("But was: " + String.valueOf(!isChecked)); + } + } + + @SuppressLint("RestrictedApi") + @Override + protected boolean matchesSafely(BottomNavigationItemView item) { + triedMatching = true; + return item.getItemData().isChecked() == isChecked; + } + }; + } +} diff --git a/src/androidTest/java/de/avalax/fitbuddy/runner/FitbuddyActivityTestRule.java b/src/androidTest/java/de/avalax/fitbuddy/runner/FitbuddyActivityTestRule.java index 3485edbe..bde27657 100644 --- a/src/androidTest/java/de/avalax/fitbuddy/runner/FitbuddyActivityTestRule.java +++ b/src/androidTest/java/de/avalax/fitbuddy/runner/FitbuddyActivityTestRule.java @@ -6,6 +6,7 @@ import javax.inject.Inject; import de.avalax.fitbuddy.application.workout.WorkoutSession; +import de.avalax.fitbuddy.domain.model.workout.WorkoutRepository; import de.avalax.fitbuddy.presentation.MainActivity; import static de.avalax.fitbuddy.runner.TestFitbuddyApplication.TestComponent; @@ -15,6 +16,9 @@ public class FitbuddyActivityTestRule extends ActivityTestRule { @Inject WorkoutSession workoutSession; + @Inject + WorkoutRepository workoutRepository; + public FitbuddyActivityTestRule(Class activityClass) { super(activityClass); } @@ -30,6 +34,10 @@ public WorkoutSession getWorkoutSession() { return workoutSession; } + public void setWorkoutRepository(WorkoutRepository workoutRepository) { + this.workoutRepository = workoutRepository; + } + public MainActivity launchActivity() { return super.launchActivity(new Intent()); } diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 9f48790b..d8c6adca 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -22,7 +22,16 @@ - + + + + + + + + + + diff --git a/src/main/java/de/avalax/fitbuddy/presentation/MainActivity.java b/src/main/java/de/avalax/fitbuddy/presentation/MainActivity.java index da5755fd..f60a07c6 100644 --- a/src/main/java/de/avalax/fitbuddy/presentation/MainActivity.java +++ b/src/main/java/de/avalax/fitbuddy/presentation/MainActivity.java @@ -1,23 +1,28 @@ package de.avalax.fitbuddy.presentation; -import android.content.Intent; import android.os.Bundle; -import android.support.v4.app.FragmentActivity; -import android.view.View; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.Menu; import de.avalax.fitbuddy.R; -import de.avalax.fitbuddy.presentation.workout.WorkoutActivity; -public class MainActivity extends FragmentActivity { +public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + + Toolbar toolbar = findViewById(R.id.app_bar); + setSupportActionBar(toolbar); } - public void continueWorkout(View view) { - Intent intent = new Intent(this, WorkoutActivity.class); - startActivity(intent); + // Menu icons are inflated just as they were with actionbar + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.menu_main, menu); + return true; } } diff --git a/src/main/java/de/avalax/fitbuddy/presentation/welcome_screen/WelcomeScreenFragment.java b/src/main/java/de/avalax/fitbuddy/presentation/welcome_screen/WelcomeScreenFragment.java index b267e31d..11455812 100644 --- a/src/main/java/de/avalax/fitbuddy/presentation/welcome_screen/WelcomeScreenFragment.java +++ b/src/main/java/de/avalax/fitbuddy/presentation/welcome_screen/WelcomeScreenFragment.java @@ -27,8 +27,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, } private void init(View view) { - View continueWorkoutButton = view.findViewById(R.id.continue_workout_button); - continueWorkoutButton.setEnabled(workoutSession.hasWorkout()); + } diff --git a/src/main/res/drawable/ic_menu_home.xml b/src/main/res/drawable/ic_menu_home.xml new file mode 100644 index 00000000..70fb2910 --- /dev/null +++ b/src/main/res/drawable/ic_menu_home.xml @@ -0,0 +1,9 @@ + + + diff --git a/src/main/res/drawable/ic_menu_summary.xml b/src/main/res/drawable/ic_menu_summary.xml new file mode 100644 index 00000000..05f2dd41 --- /dev/null +++ b/src/main/res/drawable/ic_menu_summary.xml @@ -0,0 +1,9 @@ + + + diff --git a/src/main/res/drawable/ic_menu_support.xml b/src/main/res/drawable/ic_menu_support.xml new file mode 100644 index 00000000..922fe7fa --- /dev/null +++ b/src/main/res/drawable/ic_menu_support.xml @@ -0,0 +1,9 @@ + + + diff --git a/src/main/res/drawable/ic_menu_workout.xml b/src/main/res/drawable/ic_menu_workout.xml new file mode 100644 index 00000000..7e422f03 --- /dev/null +++ b/src/main/res/drawable/ic_menu_workout.xml @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/src/main/res/drawable/navigation_colors.xml b/src/main/res/drawable/navigation_colors.xml new file mode 100644 index 00000000..4f6adc4a --- /dev/null +++ b/src/main/res/drawable/navigation_colors.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/src/main/res/layout/activity_main.xml b/src/main/res/layout/activity_main.xml index c1a624ce..5d062fea 100644 --- a/src/main/res/layout/activity_main.xml +++ b/src/main/res/layout/activity_main.xml @@ -1,14 +1,37 @@ - + android:layout_height="match_parent"> + - + + + + + + + + + diff --git a/src/main/res/layout/fragment_welcome_screen.xml b/src/main/res/layout/fragment_welcome_screen.xml index 69dce50e..5ade9f33 100644 --- a/src/main/res/layout/fragment_welcome_screen.xml +++ b/src/main/res/layout/fragment_welcome_screen.xml @@ -1,12 +1,9 @@ - - -