From bbf9a5c2bc611b8aa995b9e385edf427ad51caca Mon Sep 17 00:00:00 2001 From: nbau21 Date: Sat, 4 Mar 2017 23:57:26 -0800 Subject: [PATCH 1/8] Initial pass at tablet layout * Move fab from activity to fragment * Make tests more lenient, some tests we checking for unnecessary criteria like withParent, when we're guaranteed to have only one instance of a certain view per screen (like fab, list) --- .../notes/StarterActivityTest.java | 34 ++++----------- .../org/standardnotes/notes/MainActivity.kt | 16 +------ .../notes/frag/NoteListFragment.kt | 17 ++++++++ app/src/main/res/layout/activity_main.xml | 7 ---- app/src/main/res/layout/frag_note_list.xml | 42 +++++++++++++------ 5 files changed, 54 insertions(+), 62 deletions(-) diff --git a/app/src/androidTest/java/org/standardnotes/notes/StarterActivityTest.java b/app/src/androidTest/java/org/standardnotes/notes/StarterActivityTest.java index 7c99e87..49b2bdc 100644 --- a/app/src/androidTest/java/org/standardnotes/notes/StarterActivityTest.java +++ b/app/src/androidTest/java/org/standardnotes/notes/StarterActivityTest.java @@ -113,11 +113,8 @@ public void logout() { @Test public void createNote() { - ViewInteraction floatingActionButton = onView( - allOf(withId(R.id.fab), - withParent(allOf(withId(R.id.rootView), - withParent(withId(R.id.drawer_layout)))), - isDisplayed())); + + ViewInteraction floatingActionButton = onView(allOf(withId(R.id.fab), isDisplayed())); floatingActionButton.perform(click()); ViewInteraction appCompatEditText = onView( @@ -139,10 +136,7 @@ public void createNote() { upButton.perform(click()); ViewInteraction recyclerView = onView( - allOf(withId(R.id.list), - withParent(allOf(withId(R.id.noteListFrag), - withParent(withId(R.id.rootView)))), - isDisplayed())); + allOf(withId(R.id.list), isDisplayed())); recyclerView.perform(actionOnItemAtPosition(0, click())); ViewInteraction actionMenuItemView = onView( @@ -188,11 +182,7 @@ public void justSignInAndOut() { @Test public void tagSomething() { - ViewInteraction floatingActionButton = onView( - allOf(withId(R.id.fab), - withParent(allOf(withId(R.id.rootView), - withParent(withId(R.id.drawer_layout)))), - isDisplayed())); + ViewInteraction floatingActionButton = onView(allOf(withId(R.id.fab), isDisplayed())); floatingActionButton.perform(click()); ViewInteraction appCompatEditText = onView( @@ -235,10 +225,7 @@ public void tagSomething() { signupin(); ViewInteraction recyclerView = onView( - allOf(withId(R.id.list), - withParent(allOf(withId(R.id.noteListFrag), - withParent(withId(R.id.rootView)))), - isDisplayed())); + allOf(withId(R.id.list), isDisplayed())); recyclerView.perform(actionOnItemAtPosition(0, click())); onView(withText("tag1")).check(matches(isDisplayed())); @@ -266,11 +253,7 @@ public void tagSomething() { @Test public void openCloseOpenClose() { - ViewInteraction floatingActionButton = onView( - allOf(withId(R.id.fab), - withParent(allOf(withId(R.id.rootView), - withParent(withId(R.id.drawer_layout)))), - isDisplayed())); + ViewInteraction floatingActionButton = onView(allOf(withId(R.id.fab), isDisplayed())); floatingActionButton.perform(click()); ViewInteraction appCompatEditText = onView( @@ -287,10 +270,7 @@ public void openCloseOpenClose() { pressBack(); ViewInteraction recyclerView = onView( - allOf(withId(R.id.list), - withParent(allOf(withId(R.id.noteListFrag), - withParent(withId(R.id.rootView)))), - isDisplayed())); + allOf(withId(R.id.list), isDisplayed())); recyclerView.perform(actionOnItemAtPosition(0, click())); pressBack(); recyclerView.perform(actionOnItemAtPosition(0, click())); diff --git a/app/src/main/java/org/standardnotes/notes/MainActivity.kt b/app/src/main/java/org/standardnotes/notes/MainActivity.kt index 6d32c20..621f01b 100644 --- a/app/src/main/java/org/standardnotes/notes/MainActivity.kt +++ b/app/src/main/java/org/standardnotes/notes/MainActivity.kt @@ -55,20 +55,6 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener { header.main_account_email.text = values.email title = getString(R.string.app_name) - - var lastX: Int? = null - var lastY: Int? = null - fab.setOnTouchListener({ v, event -> - if (event.action == MotionEvent.ACTION_UP) { - lastX = event.rawX.toInt() - lastY = event.rawY.toInt() - } - false - }) - fab.setOnClickListener { view -> - noteListFragment().startNewNote(lastX!!, lastY!!, selectedTagId) - } - } fun noteListFragment(): NoteListFragment { @@ -82,7 +68,7 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener { drawer_layout.closeDrawers() selectedTagId = uuid updateTagsMenu() - noteListFragment().refreshNotesForTag(selectedTagId) + noteListFragment().refreshNotesForTag(selectedTagId) // TODO replace with some kind of listener return@setOnMenuItemClickListener true } } diff --git a/app/src/main/java/org/standardnotes/notes/frag/NoteListFragment.kt b/app/src/main/java/org/standardnotes/notes/frag/NoteListFragment.kt index 37d8bf9..4a3e3cf 100644 --- a/app/src/main/java/org/standardnotes/notes/frag/NoteListFragment.kt +++ b/app/src/main/java/org/standardnotes/notes/frag/NoteListFragment.kt @@ -15,6 +15,7 @@ import android.view.View import android.view.ViewGroup import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.frag_note_list.* +import kotlinx.android.synthetic.main.frag_note_list.view.* import kotlinx.android.synthetic.main.item_note.view.* import org.joda.time.format.DateTimeFormat import org.standardnotes.notes.NoteActivity @@ -31,6 +32,7 @@ class NoteListFragment : Fragment(), SyncManager.SyncListener { var notes = ArrayList() var tagId = "" + var selectedTagId = "" var currentSnackbar: Snackbar? = null @@ -48,12 +50,27 @@ class NoteListFragment : Fragment(), SyncManager.SyncListener { super.onCreate(savedInstanceState) if (savedInstanceState != null) { tagId = savedInstanceState.getString("tagId") + selectedTagId = savedInstanceState.getString("tag") } } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = inflater.inflate(R.layout.frag_note_list, container, false) + + var lastX: Int? = null + var lastY: Int? = null + view.fab.setOnTouchListener({ v, event -> + if (event.action == MotionEvent.ACTION_UP) { + lastX = event.rawX.toInt() + lastY = event.rawY.toInt() + } + false + }) + view.fab.setOnClickListener { view -> + startNewNote(lastX!!, lastY!!, selectedTagId) + } + return view } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index ed21f01..7d1f1d1 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -33,13 +33,6 @@ android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" class="org.standardnotes.notes.frag.NoteListFragment" /> - - - - + android:layout_height="match_parent"> + + + + + + + + From f216333fbb73bd6fb78ca88e1176ddfb13f26a7b Mon Sep 17 00:00:00 2001 From: nbau21 Date: Sun, 5 Mar 2017 17:08:41 -0800 Subject: [PATCH 2/8] Fix broken tests * Rename some things (list, fab) because these names are used in different places but refer to different things. This can confuse people and intellij when refactoring or renaming. * Moving the fab (for adding new notes) to a menu item for tablets makes sense from a UI perspective. The fab would be either on the note list (on the left side) or on top of the note fragment (on the right). The first option doesn't make sense, because the fab is supposed to be accessible. The second option doesn't make sense because it covers the note fragment. My compromise is to add it as a menu item when space permits. --- .../notes/StarterActivityForLargeLayout.java | 254 ++++++++++++++++++ .../notes/StarterActivityTest.java | 87 ++---- .../org/standardnotes/notes/TestHelper.java | 31 +++ app/src/main/AndroidManifest.xml | 5 - .../org/standardnotes/notes/MainActivity.kt | 58 ++-- .../org/standardnotes/notes/NoteActivity.kt | 105 -------- .../standardnotes/notes/StarterActivity.kt | 2 +- .../standardnotes/notes/TagListActivity.kt | 8 +- .../standardnotes/notes/frag/NoteFragment.kt | 8 +- .../notes/frag/NoteListFragment.kt | 99 ++++--- .../layout-sw600dp-land/frag_note_list.xml | 24 ++ app/src/main/res/layout/activity_main.xml | 8 +- app/src/main/res/layout/activity_tags.xml | 4 +- app/src/main/res/layout/frag_note.xml | 22 +- app/src/main/res/layout/frag_note_list.xml | 4 +- .../main/res/layout/single_pane_container.xml | 8 + .../main/res/layout/two_pane_container.xml | 22 ++ .../main/res/menu-sw600dp-land/note_list.xml | 10 + app/src/main/res/menu/logged_in.xml | 2 + app/src/main/res/menu/note.xml | 1 + app/src/main/res/menu/note_list.xml | 4 + app/src/main/res/values-sw600dp-land/refs.xml | 4 + app/src/main/res/values/refs.xml | 4 + app/src/main/res/values/strings.xml | 1 + 24 files changed, 510 insertions(+), 265 deletions(-) create mode 100644 app/src/androidTest/java/org/standardnotes/notes/StarterActivityForLargeLayout.java create mode 100644 app/src/androidTest/java/org/standardnotes/notes/TestHelper.java delete mode 100644 app/src/main/java/org/standardnotes/notes/NoteActivity.kt create mode 100644 app/src/main/res/layout-sw600dp-land/frag_note_list.xml create mode 100644 app/src/main/res/layout/single_pane_container.xml create mode 100644 app/src/main/res/layout/two_pane_container.xml create mode 100644 app/src/main/res/menu-sw600dp-land/note_list.xml create mode 100644 app/src/main/res/menu/note_list.xml create mode 100644 app/src/main/res/values-sw600dp-land/refs.xml create mode 100644 app/src/main/res/values/refs.xml diff --git a/app/src/androidTest/java/org/standardnotes/notes/StarterActivityForLargeLayout.java b/app/src/androidTest/java/org/standardnotes/notes/StarterActivityForLargeLayout.java new file mode 100644 index 0000000..01a1f3b --- /dev/null +++ b/app/src/androidTest/java/org/standardnotes/notes/StarterActivityForLargeLayout.java @@ -0,0 +1,254 @@ +package org.standardnotes.notes; + + +import android.content.Intent; +import android.support.test.espresso.Espresso; +import android.support.test.espresso.IdlingResource; +import android.support.test.espresso.ViewInteraction; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; +import android.test.suitebuilder.annotation.LargeTest; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.UUID; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.Espresso.pressBack; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard; +import static android.support.test.espresso.action.ViewActions.replaceText; +import static android.support.test.espresso.action.ViewActions.scrollTo; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withParent; +import static android.support.test.espresso.matcher.ViewMatchers.withText; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.anyOf; +import static org.hamcrest.Matchers.not; +import static org.standardnotes.notes.TestHelper.childAtPosition; + +@LargeTest +@RunWith(AndroidJUnit4.class) +public class StarterActivityForLargeLayout { + + @Rule + public ActivityTestRule mActivityTestRule = new ActivityTestRule<>(LoginActivity.class); + + static String email = UUID.randomUUID().toString(); + static boolean signedup = false; + + @Before + public void signupin() { + mActivityTestRule.launchActivity(new Intent()); + IdlingResource idlingResource = new ProgressIdlingResource(mActivityTestRule.getActivity()); + Espresso.registerIdlingResources(idlingResource); + + if (!SApplication.Companion.getInstance().getValueStore().getServer().contains("staging")) { + throw new RuntimeException("These tests add lots of test users - don't run against a live server."); + } + + ViewInteraction appCompatAutoCompleteTextView = onView( + withId(R.id.email)); + appCompatAutoCompleteTextView.perform(scrollTo(), click()); + + ViewInteraction appCompatAutoCompleteTextView3 = onView( + withId(R.id.email)); + appCompatAutoCompleteTextView3.perform(scrollTo(), replaceText(email), closeSoftKeyboard()); + + ViewInteraction appCompatEditText = onView( + withId(R.id.password)); + appCompatEditText.perform(scrollTo(), replaceText("aaa"), closeSoftKeyboard()); + + if (!signedup) { + ViewInteraction appCompatButton = onView( + allOf(withText("Register"), + withParent(allOf(withId(R.id.email_login_form), + withParent(withId(R.id.login_form)))))); + appCompatButton.perform(scrollTo(), click()); + + ViewInteraction appCompatEditText2 = onView( + allOf(withId(R.id.confirm_password), isDisplayed())); + appCompatEditText2.perform(replaceText("aaa"), closeSoftKeyboard()); + + ViewInteraction appCompatButton2 = onView( + allOf(withId(android.R.id.button1), withText("OK"))); + appCompatButton2.perform(scrollTo(), click()); + signedup = true; + } else { + onView( + allOf(withText("Sign in"))).perform(click()); + } + + Espresso.unregisterIdlingResources(idlingResource); + } + + @After + public void logout() { + ViewInteraction actionMenuItemView = onView(allOf(withId(R.id.settings), isDisplayed())); + actionMenuItemView.perform(click()); + + ViewInteraction appCompatButton = onView( + allOf(withId(R.id.logout), withText("Log out"))); + appCompatButton.perform(scrollTo(), click()); + } + + @Test + public void createNote() { + ViewInteraction newNoteButton = onView(anyOf(withId(R.id.fab_new_note), withId(R.id.new_note))); + newNoteButton.perform(click()); + + ViewInteraction appCompatEditText = onView( + withId(R.id.titleEdit)); + appCompatEditText.perform(scrollTo(), click()); + + ViewInteraction appCompatEditText2 = onView( + withId(R.id.titleEdit)); + appCompatEditText2.perform(scrollTo(), replaceText("Title1"), closeSoftKeyboard()); + + ViewInteraction appCompatEditText14 = onView( + allOf(withId(R.id.bodyEdit))); + appCompatEditText14.perform(scrollTo(), replaceText("body1"), closeSoftKeyboard()); + + ViewInteraction actionMenuItemView = onView( + allOf(withId(R.id.tags), withContentDescription("Tags"), isDisplayed())); + actionMenuItemView.perform(click()); + + pressBack(); + + appCompatEditText14.perform(replaceText("body1a"), closeSoftKeyboard()); + + // Not sure why adding this delay works, not a good solution. + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + ViewInteraction textView = onView( + allOf(withId(R.id.text), withText("body1a"), + childAtPosition( + childAtPosition( + withId(R.id.list_note), + 0), + 1), + isDisplayed())); + textView.check(matches(withText("body1a"))); + + ViewInteraction textView2 = onView( + allOf(withId(R.id.title), withText("Title1"), + childAtPosition( + childAtPosition( + withId(R.id.list_note), + 0), + 0), + isDisplayed())); + textView2.check(matches(withText("Title1"))); + + logout(); + signupin(); + + textView2.check(matches(withText("Title1"))); + textView.check(matches(withText("body1a"))); + } + + @Test + public void tagSomething() { + ViewInteraction newNoteButton = onView(anyOf(withId(R.id.fab_new_note), withId(R.id.new_note))); + newNoteButton.perform(click()); + + ViewInteraction appCompatEditText = onView( + withId(R.id.titleEdit)); + appCompatEditText.perform(scrollTo(), click()); + + ViewInteraction appCompatEditText2 = onView( + withId(R.id.titleEdit)); + appCompatEditText2.perform(scrollTo(), replaceText("Title2"), closeSoftKeyboard()); + + ViewInteraction appCompatEditText14 = onView( + allOf(withId(R.id.bodyEdit))); + appCompatEditText14.perform(scrollTo(), replaceText("body2"), closeSoftKeyboard()); + + ViewInteraction tagsAction = onView( + allOf(withId(R.id.tags), withContentDescription("Tags"), isDisplayed())); + tagsAction.perform(click()); + onView(withId(R.id.fab_new_tag)).perform(click()); + onView( + allOf(withId(R.id.tag), isDisplayed())).perform(replaceText("tag1"), closeSoftKeyboard()); + onView( + allOf(withId(android.R.id.button1), withText("OK"))).perform(scrollTo(), click()); + onView(withId(R.id.fab_new_tag)).perform(click()); + onView( + allOf(withId(R.id.tag), isDisplayed())).perform(replaceText("tag2"), closeSoftKeyboard()); + onView( + allOf(withId(android.R.id.button1), withText("OK"))).perform(scrollTo(), click()); + onView( + withText("tag1")).perform(click()); + + pressBack(); + + logout(); + signupin(); + + ViewInteraction recyclerView = onView( + allOf(withId(R.id.list_note), isDisplayed())); + recyclerView.perform(actionOnItemAtPosition(0, click())); + onView(allOf(withText("tag1"), withId(R.id.tagText))).check(matches(isDisplayed())); + + tagsAction.perform(click()); + onView( + withText("tag1")).perform(click()); // deselect + onView( + withText("tag2")).perform(click()); // select + pressBack(); + onView(allOf(withText("tag2"), withId(R.id.tagText))).check(matches(isDisplayed())); + onView(withText("tag1")).check(matches(not(isDisplayed()))); + + logout(); + signupin(); + + recyclerView.perform(actionOnItemAtPosition(0, click())); + onView(allOf(withText("tag2"), withId(R.id.tagText))).check(matches(isDisplayed())); + onView(withText("tag1")).check(matches(not(isDisplayed()))); + } + + @Test + public void openCloseOpenClose() { + ViewInteraction newNoteButton = onView(anyOf(withId(R.id.fab_new_note), withId(R.id.new_note))); + newNoteButton.perform(click()); + + ViewInteraction appCompatEditText = onView( + withId(R.id.titleEdit)); + appCompatEditText.perform(scrollTo(), click()); + + ViewInteraction appCompatEditText2 = onView( + withId(R.id.titleEdit)); + appCompatEditText2.perform(scrollTo(), replaceText("Title2"), closeSoftKeyboard()); + + ViewInteraction appCompatEditText14 = onView( + allOf(withId(R.id.bodyEdit))); + appCompatEditText14.perform(scrollTo(), replaceText("body2"), closeSoftKeyboard()); + + ViewInteraction recyclerView = onView( + allOf(withId(R.id.list_note), isDisplayed())); + + recyclerView.perform(actionOnItemAtPosition(0, click())); + recyclerView.perform(actionOnItemAtPosition(0, click())); + recyclerView.perform(actionOnItemAtPosition(0, click())); + recyclerView.perform(actionOnItemAtPosition(0, click())); + recyclerView.perform(actionOnItemAtPosition(0, click())); + recyclerView.perform(actionOnItemAtPosition(0, click())); + recyclerView.perform(actionOnItemAtPosition(0, click())); + recyclerView.perform(actionOnItemAtPosition(0, click())); + recyclerView.perform(actionOnItemAtPosition(0, click())); + recyclerView.perform(actionOnItemAtPosition(0, click())); + recyclerView.perform(actionOnItemAtPosition(0, click())); + recyclerView.perform(actionOnItemAtPosition(0, click())); + } +} diff --git a/app/src/androidTest/java/org/standardnotes/notes/StarterActivityTest.java b/app/src/androidTest/java/org/standardnotes/notes/StarterActivityTest.java index 49b2bdc..3ff9609 100644 --- a/app/src/androidTest/java/org/standardnotes/notes/StarterActivityTest.java +++ b/app/src/androidTest/java/org/standardnotes/notes/StarterActivityTest.java @@ -17,11 +17,9 @@ import org.hamcrest.TypeSafeMatcher; import org.junit.After; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.standardnotes.notes.comms.data.Tag; import java.util.UUID; @@ -31,9 +29,7 @@ import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard; import static android.support.test.espresso.action.ViewActions.replaceText; import static android.support.test.espresso.action.ViewActions.scrollTo; -import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist; import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.contrib.RecyclerViewActions.actionOnItem; import static android.support.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition; import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription; @@ -41,6 +37,9 @@ import static android.support.test.espresso.matcher.ViewMatchers.withParent; import static android.support.test.espresso.matcher.ViewMatchers.withText; import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.anyOf; +import static org.hamcrest.Matchers.not; +import static org.standardnotes.notes.TestHelper.childAtPosition; @LargeTest @RunWith(AndroidJUnit4.class) @@ -97,12 +96,9 @@ public void signupin() { Espresso.unregisterIdlingResources(idlingResource); } - - @After public void logout() { - ViewInteraction actionMenuItemView = onView( - allOf(withId(R.id.settings), withContentDescription("Settings"), isDisplayed())); + ViewInteraction actionMenuItemView = onView(allOf(withId(R.id.settings), isDisplayed())); actionMenuItemView.perform(click()); ViewInteraction appCompatButton = onView( @@ -112,10 +108,8 @@ public void logout() { @Test public void createNote() { - - - ViewInteraction floatingActionButton = onView(allOf(withId(R.id.fab), isDisplayed())); - floatingActionButton.perform(click()); + ViewInteraction newNoteButton = onView(anyOf(withId(R.id.fab_new_note), withId(R.id.new_note))); + newNoteButton.perform(click()); ViewInteraction appCompatEditText = onView( withId(R.id.titleEdit)); @@ -129,14 +123,10 @@ public void createNote() { allOf(withId(R.id.bodyEdit))); appCompatEditText14.perform(scrollTo(), replaceText("body1"), closeSoftKeyboard()); - ViewInteraction upButton = onView( - allOf(withContentDescription("Navigate up"), - withParent(withId(R.id.toolbar)), - isDisplayed())); - upButton.perform(click()); + pressBack(); ViewInteraction recyclerView = onView( - allOf(withId(R.id.list), isDisplayed())); + allOf(withId(R.id.list_note), isDisplayed())); recyclerView.perform(actionOnItemAtPosition(0, click())); ViewInteraction actionMenuItemView = onView( @@ -147,13 +137,13 @@ public void createNote() { appCompatEditText14.perform(scrollTo(), replaceText("body1a"), closeSoftKeyboard()); - upButton.perform(click()); + pressBack(); ViewInteraction textView = onView( allOf(withId(R.id.text), withText("body1a"), childAtPosition( childAtPosition( - withId(R.id.list), + withId(R.id.list_note), 0), 1), isDisplayed())); @@ -163,7 +153,7 @@ public void createNote() { allOf(withId(R.id.title), withText("Title1"), childAtPosition( childAtPosition( - withId(R.id.list), + withId(R.id.list_note), 0), 0), isDisplayed())); @@ -182,8 +172,8 @@ public void justSignInAndOut() { @Test public void tagSomething() { - ViewInteraction floatingActionButton = onView(allOf(withId(R.id.fab), isDisplayed())); - floatingActionButton.perform(click()); + ViewInteraction newNoteButton = onView(anyOf(withId(R.id.fab_new_note), withId(R.id.new_note))); + newNoteButton.perform(click()); ViewInteraction appCompatEditText = onView( withId(R.id.titleEdit)); @@ -200,12 +190,12 @@ public void tagSomething() { ViewInteraction tagsAction = onView( allOf(withId(R.id.tags), withContentDescription("Tags"), isDisplayed())); tagsAction.perform(click()); - onView(withId(R.id.fab)).perform(click()); + onView(withId(R.id.fab_new_tag)).perform(click()); onView( allOf(withId(R.id.tag), isDisplayed())).perform(replaceText("tag1"), closeSoftKeyboard()); onView( allOf(withId(android.R.id.button1), withText("OK"))).perform(scrollTo(), click()); - onView(withId(R.id.fab)).perform(click()); + onView(withId(R.id.fab_new_tag)).perform(click()); onView( allOf(withId(R.id.tag), isDisplayed())).perform(replaceText("tag2"), closeSoftKeyboard()); onView( @@ -215,19 +205,15 @@ public void tagSomething() { pressBack(); - ViewInteraction upButton = onView( - allOf(withContentDescription("Navigate up"), - withParent(withId(R.id.toolbar)), - isDisplayed())); - upButton.perform(click()); + pressBack(); logout(); signupin(); ViewInteraction recyclerView = onView( - allOf(withId(R.id.list), isDisplayed())); + allOf(withId(R.id.list_note), isDisplayed())); recyclerView.perform(actionOnItemAtPosition(0, click())); - onView(withText("tag1")).check(matches(isDisplayed())); + onView(allOf(withText("tag1"), withId(R.id.tagText))).check(matches(isDisplayed())); tagsAction.perform(click()); onView( @@ -235,26 +221,24 @@ public void tagSomething() { onView( withText("tag2")).perform(click()); // select pressBack(); - onView(withText("tag2")).check(matches(isDisplayed())); - onView(withText("tag1")).check(doesNotExist()); + onView(allOf(withText("tag2"), withId(R.id.tagText))).check(matches(isDisplayed())); + onView(withText("tag1")).check(matches(not(isDisplayed()))); pressBack(); logout(); signupin(); recyclerView.perform(actionOnItemAtPosition(0, click())); - onView(withText("tag2")).check(matches(isDisplayed())); - onView(withText("tag1")).check(doesNotExist()); - + onView(allOf(withText("tag2"), withId(R.id.tagText))).check(matches(isDisplayed())); + onView(withText("tag1")).check(matches(not(isDisplayed()))); pressBack(); } @Test public void openCloseOpenClose() { - - ViewInteraction floatingActionButton = onView(allOf(withId(R.id.fab), isDisplayed())); - floatingActionButton.perform(click()); + ViewInteraction newNoteButton = onView(anyOf(withId(R.id.fab_new_note), withId(R.id.new_note))); + newNoteButton.perform(click()); ViewInteraction appCompatEditText = onView( withId(R.id.titleEdit)); @@ -270,7 +254,7 @@ public void openCloseOpenClose() { pressBack(); ViewInteraction recyclerView = onView( - allOf(withId(R.id.list), isDisplayed())); + allOf(withId(R.id.list_note), isDisplayed())); recyclerView.perform(actionOnItemAtPosition(0, click())); pressBack(); recyclerView.perform(actionOnItemAtPosition(0, click())); @@ -296,25 +280,4 @@ public void openCloseOpenClose() { recyclerView.perform(actionOnItemAtPosition(0, click())); pressBack(); } - - - private static Matcher childAtPosition( - final Matcher parentMatcher, final int position) { - - return new TypeSafeMatcher() { - @Override - public void describeTo(Description description) { - description.appendText("Child at position " + position + " in parent "); - parentMatcher.describeTo(description); - } - - @Override - public boolean matchesSafely(View view) { - ViewParent parent = view.getParent(); - return parent instanceof ViewGroup && parentMatcher.matches(parent) - && view.equals(((ViewGroup) parent).getChildAt(position)); - } - }; - } - } diff --git a/app/src/androidTest/java/org/standardnotes/notes/TestHelper.java b/app/src/androidTest/java/org/standardnotes/notes/TestHelper.java new file mode 100644 index 0000000..0f4204b --- /dev/null +++ b/app/src/androidTest/java/org/standardnotes/notes/TestHelper.java @@ -0,0 +1,31 @@ +package org.standardnotes.notes; + +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewParent; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +public class TestHelper { + + public static Matcher childAtPosition( + final Matcher parentMatcher, final int position) { + + return new TypeSafeMatcher() { + @Override + public void describeTo(Description description) { + description.appendText("Child at position " + position + " in parent "); + parentMatcher.describeTo(description); + } + + @Override + public boolean matchesSafely(View view) { + ViewParent parent = view.getParent(); + return parent instanceof ViewGroup && parentMatcher.matches(parent) + && view.equals(((ViewGroup) parent).getChildAt(position)); + } + }; + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 16f77f0..3a135f3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -30,11 +30,6 @@ android:name=".MainActivity" android:label="@string/title_activity_main" android:theme="@style/AppTheme.NoActionBar" /> - diff --git a/app/src/main/java/org/standardnotes/notes/MainActivity.kt b/app/src/main/java/org/standardnotes/notes/MainActivity.kt index 621f01b..26e884f 100644 --- a/app/src/main/java/org/standardnotes/notes/MainActivity.kt +++ b/app/src/main/java/org/standardnotes/notes/MainActivity.kt @@ -6,14 +6,30 @@ import android.os.Bundle import android.support.v7.app.ActionBarDrawerToggle import android.view.Menu import android.view.MenuItem -import android.view.MotionEvent import kotlinx.android.synthetic.main.activity_main.* +import kotlinx.android.synthetic.main.two_pane_container.* import kotlinx.android.synthetic.main.view_navigation_header.view.* import org.standardnotes.notes.comms.SyncManager -import org.standardnotes.notes.comms.data.Note +import org.standardnotes.notes.frag.NoteFragment import org.standardnotes.notes.frag.NoteListFragment -class MainActivity : BaseActivity(), SyncManager.SyncListener { +class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment.OnNewNoteClickListener { + + override fun newNoteListener(uuid: String) { + val noteFragment = NoteFragment() + val bundle = Bundle() + bundle.putString(NoteListFragment.EXTRA_NOTE_ID, uuid) + noteFragment.arguments = bundle + if (note_container == null) { + supportFragmentManager.beginTransaction().add(R.id.note_list_container, noteFragment, "note_fragment").addToBackStack(null).commit() + } else { + supportFragmentManager.beginTransaction().replace(R.id.note_container, noteFragment, "note_fragment").commit() + } + } + + private lateinit var noteListFragment: NoteListFragment + private lateinit var drawerToggle: ActionBarDrawerToggle + private var selectedTagId = "" override fun onSyncStarted() { } @@ -23,18 +39,16 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener { } override fun onSyncCompleted() { - updateTagsMenu() // Update tags list - noteListFragment().refreshNotesForTag(selectedTagId) // Update notes in fragment + updateTagsMenu() + noteListFragment.refreshNotesForTag(selectedTagId) } override fun onSaveInstanceState(outState: Bundle?) { super.onSaveInstanceState(outState) outState!!.putString("tag", selectedTagId) + supportFragmentManager.putFragment(outState, "note_list_fragment", noteListFragment) } - private lateinit var drawerToggle: ActionBarDrawerToggle - private var selectedTagId = "" - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (savedInstanceState != null && savedInstanceState?.containsKey("tag")) { @@ -44,6 +58,20 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener { setContentView(R.layout.activity_main) setSupportActionBar(toolbar) + if (savedInstanceState == null) { + noteListFragment = NoteListFragment() + supportFragmentManager.beginTransaction().replace(R.id.note_list_container, noteListFragment, "note_list_fragment").commit() + } else { + noteListFragment = supportFragmentManager.findFragmentByTag("note_list_fragment") as NoteListFragment + } + + noteListFragment.onNewNoteListener = this + + if (note_container != null) { +// supportFragmentManager.beginTransaction().replace(R.id.note_container, NoteFragment(), "note_fragment").commit() + //TODO show first note + } + drawerToggle = ActionBarDrawerToggle(this, drawer_layout, R.string.app_name, R.string.app_name) drawer_layout.addDrawerListener(drawerToggle!!) drawerToggle.isDrawerIndicatorEnabled = true @@ -57,10 +85,6 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener { title = getString(R.string.app_name) } - fun noteListFragment(): NoteListFragment { - return supportFragmentManager.findFragmentById(R.id.noteListFrag) as NoteListFragment - } - fun updateTagsMenu() { fun tagMenuItem(it: MenuItem, uuid: String) { it.setIcon(R.drawable.ic_tag) @@ -68,7 +92,7 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener { drawer_layout.closeDrawers() selectedTagId = uuid updateTagsMenu() - noteListFragment().refreshNotesForTag(selectedTagId) // TODO replace with some kind of listener + noteListFragment.refreshNotesForTag(selectedTagId) // TODO replace with some kind of listener return@setOnMenuItemClickListener true } } @@ -106,10 +130,6 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener { SyncManager.unsubscribe(this) } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - } - override fun onCreateOptionsMenu(menu: Menu): Boolean { super.onCreateOptionsMenu(menu) menuInflater.inflate(R.menu.logged_in, menu) @@ -127,10 +147,9 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener { R.id.settings -> startActivity(Intent(this, SettingsActivity::class.java)) R.id.debug -> startActivity(Intent(this, DebugActivity::class.java)) } - return true + return false } - override fun onConfigurationChanged(newConfig: Configuration?) { super.onConfigurationChanged(newConfig) drawerToggle?.syncState() @@ -140,5 +159,4 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener { super.onPostCreate(savedInstanceState) drawerToggle?.syncState() } - } diff --git a/app/src/main/java/org/standardnotes/notes/NoteActivity.kt b/app/src/main/java/org/standardnotes/notes/NoteActivity.kt deleted file mode 100644 index 7c9cc89..0000000 --- a/app/src/main/java/org/standardnotes/notes/NoteActivity.kt +++ /dev/null @@ -1,105 +0,0 @@ -package org.standardnotes.notes - -import android.animation.Animator -import android.content.Intent -import android.os.Bundle -import android.support.v4.app.NavUtils -import android.view.* -import org.standardnotes.notes.frag.NoteFragment -import org.standardnotes.notes.frag.NoteListFragment.Companion.EXTRA_NOTE_ID -import org.standardnotes.notes.frag.NoteListFragment.Companion.EXTRA_X_COOR -import org.standardnotes.notes.frag.NoteListFragment.Companion.EXTRA_Y_COOR - -class NoteActivity : BaseActivity() { - - val REVEAL_ANIM_DURATION = 200L - var revealX: Int = 0 - var revealY: Int = 0 - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - overridePendingTransition(0, 0) - - revealX = intent.getIntExtra(EXTRA_X_COOR, 0) - revealY = intent.getIntExtra(EXTRA_Y_COOR, 0) - if (savedInstanceState == null) { - val frag: NoteFragment = NoteFragment() - frag.arguments = intent.extras - - supportFragmentManager.beginTransaction().replace(android.R.id.content, frag).commit() - - if (revealX != 0) { - - val rootView = findViewById(android.R.id.content) - val viewTreeObserver = rootView.viewTreeObserver - if (viewTreeObserver.isAlive) { - rootView.visibility = View.INVISIBLE - viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { - override fun onGlobalLayout() { - circularReveal() - rootView.viewTreeObserver.removeOnGlobalLayoutListener(this) - } - }) - } - } - } - if (intent.extras.getString(EXTRA_NOTE_ID) == null) { - window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE) - } - } - - override fun onBackPressed() { - overridePendingTransition(0, 0) - if (revealX != 0) { - circularHide() - } else { - super.onBackPressed() - } - } - - private fun circularReveal() { - val rootView = findViewById(android.R.id.content) - val circularReveal = ViewAnimationUtils.createCircularReveal(rootView, revealX, revealY, 0f, Math.max(rootView.width, rootView.height).toFloat()) - circularReveal.duration = REVEAL_ANIM_DURATION - rootView.visibility = View.VISIBLE - circularReveal.start() - } - - private fun circularHide() { - val rootView = findViewById(android.R.id.content) - val circularHide = ViewAnimationUtils.createCircularReveal(rootView, revealX, revealY, Math.max(rootView.width, rootView.height).toFloat(), 0f) - circularHide.duration = REVEAL_ANIM_DURATION - circularHide.addListener(object : Animator.AnimatorListener { - override fun onAnimationStart(animation: Animator) { - // - } - - override fun onAnimationRepeat(animation: Animator) { - // - } - - override fun onAnimationEnd(animation: Animator) { - rootView.visibility = View.GONE - overridePendingTransition(0, 0) - finish() - } - - override fun onAnimationCancel(animation: Animator) { - // - } - }) - circularHide.start() - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - if (item.itemId == android.R.id.home) { - if (NavUtils.getParentActivityIntent(this) != null) { - NavUtils.navigateUpTo(this, NavUtils.getParentActivityIntent(this).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)) - } else { - onBackPressed() - } - return true - } - return super.onOptionsItemSelected(item) - } -} \ No newline at end of file diff --git a/app/src/main/java/org/standardnotes/notes/StarterActivity.kt b/app/src/main/java/org/standardnotes/notes/StarterActivity.kt index 0f100a3..dd94331 100644 --- a/app/src/main/java/org/standardnotes/notes/StarterActivity.kt +++ b/app/src/main/java/org/standardnotes/notes/StarterActivity.kt @@ -15,7 +15,7 @@ class StarterActivity : AppCompatActivity() { if (intent.action == Intent.ACTION_SEND && intent.type == "text/plain") { var text = intent.getStringExtra(Intent.EXTRA_TEXT) if (text != null) { - val intent = Intent(this, NoteActivity::class.java) + val intent = Intent(this, MainActivity::class.java) intent.putExtra(EXTRA_TEXT, text) startActivity(intent) } diff --git a/app/src/main/java/org/standardnotes/notes/TagListActivity.kt b/app/src/main/java/org/standardnotes/notes/TagListActivity.kt index 7090e5b..db5a224 100644 --- a/app/src/main/java/org/standardnotes/notes/TagListActivity.kt +++ b/app/src/main/java/org/standardnotes/notes/TagListActivity.kt @@ -42,10 +42,10 @@ class TagListActivity : BaseActivity() { selectedTags = selectedTagsList.toSet() tags = app.noteStore.getAllTags(false).sortedBy { it.title.toLowerCase() } - list.adapter = Adapter() - list.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) + list_tag.adapter = Adapter() + list_tag.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) - fab.setOnClickListener { + fab_new_tag.setOnClickListener { val layout = LayoutInflater.from(this).inflate(R.layout.view_new_tag, null, false) val input = layout.findViewById(R.id.tag) as EditText val dialog = AlertDialog.Builder(this).setTitle(R.string.prompt_new_tag) @@ -57,7 +57,7 @@ class TagListActivity : BaseActivity() { app.noteStore.putTag(newTag.uuid, newTag) SyncManager.sync() tags = app.noteStore.getAllTags(false) - list.adapter.notifyDataSetChanged() + list_tag.adapter.notifyDataSetChanged() }) .setView(layout) .show() diff --git a/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt b/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt index 2956055..874ff30 100644 --- a/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt +++ b/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt @@ -56,16 +56,12 @@ class NoteFragment : Fragment(), SyncManager.SyncListener { override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val context = activity as AppCompatActivity - context.setSupportActionBar(toolbar) - context.supportActionBar?.setDisplayShowHomeEnabled(true) - context.supportActionBar?.setDisplayHomeAsUpEnabled(true) val noteUuid = savedInstanceState?.getString(NoteListFragment.EXTRA_NOTE_ID) ?: arguments?.getString(NoteListFragment.EXTRA_NOTE_ID) - if (noteUuid != null) { - note = SApplication.instance.noteStore.getNote(noteUuid)!! + if (noteUuid != "") { + note = SApplication.instance.noteStore.getNote(noteUuid!!)!! tags = SApplication.instance.noteStore.getTagsForNote(noteUuid) } else { note = newNote() diff --git a/app/src/main/java/org/standardnotes/notes/frag/NoteListFragment.kt b/app/src/main/java/org/standardnotes/notes/frag/NoteListFragment.kt index 4a3e3cf..3a8afa2 100644 --- a/app/src/main/java/org/standardnotes/notes/frag/NoteListFragment.kt +++ b/app/src/main/java/org/standardnotes/notes/frag/NoteListFragment.kt @@ -9,22 +9,18 @@ import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.PopupMenu import android.support.v7.widget.RecyclerView import android.text.TextUtils -import android.view.LayoutInflater -import android.view.MotionEvent -import android.view.View -import android.view.ViewGroup +import android.view.* import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.frag_note_list.* import kotlinx.android.synthetic.main.frag_note_list.view.* import kotlinx.android.synthetic.main.item_note.view.* import org.joda.time.format.DateTimeFormat -import org.standardnotes.notes.NoteActivity import org.standardnotes.notes.R import org.standardnotes.notes.SApplication import org.standardnotes.notes.comms.SyncManager import org.standardnotes.notes.comms.data.Note import java.util.* - +import android.view.MenuInflater class NoteListFragment : Fragment(), SyncManager.SyncListener { @@ -39,6 +35,8 @@ class NoteListFragment : Fragment(), SyncManager.SyncListener { var lastTouchedX: Int? = null var lastTouchedY: Int? = null + lateinit var onNewNoteListener: OnNewNoteClickListener + companion object { const val EXTRA_NOTE_ID = "noteId" const val EXTRA_TAG_ID = "tagId" @@ -46,30 +44,11 @@ class NoteListFragment : Fragment(), SyncManager.SyncListener { const val EXTRA_Y_COOR = "yCoor" } - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - if (savedInstanceState != null) { - tagId = savedInstanceState.getString("tagId") - selectedTagId = savedInstanceState.getString("tag") - } - } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = inflater.inflate(R.layout.frag_note_list, container, false) - - var lastX: Int? = null - var lastY: Int? = null - view.fab.setOnTouchListener({ v, event -> - if (event.action == MotionEvent.ACTION_UP) { - lastX = event.rawX.toInt() - lastY = event.rawY.toInt() - } - false - }) - view.fab.setOnClickListener { view -> - startNewNote(lastX!!, lastY!!, selectedTagId) - } + setHasOptionsMenu(true) + setFabClickListener(view) return view } @@ -77,14 +56,14 @@ class NoteListFragment : Fragment(), SyncManager.SyncListener { override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) SyncManager.subscribe(this) - list.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false) - list.addItemDecoration(DividerItemDecoration(activity, LinearLayoutManager.VERTICAL)) + list_note.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false) + list_note.addItemDecoration(DividerItemDecoration(activity, LinearLayoutManager.VERTICAL)) swipeRefreshLayout.setColorSchemeResources( R.color.colorPrimary, R.color.colorAccent) swipeRefreshLayout.setOnRefreshListener { SyncManager.sync() } SyncManager.sync() - list.adapter = adapter + list_note.adapter = adapter } override fun onDestroyView() { @@ -97,9 +76,32 @@ class NoteListFragment : Fragment(), SyncManager.SyncListener { refreshNotesForTag() // This is too often and slow for large datasets, but necessary until we have an event to trigger refresh } + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + inflater.inflate(R.menu.note_list, menu) + super.onCreateOptionsMenu(menu, inflater) + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + when (item?.itemId) { + R.id.new_note -> startNewNote(selectedTagId) + } + + return super.onOptionsItemSelected(item) + } + override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putString("tagId", tagId) + outState.putString("tag", selectedTagId) + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + + if (savedInstanceState != null) { + tagId = savedInstanceState.getString("tagId") + selectedTagId = savedInstanceState.getString("tag") + } } override fun onSyncStarted() { @@ -112,6 +114,25 @@ class NoteListFragment : Fragment(), SyncManager.SyncListener { currentSnackbar?.dismiss() } + fun setFabClickListener(view: View) { + if (view.fab_new_note == null) { + return + } + + var lastX: Int? = null + var lastY: Int? = null + view.fab_new_note.setOnTouchListener({ v, event -> + if (event.action == MotionEvent.ACTION_UP) { + lastX = event.rawX.toInt() + lastY = event.rawY.toInt() + } + false + }) + view.fab_new_note.setOnClickListener { view -> + startNewNote(selectedTagId) + } + } + fun refreshNotesForTag(uuid: String? = null) { if (uuid == null) { // In-place refresh after delete refreshNotesForTag(tagId) @@ -136,12 +157,12 @@ class NoteListFragment : Fragment(), SyncManager.SyncListener { currentSnackbar!!.show() } - fun startNewNote(x: Int, y: Int, uuid: String) { - val intent: Intent = Intent(activity, NoteActivity::class.java) - intent.putExtra(EXTRA_X_COOR, x) - intent.putExtra(EXTRA_Y_COOR, y) - intent.putExtra(EXTRA_TAG_ID, uuid) - startActivity(intent) + fun startNewNote(uuid: String) { + onNewNoteListener.newNoteListener(uuid) + } + + interface OnNewNoteClickListener { + fun newNoteListener(uuid: String) } inner class NoteHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { @@ -168,11 +189,7 @@ class NoteListFragment : Fragment(), SyncManager.SyncListener { false }) itemView.setOnClickListener { - val intent: Intent = Intent(activity, NoteActivity::class.java) - intent.putExtra(EXTRA_NOTE_ID, note?.uuid) - intent.putExtra(EXTRA_X_COOR, lastTouchedX) - intent.putExtra(EXTRA_Y_COOR, lastTouchedY) - startActivity(intent) + onNewNoteListener.newNoteListener(note!!.uuid) } itemView.setOnLongClickListener { val popup = PopupMenu(activity, itemView) diff --git a/app/src/main/res/layout-sw600dp-land/frag_note_list.xml b/app/src/main/res/layout-sw600dp-land/frag_note_list.xml new file mode 100644 index 0000000..2f862ed --- /dev/null +++ b/app/src/main/res/layout-sw600dp-land/frag_note_list.xml @@ -0,0 +1,24 @@ + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 7d1f1d1..95778b3 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -27,12 +27,8 @@ app:subtitleTextAppearance="@style/ToolbarSubtitleAppearance" /> - + + - + + + + - + + + + + + - + \ No newline at end of file diff --git a/app/src/main/res/layout/frag_note_list.xml b/app/src/main/res/layout/frag_note_list.xml index a4da52e..3593b24 100644 --- a/app/src/main/res/layout/frag_note_list.xml +++ b/app/src/main/res/layout/frag_note_list.xml @@ -12,7 +12,7 @@ android:layout_height="match_parent"> + diff --git a/app/src/main/res/layout/two_pane_container.xml b/app/src/main/res/layout/two_pane_container.xml new file mode 100644 index 0000000..aeb1400 --- /dev/null +++ b/app/src/main/res/layout/two_pane_container.xml @@ -0,0 +1,22 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu-sw600dp-land/note_list.xml b/app/src/main/res/menu-sw600dp-land/note_list.xml new file mode 100644 index 0000000..1ed3cdd --- /dev/null +++ b/app/src/main/res/menu-sw600dp-land/note_list.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/logged_in.xml b/app/src/main/res/menu/logged_in.xml index ebec3e1..2dc5fcb 100644 --- a/app/src/main/res/menu/logged_in.xml +++ b/app/src/main/res/menu/logged_in.xml @@ -6,12 +6,14 @@ android:id="@+id/debug" android:title="Debug" app:showAsAction="ifRoom" + android:orderInCategory="10" android:visible="false" /> \ No newline at end of file diff --git a/app/src/main/res/menu/note.xml b/app/src/main/res/menu/note.xml index 6635b75..daf63d5 100644 --- a/app/src/main/res/menu/note.xml +++ b/app/src/main/res/menu/note.xml @@ -5,6 +5,7 @@ diff --git a/app/src/main/res/menu/note_list.xml b/app/src/main/res/menu/note_list.xml new file mode 100644 index 0000000..fe187c0 --- /dev/null +++ b/app/src/main/res/menu/note_list.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values-sw600dp-land/refs.xml b/app/src/main/res/values-sw600dp-land/refs.xml new file mode 100644 index 0000000..4d76c8c --- /dev/null +++ b/app/src/main/res/values-sw600dp-land/refs.xml @@ -0,0 +1,4 @@ + + + @layout/two_pane_container + \ No newline at end of file diff --git a/app/src/main/res/values/refs.xml b/app/src/main/res/values/refs.xml new file mode 100644 index 0000000..eddce12 --- /dev/null +++ b/app/src/main/res/values/refs.xml @@ -0,0 +1,4 @@ + + + @layout/single_pane_container + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8171f1a..707feed 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -60,5 +60,6 @@ Export Data Data export failed. Share File + New Note From 959d1d457f9cb40ee8c64d554e441612aff82c7f Mon Sep 17 00:00:00 2001 From: nbau21 Date: Fri, 10 Mar 2017 11:16:07 -0800 Subject: [PATCH 3/8] Fix crashes when using multiwindow or rotating --- .../org/standardnotes/notes/MainActivity.kt | 32 +++++++++++++------ .../standardnotes/notes/frag/NoteFragment.kt | 9 +++++- .../notes/frag/NoteListFragment.kt | 2 -- app/src/main/res/layout/frag_note.xml | 21 +++--------- .../main/res/layout/two_pane_container.xml | 1 + 5 files changed, 36 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/org/standardnotes/notes/MainActivity.kt b/app/src/main/java/org/standardnotes/notes/MainActivity.kt index 26e884f..4f37be5 100644 --- a/app/src/main/java/org/standardnotes/notes/MainActivity.kt +++ b/app/src/main/java/org/standardnotes/notes/MainActivity.kt @@ -7,6 +7,7 @@ import android.support.v7.app.ActionBarDrawerToggle import android.view.Menu import android.view.MenuItem import kotlinx.android.synthetic.main.activity_main.* +import kotlinx.android.synthetic.main.frag_note_list.* import kotlinx.android.synthetic.main.two_pane_container.* import kotlinx.android.synthetic.main.view_navigation_header.view.* import org.standardnotes.notes.comms.SyncManager @@ -16,10 +17,10 @@ import org.standardnotes.notes.frag.NoteListFragment class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment.OnNewNoteClickListener { override fun newNoteListener(uuid: String) { - val noteFragment = NoteFragment() + noteFragment = NoteFragment() val bundle = Bundle() bundle.putString(NoteListFragment.EXTRA_NOTE_ID, uuid) - noteFragment.arguments = bundle + noteFragment!!.arguments = bundle if (note_container == null) { supportFragmentManager.beginTransaction().add(R.id.note_list_container, noteFragment, "note_fragment").addToBackStack(null).commit() } else { @@ -28,6 +29,8 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. } private lateinit var noteListFragment: NoteListFragment + private var noteFragment: NoteFragment? = null + private lateinit var drawerToggle: ActionBarDrawerToggle private var selectedTagId = "" @@ -47,6 +50,9 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. super.onSaveInstanceState(outState) outState!!.putString("tag", selectedTagId) supportFragmentManager.putFragment(outState, "note_list_fragment", noteListFragment) + if (noteFragment != null) { + supportFragmentManager.putFragment(outState, "note_fragment", noteFragment) + } } override fun onCreate(savedInstanceState: Bundle?) { @@ -60,18 +66,26 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. if (savedInstanceState == null) { noteListFragment = NoteListFragment() - supportFragmentManager.beginTransaction().replace(R.id.note_list_container, noteListFragment, "note_list_fragment").commit() + supportFragmentManager.beginTransaction().replace(R.id.note_list_container, noteListFragment, "note_list_fragment").addToBackStack(null).commit() + supportFragmentManager.executePendingTransactions() + if (note_container != null && noteListFragment.adapter.itemCount > 0) { + noteListFragment.list_note.findViewHolderForAdapterPosition(0).itemView.performClick() + } } else { noteListFragment = supportFragmentManager.findFragmentByTag("note_list_fragment") as NoteListFragment + if (note_container != null) { + noteFragment = supportFragmentManager.findFragmentByTag("note_fragment") as? NoteFragment + if (noteFragment != null) { + supportFragmentManager.beginTransaction().remove(noteFragment).commit() + supportFragmentManager.executePendingTransactions() + } + } else { + noteFragment = null + } } noteListFragment.onNewNoteListener = this - if (note_container != null) { -// supportFragmentManager.beginTransaction().replace(R.id.note_container, NoteFragment(), "note_fragment").commit() - //TODO show first note - } - drawerToggle = ActionBarDrawerToggle(this, drawer_layout, R.string.app_name, R.string.app_name) drawer_layout.addDrawerListener(drawerToggle!!) drawerToggle.isDrawerIndicatorEnabled = true @@ -92,7 +106,7 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. drawer_layout.closeDrawers() selectedTagId = uuid updateTagsMenu() - noteListFragment.refreshNotesForTag(selectedTagId) // TODO replace with some kind of listener + noteListFragment.refreshNotesForTag(selectedTagId) return@setOnMenuItemClickListener true } } diff --git a/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt b/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt index 874ff30..d5b3b92 100644 --- a/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt +++ b/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt @@ -1,5 +1,6 @@ package org.standardnotes.notes.frag +import android.content.Context import android.content.Intent import android.graphics.Typeface import android.os.Bundle @@ -43,6 +44,7 @@ class NoteFragment : Fragment(), SyncManager.SyncListener { lateinit var note: Note lateinit var tags: List + lateinit var mActivity: AppCompatActivity override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -120,6 +122,11 @@ class NoteFragment : Fragment(), SyncManager.SyncListener { setSubtitle(if (note.dirty) getString(R.string.sync_progress_error) else getString(R.string.sync_progress_finished)) } + override fun onAttach(context: Context?) { + super.onAttach(context) + mActivity = (context as AppCompatActivity) + } + override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putString(NoteListFragment.EXTRA_NOTE_ID, note.uuid) @@ -180,7 +187,7 @@ class NoteFragment : Fragment(), SyncManager.SyncListener { fun setSubtitle(subTitle: String) { bodyEdit.postDelayed({ - (activity as AppCompatActivity).supportActionBar!!.subtitle = subTitle + mActivity.supportActionBar!!.subtitle = subTitle }, 100) } diff --git a/app/src/main/java/org/standardnotes/notes/frag/NoteListFragment.kt b/app/src/main/java/org/standardnotes/notes/frag/NoteListFragment.kt index 3a8afa2..6c0ed53 100644 --- a/app/src/main/java/org/standardnotes/notes/frag/NoteListFragment.kt +++ b/app/src/main/java/org/standardnotes/notes/frag/NoteListFragment.kt @@ -1,6 +1,5 @@ package org.standardnotes.notes.frag -import android.content.Intent import android.os.Bundle import android.support.design.widget.Snackbar import android.support.v4.app.Fragment @@ -220,6 +219,5 @@ class NoteListFragment : Fragment(), SyncManager.SyncListener { val note: Note = notes[position] holder.note = note } - } } diff --git a/app/src/main/res/layout/frag_note.xml b/app/src/main/res/layout/frag_note.xml index eb5d458..d27a391 100644 --- a/app/src/main/res/layout/frag_note.xml +++ b/app/src/main/res/layout/frag_note.xml @@ -1,6 +1,6 @@ - @@ -8,14 +8,14 @@ + android:scrollbarStyle="outsideInset" + android:background="@android:color/white"> - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/two_pane_container.xml b/app/src/main/res/layout/two_pane_container.xml index aeb1400..c13a878 100644 --- a/app/src/main/res/layout/two_pane_container.xml +++ b/app/src/main/res/layout/two_pane_container.xml @@ -15,6 +15,7 @@ From d57148f30f4f13b246164fb2b6bb898b8c68dc0e Mon Sep 17 00:00:00 2001 From: nbau21 Date: Fri, 10 Mar 2017 15:18:58 -0800 Subject: [PATCH 4/8] Disable drawer toggle when showing NoteFragment on vertical layout --- .../org/standardnotes/notes/MainActivity.kt | 25 ++++++++++++++----- .../standardnotes/notes/frag/NoteFragment.kt | 18 ++++++++----- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/org/standardnotes/notes/MainActivity.kt b/app/src/main/java/org/standardnotes/notes/MainActivity.kt index 4f37be5..a57953d 100644 --- a/app/src/main/java/org/standardnotes/notes/MainActivity.kt +++ b/app/src/main/java/org/standardnotes/notes/MainActivity.kt @@ -14,14 +14,16 @@ import org.standardnotes.notes.comms.SyncManager import org.standardnotes.notes.frag.NoteFragment import org.standardnotes.notes.frag.NoteListFragment -class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment.OnNewNoteClickListener { +class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment.OnNewNoteClickListener, NoteFragment.DetachListener { override fun newNoteListener(uuid: String) { noteFragment = NoteFragment() + noteFragment!!.detachListener = this val bundle = Bundle() bundle.putString(NoteListFragment.EXTRA_NOTE_ID, uuid) noteFragment!!.arguments = bundle if (note_container == null) { + removeDrawerToggle() supportFragmentManager.beginTransaction().add(R.id.note_list_container, noteFragment, "note_fragment").addToBackStack(null).commit() } else { supportFragmentManager.beginTransaction().replace(R.id.note_container, noteFragment, "note_fragment").commit() @@ -31,7 +33,7 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. private lateinit var noteListFragment: NoteListFragment private var noteFragment: NoteFragment? = null - private lateinit var drawerToggle: ActionBarDrawerToggle + lateinit var drawerToggle: ActionBarDrawerToggle private var selectedTagId = "" override fun onSyncStarted() { @@ -66,7 +68,7 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. if (savedInstanceState == null) { noteListFragment = NoteListFragment() - supportFragmentManager.beginTransaction().replace(R.id.note_list_container, noteListFragment, "note_list_fragment").addToBackStack(null).commit() + supportFragmentManager.beginTransaction().replace(R.id.note_list_container, noteListFragment, "note_list_fragment").commit() supportFragmentManager.executePendingTransactions() if (note_container != null && noteListFragment.adapter.itemCount > 0) { noteListFragment.list_note.findViewHolderForAdapterPosition(0).itemView.performClick() @@ -88,9 +90,8 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. drawerToggle = ActionBarDrawerToggle(this, drawer_layout, R.string.app_name, R.string.app_name) drawer_layout.addDrawerListener(drawerToggle!!) - drawerToggle.isDrawerIndicatorEnabled = true - supportActionBar?.setDisplayHomeAsUpEnabled(true) - supportActionBar?.setHomeButtonEnabled(true) + addDrawerToggle() + val header = drawer.inflateHeaderView(R.layout.view_navigation_header) val values = SApplication.instance.valueStore header.main_account_server.text = values.server @@ -131,6 +132,18 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. selectedTagId = selectedId // In case selected tag wasn't found in list } + override fun addDrawerToggle() { + drawerToggle.isDrawerIndicatorEnabled = true + supportActionBar?.setDisplayHomeAsUpEnabled(true) + supportActionBar?.setHomeButtonEnabled(true) + } + + fun removeDrawerToggle() { + drawerToggle.isDrawerIndicatorEnabled = false + supportActionBar?.setDisplayHomeAsUpEnabled(false) + supportActionBar?.setHomeButtonEnabled(false) + } + override fun onResume() { super.onResume() SyncManager.startSyncTimer() diff --git a/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt b/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt index d5b3b92..c717dcf 100644 --- a/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt +++ b/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt @@ -16,10 +16,7 @@ import com.google.gson.reflect.TypeToken import kotlinx.android.synthetic.main.frag_note.* import kotlinx.android.synthetic.main.item_tag_lozenge.view.* import org.joda.time.DateTime -import org.standardnotes.notes.EXTRA_TAGS -import org.standardnotes.notes.R -import org.standardnotes.notes.SApplication -import org.standardnotes.notes.TagListActivity +import org.standardnotes.notes.* import org.standardnotes.notes.comms.Crypt import org.standardnotes.notes.comms.SyncManager import org.standardnotes.notes.comms.data.ContentType @@ -44,7 +41,8 @@ class NoteFragment : Fragment(), SyncManager.SyncListener { lateinit var note: Note lateinit var tags: List - lateinit var mActivity: AppCompatActivity + lateinit var mActivity: MainActivity + lateinit var detachListener: DetachListener override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -124,7 +122,7 @@ class NoteFragment : Fragment(), SyncManager.SyncListener { override fun onAttach(context: Context?) { super.onAttach(context) - mActivity = (context as AppCompatActivity) + mActivity = (context as MainActivity) } override fun onSaveInstanceState(outState: Bundle) { @@ -232,6 +230,14 @@ class NoteFragment : Fragment(), SyncManager.SyncListener { setSubtitle(getString(R.string.sync_progress_error)) } + override fun onDetach() { + super.onDetach() + detachListener.addDrawerToggle() + } + + interface DetachListener { + fun addDrawerToggle() + } } fun newNote(): Note { From 3c21a865a6033333060b63737efb6b7b3d2a51ce Mon Sep 17 00:00:00 2001 From: nbau21 Date: Fri, 10 Mar 2017 16:02:33 -0800 Subject: [PATCH 5/8] Properly load list and note fragments during rotation --- .../org/standardnotes/notes/MainActivity.kt | 73 +++++++++++++------ .../standardnotes/notes/frag/NoteFragment.kt | 5 +- 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/org/standardnotes/notes/MainActivity.kt b/app/src/main/java/org/standardnotes/notes/MainActivity.kt index a57953d..2957718 100644 --- a/app/src/main/java/org/standardnotes/notes/MainActivity.kt +++ b/app/src/main/java/org/standardnotes/notes/MainActivity.kt @@ -3,12 +3,11 @@ package org.standardnotes.notes import android.content.Intent import android.content.res.Configuration import android.os.Bundle +import android.support.v4.app.FragmentManager import android.support.v7.app.ActionBarDrawerToggle import android.view.Menu import android.view.MenuItem import kotlinx.android.synthetic.main.activity_main.* -import kotlinx.android.synthetic.main.frag_note_list.* -import kotlinx.android.synthetic.main.two_pane_container.* import kotlinx.android.synthetic.main.view_navigation_header.view.* import org.standardnotes.notes.comms.SyncManager import org.standardnotes.notes.frag.NoteFragment @@ -22,11 +21,18 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. val bundle = Bundle() bundle.putString(NoteListFragment.EXTRA_NOTE_ID, uuid) noteFragment!!.arguments = bundle - if (note_container == null) { + if (findViewById(R.id.note_container) == null) { removeDrawerToggle() - supportFragmentManager.beginTransaction().add(R.id.note_list_container, noteFragment, "note_fragment").addToBackStack(null).commit() + supportFragmentManager + .beginTransaction() + .add(R.id.note_list_container, noteFragment, "note_fragment") + .addToBackStack(null) + .commit() } else { - supportFragmentManager.beginTransaction().replace(R.id.note_container, noteFragment, "note_fragment").commit() + supportFragmentManager + .beginTransaction() + .replace(R.id.note_container, noteFragment, "note_fragment") + .commit() } } @@ -52,7 +58,7 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. super.onSaveInstanceState(outState) outState!!.putString("tag", selectedTagId) supportFragmentManager.putFragment(outState, "note_list_fragment", noteListFragment) - if (noteFragment != null) { + if (supportFragmentManager.findFragmentByTag("note_fragment") != null ) { supportFragmentManager.putFragment(outState, "note_fragment", noteFragment) } } @@ -66,32 +72,55 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. setContentView(R.layout.activity_main) setSupportActionBar(toolbar) + drawerToggle = ActionBarDrawerToggle(this, drawer_layout, R.string.app_name, R.string.app_name) + drawer_layout.addDrawerListener(drawerToggle!!) + addDrawerToggle() + if (savedInstanceState == null) { noteListFragment = NoteListFragment() - supportFragmentManager.beginTransaction().replace(R.id.note_list_container, noteListFragment, "note_list_fragment").commit() - supportFragmentManager.executePendingTransactions() - if (note_container != null && noteListFragment.adapter.itemCount > 0) { - noteListFragment.list_note.findViewHolderForAdapterPosition(0).itemView.performClick() - } + supportFragmentManager + .beginTransaction() + .replace(R.id.note_list_container, noteListFragment, "note_list_fragment") + .commit() } else { noteListFragment = supportFragmentManager.findFragmentByTag("note_list_fragment") as NoteListFragment - if (note_container != null) { - noteFragment = supportFragmentManager.findFragmentByTag("note_fragment") as? NoteFragment - if (noteFragment != null) { - supportFragmentManager.beginTransaction().remove(noteFragment).commit() - supportFragmentManager.executePendingTransactions() + noteFragment = supportFragmentManager.findFragmentByTag("note_fragment") as? NoteFragment + noteFragment?.detachListener = this + + if (noteFragment != null) { + supportFragmentManager + .popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE) + supportFragmentManager + .beginTransaction() + .remove(noteFragment) + .commitNow() + + if (findViewById(R.id.note_container) != null) { + supportFragmentManager + .beginTransaction() + .remove(noteListFragment) + .commitNow() + + supportFragmentManager + .beginTransaction() + .add(R.id.note_list_container, noteListFragment, "note_list_fragment") + .replace(R.id.note_container, noteFragment, "note_fragment") + .commit() + + } else { + + removeDrawerToggle() + supportFragmentManager + .beginTransaction() + .add(R.id.note_list_container, noteFragment, "note_fragment") + .addToBackStack(null) + .commit() } - } else { - noteFragment = null } } noteListFragment.onNewNoteListener = this - drawerToggle = ActionBarDrawerToggle(this, drawer_layout, R.string.app_name, R.string.app_name) - drawer_layout.addDrawerListener(drawerToggle!!) - addDrawerToggle() - val header = drawer.inflateHeaderView(R.layout.view_navigation_header) val values = SApplication.instance.valueStore header.main_account_server.text = values.server diff --git a/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt b/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt index c717dcf..34c59c2 100644 --- a/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt +++ b/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt @@ -7,7 +7,6 @@ import android.os.Bundle import android.os.Handler import android.preference.PreferenceManager import android.support.v4.app.Fragment -import android.support.v7.app.AppCompatActivity import android.text.Editable import android.text.TextWatcher import android.view.* @@ -42,7 +41,7 @@ class NoteFragment : Fragment(), SyncManager.SyncListener { lateinit var note: Note lateinit var tags: List lateinit var mActivity: MainActivity - lateinit var detachListener: DetachListener + var detachListener: DetachListener? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -232,7 +231,7 @@ class NoteFragment : Fragment(), SyncManager.SyncListener { override fun onDetach() { super.onDetach() - detachListener.addDrawerToggle() + detachListener?.addDrawerToggle() } interface DetachListener { From 43e8600bf769dce7a94307a222a5cd461954e4e8 Mon Sep 17 00:00:00 2001 From: nbau21 Date: Fri, 10 Mar 2017 17:55:15 -0800 Subject: [PATCH 6/8] Fix note title and menu items --- .../standardnotes/notes/frag/NoteFragment.kt | 8 ++++++ app/src/main/res/menu-sw600dp-land/note.xml | 26 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 app/src/main/res/menu-sw600dp-land/note.xml diff --git a/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt b/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt index 34c59c2..8b57b63 100644 --- a/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt +++ b/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt @@ -55,6 +55,7 @@ class NoteFragment : Fragment(), SyncManager.SyncListener { override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + activity.setTitle(R.string.title_activity_note) val noteUuid = savedInstanceState?.getString(NoteListFragment.EXTRA_NOTE_ID) ?: @@ -170,6 +171,12 @@ class NoteFragment : Fragment(), SyncManager.SyncListener { inflater.inflate(R.menu.note, menu) } + override fun onPrepareOptionsMenu(menu: Menu) { + super.onPrepareOptionsMenu(menu) + menu.clear() + activity.menuInflater.inflate(R.menu.note, menu) + } + override fun onOptionsItemSelected(item: MenuItem?): Boolean { when (item?.itemId) { R.id.tags -> { @@ -231,6 +238,7 @@ class NoteFragment : Fragment(), SyncManager.SyncListener { override fun onDetach() { super.onDetach() + activity.setTitle(R.string.app_name) detachListener?.addDrawerToggle() } diff --git a/app/src/main/res/menu-sw600dp-land/note.xml b/app/src/main/res/menu-sw600dp-land/note.xml new file mode 100644 index 0000000..ca9f94b --- /dev/null +++ b/app/src/main/res/menu-sw600dp-land/note.xml @@ -0,0 +1,26 @@ + + + + + + + + + + \ No newline at end of file From 6a7eddd2c30262f2d2cd431346c3119290391701 Mon Sep 17 00:00:00 2001 From: nbau21 Date: Fri, 10 Mar 2017 20:45:02 -0800 Subject: [PATCH 7/8] Clean up code --- .../notes/StarterActivityForLargeLayout.java | 254 ------------------ .../notes/StarterActivityTest.java | 73 +++-- .../org/standardnotes/notes/TestHelper.java | 10 + .../org/standardnotes/notes/MainActivity.kt | 102 +++---- .../standardnotes/notes/frag/NoteFragment.kt | 10 +- 5 files changed, 101 insertions(+), 348 deletions(-) delete mode 100644 app/src/androidTest/java/org/standardnotes/notes/StarterActivityForLargeLayout.java diff --git a/app/src/androidTest/java/org/standardnotes/notes/StarterActivityForLargeLayout.java b/app/src/androidTest/java/org/standardnotes/notes/StarterActivityForLargeLayout.java deleted file mode 100644 index 01a1f3b..0000000 --- a/app/src/androidTest/java/org/standardnotes/notes/StarterActivityForLargeLayout.java +++ /dev/null @@ -1,254 +0,0 @@ -package org.standardnotes.notes; - - -import android.content.Intent; -import android.support.test.espresso.Espresso; -import android.support.test.espresso.IdlingResource; -import android.support.test.espresso.ViewInteraction; -import android.support.test.rule.ActivityTestRule; -import android.support.test.runner.AndroidJUnit4; -import android.test.suitebuilder.annotation.LargeTest; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.UUID; - -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.Espresso.pressBack; -import static android.support.test.espresso.action.ViewActions.click; -import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard; -import static android.support.test.espresso.action.ViewActions.replaceText; -import static android.support.test.espresso.action.ViewActions.scrollTo; -import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition; -import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; -import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription; -import static android.support.test.espresso.matcher.ViewMatchers.withId; -import static android.support.test.espresso.matcher.ViewMatchers.withParent; -import static android.support.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.anyOf; -import static org.hamcrest.Matchers.not; -import static org.standardnotes.notes.TestHelper.childAtPosition; - -@LargeTest -@RunWith(AndroidJUnit4.class) -public class StarterActivityForLargeLayout { - - @Rule - public ActivityTestRule mActivityTestRule = new ActivityTestRule<>(LoginActivity.class); - - static String email = UUID.randomUUID().toString(); - static boolean signedup = false; - - @Before - public void signupin() { - mActivityTestRule.launchActivity(new Intent()); - IdlingResource idlingResource = new ProgressIdlingResource(mActivityTestRule.getActivity()); - Espresso.registerIdlingResources(idlingResource); - - if (!SApplication.Companion.getInstance().getValueStore().getServer().contains("staging")) { - throw new RuntimeException("These tests add lots of test users - don't run against a live server."); - } - - ViewInteraction appCompatAutoCompleteTextView = onView( - withId(R.id.email)); - appCompatAutoCompleteTextView.perform(scrollTo(), click()); - - ViewInteraction appCompatAutoCompleteTextView3 = onView( - withId(R.id.email)); - appCompatAutoCompleteTextView3.perform(scrollTo(), replaceText(email), closeSoftKeyboard()); - - ViewInteraction appCompatEditText = onView( - withId(R.id.password)); - appCompatEditText.perform(scrollTo(), replaceText("aaa"), closeSoftKeyboard()); - - if (!signedup) { - ViewInteraction appCompatButton = onView( - allOf(withText("Register"), - withParent(allOf(withId(R.id.email_login_form), - withParent(withId(R.id.login_form)))))); - appCompatButton.perform(scrollTo(), click()); - - ViewInteraction appCompatEditText2 = onView( - allOf(withId(R.id.confirm_password), isDisplayed())); - appCompatEditText2.perform(replaceText("aaa"), closeSoftKeyboard()); - - ViewInteraction appCompatButton2 = onView( - allOf(withId(android.R.id.button1), withText("OK"))); - appCompatButton2.perform(scrollTo(), click()); - signedup = true; - } else { - onView( - allOf(withText("Sign in"))).perform(click()); - } - - Espresso.unregisterIdlingResources(idlingResource); - } - - @After - public void logout() { - ViewInteraction actionMenuItemView = onView(allOf(withId(R.id.settings), isDisplayed())); - actionMenuItemView.perform(click()); - - ViewInteraction appCompatButton = onView( - allOf(withId(R.id.logout), withText("Log out"))); - appCompatButton.perform(scrollTo(), click()); - } - - @Test - public void createNote() { - ViewInteraction newNoteButton = onView(anyOf(withId(R.id.fab_new_note), withId(R.id.new_note))); - newNoteButton.perform(click()); - - ViewInteraction appCompatEditText = onView( - withId(R.id.titleEdit)); - appCompatEditText.perform(scrollTo(), click()); - - ViewInteraction appCompatEditText2 = onView( - withId(R.id.titleEdit)); - appCompatEditText2.perform(scrollTo(), replaceText("Title1"), closeSoftKeyboard()); - - ViewInteraction appCompatEditText14 = onView( - allOf(withId(R.id.bodyEdit))); - appCompatEditText14.perform(scrollTo(), replaceText("body1"), closeSoftKeyboard()); - - ViewInteraction actionMenuItemView = onView( - allOf(withId(R.id.tags), withContentDescription("Tags"), isDisplayed())); - actionMenuItemView.perform(click()); - - pressBack(); - - appCompatEditText14.perform(replaceText("body1a"), closeSoftKeyboard()); - - // Not sure why adding this delay works, not a good solution. - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - ViewInteraction textView = onView( - allOf(withId(R.id.text), withText("body1a"), - childAtPosition( - childAtPosition( - withId(R.id.list_note), - 0), - 1), - isDisplayed())); - textView.check(matches(withText("body1a"))); - - ViewInteraction textView2 = onView( - allOf(withId(R.id.title), withText("Title1"), - childAtPosition( - childAtPosition( - withId(R.id.list_note), - 0), - 0), - isDisplayed())); - textView2.check(matches(withText("Title1"))); - - logout(); - signupin(); - - textView2.check(matches(withText("Title1"))); - textView.check(matches(withText("body1a"))); - } - - @Test - public void tagSomething() { - ViewInteraction newNoteButton = onView(anyOf(withId(R.id.fab_new_note), withId(R.id.new_note))); - newNoteButton.perform(click()); - - ViewInteraction appCompatEditText = onView( - withId(R.id.titleEdit)); - appCompatEditText.perform(scrollTo(), click()); - - ViewInteraction appCompatEditText2 = onView( - withId(R.id.titleEdit)); - appCompatEditText2.perform(scrollTo(), replaceText("Title2"), closeSoftKeyboard()); - - ViewInteraction appCompatEditText14 = onView( - allOf(withId(R.id.bodyEdit))); - appCompatEditText14.perform(scrollTo(), replaceText("body2"), closeSoftKeyboard()); - - ViewInteraction tagsAction = onView( - allOf(withId(R.id.tags), withContentDescription("Tags"), isDisplayed())); - tagsAction.perform(click()); - onView(withId(R.id.fab_new_tag)).perform(click()); - onView( - allOf(withId(R.id.tag), isDisplayed())).perform(replaceText("tag1"), closeSoftKeyboard()); - onView( - allOf(withId(android.R.id.button1), withText("OK"))).perform(scrollTo(), click()); - onView(withId(R.id.fab_new_tag)).perform(click()); - onView( - allOf(withId(R.id.tag), isDisplayed())).perform(replaceText("tag2"), closeSoftKeyboard()); - onView( - allOf(withId(android.R.id.button1), withText("OK"))).perform(scrollTo(), click()); - onView( - withText("tag1")).perform(click()); - - pressBack(); - - logout(); - signupin(); - - ViewInteraction recyclerView = onView( - allOf(withId(R.id.list_note), isDisplayed())); - recyclerView.perform(actionOnItemAtPosition(0, click())); - onView(allOf(withText("tag1"), withId(R.id.tagText))).check(matches(isDisplayed())); - - tagsAction.perform(click()); - onView( - withText("tag1")).perform(click()); // deselect - onView( - withText("tag2")).perform(click()); // select - pressBack(); - onView(allOf(withText("tag2"), withId(R.id.tagText))).check(matches(isDisplayed())); - onView(withText("tag1")).check(matches(not(isDisplayed()))); - - logout(); - signupin(); - - recyclerView.perform(actionOnItemAtPosition(0, click())); - onView(allOf(withText("tag2"), withId(R.id.tagText))).check(matches(isDisplayed())); - onView(withText("tag1")).check(matches(not(isDisplayed()))); - } - - @Test - public void openCloseOpenClose() { - ViewInteraction newNoteButton = onView(anyOf(withId(R.id.fab_new_note), withId(R.id.new_note))); - newNoteButton.perform(click()); - - ViewInteraction appCompatEditText = onView( - withId(R.id.titleEdit)); - appCompatEditText.perform(scrollTo(), click()); - - ViewInteraction appCompatEditText2 = onView( - withId(R.id.titleEdit)); - appCompatEditText2.perform(scrollTo(), replaceText("Title2"), closeSoftKeyboard()); - - ViewInteraction appCompatEditText14 = onView( - allOf(withId(R.id.bodyEdit))); - appCompatEditText14.perform(scrollTo(), replaceText("body2"), closeSoftKeyboard()); - - ViewInteraction recyclerView = onView( - allOf(withId(R.id.list_note), isDisplayed())); - - recyclerView.perform(actionOnItemAtPosition(0, click())); - recyclerView.perform(actionOnItemAtPosition(0, click())); - recyclerView.perform(actionOnItemAtPosition(0, click())); - recyclerView.perform(actionOnItemAtPosition(0, click())); - recyclerView.perform(actionOnItemAtPosition(0, click())); - recyclerView.perform(actionOnItemAtPosition(0, click())); - recyclerView.perform(actionOnItemAtPosition(0, click())); - recyclerView.perform(actionOnItemAtPosition(0, click())); - recyclerView.perform(actionOnItemAtPosition(0, click())); - recyclerView.perform(actionOnItemAtPosition(0, click())); - recyclerView.perform(actionOnItemAtPosition(0, click())); - recyclerView.perform(actionOnItemAtPosition(0, click())); - } -} diff --git a/app/src/androidTest/java/org/standardnotes/notes/StarterActivityTest.java b/app/src/androidTest/java/org/standardnotes/notes/StarterActivityTest.java index 3ff9609..e5f54f0 100644 --- a/app/src/androidTest/java/org/standardnotes/notes/StarterActivityTest.java +++ b/app/src/androidTest/java/org/standardnotes/notes/StarterActivityTest.java @@ -8,13 +8,6 @@ import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.LargeTest; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewParent; - -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -123,7 +116,9 @@ public void createNote() { allOf(withId(R.id.bodyEdit))); appCompatEditText14.perform(scrollTo(), replaceText("body1"), closeSoftKeyboard()); - pressBack(); + if (!TestHelper.isScreenSw600dpAndLandscape(mActivityTestRule.getActivity())) { + pressBack(); + } ViewInteraction recyclerView = onView( allOf(withId(R.id.list_note), isDisplayed())); @@ -137,7 +132,16 @@ public void createNote() { appCompatEditText14.perform(scrollTo(), replaceText("body1a"), closeSoftKeyboard()); - pressBack(); + if (!TestHelper.isScreenSw600dpAndLandscape(mActivityTestRule.getActivity())) { + pressBack(); + } else { + // Not sure why adding this delay works, not a good solution. + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } ViewInteraction textView = onView( allOf(withId(R.id.text), withText("body1a"), @@ -205,7 +209,9 @@ public void tagSomething() { pressBack(); - pressBack(); + if (!TestHelper.isScreenSw600dpAndLandscape(mActivityTestRule.getActivity())) { + pressBack(); + } logout(); signupin(); @@ -223,7 +229,10 @@ public void tagSomething() { pressBack(); onView(allOf(withText("tag2"), withId(R.id.tagText))).check(matches(isDisplayed())); onView(withText("tag1")).check(matches(not(isDisplayed()))); - pressBack(); + + if (!TestHelper.isScreenSw600dpAndLandscape(mActivityTestRule.getActivity())) { + pressBack(); + } logout(); signupin(); @@ -232,7 +241,9 @@ public void tagSomething() { onView(allOf(withText("tag2"), withId(R.id.tagText))).check(matches(isDisplayed())); onView(withText("tag1")).check(matches(not(isDisplayed()))); - pressBack(); + if (!TestHelper.isScreenSw600dpAndLandscape(mActivityTestRule.getActivity())) { + pressBack(); + } } @Test @@ -251,33 +262,21 @@ public void openCloseOpenClose() { ViewInteraction appCompatEditText14 = onView( allOf(withId(R.id.bodyEdit))); appCompatEditText14.perform(scrollTo(), replaceText("body2"), closeSoftKeyboard()); - pressBack(); + + if (!TestHelper.isScreenSw600dpAndLandscape(mActivityTestRule.getActivity())) { + pressBack(); + } ViewInteraction recyclerView = onView( allOf(withId(R.id.list_note), isDisplayed())); - recyclerView.perform(actionOnItemAtPosition(0, click())); - pressBack(); - recyclerView.perform(actionOnItemAtPosition(0, click())); - pressBack(); - recyclerView.perform(actionOnItemAtPosition(0, click())); - pressBack(); - recyclerView.perform(actionOnItemAtPosition(0, click())); - pressBack(); - recyclerView.perform(actionOnItemAtPosition(0, click())); - pressBack(); - recyclerView.perform(actionOnItemAtPosition(0, click())); - pressBack(); - recyclerView.perform(actionOnItemAtPosition(0, click())); - pressBack(); - recyclerView.perform(actionOnItemAtPosition(0, click())); - pressBack(); - recyclerView.perform(actionOnItemAtPosition(0, click())); - pressBack(); - recyclerView.perform(actionOnItemAtPosition(0, click())); - pressBack(); - recyclerView.perform(actionOnItemAtPosition(0, click())); - pressBack(); - recyclerView.perform(actionOnItemAtPosition(0, click())); - pressBack(); + + int i = 0; + do { + recyclerView.perform(actionOnItemAtPosition(0, click())); + if (!TestHelper.isScreenSw600dpAndLandscape(mActivityTestRule.getActivity())) { + pressBack(); + } + i++; + } while (i < 10); } } diff --git a/app/src/androidTest/java/org/standardnotes/notes/TestHelper.java b/app/src/androidTest/java/org/standardnotes/notes/TestHelper.java index 0f4204b..4fc086b 100644 --- a/app/src/androidTest/java/org/standardnotes/notes/TestHelper.java +++ b/app/src/androidTest/java/org/standardnotes/notes/TestHelper.java @@ -1,5 +1,8 @@ package org.standardnotes.notes; +import android.app.Activity; +import android.content.res.Configuration; +import android.util.DisplayMetrics; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; @@ -28,4 +31,11 @@ public boolean matchesSafely(View view) { } }; } + + public static boolean isScreenSw600dpAndLandscape(Activity activity) { + DisplayMetrics displayMetrics = activity.getResources().getDisplayMetrics(); + float widthDp = displayMetrics.widthPixels / displayMetrics.density; + return widthDp >= 600 && activity.getResources().getConfiguration() + .orientation == Configuration.ORIENTATION_LANDSCAPE; + } } diff --git a/app/src/main/java/org/standardnotes/notes/MainActivity.kt b/app/src/main/java/org/standardnotes/notes/MainActivity.kt index 2957718..4061a39 100644 --- a/app/src/main/java/org/standardnotes/notes/MainActivity.kt +++ b/app/src/main/java/org/standardnotes/notes/MainActivity.kt @@ -15,58 +15,29 @@ import org.standardnotes.notes.frag.NoteListFragment class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment.OnNewNoteClickListener, NoteFragment.DetachListener { - override fun newNoteListener(uuid: String) { - noteFragment = NoteFragment() - noteFragment!!.detachListener = this - val bundle = Bundle() - bundle.putString(NoteListFragment.EXTRA_NOTE_ID, uuid) - noteFragment!!.arguments = bundle - if (findViewById(R.id.note_container) == null) { - removeDrawerToggle() - supportFragmentManager - .beginTransaction() - .add(R.id.note_list_container, noteFragment, "note_fragment") - .addToBackStack(null) - .commit() - } else { - supportFragmentManager - .beginTransaction() - .replace(R.id.note_container, noteFragment, "note_fragment") - .commit() - } - } + val TAG_NOTE_FRAGMENT = "note_fragment" + val TAG_NOTE_LIST_FRAGMENT = "note_list_fragment" + val EXTRA_TAG = "tag" private lateinit var noteListFragment: NoteListFragment private var noteFragment: NoteFragment? = null - lateinit var drawerToggle: ActionBarDrawerToggle + private lateinit var drawerToggle: ActionBarDrawerToggle private var selectedTagId = "" - override fun onSyncStarted() { - } - - override fun onSyncFailed() { - onSyncCompleted() - } - - override fun onSyncCompleted() { - updateTagsMenu() - noteListFragment.refreshNotesForTag(selectedTagId) - } - override fun onSaveInstanceState(outState: Bundle?) { super.onSaveInstanceState(outState) - outState!!.putString("tag", selectedTagId) - supportFragmentManager.putFragment(outState, "note_list_fragment", noteListFragment) - if (supportFragmentManager.findFragmentByTag("note_fragment") != null ) { - supportFragmentManager.putFragment(outState, "note_fragment", noteFragment) + outState!!.putString(EXTRA_TAG, selectedTagId) + supportFragmentManager.putFragment(outState, TAG_NOTE_LIST_FRAGMENT, noteListFragment) + if (supportFragmentManager.findFragmentByTag(TAG_NOTE_FRAGMENT) != null ) { + supportFragmentManager.putFragment(outState, TAG_NOTE_FRAGMENT, noteFragment) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - if (savedInstanceState != null && savedInstanceState?.containsKey("tag")) { - selectedTagId = savedInstanceState.getString("tag") + if (savedInstanceState != null && savedInstanceState?.containsKey(EXTRA_TAG)) { + selectedTagId = savedInstanceState.getString(EXTRA_TAG) } setContentView(R.layout.activity_main) @@ -80,11 +51,11 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. noteListFragment = NoteListFragment() supportFragmentManager .beginTransaction() - .replace(R.id.note_list_container, noteListFragment, "note_list_fragment") + .replace(R.id.note_list_container, noteListFragment, TAG_NOTE_LIST_FRAGMENT) .commit() } else { - noteListFragment = supportFragmentManager.findFragmentByTag("note_list_fragment") as NoteListFragment - noteFragment = supportFragmentManager.findFragmentByTag("note_fragment") as? NoteFragment + noteListFragment = supportFragmentManager.findFragmentByTag(TAG_NOTE_LIST_FRAGMENT) as NoteListFragment + noteFragment = supportFragmentManager.findFragmentByTag(TAG_NOTE_FRAGMENT) as? NoteFragment noteFragment?.detachListener = this if (noteFragment != null) { @@ -103,8 +74,8 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. supportFragmentManager .beginTransaction() - .add(R.id.note_list_container, noteListFragment, "note_list_fragment") - .replace(R.id.note_container, noteFragment, "note_fragment") + .add(R.id.note_list_container, noteListFragment, TAG_NOTE_LIST_FRAGMENT) + .replace(R.id.note_container, noteFragment, TAG_NOTE_FRAGMENT) .commit() } else { @@ -112,7 +83,7 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. removeDrawerToggle() supportFragmentManager .beginTransaction() - .add(R.id.note_list_container, noteFragment, "note_fragment") + .add(R.id.note_list_container, noteFragment, TAG_NOTE_FRAGMENT) .addToBackStack(null) .commit() } @@ -161,16 +132,37 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. selectedTagId = selectedId // In case selected tag wasn't found in list } + fun removeDrawerToggle() { + drawerToggle.isDrawerIndicatorEnabled = false + supportActionBar?.setDisplayHomeAsUpEnabled(false) + supportActionBar?.setHomeButtonEnabled(false) + } + override fun addDrawerToggle() { drawerToggle.isDrawerIndicatorEnabled = true supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setHomeButtonEnabled(true) } - fun removeDrawerToggle() { - drawerToggle.isDrawerIndicatorEnabled = false - supportActionBar?.setDisplayHomeAsUpEnabled(false) - supportActionBar?.setHomeButtonEnabled(false) + override fun newNoteListener(uuid: String) { + noteFragment = NoteFragment() + noteFragment!!.detachListener = this + val bundle = Bundle() + bundle.putString(NoteListFragment.EXTRA_NOTE_ID, uuid) + noteFragment!!.arguments = bundle + if (findViewById(R.id.note_container) == null) { + removeDrawerToggle() + supportFragmentManager + .beginTransaction() + .add(R.id.note_list_container, noteFragment, TAG_NOTE_FRAGMENT) + .addToBackStack(null) + .commit() + } else { + supportFragmentManager + .beginTransaction() + .replace(R.id.note_container, noteFragment, TAG_NOTE_FRAGMENT) + .commit() + } } override fun onResume() { @@ -215,4 +207,16 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. super.onPostCreate(savedInstanceState) drawerToggle?.syncState() } + + override fun onSyncStarted() { + } + + override fun onSyncFailed() { + onSyncCompleted() + } + + override fun onSyncCompleted() { + updateTagsMenu() + noteListFragment.refreshNotesForTag(selectedTagId) + } } diff --git a/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt b/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt index 8b57b63..06baa25 100644 --- a/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt +++ b/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt @@ -1,12 +1,12 @@ package org.standardnotes.notes.frag -import android.content.Context import android.content.Intent import android.graphics.Typeface import android.os.Bundle import android.os.Handler import android.preference.PreferenceManager import android.support.v4.app.Fragment +import android.support.v7.app.AppCompatActivity import android.text.Editable import android.text.TextWatcher import android.view.* @@ -40,7 +40,6 @@ class NoteFragment : Fragment(), SyncManager.SyncListener { lateinit var note: Note lateinit var tags: List - lateinit var mActivity: MainActivity var detachListener: DetachListener? = null override fun onCreate(savedInstanceState: Bundle?) { @@ -120,11 +119,6 @@ class NoteFragment : Fragment(), SyncManager.SyncListener { setSubtitle(if (note.dirty) getString(R.string.sync_progress_error) else getString(R.string.sync_progress_finished)) } - override fun onAttach(context: Context?) { - super.onAttach(context) - mActivity = (context as MainActivity) - } - override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putString(NoteListFragment.EXTRA_NOTE_ID, note.uuid) @@ -191,7 +185,7 @@ class NoteFragment : Fragment(), SyncManager.SyncListener { fun setSubtitle(subTitle: String) { bodyEdit.postDelayed({ - mActivity.supportActionBar!!.subtitle = subTitle + (activity as AppCompatActivity).supportActionBar!!.subtitle = subTitle }, 100) } From 4f12c3e8ab2240e6fcd1a8ae3ee893216f16ef47 Mon Sep 17 00:00:00 2001 From: nbau21 Date: Tue, 14 Mar 2017 22:25:23 -0700 Subject: [PATCH 8/8] Some changes as per code review: * Check for null noteUuid * Use w600dp instead of sw600dp-land * Rename note list and note containers to master and detail containers * Broke e2e test for a landscaped phablet. The way the tests are set up: When re-launching the app, the app starts in portrait mode and rotates after a split second. I think this is because for "phones", Android does not allow landscape mode in the menu. Tests in portrait and in actual tablet layout should work fine. --- .../notes/StarterActivityTest.java | 23 +++++++------------ .../org/standardnotes/notes/TestHelper.java | 6 ++--- .../org/standardnotes/notes/MainActivity.kt | 16 ++++++------- .../standardnotes/notes/frag/NoteFragment.kt | 18 +++++++-------- .../frag_note_list.xml | 0 .../main/res/layout/single_pane_container.xml | 2 +- .../main/res/layout/two_pane_container.xml | 4 ++-- .../note.xml | 0 .../note_list.xml | 0 .../refs.xml | 0 10 files changed, 30 insertions(+), 39 deletions(-) rename app/src/main/res/{layout-sw600dp-land => layout-w600dp}/frag_note_list.xml (100%) rename app/src/main/res/{menu-sw600dp-land => menu-w600dp}/note.xml (100%) rename app/src/main/res/{menu-sw600dp-land => menu-w600dp}/note_list.xml (100%) rename app/src/main/res/{values-sw600dp-land => values-w600dp}/refs.xml (100%) diff --git a/app/src/androidTest/java/org/standardnotes/notes/StarterActivityTest.java b/app/src/androidTest/java/org/standardnotes/notes/StarterActivityTest.java index e5f54f0..522a5e3 100644 --- a/app/src/androidTest/java/org/standardnotes/notes/StarterActivityTest.java +++ b/app/src/androidTest/java/org/standardnotes/notes/StarterActivityTest.java @@ -116,7 +116,7 @@ public void createNote() { allOf(withId(R.id.bodyEdit))); appCompatEditText14.perform(scrollTo(), replaceText("body1"), closeSoftKeyboard()); - if (!TestHelper.isScreenSw600dpAndLandscape(mActivityTestRule.getActivity())) { + if (!TestHelper.isScreenW600dp(mActivityTestRule.getActivity())) { pressBack(); } @@ -132,15 +132,8 @@ public void createNote() { appCompatEditText14.perform(scrollTo(), replaceText("body1a"), closeSoftKeyboard()); - if (!TestHelper.isScreenSw600dpAndLandscape(mActivityTestRule.getActivity())) { + if (!TestHelper.isScreenW600dp(mActivityTestRule.getActivity())) { pressBack(); - } else { - // Not sure why adding this delay works, not a good solution. - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } } ViewInteraction textView = onView( @@ -209,8 +202,8 @@ public void tagSomething() { pressBack(); - if (!TestHelper.isScreenSw600dpAndLandscape(mActivityTestRule.getActivity())) { - pressBack(); + if (!TestHelper.isScreenW600dp(mActivityTestRule.getActivity())) { + pressBack(); } logout(); @@ -230,7 +223,7 @@ public void tagSomething() { onView(allOf(withText("tag2"), withId(R.id.tagText))).check(matches(isDisplayed())); onView(withText("tag1")).check(matches(not(isDisplayed()))); - if (!TestHelper.isScreenSw600dpAndLandscape(mActivityTestRule.getActivity())) { + if (!TestHelper.isScreenW600dp(mActivityTestRule.getActivity())) { pressBack(); } @@ -241,7 +234,7 @@ public void tagSomething() { onView(allOf(withText("tag2"), withId(R.id.tagText))).check(matches(isDisplayed())); onView(withText("tag1")).check(matches(not(isDisplayed()))); - if (!TestHelper.isScreenSw600dpAndLandscape(mActivityTestRule.getActivity())) { + if (!TestHelper.isScreenW600dp(mActivityTestRule.getActivity())) { pressBack(); } } @@ -263,7 +256,7 @@ public void openCloseOpenClose() { allOf(withId(R.id.bodyEdit))); appCompatEditText14.perform(scrollTo(), replaceText("body2"), closeSoftKeyboard()); - if (!TestHelper.isScreenSw600dpAndLandscape(mActivityTestRule.getActivity())) { + if (!TestHelper.isScreenW600dp(mActivityTestRule.getActivity())) { pressBack(); } @@ -273,7 +266,7 @@ public void openCloseOpenClose() { int i = 0; do { recyclerView.perform(actionOnItemAtPosition(0, click())); - if (!TestHelper.isScreenSw600dpAndLandscape(mActivityTestRule.getActivity())) { + if (!TestHelper.isScreenW600dp(mActivityTestRule.getActivity())) { pressBack(); } i++; diff --git a/app/src/androidTest/java/org/standardnotes/notes/TestHelper.java b/app/src/androidTest/java/org/standardnotes/notes/TestHelper.java index 4fc086b..78e95ea 100644 --- a/app/src/androidTest/java/org/standardnotes/notes/TestHelper.java +++ b/app/src/androidTest/java/org/standardnotes/notes/TestHelper.java @@ -1,7 +1,6 @@ package org.standardnotes.notes; import android.app.Activity; -import android.content.res.Configuration; import android.util.DisplayMetrics; import android.view.View; import android.view.ViewGroup; @@ -32,10 +31,9 @@ public boolean matchesSafely(View view) { }; } - public static boolean isScreenSw600dpAndLandscape(Activity activity) { + public static boolean isScreenW600dp(Activity activity) { DisplayMetrics displayMetrics = activity.getResources().getDisplayMetrics(); float widthDp = displayMetrics.widthPixels / displayMetrics.density; - return widthDp >= 600 && activity.getResources().getConfiguration() - .orientation == Configuration.ORIENTATION_LANDSCAPE; + return widthDp >= 600; } } diff --git a/app/src/main/java/org/standardnotes/notes/MainActivity.kt b/app/src/main/java/org/standardnotes/notes/MainActivity.kt index 4061a39..aead60d 100644 --- a/app/src/main/java/org/standardnotes/notes/MainActivity.kt +++ b/app/src/main/java/org/standardnotes/notes/MainActivity.kt @@ -51,7 +51,7 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. noteListFragment = NoteListFragment() supportFragmentManager .beginTransaction() - .replace(R.id.note_list_container, noteListFragment, TAG_NOTE_LIST_FRAGMENT) + .replace(R.id.master_container, noteListFragment, TAG_NOTE_LIST_FRAGMENT) .commit() } else { noteListFragment = supportFragmentManager.findFragmentByTag(TAG_NOTE_LIST_FRAGMENT) as NoteListFragment @@ -66,7 +66,7 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. .remove(noteFragment) .commitNow() - if (findViewById(R.id.note_container) != null) { + if (findViewById(R.id.detail_container) != null) { supportFragmentManager .beginTransaction() .remove(noteListFragment) @@ -74,8 +74,8 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. supportFragmentManager .beginTransaction() - .add(R.id.note_list_container, noteListFragment, TAG_NOTE_LIST_FRAGMENT) - .replace(R.id.note_container, noteFragment, TAG_NOTE_FRAGMENT) + .add(R.id.master_container, noteListFragment, TAG_NOTE_LIST_FRAGMENT) + .replace(R.id.detail_container, noteFragment, TAG_NOTE_FRAGMENT) .commit() } else { @@ -83,7 +83,7 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. removeDrawerToggle() supportFragmentManager .beginTransaction() - .add(R.id.note_list_container, noteFragment, TAG_NOTE_FRAGMENT) + .add(R.id.master_container, noteFragment, TAG_NOTE_FRAGMENT) .addToBackStack(null) .commit() } @@ -150,17 +150,17 @@ class MainActivity : BaseActivity(), SyncManager.SyncListener, NoteListFragment. val bundle = Bundle() bundle.putString(NoteListFragment.EXTRA_NOTE_ID, uuid) noteFragment!!.arguments = bundle - if (findViewById(R.id.note_container) == null) { + if (findViewById(R.id.detail_container) == null) { removeDrawerToggle() supportFragmentManager .beginTransaction() - .add(R.id.note_list_container, noteFragment, TAG_NOTE_FRAGMENT) + .add(R.id.master_container, noteFragment, TAG_NOTE_FRAGMENT) .addToBackStack(null) .commit() } else { supportFragmentManager .beginTransaction() - .replace(R.id.note_container, noteFragment, TAG_NOTE_FRAGMENT) + .replace(R.id.detail_container, noteFragment, TAG_NOTE_FRAGMENT) .commit() } } diff --git a/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt b/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt index 06baa25..da32747 100644 --- a/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt +++ b/app/src/main/java/org/standardnotes/notes/frag/NoteFragment.kt @@ -42,14 +42,14 @@ class NoteFragment : Fragment(), SyncManager.SyncListener { lateinit var tags: List var detachListener: DetachListener? = null - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setHasOptionsMenu(true) - } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setHasOptionsMenu(true) + } - override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { - val view = inflater!!.inflate(R.layout.frag_note, container, false) - return view + override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { + val view = inflater!!.inflate(R.layout.frag_note, container, false) + return view } override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { @@ -59,8 +59,8 @@ class NoteFragment : Fragment(), SyncManager.SyncListener { val noteUuid = savedInstanceState?.getString(NoteListFragment.EXTRA_NOTE_ID) ?: arguments?.getString(NoteListFragment.EXTRA_NOTE_ID) - if (noteUuid != "") { - note = SApplication.instance.noteStore.getNote(noteUuid!!)!! + if (noteUuid != null && noteUuid != "") { + note = SApplication.instance.noteStore.getNote(noteUuid)!! tags = SApplication.instance.noteStore.getTagsForNote(noteUuid) } else { note = newNote() diff --git a/app/src/main/res/layout-sw600dp-land/frag_note_list.xml b/app/src/main/res/layout-w600dp/frag_note_list.xml similarity index 100% rename from app/src/main/res/layout-sw600dp-land/frag_note_list.xml rename to app/src/main/res/layout-w600dp/frag_note_list.xml diff --git a/app/src/main/res/layout/single_pane_container.xml b/app/src/main/res/layout/single_pane_container.xml index e9d31fb..42d6727 100644 --- a/app/src/main/res/layout/single_pane_container.xml +++ b/app/src/main/res/layout/single_pane_container.xml @@ -1,6 +1,6 @@