├── flow ├── gradle.properties ├── src │ ├── main │ │ ├── java │ │ │ └── flow │ │ │ │ ├── HistoryFilter.java │ │ │ │ ├── NotPersistentHistoryFilter.java │ │ │ │ ├── Direction.java │ │ │ │ ├── MultiKey.java │ │ │ │ ├── ClassKey.java │ │ │ │ ├── KeyParceler.java │ │ │ │ ├── TreeKey.java │ │ │ │ ├── TraversalCallback.java │ │ │ │ ├── NotPersistent.java │ │ │ │ ├── ServicesFactory.java │ │ │ │ ├── Preconditions.java │ │ │ │ ├── KeyChanger.java │ │ │ │ ├── DefaultKeyChanger.java │ │ │ │ ├── FlowContextWrapper.java │ │ │ │ ├── Traversal.java │ │ │ │ ├── Dispatcher.java │ │ │ │ ├── InternalContextWrapper.java │ │ │ │ ├── Services.java │ │ │ │ ├── Installer.java │ │ │ │ ├── KeyDispatcher.java │ │ │ │ ├── State.java │ │ │ │ └── KeyManager.java │ │ └── AndroidManifest.xml │ └── test │ │ └── java │ │ └── flow │ │ ├── TestKey.java │ │ └── HistoryTest.java └── build.gradle ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties └── gradle-mvn-push.gradle ├── flow-sample-multikey ├── src │ ├── main │ │ ├── res │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ └── styles.xml │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ └── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ ├── java │ │ │ └── flow │ │ │ │ └── sample │ │ │ │ └── multikey │ │ │ │ ├── ScreenOne.java │ │ │ │ ├── ScreenTwo.java │ │ │ │ ├── DialogScreen.java │ │ │ │ ├── ActivityLifecycleCallbackAdapter.java │ │ │ │ └── MultiKeySampleActivity.java │ │ └── AndroidManifest.xml │ └── androidTest │ │ └── java │ │ └── flow │ │ └── sample │ │ └── multikey │ │ └── MultiKeySampleTest.java └── build.gradle ├── flow-sample-basic ├── src │ ├── main │ │ ├── res │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ └── styles.xml │ │ │ └── layout │ │ │ │ ├── basic_activity_frame.xml │ │ │ │ ├── welcome_screen.xml │ │ │ │ └── hello_screen.xml │ │ ├── java │ │ │ └── flow │ │ │ │ └── sample │ │ │ │ └── basic │ │ │ │ ├── BasicKeyParceler.java │ │ │ │ ├── WelcomeScreen.java │ │ │ │ ├── BasicSampleActivity.java │ │ │ │ ├── WelcomeView.java │ │ │ │ ├── HelloView.java │ │ │ │ ├── HelloScreen.java │ │ │ │ └── BasicDispatcher.java │ │ └── AndroidManifest.xml │ └── androidTest │ │ └── java │ │ └── flow │ │ └── sample │ │ └── basic │ │ └── BasicSampleTest.java └── build.gradle ├── flow-sample-tree ├── src │ ├── main │ │ ├── res │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ └── styles.xml │ │ │ └── layout │ │ │ │ ├── list_contacts_screen.xml │ │ │ │ ├── list_contacts_screen_row_view.xml │ │ │ │ ├── edit_name_screen.xml │ │ │ │ └── edit_email_screen.xml │ │ ├── java │ │ │ └── flow │ │ │ │ └── sample │ │ │ │ └── tree │ │ │ │ ├── ui │ │ │ │ ├── contacts │ │ │ │ │ ├── ContactsUiKey.java │ │ │ │ │ ├── list │ │ │ │ │ │ ├── ListContactsScreen.java │ │ │ │ │ │ ├── ListContactsView.java │ │ │ │ │ │ └── ContactsAdapter.java │ │ │ │ │ └── edit │ │ │ │ │ │ ├── EditEmailScreen.java │ │ │ │ │ │ ├── EditNameScreen.java │ │ │ │ │ │ ├── EditContactKey.java │ │ │ │ │ │ ├── ContactKey.java │ │ │ │ │ │ ├── EditNameView.java │ │ │ │ │ │ └── EditEmailView.java │ │ │ │ └── welcome │ │ │ │ │ └── WelcomeScreen.java │ │ │ │ ├── model │ │ │ │ ├── Contact.java │ │ │ │ ├── ContactEditor.java │ │ │ │ └── ContactsStorage.java │ │ │ │ ├── FlowServices.java │ │ │ │ └── TreeSampleActivity.java │ │ └── AndroidManifest.xml │ └── androidTest │ │ └── java │ │ └── flow │ │ └── sample │ │ └── tree │ │ └── FlowViewAssertions.java └── build.gradle ├── flow-sample-intents ├── src │ ├── main │ │ ├── res │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ └── styles.xml │ │ ├── java │ │ │ └── flow │ │ │ │ └── sample │ │ │ │ └── intents │ │ │ │ ├── IntentsStandardSampleActivity.java │ │ │ │ ├── StringParceler.java │ │ │ │ └── IntentsSingleInstanceSampleActivity.java │ │ └── AndroidManifest.xml │ └── androidTest │ │ └── java │ │ └── flow │ │ └── sample │ │ └── intents │ │ └── IntentsSampleTest.java └── build.gradle ├── flow-sample-helloworld ├── src │ ├── main │ │ ├── res │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ └── styles.xml │ │ ├── java │ │ │ └── flow │ │ │ │ └── sample │ │ │ │ └── helloworld │ │ │ │ └── HelloWorldActivity.java │ │ └── AndroidManifest.xml │ └── androidTest │ │ └── java │ │ └── flow │ │ └── sample │ │ └── helloworld │ │ └── HelloTest.java └── build.gradle ├── flow-sample-orientation-lock ├── src │ └── main │ │ ├── res │ │ ├── values │ │ │ ├── bools.xml │ │ │ ├── strings.xml │ │ │ ├── colors.xml │ │ │ └── styles.xml │ │ ├── values-land │ │ │ └── bools.xml │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ └── layout │ │ │ ├── orientation_activity_frame.xml │ │ │ ├── landscape_screen.xml │ │ │ └── loose_screen.xml │ │ ├── java │ │ └── flow │ │ │ └── sample │ │ │ └── orientation │ │ │ ├── OrientationSampleScreen.java │ │ │ ├── LooseScreen.java │ │ │ ├── LandscapeScreen.java │ │ │ ├── LandscapeView.java │ │ │ ├── LooseView.java │ │ │ ├── OrientationSampleActivity.java │ │ │ └── OrientationSampleDispatcher.java │ │ └── AndroidManifest.xml └── build.gradle ├── .gitignore ├── settings.gradle ├── CONTRIBUTING.md ├── gradle.properties ├── RELEASING.md ├── .travis.yml ├── .buildscript └── deploy_snapshot.sh ├── checkstyle.xml ├── CHANGELOG.md └── gradlew /flow/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_NAME=Flow 2 | POM_ARTIFACT_ID=flow 3 | POM_PACKAGING=jar 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /flow-sample-multikey/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Flow MultiKey Sample 3 | 4 | -------------------------------------------------------------------------------- /flow-sample-basic/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-basic/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-basic/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-basic/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-tree/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-tree/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-tree/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-tree/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-tree/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-tree/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-basic/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-basic/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-basic/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-basic/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-intents/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-intents/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-intents/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-intents/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-tree/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-tree/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-tree/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-tree/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-basic/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-basic/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-helloworld/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-helloworld/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-helloworld/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-helloworld/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-intents/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-intents/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-intents/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-intents/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-intents/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-intents/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-multikey/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-multikey/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-multikey/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-multikey/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-multikey/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-multikey/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-multikey/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-multikey/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-helloworld/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-helloworld/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-helloworld/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-helloworld/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-multikey/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-multikey/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/res/values/bools.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | 5 | -------------------------------------------------------------------------------- /flow-sample-helloworld/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-helloworld/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/res/values-land/bools.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | 5 | -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-orientation-lock/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-orientation-lock/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-orientation-lock/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-orientation-lock/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/square/flow/HEAD/flow-sample-orientation-lock/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IntelliJ IDEA 2 | .idea 3 | *.iml 4 | gen 5 | 6 | # Maven 7 | target/ 8 | pom.xml.versionsBackup 9 | 10 | # Gradle 11 | .gradle 12 | gradlew.bat 13 | build 14 | local.properties 15 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':flow' 2 | include ':flow-sample-helloworld' 3 | include ':flow-sample-intents' 4 | include ':flow-sample-basic' 5 | include ':flow-sample-multikey' 6 | include ':flow-sample-orientation-lock' 7 | include ':flow-sample-tree' 8 | -------------------------------------------------------------------------------- /flow-sample-multikey/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Sep 12 02:43:35 PDT 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip 7 | -------------------------------------------------------------------------------- /flow/src/main/java/flow/HistoryFilter.java: -------------------------------------------------------------------------------- 1 | package flow; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | /** 6 | * An object to which gets a chance to scrub the current {@link History} before 7 | * it is persisted. 8 | */ 9 | public interface HistoryFilter { 10 | @NonNull History scrubHistory(@NonNull History history); 11 | } 12 | -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/java/flow/sample/orientation/OrientationSampleScreen.java: -------------------------------------------------------------------------------- 1 | package flow.sample.orientation; 2 | 3 | import android.support.annotation.LayoutRes; 4 | 5 | abstract class OrientationSampleScreen { 6 | @LayoutRes abstract int getLayoutId(); 7 | 8 | boolean requiresLandscape() { 9 | return false; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /flow-sample-multikey/src/main/java/flow/sample/multikey/ScreenOne.java: -------------------------------------------------------------------------------- 1 | package flow.sample.multikey; 2 | 3 | public final class ScreenOne { 4 | @Override public String toString() { 5 | return "Click to advance to screen two."; 6 | } 7 | 8 | @Override public boolean equals(Object o) { 9 | return getClass().isInstance(o); 10 | } 11 | 12 | @Override public int hashCode() { 13 | return getClass().hashCode(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /flow-sample-multikey/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /flow-sample-multikey/src/main/java/flow/sample/multikey/ScreenTwo.java: -------------------------------------------------------------------------------- 1 | package flow.sample.multikey; 2 | 3 | public class ScreenTwo { 4 | @Override public String toString() { 5 | return "Click to pop back to screen one, skipping the dialog. " 6 | + "Or hit the back button to see the dialog again."; 7 | } 8 | 9 | @Override public boolean equals(Object o) { 10 | return getClass().isInstance(o); 11 | } 12 | 13 | @Override public int hashCode() { 14 | return getClass().hashCode(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /flow/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion versions.compileSdk 5 | buildToolsVersion versions.buildTools 6 | 7 | defaultConfig { 8 | minSdkVersion versions.minSdk 9 | versionName VERSION_NAME 10 | } 11 | } 12 | 13 | dependencies { 14 | implementation deps.support.annotations 15 | testImplementation deps.junit 16 | testImplementation deps.assertj 17 | testImplementation deps.mockito 18 | testImplementation deps.robolectric 19 | testImplementation deps.antTasks 20 | } 21 | 22 | apply from: rootProject.file('gradle/gradle-mvn-push.gradle') 23 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ============ 3 | 4 | If you would like to contribute code to Flow you can do so through GitHub by 5 | forking the repository and sending a pull request. 6 | 7 | When submitting code, please make every effort to follow existing conventions 8 | and style in order to keep the code as readable as possible. Please also make 9 | sure your code compiles by running `./gradlew clean build check`. 10 | 11 | Before your code can be accepted into the project you must also sign the 12 | [Individual Contributor License Agreement (CLA)][1]. 13 | 14 | 15 | [1]: https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1 16 | -------------------------------------------------------------------------------- /flow-sample-multikey/src/main/java/flow/sample/multikey/DialogScreen.java: -------------------------------------------------------------------------------- 1 | package flow.sample.multikey; 2 | 3 | import android.support.annotation.NonNull; 4 | import flow.MultiKey; 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | public final class DialogScreen implements MultiKey { 9 | final Object mainContent; 10 | 11 | public DialogScreen(Object mainContent) { 12 | this.mainContent = mainContent; 13 | } 14 | 15 | @Override public String toString() { 16 | return "Do you really want to see screen two?"; 17 | } 18 | 19 | @NonNull @Override public List getKeys() { 20 | return Collections.singletonList(mainContent); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /flow-sample-helloworld/src/androidTest/java/flow/sample/helloworld/HelloTest.java: -------------------------------------------------------------------------------- 1 | package flow.sample.helloworld; 2 | 3 | import android.support.test.rule.ActivityTestRule; 4 | import org.junit.Rule; 5 | import org.junit.Test; 6 | 7 | import static android.support.test.espresso.Espresso.onView; 8 | import static android.support.test.espresso.action.ViewActions.click; 9 | import static android.support.test.espresso.matcher.ViewMatchers.withText; 10 | 11 | public class HelloTest { 12 | @Rule public ActivityTestRule rule = new ActivityTestRule<>(HelloWorldActivity.class); 13 | 14 | @Test public void hello() { 15 | onView(withText("Hello, World!")).perform(click()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | VERSION_NAME=1.0.0-alpha4-SNAPSHOT 2 | GROUP=com.squareup.flow 3 | 4 | POM_DESCRIPTION=Flow helps you describe your app as a set of distinct screens. 5 | POM_URL=https://github.com/square/flow/ 6 | POM_SCM_URL=https://github.com/square/flow/ 7 | POM_SCM_CONNECTION=scm:git:git://github.com/square/flow.git 8 | POM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com/square/flow.git 9 | POM_LICENCE_NAME=Apache 2.0 10 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt 11 | POM_LICENCE_DIST=repo 12 | POM_ORGANIZATION_NAME=Square, Inc. 13 | POM_ORGANIZATION_URL=http://squareup.com 14 | POM_DEVELOPER_ID=square 15 | POM_DEVELOPER_NAME=Square, Inc. 16 | 17 | org.gradle.jvmargs=-Xmx1536M -------------------------------------------------------------------------------- /flow/src/main/java/flow/NotPersistentHistoryFilter.java: -------------------------------------------------------------------------------- 1 | package flow; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | /** 6 | * Default implementation of {@link HistoryFilter}, enforces the contract 7 | * documented on {@link NotPersistent}. 8 | */ 9 | class NotPersistentHistoryFilter implements HistoryFilter { 10 | @NonNull @Override public History scrubHistory(@NonNull History history) { 11 | History.Builder builder = History.emptyBuilder(); 12 | 13 | for (Object key : history.framesFromBottom()) { 14 | if (!key.getClass().isAnnotationPresent(NotPersistent.class)) { 15 | builder.push(key); 16 | } 17 | } 18 | 19 | return builder.build(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /flow-sample-multikey/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /flow/src/main/java/flow/Direction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow; 18 | 19 | public enum Direction { 20 | FORWARD, BACKWARD, REPLACE 21 | } 22 | -------------------------------------------------------------------------------- /flow-sample-basic/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | Flow Basic Sample 19 | 20 | -------------------------------------------------------------------------------- /flow-sample-tree/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | Flow Tree Sample 19 | 20 | -------------------------------------------------------------------------------- /flow-sample-helloworld/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | Flow Hello World 19 | 20 | -------------------------------------------------------------------------------- /flow-sample-intents/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | Flow Intents Sample 19 | 20 | -------------------------------------------------------------------------------- /flow/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 21 | -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | Flow Orientation Sample 19 | 20 | -------------------------------------------------------------------------------- /RELEASING.md: -------------------------------------------------------------------------------- 1 | Releasing 2 | ======== 3 | 4 | 1. Ensure everything builds and all tests pass, including integration tests. 5 | (Note that Integration tests can be flaky.) 6 | `./gradlew clean build check connectedCheck` 7 | 2. Change the version in `gradle.properties` to a non-SNAPSHOT version. 8 | 3. Update the `CHANGELOG.md` for the impending release. 9 | 4. Update the `README.md` with the new version. 10 | 5. `git commit -am "Prepare for release X.Y."` (where X.Y is the new version) 11 | 6. `git tag -a X.Y -m "Version X.Y"` (where X.Y is the new version) 12 | 7. `./gradlew clean uploadArchives` 13 | 8. Update the `gradle.properties` to the next SNAPSHOT version. 14 | 9. `git commit -am "Prepare next development version."` 15 | 10. `git push && git push --tags` 16 | 11. Visit [Sonatype Nexus](https://oss.sonatype.org/) and promote the artifact. 17 | -------------------------------------------------------------------------------- /flow-sample-helloworld/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion versions.compileSdk 5 | buildToolsVersion versions.buildTools 6 | 7 | defaultConfig { 8 | applicationId "flow.sample.helloworld" 9 | 10 | minSdkVersion versions.minSdk 11 | versionName VERSION_NAME 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | } 19 | } 20 | 21 | packagingOptions { 22 | exclude 'LICENSE.txt' 23 | } 24 | } 25 | 26 | dependencies { 27 | implementation project(':flow') 28 | implementation deps.support.appcompat 29 | androidTestImplementation deps.support.test.runner 30 | androidTestImplementation deps.support.test.rules 31 | androidTestImplementation deps.support.test.espresso 32 | } -------------------------------------------------------------------------------- /flow-sample-tree/src/main/java/flow/sample/tree/ui/contacts/ContactsUiKey.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.tree.ui.contacts; 18 | 19 | import flow.ClassKey; 20 | 21 | public final class ContactsUiKey extends ClassKey { 22 | } 23 | -------------------------------------------------------------------------------- /flow-sample-tree/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion versions.compileSdk 5 | buildToolsVersion versions.buildTools 6 | 7 | defaultConfig { 8 | applicationId "flow.sample.tree" 9 | 10 | minSdkVersion versions.minSdk 11 | versionName VERSION_NAME 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | } 19 | } 20 | 21 | packagingOptions { 22 | exclude 'LICENSE.txt' 23 | } 24 | } 25 | 26 | dependencies { 27 | implementation project(':flow') 28 | implementation deps.support.appcompat 29 | implementation deps.support.design 30 | androidTestImplementation deps.support.test.runner 31 | androidTestImplementation deps.support.test.rules 32 | androidTestImplementation deps.support.test.espresso 33 | } -------------------------------------------------------------------------------- /flow-sample-basic/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion versions.compileSdk 5 | buildToolsVersion versions.buildTools 6 | 7 | defaultConfig { 8 | applicationId "flow.sample.basic" 9 | 10 | minSdkVersion versions.minSdk 11 | versionName VERSION_NAME 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | } 19 | } 20 | 21 | packagingOptions { 22 | exclude 'LICENSE.txt' 23 | } 24 | } 25 | 26 | dependencies { 27 | implementation project(':flow') 28 | implementation deps.support.appcompat 29 | implementation deps.support.design 30 | androidTestImplementation deps.support.test.runner 31 | androidTestImplementation deps.support.test.rules 32 | androidTestImplementation deps.support.test.espresso 33 | } -------------------------------------------------------------------------------- /flow-sample-intents/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion versions.compileSdk 5 | buildToolsVersion versions.buildTools 6 | 7 | defaultConfig { 8 | applicationId "flow.sample.intents" 9 | 10 | minSdkVersion versions.minSdk 11 | versionName VERSION_NAME 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | } 19 | } 20 | 21 | packagingOptions { 22 | exclude 'LICENSE.txt' 23 | } 24 | } 25 | 26 | dependencies { 27 | implementation project(':flow') 28 | implementation deps.support.appcompat 29 | implementation deps.support.design 30 | androidTestImplementation deps.support.test.runner 31 | androidTestImplementation deps.support.test.rules 32 | androidTestImplementation deps.support.test.espresso 33 | } -------------------------------------------------------------------------------- /flow-sample-multikey/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion versions.compileSdk 5 | buildToolsVersion versions.buildTools 6 | 7 | defaultConfig { 8 | applicationId "flow.sample.multikey" 9 | 10 | minSdkVersion versions.minSdk 11 | versionName VERSION_NAME 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | } 19 | } 20 | 21 | packagingOptions { 22 | exclude 'LICENSE.txt' 23 | } 24 | } 25 | 26 | dependencies { 27 | implementation project(':flow') 28 | implementation deps.support.appcompat 29 | implementation deps.support.design 30 | androidTestImplementation deps.support.test.runner 31 | androidTestImplementation deps.support.test.rules 32 | androidTestImplementation deps.support.test.espresso 33 | } -------------------------------------------------------------------------------- /flow-sample-orientation-lock/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion versions.compileSdk 5 | buildToolsVersion versions.buildTools 6 | 7 | defaultConfig { 8 | applicationId "flow.sample.orientation" 9 | 10 | minSdkVersion versions.minSdk 11 | versionName VERSION_NAME 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | } 19 | } 20 | 21 | packagingOptions { 22 | exclude 'LICENSE.txt' 23 | } 24 | } 25 | 26 | dependencies { 27 | implementation project(':flow') 28 | implementation deps.support.appcompat 29 | implementation deps.support.design 30 | androidTestImplementation deps.support.test.runner 31 | androidTestImplementation deps.support.test.rules 32 | androidTestImplementation deps.support.test.espresso 33 | } 34 | -------------------------------------------------------------------------------- /flow-sample-basic/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | #3F51B5 20 | #303F9F 21 | #FF4081 22 | 23 | -------------------------------------------------------------------------------- /flow-sample-intents/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | #3F51B5 20 | #303F9F 21 | #FF4081 22 | 23 | -------------------------------------------------------------------------------- /flow-sample-tree/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | #3F51B5 20 | #303F9F 21 | #FF4081 22 | 23 | -------------------------------------------------------------------------------- /flow-sample-helloworld/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | #3F51B5 20 | #303F9F 21 | #FF4081 22 | 23 | -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | #3F51B5 20 | #303F9F 21 | #FF4081 22 | 23 | -------------------------------------------------------------------------------- /flow-sample-multikey/src/main/java/flow/sample/multikey/ActivityLifecycleCallbackAdapter.java: -------------------------------------------------------------------------------- 1 | package flow.sample.multikey; 2 | 3 | import android.app.Activity; 4 | import android.app.Application; 5 | import android.os.Bundle; 6 | 7 | class ActivityLifecycleCallbackAdapter implements Application.ActivityLifecycleCallbacks { 8 | @Override public void onActivityCreated(Activity activity, Bundle bundle) { 9 | 10 | } 11 | 12 | @Override public void onActivityStarted(Activity activity) { 13 | 14 | } 15 | 16 | @Override public void onActivityResumed(Activity activity) { 17 | 18 | } 19 | 20 | @Override public void onActivityPaused(Activity activity) { 21 | 22 | } 23 | 24 | @Override public void onActivityStopped(Activity activity) { 25 | 26 | } 27 | 28 | @Override public void onActivitySaveInstanceState(Activity activity, Bundle bundle) { 29 | 30 | } 31 | 32 | @Override public void onActivityDestroyed(Activity activity) { 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /flow-sample-tree/src/main/java/flow/sample/tree/ui/welcome/WelcomeScreen.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.tree.ui.welcome; 18 | 19 | import flow.ClassKey; 20 | 21 | public final class WelcomeScreen extends ClassKey { 22 | 23 | @Override public String toString() { 24 | return "Welcome!\nClick to continue."; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /flow/src/main/java/flow/MultiKey.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow; 18 | 19 | import android.support.annotation.NonNull; 20 | import java.util.List; 21 | 22 | /** 23 | * A key composed of keys. 24 | * 25 | * Component keys may be ordinary objects, {@link TreeKey}s, or MultiKeys. 26 | */ 27 | public interface MultiKey { 28 | @NonNull List getKeys(); 29 | } 30 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | 3 | android: 4 | components: 5 | - tools 6 | - platform-tools 7 | 8 | jdk: 9 | - oraclejdk8 10 | 11 | before_script: 12 | # Install SDK license so Android Gradle plugin can install deps. 13 | - mkdir "$ANDROID_HOME/licenses" || true 14 | - echo "d56f5187479451eabf01fb78af6dfcb131a6481e" > "$ANDROID_HOME/licenses/android-sdk-license" 15 | 16 | script: 17 | - ./gradlew clean build check 18 | 19 | after_success: 20 | - .buildscript/deploy_snapshot.sh 21 | 22 | env: 23 | global: 24 | - secure: "LnEHmq5BKRzXvuWJwOjZsIW0gNTr6d/JT1dOuYLsKYmGQ+0MLbjoB1J1AIpZ5X1qcDDUbPomQ2YDYvi+cavjk6FMccyKxnnC5sqjUgTnkHOnVzteGFP+0TYT3JZnjFrzp6mxNXG2vPeuyIAdDZRTogEOe83nfFRvytj6VGK/seI=" 25 | - secure: "qdCwZom4m109rrqm80N/Q+JTYob5WubDnPVKJlXoMIzh+ppq6XWiqKsBUypzn9sSEVHuYSQAzeUqyp3ET0E/sNyvnOe9cRQEs7aMjYSXw5XUYrsPT10HbAStmqPeGp6X+LuOr+jmfPQyyKeZGBOLq3Trb1yRGlrwMQhE6BFbX8g=" 26 | 27 | notifications: 28 | email: false 29 | 30 | sudo: false 31 | 32 | cache: 33 | directories: 34 | - $HOME/.gradle 35 | -------------------------------------------------------------------------------- /flow-sample-tree/src/main/java/flow/sample/tree/model/Contact.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.tree.model; 18 | 19 | public final class Contact { 20 | public final String id; 21 | public final String name; 22 | public final String email; 23 | 24 | public Contact(String id, String name, String email) { 25 | this.id = id; 26 | this.name = name; 27 | this.email = email; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.buildscript/deploy_snapshot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Deploy a jar, source jar, and javadoc jar to Sonatype's snapshot repo. 4 | # 5 | # Adapted from https://coderwall.com/p/9b_lfq and 6 | # http://benlimmer.com/2013/12/26/automatically-publish-javadoc-to-gh-pages-with-travis-ci/ 7 | 8 | SLUG="square/flow" 9 | JDK="oraclejdk8" 10 | BRANCH="master" 11 | 12 | set -e 13 | 14 | if [ "$TRAVIS_REPO_SLUG" != "$SLUG" ]; then 15 | echo "Skipping snapshot deployment: wrong repository. Expected '$SLUG' but was '$TRAVIS_REPO_SLUG'." 16 | elif [ "$TRAVIS_JDK_VERSION" != "$JDK" ]; then 17 | echo "Skipping snapshot deployment: wrong JDK. Expected '$JDK' but was '$TRAVIS_JDK_VERSION'." 18 | elif [ "$TRAVIS_PULL_REQUEST" != "false" ]; then 19 | echo "Skipping snapshot deployment: was pull request." 20 | elif [ "$TRAVIS_BRANCH" != "$BRANCH" ]; then 21 | echo "Skipping snapshot deployment: wrong branch. Expected '$BRANCH' but was '$TRAVIS_BRANCH'." 22 | else 23 | echo "Deploying snapshot..." 24 | ./gradlew clean uploadArchives 25 | echo "Snapshot deployed!" 26 | fi 27 | -------------------------------------------------------------------------------- /flow-sample-tree/src/main/res/layout/list_contacts_screen.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 25 | -------------------------------------------------------------------------------- /flow/src/main/java/flow/ClassKey.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow; 18 | 19 | /** 20 | * Convenience base class for keys. All instances of a given subclass are equal. 21 | */ 22 | public abstract class ClassKey { 23 | 24 | @Override public boolean equals(Object o) { 25 | return this == o || (o != null && getClass() == o.getClass()); 26 | } 27 | 28 | @Override public int hashCode() { 29 | return getClass().hashCode(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /flow/src/main/java/flow/KeyParceler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow; 18 | 19 | import android.os.Parcelable; 20 | import android.support.annotation.NonNull; 21 | 22 | /** 23 | * Used by History to convert your key objects to and from instances of 24 | * {@link android.os.Parcelable}. 25 | */ 26 | public interface KeyParceler { 27 | @NonNull Parcelable toParcelable(@NonNull Object key); 28 | @NonNull Object toKey(@NonNull Parcelable parcelable); 29 | } 30 | -------------------------------------------------------------------------------- /flow-sample-basic/src/main/res/layout/basic_activity_frame.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 26 | -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/res/layout/orientation_activity_frame.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 26 | -------------------------------------------------------------------------------- /flow-sample-helloworld/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 25 | 26 | -------------------------------------------------------------------------------- /flow-sample-tree/src/main/java/flow/sample/tree/ui/contacts/list/ListContactsScreen.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.tree.ui.contacts.list; 18 | 19 | import android.support.annotation.NonNull; 20 | import flow.ClassKey; 21 | import flow.TreeKey; 22 | import flow.sample.tree.ui.contacts.ContactsUiKey; 23 | 24 | public final class ListContactsScreen extends ClassKey implements TreeKey { 25 | @NonNull @Override public Object getParentKey() { 26 | return new ContactsUiKey(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /flow-sample-basic/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /flow-sample-intents/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /flow-sample-tree/src/main/java/flow/sample/tree/ui/contacts/edit/EditEmailScreen.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.tree.ui.contacts.edit; 18 | 19 | import android.support.annotation.NonNull; 20 | import flow.TreeKey; 21 | 22 | public final class EditEmailScreen extends ContactKey implements TreeKey { 23 | EditEmailScreen(String contactId) { 24 | super(contactId); 25 | } 26 | 27 | @NonNull @Override public Object getParentKey() { 28 | return new EditContactKey(contactId); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /flow-sample-tree/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /flow-sample-tree/src/main/java/flow/sample/tree/model/ContactEditor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.tree.model; 18 | 19 | public final class ContactEditor { 20 | public final String id; 21 | public String name; 22 | public String email; 23 | 24 | public ContactEditor(Contact contact) { 25 | this.id = contact.id; 26 | this.name = contact.name; 27 | this.email = contact.email; 28 | } 29 | 30 | public Contact toContact() { 31 | return new Contact(id, name, email); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /flow-sample-tree/src/main/java/flow/sample/tree/ui/contacts/edit/EditNameScreen.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.tree.ui.contacts.edit; 18 | 19 | import android.support.annotation.NonNull; 20 | import flow.TreeKey; 21 | 22 | public final class EditNameScreen extends ContactKey implements TreeKey { 23 | public EditNameScreen(String contactId) { 24 | super(contactId); 25 | } 26 | 27 | @NonNull @Override public Object getParentKey() { 28 | return new EditContactKey(contactId); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /flow/src/main/java/flow/TreeKey.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow; 18 | 19 | import android.support.annotation.NonNull; 20 | 21 | /** 22 | * Represents an absolute path in the logical information tree of an app, from the root of the tree 23 | * to a leaf, which is typically associated with app "screen" or "state". Each element in a path 24 | * typically represents a scope, narrowing and adding information from root to leaf. 25 | */ 26 | public interface TreeKey { 27 | @NonNull Object getParentKey(); 28 | } 29 | -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /flow/src/main/java/flow/TraversalCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow; 18 | 19 | /** Supplied by Flow to the Listener, which is responsible for calling onComplete(). */ 20 | public interface TraversalCallback { 21 | /** 22 | * Must be called exactly once to indicate that the corresponding transition has completed. 23 | * 24 | * If not called, the history will not be updated and further calls to Flow will not execute. 25 | * Calling more than once will result in an exception. 26 | */ 27 | void onTraversalCompleted(); 28 | } 29 | -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/java/flow/sample/orientation/LooseScreen.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.orientation; 18 | 19 | import android.support.annotation.LayoutRes; 20 | 21 | /** 22 | * A screen that is willing to render in any orientation. 23 | */ 24 | final class LooseScreen extends OrientationSampleScreen { 25 | static final LooseScreen INSTANCE = new LooseScreen(); 26 | 27 | private LooseScreen() { 28 | } 29 | 30 | @Override public @LayoutRes int getLayoutId() { 31 | return R.layout.loose_screen; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /flow/src/main/java/flow/NotPersistent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package flow; 17 | 18 | import java.lang.annotation.ElementType; 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import java.lang.annotation.Target; 22 | 23 | /** 24 | * Applied to a state object, indicates that it should not be persisted with the history. 25 | * This behavior can be changed via {@link Flow#setHistoryFilter}. 26 | */ 27 | @Target(ElementType.TYPE) 28 | @Retention(RetentionPolicy.RUNTIME) 29 | public @interface NotPersistent { 30 | } 31 | -------------------------------------------------------------------------------- /flow-sample-tree/src/main/java/flow/sample/tree/ui/contacts/edit/EditContactKey.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.tree.ui.contacts.edit; 18 | 19 | import android.support.annotation.NonNull; 20 | import flow.TreeKey; 21 | import flow.sample.tree.ui.contacts.ContactsUiKey; 22 | 23 | public final class EditContactKey extends ContactKey implements TreeKey { 24 | 25 | EditContactKey(String contactId) { 26 | super(contactId); 27 | } 28 | 29 | @NonNull @Override public Object getParentKey() { 30 | return new ContactsUiKey(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /flow-sample-helloworld/src/main/java/flow/sample/helloworld/HelloWorldActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.helloworld; 18 | 19 | import android.app.Activity; 20 | import android.content.Context; 21 | import flow.Flow; 22 | 23 | public class HelloWorldActivity extends Activity { 24 | 25 | @Override protected void attachBaseContext(Context baseContext) { 26 | baseContext = Flow.configure(baseContext, this).install(); 27 | super.attachBaseContext(baseContext); 28 | } 29 | 30 | @Override public void onBackPressed() { 31 | if (!Flow.get(this).goBack()) { 32 | super.onBackPressed(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/java/flow/sample/orientation/LandscapeScreen.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.orientation; 18 | 19 | import android.support.annotation.LayoutRes; 20 | 21 | /** 22 | * Screen that requires landscape orientation. 23 | */ 24 | final class LandscapeScreen extends OrientationSampleScreen { 25 | static final LandscapeScreen INSTANCE = new LandscapeScreen(); 26 | 27 | private LandscapeScreen() { 28 | } 29 | 30 | @Override public @LayoutRes int getLayoutId() { 31 | return R.layout.landscape_screen; 32 | } 33 | 34 | @Override boolean requiresLandscape() { 35 | return true; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /flow/src/test/java/flow/TestKey.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow; 18 | 19 | class TestKey { 20 | final String name; 21 | 22 | TestKey(String name) { 23 | this.name = name; 24 | } 25 | 26 | @Override 27 | public boolean equals(Object o) { 28 | if (this == o) return true; 29 | if (o == null || getClass() != o.getClass()) return false; 30 | TestKey key = (TestKey) o; 31 | return name.equals(key.name); 32 | } 33 | 34 | @Override 35 | public int hashCode() { 36 | return name.hashCode(); 37 | } 38 | 39 | @Override public String toString() { 40 | return String.format("%s{%h}", name, this); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /flow-sample-intents/src/main/java/flow/sample/intents/IntentsStandardSampleActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.intents; 18 | 19 | import android.app.Activity; 20 | import android.content.Context; 21 | import flow.Flow; 22 | 23 | public class IntentsStandardSampleActivity extends Activity { 24 | 25 | @Override protected void attachBaseContext(Context baseContext) { 26 | baseContext = Flow.configure(baseContext, this).keyParceler(new StringParceler()).install(); 27 | super.attachBaseContext(baseContext); 28 | } 29 | 30 | @Override public void onBackPressed() { 31 | if (!Flow.get(this).goBack()) { 32 | super.onBackPressed(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /flow-sample-intents/src/main/java/flow/sample/intents/StringParceler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.intents; 18 | 19 | import android.os.Bundle; 20 | import android.os.Parcelable; 21 | import android.support.annotation.NonNull; 22 | import flow.KeyParceler; 23 | 24 | public class StringParceler implements KeyParceler { 25 | @NonNull @Override public Parcelable toParcelable(@NonNull Object key) { 26 | Bundle bundle = new Bundle(); 27 | bundle.putString("stringKey", (String) key); 28 | return bundle; 29 | } 30 | 31 | @NonNull @Override public Object toKey(@NonNull Parcelable parcelable) { 32 | Bundle bundle = (Bundle) parcelable; 33 | return bundle.getString("stringKey"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /flow-sample-basic/src/main/java/flow/sample/basic/BasicKeyParceler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.basic; 18 | 19 | import android.os.Parcelable; 20 | import android.support.annotation.NonNull; 21 | import flow.KeyParceler; 22 | 23 | /** 24 | * Assumes states are {@link Parcelable}. 25 | * 26 | * A more realistic implementation might rely on a library like auto-value-parcel, 27 | * auto-parcel, or parceler. 28 | * */ 29 | final class BasicKeyParceler implements KeyParceler { 30 | @NonNull @Override public Parcelable toParcelable(@NonNull Object key) { 31 | return (Parcelable) key; 32 | } 33 | 34 | @NonNull @Override public Object toKey(@NonNull Parcelable parcelable) { 35 | return parcelable; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /flow-sample-tree/src/main/java/flow/sample/tree/ui/contacts/edit/ContactKey.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.tree.ui.contacts.edit; 18 | 19 | import flow.ClassKey; 20 | 21 | abstract class ContactKey extends ClassKey { 22 | public final String contactId; 23 | 24 | protected ContactKey(String contactId) { 25 | this.contactId = contactId; 26 | } 27 | 28 | @Override public boolean equals(Object o) { 29 | return super.equals(o) && contactId.equals(((ContactKey) o).contactId); 30 | } 31 | 32 | @Override public int hashCode() { 33 | return contactId.hashCode(); 34 | } 35 | 36 | @Override public String toString() { 37 | return getClass().getSimpleName() + "{contactId=" + contactId + "}"; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /flow/src/main/java/flow/ServicesFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow; 18 | 19 | import android.support.annotation.NonNull; 20 | 21 | public abstract class ServicesFactory { 22 | /** 23 | * Sets up any services associated with the key, and make them accessible via the context. 24 | * Typically this means returning a new context that wraps the given one. 25 | */ 26 | public abstract void bindServices(@NonNull Services.Binder services); 27 | 28 | /** 29 | * Tears down any services previously bound by {@link #bindServices}. Note that the Services 30 | * instance given here may be a wrapper around an instance that this factory created. 31 | */ 32 | public void tearDownServices(@NonNull Services services) { 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /flow-sample-tree/src/main/res/layout/list_contacts_screen_row_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 24 | 29 | 34 | 35 | -------------------------------------------------------------------------------- /flow-sample-tree/src/main/res/layout/edit_name_screen.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 24 | 29 | 34 | 35 | -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/res/layout/landscape_screen.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 25 | 33 | 34 | -------------------------------------------------------------------------------- /flow-sample-basic/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /flow-sample-tree/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /flow-sample-helloworld/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/res/layout/loose_screen.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 26 | 34 | 35 | -------------------------------------------------------------------------------- /flow-sample-intents/src/main/java/flow/sample/intents/IntentsSingleInstanceSampleActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.intents; 18 | 19 | import android.app.Activity; 20 | import android.content.Context; 21 | import android.content.Intent; 22 | import flow.Flow; 23 | 24 | public class IntentsSingleInstanceSampleActivity extends Activity { 25 | 26 | @Override protected void attachBaseContext(Context baseContext) { 27 | baseContext = Flow.configure(baseContext, this).keyParceler(new StringParceler()).install(); 28 | super.attachBaseContext(baseContext); 29 | } 30 | 31 | @Override protected void onNewIntent(Intent intent) { 32 | Flow.onNewIntent(intent, this); 33 | } 34 | 35 | @Override public void onBackPressed() { 36 | if (!Flow.get(this).goBack()) { 37 | super.onBackPressed(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /flow-sample-basic/src/main/java/flow/sample/basic/WelcomeScreen.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.basic; 18 | 19 | import android.os.Parcel; 20 | import android.os.Parcelable; 21 | 22 | final class WelcomeScreen implements Parcelable { 23 | @Override public void writeToParcel(Parcel dest, int flags) { 24 | } 25 | 26 | @Override public int describeContents() { 27 | return 0; 28 | } 29 | 30 | public static final Creator CREATOR = new Creator() { 31 | @Override public WelcomeScreen createFromParcel(Parcel in) { 32 | return new WelcomeScreen(); 33 | } 34 | 35 | @Override public WelcomeScreen[] newArray(int size) { 36 | return new WelcomeScreen[size]; 37 | } 38 | }; 39 | 40 | @Override public boolean equals(Object o) { 41 | return o != null && o instanceof WelcomeScreen; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /flow-sample-basic/src/main/res/layout/welcome_screen.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 25 | 29 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/java/flow/sample/orientation/LandscapeView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.orientation; 18 | 19 | import android.content.Context; 20 | import android.util.AttributeSet; 21 | import android.view.View; 22 | import android.widget.LinearLayout; 23 | import android.widget.TextView; 24 | import flow.Flow; 25 | 26 | public final class LandscapeView extends LinearLayout { 27 | 28 | public LandscapeView(Context context, AttributeSet attrs) { 29 | super(context, attrs); 30 | setOrientation(VERTICAL); 31 | } 32 | 33 | @Override protected void onAttachedToWindow() { 34 | super.onAttachedToWindow(); 35 | findViewById(R.id.landscape_text).setOnClickListener(new OnClickListener() { 36 | @Override public void onClick(View v) { 37 | Flow.get(getContext()).set(LooseScreen.INSTANCE); 38 | } 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /flow/src/main/java/flow/Preconditions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007 The Guava Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package flow; 16 | 17 | final class Preconditions { 18 | private Preconditions() { 19 | throw new AssertionError(); 20 | } 21 | 22 | /** 23 | * @throws java.lang.IllegalArgumentException if condition is false. 24 | */ 25 | static void checkArgument(boolean condition, String errorMessage) { 26 | if (!condition) { 27 | throw new IllegalArgumentException(errorMessage); 28 | } 29 | } 30 | 31 | /** 32 | * @param reference an object reference 33 | * @return the non-null reference that was validated 34 | * @throws NullPointerException if {@code reference} is null 35 | */ 36 | static T checkNotNull(T reference, String errorMessage, Object... args) { 37 | if (reference == null) { 38 | throw new NullPointerException(String.format(errorMessage, args)); 39 | } 40 | return reference; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /flow/src/main/java/flow/KeyChanger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow; 18 | 19 | import android.content.Context; 20 | import android.support.annotation.NonNull; 21 | import android.support.annotation.Nullable; 22 | import android.view.View; 23 | import java.util.Map; 24 | 25 | public interface KeyChanger { 26 | /** 27 | * Transition from outgoing state to incoming state. Implementations should call 28 | * {@link State#restore(View)} on the incoming view, and (if outgoingState is not null) 29 | * {@link State#save(View)} on the outgoing view. And don't forget to declare your screen layouts 30 | * with ids (only layouts with ids will have their state saved/restored)! 31 | */ 32 | void changeKey(@Nullable State outgoingState, @NonNull State incomingState, 33 | @NonNull Direction direction, @NonNull Map incomingContexts, 34 | @NonNull TraversalCallback callback); 35 | } 36 | -------------------------------------------------------------------------------- /flow-sample-orientation-lock/src/main/java/flow/sample/orientation/LooseView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package flow.sample.orientation; 18 | 19 | import android.content.Context; 20 | import android.util.AttributeSet; 21 | import android.view.KeyEvent; 22 | import android.view.View; 23 | import android.widget.EditText; 24 | import android.widget.LinearLayout; 25 | import android.widget.TextView; 26 | import flow.Flow; 27 | 28 | public final class LooseView extends LinearLayout { 29 | 30 | public LooseView(Context context, AttributeSet attrs) { 31 | super(context, attrs); 32 | setOrientation(VERTICAL); 33 | } 34 | 35 | @Override protected void onFinishInflate() { 36 | super.onFinishInflate(); 37 | findViewById(R.id.loose_text).setOnClickListener(new OnClickListener() { 38 | @Override public void onClick(View v) { 39 | Flow.get(getContext()).set(LandscapeScreen.INSTANCE); 40 | } 41 | }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /flow-sample-tree/src/main/res/layout/edit_email_screen.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 25 | 30 | 35 |