Full Code of uber/RIBs for AI

main f08e54ecde89 cached
665 files
18.8 MB
335.1k tokens
1478 symbols
1 requests
Download .txt
Showing preview only (1,503K chars total). Download the full file or copy to clipboard to get everything.
Repository: uber/RIBs
Branch: main
Commit: f08e54ecde89
Files: 665
Total size: 18.8 MB

Directory structure:
gitextract_os7hyq2r/

├── .github/
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       └── android.yml
├── .gitignore
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE.txt
├── README.md
├── RELEASING.md
├── build.gradle.kts
├── config/
│   ├── lint/
│   │   └── lint.xml
│   └── spotless/
│       ├── copyright.java
│       └── copyright.kt
├── conventions/
│   ├── build.gradle.kts
│   ├── settings.gradle.kts
│   └── src/
│       └── main/
│           └── kotlin/
│               ├── Extensions.kt
│               ├── ribs.android.application.errorprone.gradle.kts
│               ├── ribs.android.application.gradle.kts
│               ├── ribs.android.library.gradle.kts
│               ├── ribs.kotlin.library.gradle.kts
│               └── ribs.spotless.gradle.kts
├── demos/
│   ├── compose/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── kotlin/
│   │           │   └── com/
│   │           │       └── uber/
│   │           │           └── rib/
│   │           │               └── compose/
│   │           │                   ├── ComposeApplication.kt
│   │           │                   ├── root/
│   │           │                   │   ├── RootActivity.kt
│   │           │                   │   ├── RootInteractor.kt
│   │           │                   │   ├── RootRouter.kt
│   │           │                   │   ├── RootScope.kt
│   │           │                   │   ├── RootView.kt
│   │           │                   │   └── main/
│   │           │                   │       ├── AuthStream.kt
│   │           │                   │       ├── MainInteractor.kt
│   │           │                   │       ├── MainRouter.kt
│   │           │                   │       ├── MainScope.kt
│   │           │                   │       ├── MainView.kt
│   │           │                   │       ├── loggedin/
│   │           │                   │       │   ├── LoggedInEvent.kt
│   │           │                   │       │   ├── LoggedInInteractor.kt
│   │           │                   │       │   ├── LoggedInRouter.kt
│   │           │                   │       │   ├── LoggedInScope.kt
│   │           │                   │       │   ├── LoggedInView.kt
│   │           │                   │       │   ├── ScoreStream.kt
│   │           │                   │       │   ├── offgame/
│   │           │                   │       │   │   ├── OffGameEvent.kt
│   │           │                   │       │   │   ├── OffGameInteractor.kt
│   │           │                   │       │   │   ├── OffGameRouter.kt
│   │           │                   │       │   │   ├── OffGameScope.kt
│   │           │                   │       │   │   ├── OffGameView.kt
│   │           │                   │       │   │   └── OffGameViewModel.kt
│   │           │                   │       │   └── tictactoe/
│   │           │                   │       │       ├── Board.kt
│   │           │                   │       │       ├── BoardCoordinate.kt
│   │           │                   │       │       ├── TicTacToeEvent.kt
│   │           │                   │       │       ├── TicTacToeInteractor.kt
│   │           │                   │       │       ├── TicTacToeRouter.kt
│   │           │                   │       │       ├── TicTacToeScope.kt
│   │           │                   │       │       ├── TicTacToeView.kt
│   │           │                   │       │       └── TicTacToeViewModel.kt
│   │           │                   │       └── loggedout/
│   │           │                   │           ├── LoggedOutEvent.kt
│   │           │                   │           ├── LoggedOutInteractor.kt
│   │           │                   │           ├── LoggedOutRouter.kt
│   │           │                   │           ├── LoggedOutScope.kt
│   │           │                   │           ├── LoggedOutView.kt
│   │           │                   │           └── LoggedOutViewModel.kt
│   │           │                   └── util/
│   │           │                       ├── AnalyticsClient.kt
│   │           │                       ├── CustomButton.kt
│   │           │                       ├── CustomClientProvider.kt
│   │           │                       ├── EventStream.kt
│   │           │                       ├── ExperimentClient.kt
│   │           │                       ├── LoggerClient.kt
│   │           │                       └── StateStream.kt
│   │           └── res/
│   │               ├── drawable/
│   │               │   └── ic_launcher_background.xml
│   │               ├── drawable-v24/
│   │               │   └── ic_launcher_foreground.xml
│   │               ├── mipmap-anydpi-v26/
│   │               │   ├── ic_launcher.xml
│   │               │   └── ic_launcher_round.xml
│   │               └── values/
│   │                   ├── ids.xml
│   │                   ├── strings.xml
│   │                   └── themes.xml
│   ├── flipper/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── uber/
│   │           │           └── rib/
│   │           │               ├── RootActivity.java
│   │           │               ├── SampleApplication.java
│   │           │               └── root/
│   │           │                   ├── RootBuilder.java
│   │           │                   ├── RootInteractor.java
│   │           │                   ├── RootRouter.java
│   │           │                   ├── RootView.java
│   │           │                   ├── loggedin/
│   │           │                   │   ├── LoggedInBuilder.java
│   │           │                   │   ├── LoggedInInteractor.java
│   │           │                   │   ├── LoggedInRouter.java
│   │           │                   │   ├── offgame/
│   │           │                   │   │   ├── OffGameBuilder.java
│   │           │                   │   │   ├── OffGameInteractor.java
│   │           │                   │   │   ├── OffGameRouter.java
│   │           │                   │   │   └── OffGameView.java
│   │           │                   │   └── tictactoe/
│   │           │                   │       ├── Board.java
│   │           │                   │       ├── BoardCoordinate.java
│   │           │                   │       ├── TicTacToeBuilder.java
│   │           │                   │       ├── TicTacToeInteractor.java
│   │           │                   │       ├── TicTacToeRouter.java
│   │           │                   │       └── TicTacToeView.java
│   │           │                   └── loggedout/
│   │           │                       ├── LoggedOutBuilder.java
│   │           │                       ├── LoggedOutInteractor.java
│   │           │                       ├── LoggedOutRouter.java
│   │           │                       └── LoggedOutView.java
│   │           └── res/
│   │               ├── layout/
│   │               │   ├── logged_out_rib.xml
│   │               │   ├── off_game_rib.xml
│   │               │   ├── root_rib.xml
│   │               │   └── tic_tac_toe_rib.xml
│   │               └── values/
│   │                   └── ub__strings.xml
│   ├── intellij/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── uber/
│   │           │           └── rib/
│   │           │               ├── RootActivity.java
│   │           │               ├── SampleApplication.java
│   │           │               └── root/
│   │           │                   ├── RootBuilder.java
│   │           │                   ├── RootInteractor.java
│   │           │                   ├── RootRouter.java
│   │           │                   ├── RootView.java
│   │           │                   ├── loggedin/
│   │           │                   │   ├── LoggedInBuilder.java
│   │           │                   │   ├── LoggedInInteractor.java
│   │           │                   │   ├── LoggedInRouter.java
│   │           │                   │   ├── offgame/
│   │           │                   │   │   ├── OffGameBuilder.java
│   │           │                   │   │   ├── OffGameInteractor.java
│   │           │                   │   │   ├── OffGameRouter.java
│   │           │                   │   │   └── OffGameView.java
│   │           │                   │   └── tictactoe/
│   │           │                   │       ├── Board.java
│   │           │                   │       ├── BoardCoordinate.java
│   │           │                   │       ├── TicTacToeBuilder.java
│   │           │                   │       ├── TicTacToeInteractor.java
│   │           │                   │       ├── TicTacToeRouter.java
│   │           │                   │       └── TicTacToeView.java
│   │           │                   └── loggedout/
│   │           │                       ├── LoggedOutBuilder.java
│   │           │                       ├── LoggedOutInteractor.java
│   │           │                       ├── LoggedOutRouter.java
│   │           │                       └── LoggedOutView.java
│   │           └── res/
│   │               ├── layout/
│   │               │   ├── logged_out_rib.xml
│   │               │   ├── off_game_rib.xml
│   │               │   ├── root_rib.xml
│   │               │   └── tic_tac_toe_rib.xml
│   │               └── values/
│   │                   └── ub__strings.xml
│   ├── memory-leaks/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── uber/
│   │           │           └── rib/
│   │           │               ├── RootActivity.java
│   │           │               ├── SampleApplication.java
│   │           │               └── root/
│   │           │                   ├── RootBuilder.java
│   │           │                   ├── RootInteractor.java
│   │           │                   ├── RootRouter.java
│   │           │                   ├── RootView.java
│   │           │                   ├── loggedin/
│   │           │                   │   ├── LoggedInBuilder.java
│   │           │                   │   ├── LoggedInInteractor.java
│   │           │                   │   └── LoggedInRouter.java
│   │           │                   └── loggedout/
│   │           │                       ├── LoggedOutBuilder.java
│   │           │                       ├── LoggedOutInteractor.java
│   │           │                       ├── LoggedOutRouter.java
│   │           │                       └── LoggedOutView.java
│   │           └── res/
│   │               ├── layout/
│   │               │   ├── logged_out_rib.xml
│   │               │   └── root_rib.xml
│   │               └── values/
│   │                   └── ub__strings.xml
│   └── rib-workers/
│       ├── README.md
│       ├── build.gradle.kts
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── kotlin/
│               │   └── com/
│               │       └── uber/
│               │           └── rib/
│               │               └── workers/
│               │                   ├── ComposeApplication.kt
│               │                   ├── root/
│               │                   │   ├── RootActivity.kt
│               │                   │   ├── RootInteractor.kt
│               │                   │   ├── RootRouter.kt
│               │                   │   ├── RootScope.kt
│               │                   │   ├── RootView.kt
│               │                   │   ├── logger/
│               │                   │   │   └── ApplicationLevelWorkerLogger.kt
│               │                   │   └── main/
│               │                   │       ├── MainInteractor.kt
│               │                   │       ├── MainRouter.kt
│               │                   │       ├── MainScope.kt
│               │                   │       ├── MainView.kt
│               │                   │       ├── ribworkerselection/
│               │                   │       │   ├── RibWorkerBindTypeClickType.kt
│               │                   │       │   ├── RibWorkerSelectionInteractor.kt
│               │                   │       │   ├── RibWorkerSelectionRouter.kt
│               │                   │       │   ├── RibWorkerSelectionScope.kt
│               │                   │       │   ├── RibWorkerSelectionView.kt
│               │                   │       │   └── RibWorkerSelectionViewModel.kt
│               │                   │       └── workers/
│               │                   │           ├── BackgroundWorker.kt
│               │                   │           ├── DefaultRibCoroutineWorker.kt
│               │                   │           ├── DefaultWorker.kt
│               │                   │           ├── IoWorker.kt
│               │                   │           └── UiWorker.kt
│               │                   └── util/
│               │                       ├── EventStream.kt
│               │                       └── StateStream.kt
│               └── res/
│                   ├── drawable/
│                   │   └── ic_launcher_background.xml
│                   ├── drawable-v24/
│                   │   └── ic_launcher_foreground.xml
│                   ├── mipmap-anydpi-v26/
│                   │   ├── ic_launcher.xml
│                   │   └── ic_launcher_round.xml
│                   └── values/
│                       ├── strings.xml
│                       └── themes.xml
├── gradle/
│   ├── app-libs.versions.toml
│   ├── japicmp.gradle
│   ├── libs.versions.toml
│   ├── test-libs.versions.toml
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── libraries/
│   ├── rib-android/
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── core/
│   │       │                       ├── ActivityContext.kt
│   │       │                       ├── ActivityStarter.kt
│   │       │                       ├── BasicViewRouter.kt
│   │       │                       ├── IntentCreator.kt
│   │       │                       ├── IntentCreatorImpl.kt
│   │       │                       ├── IntentFactory.kt
│   │       │                       ├── RibActivity.kt
│   │       │                       ├── RibDebugOverlay.kt
│   │       │                       ├── RxActivityEvents.kt
│   │       │                       ├── ViewBuilder.kt
│   │       │                       ├── ViewPresenter.kt
│   │       │                       ├── ViewRouter.kt
│   │       │                       ├── XRay.kt
│   │       │                       └── lifecycle/
│   │       │                           ├── ActivityCallbackEvent.kt
│   │       │                           ├── ActivityEvent.kt
│   │       │                           └── ActivityLifecycleEvent.kt
│   │       └── test/
│   │           ├── kotlin/
│   │           │   └── com/
│   │           │       └── uber/
│   │           │           └── rib/
│   │           │               └── core/
│   │           │                   ├── BundleTest.kt
│   │           │                   ├── RibActivityTest.kt
│   │           │                   ├── ViewBuilderTest.kt
│   │           │                   └── XRayTest.kt
│   │           └── resources/
│   │               └── robolectric.properties
│   ├── rib-android-compose/
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       └── main/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── core/
│   │                               ├── BasicComposeRouter.kt
│   │                               └── ComposePresenter.kt
│   ├── rib-android-core/
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── core/
│   │       │                       ├── ActivityDelegate.kt
│   │       │                       ├── CoreAppCompatActivity.kt
│   │       │                       └── HasActivityDelegate.kt
│   │       └── test/
│   │           └── resources/
│   │               └── robolectric.properties
│   ├── rib-base/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── core/
│   │       │                       ├── BasicInteractor.kt
│   │       │                       ├── BasicRouter.kt
│   │       │                       ├── Builder.kt
│   │       │                       ├── Bundle.kt
│   │       │                       ├── EmptyPresenter.kt
│   │       │                       ├── FlowAsScope.kt
│   │       │                       ├── Initializer.kt
│   │       │                       ├── Interactor.kt
│   │       │                       ├── InteractorAndViewModule.kt
│   │       │                       ├── InteractorBaseComponent.kt
│   │       │                       ├── InteractorComponent.kt
│   │       │                       ├── InteractorModule.kt
│   │       │                       ├── InteractorType.kt
│   │       │                       ├── LazyBackingProperty.kt
│   │       │                       ├── Presenter.kt
│   │       │                       ├── Rib.kt
│   │       │                       ├── RibBuilder.kt
│   │       │                       ├── RibCoroutineWorker.kt
│   │       │                       ├── RibEventType.kt
│   │       │                       ├── RibEvents.kt
│   │       │                       ├── RibInteractor.kt
│   │       │                       ├── RibRefWatcher.kt
│   │       │                       ├── RibRouterEvent.kt
│   │       │                       ├── Router.kt
│   │       │                       ├── Worker.kt
│   │       │                       ├── WorkerBinder.kt
│   │       │                       ├── WorkerScopeProvider.kt
│   │       │                       ├── WorkerUnbinder.kt
│   │       │                       ├── internal/
│   │       │                       │   └── CoreFriendModuleApi.kt
│   │       │                       └── lifecycle/
│   │       │                           ├── InteractorEvent.kt
│   │       │                           ├── PresenterEvent.kt
│   │       │                           └── WorkerEvent.kt
│   │       └── test/
│   │           └── kotlin/
│   │               ├── android/
│   │               │   └── os/
│   │               │       ├── Bundle.kt
│   │               │       └── Parcelable.kt
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── core/
│   │                               ├── InteractorAndRouterTest.kt
│   │                               ├── LazyBackingPropertyTest.kt
│   │                               ├── RecordingObserver.kt
│   │                               ├── RibCoroutineWorkerTest.kt
│   │                               ├── RibEventsTest.kt
│   │                               ├── RibEventsUtils.kt
│   │                               ├── RibRefWatcherTest.kt
│   │                               ├── RouterTest.kt
│   │                               ├── WorkerBinderTest.kt
│   │                               ├── WorkerScopeProviderTest.kt
│   │                               └── WorkerTest.kt
│   ├── rib-compiler-app/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── compiler/
│   │       │                       ├── AnnotatedClass.kt
│   │       │                       ├── AnnotationVerifier.kt
│   │       │                       ├── CompilerUtils.kt
│   │       │                       ├── Constants.kt
│   │       │                       ├── ErrorReporter.kt
│   │       │                       ├── Generator.kt
│   │       │                       ├── InteractorAnnotatedClass.kt
│   │       │                       ├── InteractorAnnotationVerifier.kt
│   │       │                       ├── ProcessContext.kt
│   │       │                       ├── ProcessorPipeline.kt
│   │       │                       ├── RibInteractorProcessorPipeline.kt
│   │       │                       ├── RibProcessor.kt
│   │       │                       ├── TypeProcessorPipeline.kt
│   │       │                       └── VerificationFailedException.kt
│   │       └── test/
│   │           ├── kotlin/
│   │           │   └── com/
│   │           │       └── uber/
│   │           │           └── rib/
│   │           │               └── compiler/
│   │           │                   ├── InteractorAnnotationVerifierTest.kt
│   │           │                   └── InteractorProcessorTestBase.kt
│   │           └── resources/
│   │               └── fixtures/
│   │                   ├── AnnotatedInteractor.java
│   │                   ├── AnnotatedInteractorNoSuffix.java
│   │                   ├── AnnotatedNonInteractor.java
│   │                   └── CustomConstructorInteractor.java
│   ├── rib-compiler-test/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   ├── libs/
│   │   │   └── tools.jar
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── compiler/
│   │       │                       ├── Constants.kt
│   │       │                       ├── InteractorTestGenerator.kt
│   │       │                       └── RibTestProcessor.kt
│   │       └── test/
│   │           ├── kotlin/
│   │           │   └── com/
│   │           │       └── uber/
│   │           │           └── rib/
│   │           │               └── compiler/
│   │           │                   ├── InteractorTestGeneratorProcessorTestBase.kt
│   │           │                   └── InteractorTestGeneratorTest.kt
│   │           └── resources/
│   │               └── fixtures/
│   │                   ├── AnnotatedBasicInteractor.java
│   │                   ├── AnnotatedInteractor.java
│   │                   ├── TestAnnotatedBasicInteractor.java
│   │                   ├── TestAnnotatedInteractor.java
│   │                   └── TestForcedBasicInteractor.java
│   ├── rib-coroutines/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── core/
│   │       │                       ├── RibCoroutineScopes.kt
│   │       │                       ├── RibCoroutinesConfig.kt
│   │       │                       ├── RibDispatchers.kt
│   │       │                       └── internal/
│   │       │                           └── CoroutinesFriendModuleApi.kt
│   │       └── test/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── core/
│   │                               └── RibCoroutineScopesTest.kt
│   ├── rib-coroutines-test/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── core/
│   │       │                       ├── RibCoroutinesRule.kt
│   │       │                       ├── TestRibCoroutineScopes.kt
│   │       │                       └── TestRibDispatchers.kt
│   │       └── test/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── core/
│   │                               ├── RibCoroutinesRuleTest.kt
│   │                               ├── RibDispatchersTest.kt
│   │                               └── RibScopesTest.kt
│   ├── rib-debug-utils/
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       └── main/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── core/
│   │                               └── RouterDebugUtils.kt
│   ├── rib-router-navigator/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── core/
│   │       │                       ├── RouterAndState.kt
│   │       │                       ├── RouterNavigator.kt
│   │       │                       ├── RouterNavigatorEvent.kt
│   │       │                       ├── RouterNavigatorEventType.kt
│   │       │                       ├── RouterNavigatorEvents.kt
│   │       │                       ├── RouterNavigatorFactory.kt
│   │       │                       ├── RouterNavigatorState.kt
│   │       │                       └── StackRouterNavigator.kt
│   │       └── test/
│   │           └── kotlin/
│   │               ├── com/
│   │               │   └── uber/
│   │               │       └── rib/
│   │               │           └── core/
│   │               │               ├── RouterAndStateTest.kt
│   │               │               └── StackRouterNavigatorTest.kt
│   │               └── os/
│   │                   ├── Bundle.kt
│   │                   └── Parcelable.kt
│   ├── rib-screen-stack-base/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       └── main/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── core/
│   │                               └── screenstack/
│   │                                   ├── ScreenStackBase.kt
│   │                                   ├── ViewProvider.kt
│   │                                   └── lifecycle/
│   │                                       └── ScreenStackEvent.kt
│   ├── rib-test/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       └── main/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── core/
│   │                               ├── AndroidRecordingRx2Observer.kt
│   │                               ├── FakeComponent.kt
│   │                               ├── FakeInteractor.kt
│   │                               ├── FakePresenter.kt
│   │                               ├── FakeRouter.kt
│   │                               ├── FakeWorker.kt
│   │                               ├── InteractorHelper.kt
│   │                               ├── PresenterHelper.kt
│   │                               ├── RibTestBasePlaceholder.kt
│   │                               ├── RouterHelper.kt
│   │                               ├── TestRibCoroutineWorker.kt
│   │                               └── WorkerHelper.kt
│   ├── rib-workflow/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── workflow/
│   │       │                       └── core/
│   │       │                           ├── ActionableItem.kt
│   │       │                           ├── Step.kt
│   │       │                           ├── Workflow.kt
│   │       │                           └── internal/
│   │       │                               └── WorkflowFriendModuleApi.kt
│   │       └── test/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── workflow/
│   │                               └── core/
│   │                                   ├── AndroidSchedulersRule.kt
│   │                                   ├── DelegatingScheduler.kt
│   │                                   ├── StepTest.kt
│   │                                   └── WorkflowTest.kt
│   └── rib-workflow-test/
│       ├── build.gradle.kts
│       ├── gradle.properties
│       └── src/
│           └── main/
│               └── kotlin/
│                   └── com/
│                       └── uber/
│                           └── rib/
│                               └── workflow/
│                                   └── core/
│                                       └── StepTester.kt
├── releasing.sh
├── settings.gradle
├── tooling/
│   ├── rib-flipper-plugin/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── desktop/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   └── src/
│   │   │       ├── TreeChart.js
│   │   │       ├── index.js
│   │   │       └── utils.js
│   │   ├── gradle.properties
│   │   └── src/
│   │       └── main/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── flipper/
│   │                               ├── RibEventPayload.kt
│   │                               ├── RibTreeMessageType.kt
│   │                               └── RibTreePlugin.kt
│   ├── rib-intellij-plugin/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── deploy/
│   │   │   └── rib-intellij-plugin.jar
│   │   ├── gradle.properties
│   │   ├── native/
│   │   │   ├── gradle.properties
│   │   │   └── intellij-broadcast-rib/
│   │   │       ├── README.md
│   │   │       ├── build.gradle.kts
│   │   │       └── src/
│   │   │           └── main/
│   │   │               └── java/
│   │   │                   └── com/
│   │   │                       └── uber/
│   │   │                           └── debug/
│   │   │                               └── broadcast/
│   │   │                                   └── rib/
│   │   │                                       ├── RibHierarchyDebugBroadcastHandler.java
│   │   │                                       ├── RibHierarchyPayload.java
│   │   │                                       ├── RibHierarchyUtils.java
│   │   │                                       └── RibHierarchyWithSelectionPayload.java
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── uber/
│   │       │   │           └── presidio/
│   │       │   │               └── intellij_plugin/
│   │       │   │                   ├── action/
│   │       │   │                   │   └── rib/
│   │       │   │                   │       ├── GenerateAction.java
│   │       │   │                   │       ├── GenerateRibAction.java
│   │       │   │                   │       ├── GenerateRibDialog.form
│   │       │   │                   │       ├── GenerateRibDialog.java
│   │       │   │                   │       └── Generators.java
│   │       │   │                   └── generator/
│   │       │   │                       ├── Generator.java
│   │       │   │                       ├── GeneratorPair.java
│   │       │   │                       └── rib/
│   │       │   │                           ├── BuilderGenerator.java
│   │       │   │                           ├── InteractorWithEmptyPresenterGenerator.java
│   │       │   │                           ├── InteractorWithEmptyPresenterTestGenerator.java
│   │       │   │                           ├── InteractorWithPresenterGenerator.java
│   │       │   │                           ├── InteractorWithPresenterTestGenerator.java
│   │       │   │                           ├── RouterGenerator.java
│   │       │   │                           ├── RouterTestGenerator.java
│   │       │   │                           ├── ViewBuilderGenerator.java
│   │       │   │                           ├── ViewGenerator.java
│   │       │   │                           ├── ViewRouterGenerator.java
│   │       │   │                           └── ViewRouterTestGenerator.java
│   │       │   ├── kotlin/
│   │       │   │   └── com/
│   │       │   │       └── uber/
│   │       │   │           └── intellij/
│   │       │   │               └── plugin/
│   │       │   │                   └── android/
│   │       │   │                       └── rib/
│   │       │   │                           ├── AndroidDeviceRepository.kt
│   │       │   │                           ├── AttachRibProjectServiceActivity.kt
│   │       │   │                           ├── CommandLineUtils.kt
│   │       │   │                           ├── RibHierarchyBrowser.kt
│   │       │   │                           ├── RibHierarchyPanel.kt
│   │       │   │                           ├── RibHierarchyUtils.kt
│   │       │   │                           ├── RibIcons.kt
│   │       │   │                           ├── RibProjectService.kt
│   │       │   │                           ├── RibViewBrowser.kt
│   │       │   │                           ├── io/
│   │       │   │                           │   ├── AckRequest.kt
│   │       │   │                           │   ├── LogcatMessageDecoder.kt
│   │       │   │                           │   ├── LogcatRequestProcessor.kt
│   │       │   │                           │   ├── Request.kt
│   │       │   │                           │   ├── RequestProcessor.kt
│   │       │   │                           │   ├── Response.kt
│   │       │   │                           │   ├── RibHierarchyRequest.kt
│   │       │   │                           │   ├── RibHighlightRequest.kt
│   │       │   │                           │   └── RibLocateRequest.kt
│   │       │   │                           └── ui/
│   │       │   │                               ├── HierarchyBrowserBase.kt
│   │       │   │                               ├── RibHierarchyActivityDescriptor.kt
│   │       │   │                               ├── RibHierarchyApplicationDescriptor.kt
│   │       │   │                               ├── RibHierarchyDescriptor.kt
│   │       │   │                               ├── RibHierarchyNodeDescriptor.kt
│   │       │   │                               ├── RibHierarchyRootNodeDescriptor.kt
│   │       │   │                               ├── RibHierarchyTreeStructure.kt
│   │       │   │                               ├── RibViewNodeDescriptor.kt
│   │       │   │                               └── RibViewRootNodeDescriptor.kt
│   │       │   └── resources/
│   │       │       ├── META-INF/
│   │       │       │   └── plugin.xml
│   │       │       ├── partials/
│   │       │       │   ├── ExampleInteractorTest.java.partial
│   │       │       │   ├── ExampleRouterTest.java.partial
│   │       │       │   ├── RibInteractorDidBecomeActive.java.partial
│   │       │       │   └── RibInteractorWillResignActive.java.partial
│   │       │       └── templates/
│   │       │           ├── java/
│   │       │           │   ├── RibBuilder.java.template
│   │       │           │   ├── RibInteractorWithEmptyPresenter.java.template
│   │       │           │   ├── RibInteractorWithEmptyPresenterTest.java.template
│   │       │           │   ├── RibInteractorWithPresenter.java.template
│   │       │           │   ├── RibInteractorWithPresenterTest.java.template
│   │       │           │   ├── RibRouter.java.template
│   │       │           │   ├── RibRouterTest.java.template
│   │       │           │   ├── RibView.java.template
│   │       │           │   ├── RibViewBuilder.java.template
│   │       │           │   ├── RibViewRouter.java.template
│   │       │           │   └── RibViewRouterTest.java.template
│   │       │           └── kotlin/
│   │       │               ├── RibBuilder.kt.template
│   │       │               ├── RibInteractorWithEmptyPresenter.kt.template
│   │       │               ├── RibInteractorWithEmptyPresenterTest.kt.template
│   │       │               ├── RibInteractorWithPresenter.kt.template
│   │       │               ├── RibInteractorWithPresenterTest.kt.template
│   │       │               ├── RibRouter.kt.template
│   │       │               ├── RibRouterTest.kt.template
│   │       │               ├── RibView.kt.template
│   │       │               ├── RibViewBuilder.kt.template
│   │       │               ├── RibViewRouter.kt.template
│   │       │               └── RibViewRouterTest.kt.template
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── uber/
│   │                       └── presidio/
│   │                           └── intellij_plugin/
│   │                               └── action/
│   │                                   └── rib/
│   │                                       └── RibGeneratorsTest.java
│   └── utils/
│       └── intellij-broadcast-core/
│           ├── README.md
│           ├── build.gradle.kts
│           ├── gradle.properties
│           └── src/
│               └── main/
│                   └── java/
│                       └── com/
│                           └── uber/
│                               └── debug/
│                                   └── broadcast/
│                                       └── core/
│                                           ├── AckDebugBroadcastHandler.java
│                                           ├── DebugBroadcastReceiver.java
│                                           ├── DebugBroadcastRequest.java
│                                           └── DebugBroadcastResponse.java
└── tutorials/
    ├── tutorial1/
    │   ├── README.md
    │   ├── build.gradle.kts
    │   └── src/
    │       ├── main/
    │       │   ├── AndroidManifest.xml
    │       │   ├── java/
    │       │   │   └── com/
    │       │   │       └── uber/
    │       │   │           └── rib/
    │       │   │               ├── RootActivity.java
    │       │   │               ├── SampleApplication.java
    │       │   │               └── root/
    │       │   │                   ├── RootBuilder.java
    │       │   │                   ├── RootInteractor.java
    │       │   │                   ├── RootRouter.java
    │       │   │                   └── RootView.java
    │       │   └── res/
    │       │       ├── layout/
    │       │       │   └── root_rib.xml
    │       │       └── values/
    │       │           └── ub__strings.xml
    │       └── test/
    │           └── java/
    │               └── com/
    │                   └── uber/
    │                       └── rib/
    │                           └── root/
    │                               ├── RootInteractorTest.java
    │                               └── RootRouterTest.java
    ├── tutorial2/
    │   ├── README.md
    │   ├── build.gradle.kts
    │   └── src/
    │       ├── main/
    │       │   ├── AndroidManifest.xml
    │       │   ├── java/
    │       │   │   └── com/
    │       │   │       └── uber/
    │       │   │           └── rib/
    │       │   │               ├── RootActivity.java
    │       │   │               ├── SampleApplication.java
    │       │   │               └── root/
    │       │   │                   ├── RootBuilder.java
    │       │   │                   ├── RootInteractor.java
    │       │   │                   ├── RootRouter.java
    │       │   │                   ├── RootView.java
    │       │   │                   ├── loggedin/
    │       │   │                   │   ├── offgame/
    │       │   │                   │   │   ├── OffGameBuilder.java
    │       │   │                   │   │   ├── OffGameInteractor.java
    │       │   │                   │   │   ├── OffGameRouter.java
    │       │   │                   │   │   └── OffGameView.java
    │       │   │                   │   └── tictactoe/
    │       │   │                   │       ├── Board.java
    │       │   │                   │       ├── BoardCoordinate.java
    │       │   │                   │       ├── TicTacToeBuilder.java
    │       │   │                   │       ├── TicTacToeInteractor.java
    │       │   │                   │       ├── TicTacToeRouter.java
    │       │   │                   │       └── TicTacToeView.java
    │       │   │                   └── loggedout/
    │       │   │                       ├── LoggedOutBuilder.java
    │       │   │                       ├── LoggedOutInteractor.java
    │       │   │                       ├── LoggedOutRouter.java
    │       │   │                       └── LoggedOutView.java
    │       │   └── res/
    │       │       ├── layout/
    │       │       │   ├── logged_out_rib.xml
    │       │       │   ├── off_game_rib.xml
    │       │       │   ├── root_rib.xml
    │       │       │   └── tic_tac_toe_rib.xml
    │       │       └── values/
    │       │           └── ub__strings.xml
    │       └── test/
    │           └── java/
    │               └── com/
    │                   └── uber/
    │                       └── rib/
    │                           └── root/
    │                               ├── RootInteractorTest.java
    │                               ├── RootRouterTest.java
    │                               └── loggedout/
    │                                   ├── LoggedOutInteractorTest.java
    │                                   └── LoggedOutRouterTest.java
    ├── tutorial3/
    │   ├── README.md
    │   ├── build.gradle.kts
    │   └── src/
    │       ├── main/
    │       │   ├── AndroidManifest.xml
    │       │   ├── java/
    │       │   │   └── com/
    │       │   │       └── uber/
    │       │   │           └── rib/
    │       │   │               ├── RootActivity.java
    │       │   │               ├── SampleApplication.java
    │       │   │               └── root/
    │       │   │                   ├── RootBuilder.java
    │       │   │                   ├── RootInteractor.java
    │       │   │                   ├── RootRouter.java
    │       │   │                   ├── RootView.java
    │       │   │                   ├── loggedin/
    │       │   │                   │   ├── LoggedInBuilder.java
    │       │   │                   │   ├── LoggedInInteractor.java
    │       │   │                   │   ├── LoggedInRouter.java
    │       │   │                   │   ├── offgame/
    │       │   │                   │   │   ├── OffGameBuilder.java
    │       │   │                   │   │   ├── OffGameInteractor.java
    │       │   │                   │   │   ├── OffGameRouter.java
    │       │   │                   │   │   └── OffGameView.java
    │       │   │                   │   └── tictactoe/
    │       │   │                   │       ├── Board.java
    │       │   │                   │       ├── BoardCoordinate.java
    │       │   │                   │       ├── TicTacToeBuilder.java
    │       │   │                   │       ├── TicTacToeInteractor.java
    │       │   │                   │       ├── TicTacToeRouter.java
    │       │   │                   │       └── TicTacToeView.java
    │       │   │                   └── loggedout/
    │       │   │                       ├── LoggedOutBuilder.java
    │       │   │                       ├── LoggedOutInteractor.java
    │       │   │                       ├── LoggedOutRouter.java
    │       │   │                       └── LoggedOutView.java
    │       │   └── res/
    │       │       ├── layout/
    │       │       │   ├── logged_out_rib.xml
    │       │       │   ├── off_game_rib.xml
    │       │       │   ├── root_rib.xml
    │       │       │   └── tic_tac_toe_rib.xml
    │       │       └── values/
    │       │           └── ub__strings.xml
    │       └── test/
    │           └── java/
    │               └── com/
    │                   └── uber/
    │                       └── rib/
    │                           └── root/
    │                               ├── RootInteractorTest.java
    │                               ├── RootRouterTest.java
    │                               ├── loggedin/
    │                               │   ├── LoggedInInteractorTest.java
    │                               │   ├── LoggedInRouterTest.java
    │                               │   ├── offgame/
    │                               │   │   ├── OffGameInteractorTest.java
    │                               │   │   └── OffGameRouterTest.java
    │                               │   └── tictactoe/
    │                               │       ├── TicTacToeInteractorTest.java
    │                               │       └── TicTacToeRouterTest.java
    │                               └── loggedout/
    │                                   ├── LoggedOutInteractorTest.java
    │                                   └── LoggedOutRouterTest.java
    ├── tutorial3-completed/
    │   ├── README.md
    │   ├── build.gradle.kts
    │   └── src/
    │       ├── main/
    │       │   ├── AndroidManifest.xml
    │       │   ├── java/
    │       │   │   └── com/
    │       │   │       └── uber/
    │       │   │           └── rib/
    │       │   │               ├── RootActivity.java
    │       │   │               ├── SampleApplication.java
    │       │   │               └── root/
    │       │   │                   ├── RootBuilder.java
    │       │   │                   ├── RootInteractor.java
    │       │   │                   ├── RootRouter.java
    │       │   │                   ├── RootView.java
    │       │   │                   ├── loggedin/
    │       │   │                   │   ├── LoggedInBuilder.java
    │       │   │                   │   ├── LoggedInInteractor.java
    │       │   │                   │   ├── LoggedInRouter.java
    │       │   │                   │   ├── MutableScoreStream.java
    │       │   │                   │   ├── ScoreStream.java
    │       │   │                   │   ├── offgame/
    │       │   │                   │   │   ├── OffGameBuilder.java
    │       │   │                   │   │   ├── OffGameInteractor.java
    │       │   │                   │   │   ├── OffGameRouter.java
    │       │   │                   │   │   └── OffGameView.java
    │       │   │                   │   └── tictactoe/
    │       │   │                   │       ├── Board.java
    │       │   │                   │       ├── BoardCoordinate.java
    │       │   │                   │       ├── TicTacToeBuilder.java
    │       │   │                   │       ├── TicTacToeInteractor.java
    │       │   │                   │       ├── TicTacToeRouter.java
    │       │   │                   │       └── TicTacToeView.java
    │       │   │                   └── loggedout/
    │       │   │                       ├── LoggedOutBuilder.java
    │       │   │                       ├── LoggedOutInteractor.java
    │       │   │                       ├── LoggedOutRouter.java
    │       │   │                       └── LoggedOutView.java
    │       │   └── res/
    │       │       ├── layout/
    │       │       │   ├── logged_out_rib.xml
    │       │       │   ├── off_game_rib.xml
    │       │       │   ├── root_rib.xml
    │       │       │   └── tic_tac_toe_rib.xml
    │       │       └── values/
    │       │           └── ub__strings.xml
    │       └── test/
    │           └── java/
    │               └── com/
    │                   └── uber/
    │                       └── rib/
    │                           └── root/
    │                               ├── RootInteractorTest.java
    │                               ├── RootRouterTest.java
    │                               ├── loggedin/
    │                               │   ├── LoggedInInteractorTest.java
    │                               │   ├── LoggedInRouterTest.java
    │                               │   ├── offgame/
    │                               │   │   ├── OffGameInteractorTest.java
    │                               │   │   └── OffGameRouterTest.java
    │                               │   └── tictactoe/
    │                               │       ├── TicTacToeInteractorTest.java
    │                               │       └── TicTacToeRouterTest.java
    │                               └── loggedout/
    │                                   ├── LoggedOutInteractorTest.java
    │                                   └── LoggedOutRouterTest.java
    └── tutorial4/
        ├── README.md
        ├── build.gradle.kts
        └── src/
            └── main/
                ├── AndroidManifest.xml
                ├── java/
                │   └── com/
                │       └── uber/
                │           └── rib/
                │               ├── RootActivity.java
                │               ├── SampleApplication.java
                │               └── root/
                │                   ├── RootActionableItem.java
                │                   ├── RootBuilder.java
                │                   ├── RootInteractor.java
                │                   ├── RootRouter.java
                │                   ├── RootView.java
                │                   ├── RootWorkflow.java
                │                   ├── RootWorkflowModel.java
                │                   ├── UserName.kt
                │                   ├── WorkflowFactory.java
                │                   ├── loggedin/
                │                   │   ├── GameKey.java
                │                   │   ├── GameProvider.java
                │                   │   ├── LoggedInActionableItem.java
                │                   │   ├── LoggedInBuilder.java
                │                   │   ├── LoggedInInteractor.java
                │                   │   ├── LoggedInRouter.java
                │                   │   ├── MutableScoreStream.java
                │                   │   ├── ScoreStream.java
                │                   │   ├── offgame/
                │                   │   │   ├── OffGameBuilder.java
                │                   │   │   ├── OffGameInteractor.java
                │                   │   │   ├── OffGameRouter.java
                │                   │   │   └── OffGameView.java
                │                   │   ├── randomWinner/
                │                   │   │   ├── RandomWinnerBuilder.java
                │                   │   │   ├── RandomWinnerInteractor.java
                │                   │   │   ├── RandomWinnerRouter.java
                │                   │   │   └── RandomWinnerView.java
                │                   │   └── tictactoe/
                │                   │       ├── Board.java
                │                   │       ├── BoardCoordinate.java
                │                   │       ├── TicTacToeBuilder.java
                │                   │       ├── TicTacToeInteractor.java
                │                   │       ├── TicTacToeRouter.java
                │                   │       └── TicTacToeView.java
                │                   └── loggedout/
                │                       ├── LoggedOutBuilder.java
                │                       ├── LoggedOutInteractor.java
                │                       ├── LoggedOutRouter.java
                │                       └── LoggedOutView.java
                └── res/
                    ├── layout/
                    │   ├── game_button.xml
                    │   ├── logged_out_rib.xml
                    │   ├── off_game_rib.xml
                    │   ├── root_rib.xml
                    │   └── tic_tac_toe_rib.xml
                    └── values/
                        └── ub__strings.xml

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
<!--
Thank you for contributing to RIBs. Before pressing the "Create Pull Request" button, please consider the following points.
Feel free to remove any irrelevant parts that you know are not related to the issue.
Any HTML comment like this will be stripped when rendering markdown, no need to delete them.
-->

<!-- Please give a description about what and why you are contributing, even if it's trivial. -->
**Description**:

<!-- Please include the issue list number(s) or other PR numbers in the description if you are contributing in response to those. -->
**Related issue(s)**:

<!-- Please include a reasonable set of unit tests if you contribute new code or change an existing one. -->


================================================
FILE: .github/workflows/android.yml
================================================
name: CI Android

on: [push, pull_request]

jobs:
  build:
    name: JDK ${{ matrix.java_version }}
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: ./
    strategy:
      matrix:
        java_version: [17]
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Install JDK
        uses: actions/setup-java@v2
        with:
          distribution: 'zulu'
          java-version: ${{ matrix.java_version }}
      - name: Install Android SDK
        uses: malinskiy/action-android/install-sdk@release/0.1.1
      - name: Gradle Wrapper Validation
        uses: gradle/wrapper-validation-action@v1
      - name: Configure Gradle
        # Gradle configuration install deps
        run: ./gradlew help
      - name: Spot check
        run: ./gradlew spotlessCheck --stacktrace
      - name: Build Project
        run: ./gradlew assemble --stacktrace
      - name : Testing
        run: ./gradlew test --stacktrace
      - name: Final Checks
        run: ./gradlew check --stacktrace
      - name: Upload snapshot
        run: ./gradlew publish -PmavenCentralUsername="${{ secrets.SonatypeUsername }}" -PmavenCentralPassword="${{ secrets.SonatypePassword }}"
        if: success() && github.ref == 'refs/heads/main' && github.event_name != 'pull_request' && matrix.java_version == '11'


================================================
FILE: .gitignore
================================================
###OSX###

.DS_Store
.AppleDouble
.LSOverride

# Icon must ends with two \r.
Icon


# Thumbnails
._*

# Files that might appear on external disk
.Spotlight-V100
.Trashes


###Linux###

*~

# KDE directory preferences
.directory


###Android###

# Built application files
*.apk
*.ap_

# Files for ART and Dalvik VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/

# Gradle files
.gradle/
.gradletasknamecache
build/

# Local configuration file (sdk path, etc)
local.properties

# Proguard folder generated by Eclipse
proguard/

# Lint
lint-report.html
lint-report_files/
lint_result.txt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.war
*.ear

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*


###IntelliJ###

*.iml
*.ipr
*.iws
.idea/
.intellijPlatform/

###Eclipse###

*.pydevproject
.metadata
tmp/
*.tmp
*.bak
*.swp
*~.nib
.settings/
.loadpath


### Xcode ###
# Build generated
build/
DerivedData/

# Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata/

## Other
*.moved-aside
*.xccheckout
*.xcscmblueprint

## Obj-C/Swift specific
*.hmap
*.ipa
*.dSYM.zip
*.dSYM

# Swift Package Manager
.build/

# CocoaPods
Pods/
Podfile.lock
*.xcworkspace/

# Carthage
Cartfile.resolved
Carthage/


### Other ###

# External tool builders
.externalToolBuilders/

# Locally stored "Eclipse launch configurations"
*.launch

# CDT-specific
.cproject

# PDT-specific
.buildpath

# sbteclipse plugin
.target

# TeXlipse plugin
.texlipse

# kotlin
annotations/


================================================
FILE: CHANGELOG.md
================================================
# Changelog

### Version 0.1.0

* Initial release

### Version 0.9.2

* Fix forked Workflow invoking didComplete multiple times

### Version 0.9.3

* Upgraded iOS library to Swift 5

### Version 0.10.0

* Updates from the internal fork of RIBs (see Releases section)

### Version 0.10.1

* Added REPLACE_TOP `RouterNavigator` flag

### Version 0.11.0

* Migrate library modules to Kotlin but keep the same APIs

### Version 0.11.1

* Bugfixes for Kotlin migration

### Version 0.11.2

* One more bugfix and log message for Kotlin migration edge case

### Version 0.11.3

* Added NEW_TASK_REPLACE `RouterNavigator` flag

### Version 0.12.0

* Added Jetpack Compose RIB classes

### Version 0.12.1

* `BasicComposeRouter` now auto-attaches child composable content

### Version 0.12.2

* Work around Bazel desugar issues

### Version 0.13.0

* [Android] Adds rib-coroutines and rib-coroutines-test to enable corotouines interop

### Version 0.13.1

* [Android] Upgrade to Kotlin 1.7
* [Android] Add Window Focus Event API
* [Android] Add open modifier to doOnRemoved()8
* [Android] Deprecate mockitokotlin2

### Version 0.13.2
* [Android] Reverting binary breaking change from 0.13.1 on Basic Interactor

### Version 0.13.3
* [Intellij] Plugin 0.1.5 
* [Android] Clear cached CoroutineScope instance once its job completes 
* [Android] Make all TestDispatchers in TestRibDispatchers use the same TestCoroutineScheduler

### Version 0.14.0
* [Android] Bump Kotlin, Gradle, and other dependencies versions.
* [Android] Provide option to bind multiple Workers at once on specific RibDispatchers  AndroidAndroid related tickets
* [Android] Use Kotlin contracts to remove var and !! usage in RibCoroutineWorker
* [Android] [Draft] Add capability for binding multiple Workers in specified CoroutineDispatcher  AndroidAndroid related tickets
* [Android] Enable explicit api mode for Kotlin libraries  AndroidAndroid related tickets
* [Android] Provide a more idiomatic Java API for RibDispatchers
* [Android] Upgrade code formatters versions  AndroidAndroid related tickets
* [Android] Create README for Compose Demo  AndroidAndroid related tickets
* [Android] [Rib Worker] Specify CoroutineDispatcher for onStart/onStop and provide WorkerBinder monitoring option  AndroidAndroid related tickets
* [Android] Reduce Rx <-> Coroutines interop and allow unconfined coroutines to run eagerly inside Workers onStart
* [Android] Redesign RouterAndState to avoid router caching
* [Android] Fix router navigator events source compatibility
* [Android] Enable strict explicit API mode on rib-base
* [Android] Introduce RibCoroutineWorker  AndroidAndroid related tickets
* [Android] Replacing some Behavior/Publish Relay usage in core artifacts with coroutines

### Version 0.14.1
* [Android] Open lifecycleFlow, thus enabling it for mocking 
* [Android] [WorkerBinder] Guard against potential Worker.coroutineContext being null while using Mockito

### Version 0.14.2
* [Android] Fix potential for deadlocks in `Worker` binding. by @psteiger in https://github.com/uber/RIBs/pull/582
* [Android] Add  Rib Worker demo app by @FranAguilera in https://github.com/uber/RIBs/pull/575

### Version 0.15.0
* Only complete the worker's scope after calling `Worker.onStop` by @psteiger in https://github.com/uber/RIBs/pull/585
* Improve KDoc on `ActivityLifecycleEvent` by explaining ordering semantics. by @psteiger in https://github.com/uber/RIBs/pull/586
* Make use of `jvmToolchain` for building the project. by @psteiger in https://github.com/uber/RIBs/pull/583
* Revamp Gradle scripts by @psteiger in https://github.com/uber/RIBs/pull/588
* Deprecate old worker by @FranAguilera in https://github.com/uber/RIBs/pull/597
* Allow overriding default CoroutineDispatcher for WorkerBinder calls by @FranAguilera in https://github.com/uber/RIBs/pull/596
* Update README.md by @FranAguilera in https://github.com/uber/RIBs/pull/600
* Deprecate WorkerUnbinder by @FranAguilera in https://github.com/uber/RIBs/pull/601
* Expose ribActionEvents stream by @FranAguilera in https://github.com/uber/RIBs/pull/599

### Version 0.15.1
* [Android] Remove use of @JvmDefault in favor of using -Xjvm-default=all by @psteiger in https://github.com/uber/RIBs/pull/576

### Version 0.15.2
* [Android] Set view tree owners for RibActivity

### Version 0.15.3
* Add RibCoroutineWorker.bind that receives multiple workers by @FranAguilera in https://github.com/uber/RIBs/pull/607
* Change default CoroutineContext from empty to default for the RibCoroutineWorker<>Worker conversion by @FranAguilera in https://github.com/uber/RIBs/pull/608
* Add `RibCoroutineWorker` factory method with `CoroutineScope` as receiver by @psteiger in https://github.com/uber/RIBs/pull/610
* Update coroutines 1.7.3 by @tyvsmith in https://github.com/uber/RIBs/pull/609
* Bump kotlinx.coroutines.test to 1.7.3 by @psteiger in https://github.com/uber/RIBs/pull/611

### Version 0.15.4
* Set JvmVersion to 1.8

### Version 0.16.0
* Get rid of suppressions for "invisible_reference" and "invisible_member" by @psteiger in https://github.com/uber/RIBs/pull/618
* Introduce `TestScope.test(RibCoroutineWorker)` test helper utility. by @psteiger in https://github.com/uber/RIBs/pull/620

### Version 0.16.1
* [Android] Remove duplicate method by @jbarr in https://github.com/uber/RIBs/pull/621

### Version 0.16.2
* Make suspend functions callable inside `test(worker) { }` by @psteiger in https://github.com/uber/RIBs/pull/624
* [RibCoroutineWorker] In `asWorker()`, keep scope alive until lifecycl… by @psteiger in https://github.com/uber/RIBs/pull/625

### Version 0.16.3
* Fix Flipper Ribtree Plugin memory leak by @mamykin-andrey in https://github.com/uber/RIBs/pull/630
* Support classes that are both `Worker` and `RibCoroutineWorker` in co… by @psteiger in https://github.com/uber/RIBs/pull/629
* Increase buffer capacity for mutableRouterEvents flow within RibEvents by @RahulDMello in https://github.com/uber/RIBs/pull/635
* Add test asserting Rx subscription is disposed after `RibCoroutineWor… by @psteiger in https://github.com/uber/RIBs/pull/628

### Version 0.16.4
* Remove intrinsics usage in `RibCoroutineWorker` by @psteiger in https://github.com/uber/RIBs/pull/627
* Remove ios to prep for separate repos by @tyvsmith in https://github.com/uber/RIBs/pull/646
* fix url typo for ribs-ios by @tyvsmith in https://github.com/uber/RIBs/pull/647
* Replace the SharedFlow with a StateFlow in the Interactor class by @rysh88 in https://github.com/uber/RIBs/pull/651
* Remove Java 8 usage from repository. by @psteiger in https://github.com/uber/RIBs/pull/652
* Bump Kotlin, Compose, Coroutines, AGP. by @psteiger in https://github.com/uber/RIBs/pull/653
* Add tests for RibEvents buffer size configuration by @psteiger in https://github.com/uber/RIBs/pull/642
* `ScopeProvider.coroutineScope`: Fail silently when accessing outside of RIB scope. by @psteiger in https://github.com/uber/RIBs/pull/632

### Version 0.16.5
* Remove unneeded deps
* Restore source compatibility for Interactor
* Add mavenCentral publishing by @psteiger in https://github.com/uber/RIBs/pull/655



================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at mobile-open-source@uber.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]

[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to RIBs

Uber welcomes contributions of all kinds and sizes. This includes everything from from simple bug reports to large features.

Before we can accept your contributions, we kindly ask you to sign our [Contributor License Agreement](https://cla-assistant.io/uber/RIBs).

Workflow
--------

We love GitHub issues!

For small feature requests, an issue first proposing it for discussion or demo implementation in a PR suffice.

For big features, please open an issue so that we can agree on the direction, and hopefully avoid investing a lot of time on a feature that might need reworking.

Small pull requests for things like typos, bug fixes, etc are always welcome.

### Code style

This project uses [ktfmt](https://github.com/facebookincubator/ktfmt), [ktlint](https://github.com/pinterest/ktlint), and [GJF](https://github.com/google/google-java-format),
provided via the [spotless](https://github.com/diffplug/spotless) gradle plugin.

If you find that one of your pull reviews does not pass the CI server check due to a code style
conflict, you can easily fix it by running: `./gradlew spotlessApply`.

Generally speaking - we use ktfmt, vanilla ktlint + 2space indents, and vanilla GJF. You can integrate both of
these in IntelliJ code style via either [GJF's official plugin](https://plugins.jetbrains.com/plugin/8527-google-java-format) or applying code style from Jetbrains' official style.

No star imports please!

DOs and DON'Ts
--------------

* DO follow our [coding style](https://github.com/uber/java-code-styles)
* DO include tests when adding new features. When fixing bugs, start with adding a test that highlights how the current behavior is broken.
* DO keep the discussions focused. When a new or related topic comes up it's often better to create new issue than to side track the discussion.

* DON'T submit PRs that alter licensing related files or headers. If you believe there's a problem with them, file an issue and we'll be happy to discuss it.

Guiding Principles
------------------

* We allow anyone to participate in our projects. Tasks can be carried out by anyone that demonstrates the capability to complete them
* Always be respectful of one another. Assume the best in others and act with empathy at all times
* Collaborate closely with individuals maintaining the project or experienced users. Getting ideas out in the open and seeing a proposal before it's a pull request helps reduce redundancy and ensures we're all connected to the decision making process


================================================
FILE: LICENSE.txt
================================================

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


  RIBs depends on the following libraries:

  Copyright (C) 2017 The Guava Authors
   
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.


================================================
FILE: README.md
================================================
<p align="center">
<img src="https://github.com/uber/ribs/blob/assets/rib_horizontal_black.png" width="60%" height="60%" alt="RIBs"/>
</p>

[![Android CI](https://github.com/uber/RIBs/actions/workflows/android.yml/badge.svg?branch=main)](https://github.com/uber/RIBs/actions/workflows/android.yml)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Maven Central](https://img.shields.io/maven-central/v/com.uber.rib/rib-android.svg)](https://search.maven.org/artifact/com.uber.rib/rib-android)

> ⚠️ **Alert:** RIBs for IOS has been has been moved to a [separate repo](https://github.com/uber/ribs-ios)

RIBs is the cross-platform architecture framework behind many mobile apps at Uber. The name RIBs is short for Router, Interactor and Builder, which are core components of this architecture. This framework is designed for mobile apps with a large number of engineers and nested states.

The RIBs architecture provides:
* **Shared architecture across iOS and Android.** Build cross-platform apps that have similar architecture, enabling iOS and Android teams to cross-review business logic code.
* **Testability and Isolation.** Classes must be easy to unit test and reason about in isolation. Individual RIB classes have distinct responsibilities like: routing, business, view logic, creation. Plus, most RIB logic is decoupled from child RIB logic. This makes RIB classes easy to test and reason about independently.
* **Tooling for developer productivity.** RIBs come with IDE tooling around code generation, memory leak detection, static analysis and runtime integrations - all which improve developer productivity for large teams or small.
* **An architecture that scales.** This architecture has proven to scale to hundreds of engineers working on the same codebase and apps with hundreds of RIBs.


## Documentation
To get started with RIBs, please refer to the [RIBs documentation](https://github.com/uber/RIBs/wiki). This describes key concepts on RIBs, from what they are for, their structure and common use cases.

To get more hands on with RIBs, we have written a [series of tutorials](https://github.com/uber/RIBs/wiki) that run you through the main aspects of the architecture with hands-on examples.

To read about the backstory on why we created RIBs, see [this blog post](https://www.uber.com/blog/new-rider-app-architecture/) we wrote when releasing RIBs in production the first time and see [this short video](https://www.youtube.com/watch?v=Q5cTT0M0YXg) where we discussed how the RIBs architecture works.

#### What is the difference between RIBs and MV*/VIPER?

MVC, MVP, MVI, MVVM and VIPER are architecture patterns. RIBs is a framework. What differentiates RIBs from frameworks based on MV*/VIPER is:

- **Business logic drives the app, not the view tree**. Unlike with MV*/VIPER, a RIB does not have to have a view. This means that the app hierarchy is driven by the business logic, not the view tree.
- **Independent business logic and view trees**. RIBs decouple how the business logic scopes are structured from view hierarchies. This allows the application to have a deep business logic tree, isolating business logic nodes, while maintaining a shallow view hierarchy making layouts, animations and transitions easy.

There are some other novel things about RIBs. However, these could also be implemented with other MV*/VIPER frameworks. These are:
- **Cross-platform approach**, allowing iOS and Android architecture to stay in sync.
- **Tooling for easier adoption** on larger apps or teams. Tooling we are open sourcing includes IDE plugins for code generation and static code analysis.
- **Strong opinions about how state should be communicated**, using DI and Rx. Each RIB defines its dependencies and what dependencies it needs from its parent. Parent components that fulfill a child’s parent dependencies are provided to child Builders as a constructor dependency to allow for hierarchical DI scoping. This means that information is communicated via these dependencies up and down the tree.

## Usage

1. Clone this repository
2. Integrate using your preferred installation mechanism

For usage of the tooling built around RIBs, please see the [Tooling section](https://github.com/uber/RIBs/wiki#rib-tooling) in our documentation.

## Installation for Android

To integrate the recommended minimum setup for RIBs add the following to your `build.gradle`:

```gradle
dependencies {
  annotationProcessor 'com.uber.rib:rib-compiler-test:0.16.5'
  implementation 'com.uber.rib:rib-android:0.16.5'
  testImplementation 'com.uber.rib:rib-test:0.16.5'
}
```
There are a number of extension packages available as well including Kotlin extensions, Jetpack Compose support, Coroutines support

## Related projects

If you like RIBs, check out other related open source projects from our team:
- [RIBs-iOS](https://github.com/uber/ribs-ios): The iOS version of RIBs
- [Needle](https://github.com/uber/needle): a compile-time safe Swift dependency injection framework.
- [Motif](https://github.com/uber/motif): An abstract on top of Dagger offering simpler APIs for nested scopes.
- [Swift Concurrency](https://github.com/uber/swift-concurrency): a set of concurrency utility classes used by Uber, inspired by the equivalent [java.util.concurrent](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/package-summary.html) package classes.
- [Swift Abstract Class](https://github.com/uber/swift-abstract-class): a light-weight library along with an executable that enables compile-time safe abstract class development for Swift projects.
- [Swift Common](https://github.com/uber/swift-common): common libraries used by this set of Swift open source projects.

## License

    Copyright (C) 2017 Uber Technologies

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.


================================================
FILE: RELEASING.md
================================================
Releasing
=========

Android
-------

 1. Change the version in `gradle.properties` to a non-SNAPSHOT version.
 2. Update the `README.md` with the new version.
 3. Update the `CHANGELOG.md` for the impending release.
 4. `git commit -am "Prepare for release X.Y.Z."` (where X.Y.Z is the new version)
 5. `git tag -a X.Y.Z -m "Version X.Y.Z"` (where X.Y.Z is the new version)
 6. `./gradlew clean publish --no-daemon --no-parallel && ./gradlew closeAndReleaseRepository`
 7. Update the `gradle.properties` to the next SNAPSHOT version.
 8. `git commit -am "Prepare next development version."`
 9. `git push && git push --tags`


================================================
FILE: build.gradle.kts
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
plugins {
    alias(libs.plugins.android.application) apply false
    alias(libs.plugins.android.library) apply false
    alias(libs.plugins.kotlin.android) apply false
    alias(libs.plugins.kotlin.kapt) apply false
    alias(libs.plugins.kotlin.ksp) apply false
    alias(libs.plugins.compose.compiler) apply false
    alias(libs.plugins.maven.publish) apply false
    alias(libs.plugins.errorprone) apply false
    alias(libs.plugins.nullaway) apply false
    alias(libs.plugins.intellij.platform) apply false
    alias(libs.plugins.spotless) apply false
}


================================================
FILE: config/lint/lint.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<lint>
    <issue id="GoogleAppIndexingWarning" severity="ignore" />
</lint>


================================================
FILE: config/spotless/copyright.java
================================================
/*
 * Copyright (C) $YEAR. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

================================================
FILE: config/spotless/copyright.kt
================================================
/*
 * Copyright (C) $YEAR. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

================================================
FILE: conventions/build.gradle.kts
================================================
/*
 * Copyright (C) 2023. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
plugins {
    `kotlin-dsl`
    `kotlin-dsl-precompiled-script-plugins`
}

repositories {
    google()
    mavenCentral()
    gradlePluginPortal()
}

dependencies {
    // Workaround for using version catalog on precompiled scripts.
    // https://github.com/gradle/gradle/issues/15383#issuecomment-779893192
    implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
    implementation(files(appLibs.javaClass.superclass.protectionDomain.codeSource.location))
    implementation(gradleApi())
    implementation(libs.gradle.android.plugin)
    implementation(libs.gradle.kotlin.plugin)
    implementation(plugin(libs.plugins.errorprone))
    implementation(plugin(libs.plugins.nullaway))
    implementation(plugin(libs.plugins.spotless))
    implementation(plugin(libs.plugins.kotlin.ksp))
}

// Helper function that transforms a Gradle Plugin alias from a
// Version Catalog into a valid dependency notation for buildSrc
// See https://docs.gradle.org/current/userguide/version_catalogs.html
@Suppress("UnusedReceiverParameter")
fun DependencyHandlerScope.plugin(plugin: Provider<PluginDependency>) =
    plugin.map { "${it.pluginId}:${it.pluginId}.gradle.plugin:${it.version}" }

================================================
FILE: conventions/settings.gradle.kts
================================================
/*
 * Copyright (C) 2023. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
dependencyResolutionManagement {
  versionCatalogs {
    create("libs") {
      from(files("../gradle/libs.versions.toml"))
    }
    create("appLibs") {
      from(files("../gradle/app-libs.versions.toml"))
    }
  }
}

rootProject.name = "conventions"


================================================
FILE: conventions/src/main/kotlin/Extensions.kt
================================================
/*
 * Copyright (C) 2023. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import com.android.build.gradle.AbstractAppExtension
import com.android.build.gradle.LibraryExtension
import com.android.build.gradle.TestedExtension
import com.android.build.gradle.api.BaseVariant
import net.ltgt.gradle.errorprone.CheckSeverity
import net.ltgt.gradle.errorprone.errorprone
import net.ltgt.gradle.nullaway.nullaway

fun AbstractAppExtension.errorprone() {
  applicationVariants.configureEach { errorprone() }
  testErrorprone()
}

fun LibraryExtension.errorprone() {
  libraryVariants.configureEach { errorprone() }
  testErrorprone()
}

fun TestedExtension.testErrorprone() {
  testVariants.configureEach { errorprone() }
  unitTestVariants.configureEach { errorprone() }
}

fun BaseVariant.errorprone() {
  javaCompileProvider.configure {
    options.errorprone.nullaway {
      severity.set(CheckSeverity.ERROR)
      annotatedPackages.add("com.uber")
    }
    options.errorprone.excludedPaths.set(".*/build/generated/.*")
  }
}


================================================
FILE: conventions/src/main/kotlin/ribs.android.application.errorprone.gradle.kts
================================================
/*
 * Copyright (C) 2023. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
val libs = the<org.gradle.accessors.dm.LibrariesForLibs>()
val appLibs = the<VersionCatalogsExtension>().named("appLibs")

plugins {
    id("ribs.android.application")
    id("com.google.devtools.ksp")
    id("net.ltgt.errorprone")
    id("net.ltgt.nullaway")
    id("ribs.spotless")
}

android {
    errorprone()
}

dependencies {
    ksp(appLibs.findLibrary("autodispose-errorprone").get())
    ksp(appLibs.findLibrary("uber-nullaway").get())
    errorprone(appLibs.findLibrary("errorprone-core").get())
    errorprone(libs.guava.jre)
    errorproneJavac(appLibs.findLibrary("errorprone-javac").get())
    errorprone(appLibs.findLibrary("uber-nullaway").get())
}


================================================
FILE: conventions/src/main/kotlin/ribs.android.application.gradle.kts
================================================
/*
 * Copyright (C) 2023. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

val libs = the<org.gradle.accessors.dm.LibrariesForLibs>()

plugins {
    kotlin("android")
    id("com.android.application")
    id("ribs.spotless")
}

kotlin {
    jvmToolchain(17)

    compilerOptions {
        jvmTarget = JvmTarget.JVM_1_8
        optIn.add("kotlin.RequiresOptIn")
        freeCompilerArgs.add("-Xjvm-default=all")
        // TODO: For Kotlin 2.2, delete the line above and uncomment the line below.
        // jvmDefault = JvmDefaultMode.NO_COMPATIBILITY
    }
}

android {
    compileSdk = 36

    defaultConfig {
        minSdk = 21
        targetSdk = 35
        versionCode = 1
        versionName = "1.0"
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }

    lint {
        // Those are just tutorials/demos. Don't fail the build because of them.
        abortOnError = false
        quiet = true
        // FlowOperatorInvokedInComposition Lint detector crashes on lintAnalyzeDebug task
        // due to version mismatch in kotlinx-metadata-jvm dependency. After bumping compose,
        // verify if this can be removed and pass CI.
        disable.add("FlowOperatorInvokedInComposition")
    }

    buildTypes {
        debug {
            matchingFallbacks.add("release")
        }
    }
}

androidComponents {
    beforeVariants { variantBuilder ->
        if (variantBuilder.buildType == "release") {
            variantBuilder.enable = false
        }
    }
}


================================================
FILE: conventions/src/main/kotlin/ribs.android.library.gradle.kts
================================================
/*
 * Copyright (C) 2023. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
    kotlin("android")
    id("com.android.library")
    id("ribs.spotless")
}

kotlin {
    jvmToolchain(17)
    explicitApi()

    compilerOptions {
        jvmTarget = JvmTarget.JVM_1_8
        optIn.add("kotlin.RequiresOptIn")
        freeCompilerArgs.add("-Xjvm-default=all")
        // TODO: For Kotlin 2.2, delete the line above and uncomment the line below.
        // jvmDefault = JvmDefaultMode.NO_COMPATIBILITY
    }
}

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

android {
    compileSdk = 36

    defaultConfig {
        minSdk = 21
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }

    testOptions {
        targetSdk = 35

        unitTests {
            isIncludeAndroidResources = true
        }
    }
}

androidComponents {
    beforeVariants { variantBuilder ->
        if (variantBuilder.buildType == "debug") {
            variantBuilder.enable = false
        }
    }
}


================================================
FILE: conventions/src/main/kotlin/ribs.kotlin.library.gradle.kts
================================================
/*
 * Copyright (C) 2023. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
    kotlin("jvm")
    id("ribs.spotless")
}

kotlin {
    jvmToolchain(17)
    explicitApi()

    compilerOptions {
        freeCompilerArgs.add("-Xjvm-default=all")
        jvmTarget = JvmTarget.JVM_1_8
    }
}

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}


================================================
FILE: conventions/src/main/kotlin/ribs.spotless.gradle.kts
================================================
/*
 * Copyright (C) 2023. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
plugins {
  id("com.diffplug.spotless")
}

val libs = the<org.gradle.accessors.dm.LibrariesForLibs>()

configure<com.diffplug.gradle.spotless.SpotlessExtension> {
  format("misc") {
    target("**/*.md", "**/.gitignore")
    trimTrailingWhitespace()
    endWithNewline()
  }
  kotlin {
    target("**/*.kt")
    ktlint(libs.versions.ktlint.get()).editorConfigOverride(
        mapOf(
            "indent_size" to "2",
            "continuation_indent_size" to "4",
        )
    )
    ktfmt(libs.versions.ktfmt.get()).googleStyle()
    licenseHeaderFile(rootProject.file("config/spotless/copyright.kt"))
    trimTrailingWhitespace()
    endWithNewline()
  }
  java {
    target("src/*/java/**/*.java")
    googleJavaFormat(libs.versions.google.java.format.get())
    licenseHeaderFile(rootProject.file("config/spotless/copyright.java"))
    removeUnusedImports()
    trimTrailingWhitespace()
    endWithNewline()
  }
  kotlinGradle {
    target("**/*.gradle.kts")
    trimTrailingWhitespace()
    endWithNewline()
  }
  groovyGradle {
    target("**/*.gradle")
    trimTrailingWhitespace()
    endWithNewline()
  }
}


================================================
FILE: demos/compose/README.md
================================================
The Uber RIBs Compose Demo showcases the integration of RIBs with Jetpack Compose, an Android UI toolkit for building native interfaces using a declarative approach. It demonstrates how to combine RIBs concepts such as Routers, Interactors, and Scopes with Jetpack Compose components like Composable functions and ComposeView.

Here's a summary of the key differences this demo offers:

- RIBs: RIBs (Router, Interactor, Builder) is a mobile app architecture developed by Uber, designed to manage complex navigation flows and business logic in a modular and scalable manner. RIBs have three core components: Router, Interactor, and Builder (now replaced with Motif Scope).

- Scope: In traditional RIBs architecture, the Builder creates and connects the components of a RIB, including the Router, Interactor, and View, while handling dependency injection. The Compose Demo replaces the Builder with Motif Scope, a lightweight dependency injection (DI) library. A Scope provides the necessary dependencies for a RIB, which can be shared across multiple RIBs, enhancing modularity and scalability.

- ComposePresenter: Traditional RIBs architecture employs a Presenter for communication between the Interactor and View. The Compose Demo introduces the ComposePresenter, containing a composable function that describes the UI, allowing RIBs to utilize Jetpack Compose for UI creation.

- ComposeView: While traditional RIBs architecture uses Android ViewGroup components for the View, the Compose Demo employs a ComposeView to host Jetpack Compose content within the RIB's view hierarchy.

- UI: The demo app leverages Jetpack Compose for UI definition in each RIB, with the MainView composable function displaying the Main RIB UI and hosting the content of the active child RIB.

- Coroutines: The Compose Demo uses coroutines to handle asynchronous tasks. Integrated into the RIBs architecture by extending the BasicInteractor with a coroutineScope property, coroutines enable non-blocking, concurrent, and readable asynchronous code while automatically managing their lifecycle.

- Flow: Flow, a Kotlin library for reactive data streams, is used in the Compose Demo to observe and manage state changes. For example, AuthStream employs MutableStateFlow and StateFlow to handle authentication state changes. Integrated with coroutines, Flow allows launching and consuming flows within a coroutine scope.
  - For example, The MainInteractor observes authStream with the onEach and launchIn functions, reacting to state changes and updating the UI.

In conclusion, the demo offers an innovative way to build mobile apps using RIBs architecture, effectively creating a SIRs (Scope, Interactor, Router) Architecture.


================================================
FILE: demos/compose/build.gradle.kts
================================================
/*
 * Copyright (C) 2025. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
plugins {
    id("ribs.android.application")
    alias(libs.plugins.kotlin.ksp)
    alias(libs.plugins.compose.compiler)
}

android {
    namespace = "com.uber.rib.compose"

    defaultConfig {
        applicationId = "com.uber.rib.compose"
    }
    buildFeatures {
        compose = true
        buildConfig = true
    }
}

dependencies {
    ksp(appLibs.motif.compiler)
    implementation(project(":libraries:rib-android"))
    implementation(project(":libraries:rib-android-compose"))
    implementation(project(":libraries:rib-coroutines"))
    implementation(appLibs.activity.compose)
    implementation(libs.compose.foundation)
    implementation(appLibs.compose.material)
    implementation(libs.compose.runtime)
    implementation(libs.compose.ui)
    implementation(libs.compose.uitooling)
    implementation(libs.savedstate)
    implementation(libs.rxandroid2)
    implementation(libs.kotlinx.coroutines.android)
    implementation(libs.kotlinx.coroutines.rx2)
    implementation(libs.autodispose.coroutines)
    implementation(appLibs.motif.library)


    // Flipper Debug tool integration
    debugImplementation(libs.flipper)
    debugImplementation(appLibs.soloader)
    releaseImplementation(libs.flipper.noop)

    // Flipper RIBs plugin
    implementation(project(":tooling:rib-flipper-plugin"))

    testImplementation(testLibs.junit)
}


================================================
FILE: demos/compose/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:name=".ComposeApplication"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Android">

        <activity
            android:name=".root.RootActivity"
            android:label="RIB Compose"
            android:windowSoftInputMode="adjustResize"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

    </application>

</manifest>

================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/ComposeApplication.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose

import android.app.Application
import com.facebook.flipper.android.AndroidFlipperClient
import com.facebook.flipper.android.utils.FlipperUtils
import com.facebook.flipper.core.FlipperClient
import com.facebook.flipper.plugins.inspector.DescriptorMapping
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin
import com.facebook.soloader.SoLoader
import com.uber.rib.flipper.RibTreePlugin

class ComposeApplication : Application() {

  override fun onCreate() {
    super.onCreate()
    SoLoader.init(this, false)

    if (BuildConfig.DEBUG && FlipperUtils.shouldEnableFlipper(this)) {
      val client: FlipperClient = AndroidFlipperClient.getInstance(this)
      client.addPlugin(RibTreePlugin())
      client.addPlugin(InspectorFlipperPlugin(this, DescriptorMapping.withDefaults()))
      client.start()
    }
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/RootActivity.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root

import android.view.ViewGroup
import com.uber.rib.core.RibActivity
import com.uber.rib.core.ViewRouter
import motif.Creatable
import motif.Expose
import motif.NoDependencies
import motif.ScopeFactory

class RootActivity : RibActivity() {

  override fun createRouter(parentViewGroup: ViewGroup): ViewRouter<*, *> {
    return ScopeFactory.create(Parent::class.java)
      .rootScope(this, findViewById(android.R.id.content))
      .router()
  }

  @motif.Scope
  interface Parent : Creatable<NoDependencies> {
    fun rootScope(@Expose activity: RibActivity, parentViewGroup: ViewGroup): RootScope
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/RootInteractor.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root

import com.uber.rib.core.BasicInteractor
import com.uber.rib.core.EmptyPresenter

class RootInteractor(presenter: EmptyPresenter) :
  BasicInteractor<EmptyPresenter, RootRouter>(presenter)


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/RootRouter.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root

import com.uber.rib.compose.root.main.MainRouter
import com.uber.rib.core.BasicViewRouter

class RootRouter(
  view: RootView,
  interactor: RootInteractor,
  private val scope: RootScope,
) : BasicViewRouter<RootView, RootInteractor>(view, interactor) {

  private var mainRouter: MainRouter? = null

  override fun willAttach() {
    attachMain()
  }

  override fun willDetach() {
    detachMain()
  }

  private fun attachMain() {
    if (mainRouter == null) {
      mainRouter = scope.mainScope(view).router().also { attachChild(it) }
    }
  }

  private fun detachMain() {
    mainRouter?.let { detachChild(it) }
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/RootScope.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root

import android.view.ViewGroup
import com.uber.rib.compose.root.main.MainScope
import com.uber.rib.compose.util.AnalyticsClient
import com.uber.rib.compose.util.AnalyticsClientImpl
import com.uber.rib.compose.util.ExperimentClient
import com.uber.rib.compose.util.ExperimentClientImpl
import com.uber.rib.compose.util.LoggerClient
import com.uber.rib.compose.util.LoggerClientImpl
import com.uber.rib.core.EmptyPresenter
import com.uber.rib.core.RibActivity
import motif.Expose

@motif.Scope
interface RootScope {
  fun router(): RootRouter

  fun mainScope(parentViewGroup: ViewGroup): MainScope

  @motif.Objects
  abstract class Objects {
    abstract fun router(): RootRouter

    abstract fun interactor(): RootInteractor

    abstract fun presenter(): EmptyPresenter

    fun view(parentViewGroup: ViewGroup): RootView {
      return RootView(parentViewGroup.context)
    }

    @Expose
    fun analyticsClient(activity: RibActivity): AnalyticsClient {
      return AnalyticsClientImpl(activity.application)
    }

    @Expose
    fun experimentClient(activity: RibActivity): ExperimentClient {
      return ExperimentClientImpl(activity.application)
    }

    @Expose
    fun loggerClient(activity: RibActivity): LoggerClient {
      return LoggerClientImpl(activity.application)
    }
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/RootView.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root

import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.widget.FrameLayout
import android.widget.TextView

class RootView
@JvmOverloads
constructor(
  context: Context,
  attrs: AttributeSet? = null,
  defStyle: Int = 0,
) : FrameLayout(context, attrs, defStyle) {

  init {
    setBackgroundColor(Color.RED)
    addView(
      TextView(context).apply {
        text = "root (view)"
        setTextColor(Color.WHITE)
      },
    )
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/AuthStream.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main

import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update

class AuthStream {
  private val _authFlow = MutableStateFlow(AuthInfo(false, "", ""))
  private val authFlow = _authFlow.asStateFlow()

  fun observe() = authFlow

  fun accept(value: AuthInfo) {
    _authFlow.update { value }
  }
}

data class AuthInfo(
  val isLoggedIn: Boolean,
  val playerOne: String = "",
  val playerTwo: String = "",
)


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/MainInteractor.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main

import com.uber.rib.core.BasicInteractor
import com.uber.rib.core.Bundle
import com.uber.rib.core.ComposePresenter
import com.uber.rib.core.coroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach

class MainInteractor(
  presenter: ComposePresenter,
  private val authStream: AuthStream,
  private val childContent: MainRouter.ChildContent,
) : BasicInteractor<ComposePresenter, MainRouter>(presenter) {

  override fun didBecomeActive(savedInstanceState: Bundle?) {
    super.didBecomeActive(savedInstanceState)

    router.view.setContent { MainView(childContent = childContent) }
    authStream
      .observe()
      .onEach {
        if (it.isLoggedIn) {
          router.detachLoggedOut()
          router.attachLoggedIn(it)
        } else {
          router.detachLoggedIn()
          router.attachLoggedOut()
        }
      }
      .launchIn(coroutineScope)
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/MainRouter.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main

import android.view.ViewGroup
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.platform.ComposeView
import com.uber.rib.compose.root.main.loggedin.LoggedInRouter
import com.uber.rib.compose.root.main.loggedout.LoggedOutRouter
import com.uber.rib.core.BasicViewRouter

class MainRouter(
  view: ComposeView,
  interactor: MainInteractor,
  private val parentView: ViewGroup,
  private val scope: MainScope,
  private val childContent: ChildContent,
) : BasicViewRouter<ComposeView, MainInteractor>(view, interactor) {

  private var loggedOutRouter: LoggedOutRouter? = null
  private var loggedInRouter: LoggedInRouter? = null

  override fun willAttach() {
    super.willAttach()
    parentView.addView(view)
  }

  override fun willDetach() {
    parentView.removeView(view)
    super.willDetach()
  }

  internal fun attachLoggedOut() {
    if (loggedOutRouter == null) {
      loggedOutRouter =
        scope.loggedOutScope(childContent.fullScreenSlot).router().also { attachChild(it) }
    }
  }

  internal fun attachLoggedIn(authInfo: AuthInfo) {
    if (loggedInRouter == null) {
      loggedInRouter =
        scope.loggedInScope(childContent.fullScreenSlot, authInfo).router().also { attachChild(it) }
    }
  }

  internal fun detachLoggedOut() {
    loggedOutRouter?.let { detachChild(it) }
    loggedOutRouter = null
  }

  internal fun detachLoggedIn() {
    loggedInRouter?.let { detachChild(it) }
    loggedInRouter = null
  }

  class ChildContent {
    internal var fullScreenSlot: MutableState<@Composable () -> Unit> = mutableStateOf({})
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/MainScope.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main

import android.view.ViewGroup
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.ui.platform.ComposeView
import com.uber.rib.compose.root.main.loggedin.LoggedInScope
import com.uber.rib.compose.root.main.loggedout.LoggedOutScope
import com.uber.rib.core.ComposePresenter
import motif.Expose

@motif.Scope
interface MainScope {
  fun router(): MainRouter

  fun loggedOutScope(slot: MutableState<@Composable () -> Unit>): LoggedOutScope

  fun loggedInScope(slot: MutableState<@Composable () -> Unit>, authInfo: AuthInfo): LoggedInScope

  @motif.Objects
  abstract class Objects {
    abstract fun router(): MainRouter

    abstract fun interactor(): MainInteractor

    fun presenter(childContent: MainRouter.ChildContent): ComposePresenter {
      return object : ComposePresenter() {
        override val composable = @Composable { MainView(childContent) }
      }
    }

    fun view(parentViewGroup: ViewGroup): ComposeView {
      return ComposeView(parentViewGroup.context)
    }

    abstract fun childContent(): MainRouter.ChildContent

    @Expose abstract fun authStream(): AuthStream
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/MainView.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp

@Composable
fun MainView(childContent: MainRouter.ChildContent) {
  Column(
    horizontalAlignment = Alignment.CenterHorizontally,
    verticalArrangement = Arrangement.Top,
    modifier =
      Modifier.fillMaxSize().padding(all = 4.dp).padding(top = 14.dp).background(Color(0xFFFFA500)),
  ) {
    Text("Main RIB (Compose w/ CompView)")
    Box(
      modifier = Modifier.fillMaxWidth().weight(1.0f).padding(4.dp).background(Color.Yellow),
    ) {
      childContent.fullScreenSlot.value.invoke()
    }
  }
}

@Preview
@Composable
fun MainViewPreview() {
  MainView(MainRouter.ChildContent())
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/LoggedInEvent.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin

sealed class LoggedInEvent {
  object LogOutClick : LoggedInEvent()
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/LoggedInInteractor.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin

import com.uber.rib.compose.root.main.AuthInfo
import com.uber.rib.compose.root.main.AuthStream
import com.uber.rib.compose.root.main.loggedin.offgame.OffGameInteractor
import com.uber.rib.compose.root.main.loggedin.tictactoe.TicTacToeInteractor
import com.uber.rib.compose.util.EventStream
import com.uber.rib.core.BasicInteractor
import com.uber.rib.core.Bundle
import com.uber.rib.core.ComposePresenter
import com.uber.rib.core.coroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch

class LoggedInInteractor(
  presenter: ComposePresenter,
  private val authInfo: AuthInfo,
  private val authStream: AuthStream,
  private val eventStream: EventStream<LoggedInEvent>,
  private val scoreStream: ScoreStream,
) :
  BasicInteractor<ComposePresenter, LoggedInRouter>(presenter),
  OffGameInteractor.Listener,
  TicTacToeInteractor.Listener {

  override fun didBecomeActive(savedInstanceState: Bundle?) {
    super.didBecomeActive(savedInstanceState)

    eventStream
      .observe()
      .onEach {
        when (it) {
          is LoggedInEvent.LogOutClick -> authStream.accept(AuthInfo(false))
        }
      }
      .launchIn(coroutineScope)

    router.attachOffGame(authInfo)
  }

  override fun onStartGame() {
    router.detachOffGame()
    router.attachTicTacToe(authInfo)
  }

  override fun onGameWon(winner: String?) {
    if (winner != null) {
      coroutineScope.launch { scoreStream.addVictory(winner) }
    }

    router.detachTicTacToe()
    router.attachOffGame(authInfo)
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/LoggedInRouter.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin

import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import com.uber.rib.compose.root.main.AuthInfo
import com.uber.rib.compose.root.main.loggedin.offgame.OffGameRouter
import com.uber.rib.compose.root.main.loggedin.tictactoe.TicTacToeRouter
import com.uber.rib.core.BasicComposeRouter
import com.uber.rib.core.ComposePresenter

class LoggedInRouter(
  presenter: ComposePresenter,
  interactor: LoggedInInteractor,
  slot: MutableState<@Composable () -> Unit>,
  private val scope: LoggedInScope,
  private val childContent: ChildContent,
) : BasicComposeRouter<LoggedInInteractor>(presenter, interactor, slot) {

  private var offGameRouter: OffGameRouter? = null
  private var ticTacToeRouter: TicTacToeRouter? = null

  internal fun attachOffGame(authInfo: AuthInfo) {
    if (offGameRouter == null) {
      offGameRouter =
        scope.offGameScope(childContent.fullScreenSlot, authInfo).router().also { attachChild(it) }
    }
  }

  internal fun attachTicTacToe(authInfo: AuthInfo) {
    if (ticTacToeRouter == null) {
      ticTacToeRouter =
        scope.ticTacToeScope(childContent.fullScreenSlot, authInfo).router().also {
          attachChild(it)
        }
    }
  }

  internal fun detachOffGame() {
    offGameRouter?.let { detachChild(it) }
    offGameRouter = null
  }

  internal fun detachTicTacToe() {
    ticTacToeRouter?.let { detachChild(it) }
    ticTacToeRouter = null
  }

  class ChildContent {
    internal var fullScreenSlot: MutableState<@Composable () -> Unit> = mutableStateOf({})
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/LoggedInScope.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin

import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import com.uber.rib.compose.root.main.AuthInfo
import com.uber.rib.compose.root.main.loggedin.offgame.OffGameInteractor
import com.uber.rib.compose.root.main.loggedin.offgame.OffGameScope
import com.uber.rib.compose.root.main.loggedin.tictactoe.TicTacToeInteractor
import com.uber.rib.compose.root.main.loggedin.tictactoe.TicTacToeScope
import com.uber.rib.compose.util.EventStream
import com.uber.rib.core.ComposePresenter
import motif.Expose

@motif.Scope
interface LoggedInScope {
  fun router(): LoggedInRouter

  fun offGameScope(slot: MutableState<@Composable () -> Unit>, authInfo: AuthInfo): OffGameScope

  fun ticTacToeScope(
    slot: MutableState<@Composable () -> Unit>,
    authInfo: AuthInfo,
  ): TicTacToeScope

  @motif.Objects
  abstract class Objects {
    abstract fun router(): LoggedInRouter

    abstract fun interactor(): LoggedInInteractor

    abstract fun childContent(): LoggedInRouter.ChildContent

    fun presenter(
      eventStream: EventStream<LoggedInEvent>,
      childContent: LoggedInRouter.ChildContent,
    ): ComposePresenter {
      return object : ComposePresenter() {
        override val composable = @Composable { LoggedInView(eventStream, childContent) }
      }
    }

    fun eventStream() = EventStream<LoggedInEvent>()

    @Expose
    fun scoreSteam(authInfo: AuthInfo): ScoreStream {
      return ScoreStream(authInfo.playerOne, authInfo.playerTwo)
    }

    @Expose
    abstract fun startGameListener(interactor: LoggedInInteractor): OffGameInteractor.Listener

    @Expose
    abstract fun gameWonListener(interactor: LoggedInInteractor): TicTacToeInteractor.Listener
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/LoggedInView.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.uber.rib.compose.util.CustomButton
import com.uber.rib.compose.util.EventStream

@Composable
fun LoggedInView(
  eventStream: EventStream<LoggedInEvent>,
  childContent: LoggedInRouter.ChildContent,
) {
  Column(
    horizontalAlignment = Alignment.CenterHorizontally,
    verticalArrangement = Arrangement.Top,
    modifier = Modifier.fillMaxSize().background(Color.Green),
  ) {
    Text("Logged In! (Compose RIB)")
    Spacer(Modifier.height(16.dp))
    Box(
      modifier = Modifier.fillMaxWidth().weight(1.0f).padding(4.dp).background(Color.LightGray),
    ) {
      childContent.fullScreenSlot.value.invoke()
    }
    CustomButton(
      analyticsId = "8a570808-07a4",
      onClick = { eventStream.notify(LoggedInEvent.LogOutClick) },
      modifier = Modifier.fillMaxWidth().padding(16.dp),
    ) {
      Text(text = "LOGOUT")
    }
  }
}

@Preview
@Composable
fun LoggedInViewPreview() {
  LoggedInView(EventStream(), LoggedInRouter.ChildContent())
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/ScoreStream.kt
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin

import com.uber.rib.core.RibDispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.withContext

class ScoreStream(playerOne: String, playerTwo: String) {

  private val _scoresFlow =
    MutableStateFlow(
      mapOf(
        playerOne to 0,
        playerTwo to 0,
      ),
    )
  private val scoresFlow = _scoresFlow.asStateFlow()

  suspend fun addVictory(userName: String) =
    withContext(RibDispatchers.Default) {
      _scoresFlow.update { scores ->
        scores
          .toMutableMap()
          .apply {
            if (userName in scores) {
              set(userName, getValue(userName) + 1)
            }
          }
          .toMap()
      }
    }

  fun scores() = scoresFlow
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/offgame/OffGameEvent.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin.offgame

sealed class OffGameEvent {
  object StartGame : OffGameEvent()
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/offgame/OffGameInteractor.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin.offgame

import com.uber.rib.compose.root.main.loggedin.ScoreStream
import com.uber.rib.compose.util.EventStream
import com.uber.rib.compose.util.StateStream
import com.uber.rib.core.BasicInteractor
import com.uber.rib.core.Bundle
import com.uber.rib.core.ComposePresenter
import com.uber.rib.core.coroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach

class OffGameInteractor(
  presenter: ComposePresenter,
  private val eventStream: EventStream<OffGameEvent>,
  private val stateStream: StateStream<OffGameViewModel>,
  private val scoreStream: ScoreStream,
  private val listener: Listener,
) : BasicInteractor<ComposePresenter, OffGameRouter>(presenter) {

  override fun didBecomeActive(savedInstanceState: Bundle?) {
    super.didBecomeActive(savedInstanceState)

    eventStream
      .observe()
      .onEach {
        when (it) {
          is OffGameEvent.StartGame -> {
            listener.onStartGame()
          }
        }
      }
      .launchIn(coroutineScope)

    scoreStream
      .scores()
      .onEach {
        val currentState = stateStream.current()
        stateStream.dispatch(
          currentState.copy(
            playerOneWins = it[currentState.playerOne] ?: 0,
            playerTwoWins = it[currentState.playerTwo] ?: 0,
          ),
        )
      }
      .launchIn(coroutineScope)
  }

  interface Listener {
    fun onStartGame()
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/offgame/OffGameRouter.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin.offgame

import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import com.uber.rib.core.BasicComposeRouter
import com.uber.rib.core.ComposePresenter

class OffGameRouter(
  presenter: ComposePresenter,
  interactor: OffGameInteractor,
  slot: MutableState<@Composable () -> Unit>,
) : BasicComposeRouter<OffGameInteractor>(presenter, interactor, slot)


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/offgame/OffGameScope.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin.offgame

import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import com.uber.rib.compose.root.main.AuthInfo
import com.uber.rib.compose.util.EventStream
import com.uber.rib.compose.util.StateStream
import com.uber.rib.core.ComposePresenter

@motif.Scope
interface OffGameScope {
  fun router(): OffGameRouter

  @motif.Objects
  abstract class Objects {
    abstract fun router(): OffGameRouter

    abstract fun interactor(): OffGameInteractor

    fun presenter(
      stateStream: StateStream<OffGameViewModel>,
      eventStream: EventStream<OffGameEvent>,
    ): ComposePresenter {
      return object : ComposePresenter() {
        override val composable =
          @Composable {
            OffGameView(
              stateStream.observe().collectAsState(initial = stateStream.current()),
              eventStream,
            )
          }
      }
    }

    fun eventStream() = EventStream<OffGameEvent>()

    fun stateStream(authInfo: AuthInfo) =
      StateStream(
        OffGameViewModel(
          playerOne = authInfo.playerOne,
          playerTwo = authInfo.playerTwo,
        ),
      )
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/offgame/OffGameView.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin.offgame

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.uber.rib.compose.util.CustomButton
import com.uber.rib.compose.util.EventStream

@Composable
fun OffGameView(viewModel: State<OffGameViewModel>, eventStream: EventStream<OffGameEvent>) {
  Column(
    modifier = Modifier.fillMaxSize().padding(16.dp),
    verticalArrangement = Arrangement.spacedBy(16.dp, alignment = Alignment.Bottom),
  ) {
    Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
      Text(text = viewModel.value.playerOne)
      Text(text = "Win Count: ${viewModel.value.playerOneWins}")
    }
    Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
      Text(text = viewModel.value.playerTwo)
      Text(text = "Win Count: ${viewModel.value.playerTwoWins}")
    }
    CustomButton(
      analyticsId = "26882559-fc45",
      onClick = { eventStream.notify(OffGameEvent.StartGame) },
      modifier = Modifier.fillMaxWidth(),
    ) {
      Text(text = "START GAME")
    }
  }
}

@Preview
@Composable
fun OffGameViewPreview() {
  val viewModel = remember { mutableStateOf(OffGameViewModel("James", "Alejandro", 3, 0)) }
  OffGameView(viewModel, EventStream())
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/offgame/OffGameViewModel.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin.offgame

data class OffGameViewModel(
  val playerOne: String = "",
  val playerTwo: String = "",
  val playerOneWins: Int = 0,
  val playerTwoWins: Int = 0,
)


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/tictactoe/Board.kt
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin.tictactoe

import javax.inject.Inject

class Board @Inject constructor() {
  var cells: Array<Array<MarkerType?>>
  var currentRow = 0
  var currentCol = 0

  /** Return true if it is a draw (i.e., no more EMPTY cell) */
  fun isDraw(): Boolean {
    for (row in 0 until ROWS) {
      for (col in 0 until COLS) {
        if (cells[row][col] == null) {
          return false
        }
      }
    }
    return !hasWon(MarkerType.CROSS) && !hasWon(MarkerType.NOUGHT)
  }

  /** Return true if the player with "theSeed" has won after placing at (currentRow, currentCol) */
  fun hasWon(theSeed: MarkerType): Boolean {
    return (cells[currentRow][0] == theSeed &&
      cells[currentRow][1] == theSeed &&
      cells[currentRow][2] == theSeed ||
      cells[0][currentCol] == theSeed &&
        cells[1][currentCol] == theSeed &&
        cells[2][currentCol] == theSeed ||
      currentRow == currentCol &&
        cells[0][0] == theSeed &&
        cells[1][1] == theSeed &&
        cells[2][2] == theSeed ||
      currentRow + currentCol == 2 &&
        cells[0][2] == theSeed &&
        cells[1][1] == theSeed &&
        cells[2][0] == theSeed)
  }

  enum class MarkerType {
    CROSS,
    NOUGHT,
  }

  companion object {
    const val ROWS = 3
    const val COLS = 3
  }

  init {
    cells = Array(ROWS) { arrayOfNulls(COLS) }
    for (row in 0 until ROWS) {
      for (col in 0 until COLS) {
        cells[row][col] = null
      }
    }
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/tictactoe/BoardCoordinate.kt
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin.tictactoe

data class BoardCoordinate(val x: Int, val y: Int)


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/tictactoe/TicTacToeEvent.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin.tictactoe

sealed class TicTacToeEvent {
  object XpButtonClick : TicTacToeEvent()
  class BoardClick(val coordinate: BoardCoordinate) : TicTacToeEvent()
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/tictactoe/TicTacToeInteractor.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin.tictactoe

import com.uber.rib.compose.root.main.AuthInfo
import com.uber.rib.compose.util.EventStream
import com.uber.rib.compose.util.StateStream
import com.uber.rib.core.BasicInteractor
import com.uber.rib.core.Bundle
import com.uber.rib.core.ComposePresenter
import com.uber.rib.core.coroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach

class TicTacToeInteractor(
  presenter: ComposePresenter,
  private val authInfo: AuthInfo,
  private val eventStream: EventStream<TicTacToeEvent>,
  private val stateStream: StateStream<TicTacToeViewModel>,
  private val listener: Listener,
) : BasicInteractor<ComposePresenter, TicTacToeRouter>(presenter) {

  var currentPlayer: Board.MarkerType = Board.MarkerType.CROSS

  override fun didBecomeActive(savedInstanceState: Bundle?) {
    super.didBecomeActive(savedInstanceState)

    eventStream
      .observe()
      .onEach {
        when (it) {
          is TicTacToeEvent.BoardClick -> {
            val board: Board = stateStream.current().board
            val coord = it.coordinate

            if (board.cells[coord.x][coord.y] == null) {
              if (currentPlayer == Board.MarkerType.CROSS) {
                board.cells[coord.x][coord.y] = Board.MarkerType.CROSS
                board.currentRow = coord.x
                board.currentCol = coord.y
                currentPlayer = Board.MarkerType.NOUGHT
              } else {
                board.cells[coord.x][coord.y] = Board.MarkerType.NOUGHT
                board.currentRow = coord.x
                board.currentCol = coord.y
                currentPlayer = Board.MarkerType.CROSS
              }
            }

            if (board.hasWon(Board.MarkerType.CROSS)) {
              listener.onGameWon(authInfo.playerOne)
            } else if (board.hasWon(Board.MarkerType.NOUGHT)) {
              listener.onGameWon(authInfo.playerTwo)
            } else if (board.isDraw()) {
              listener.onGameWon(null)
            }

            val newPlayerName =
              if (currentPlayer == Board.MarkerType.CROSS) {
                authInfo.playerOne
              } else {
                authInfo.playerTwo
              }

            stateStream.dispatch(
              stateStream
                .current()
                .copy(
                  board = board,
                  currentPlayer = newPlayerName,
                ),
            )
          }
          TicTacToeEvent.XpButtonClick -> TODO("Go somewhere")
        }
      }
      .launchIn(coroutineScope)
  }

  interface Listener {
    fun onGameWon(winnerName: String?)
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/tictactoe/TicTacToeRouter.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin.tictactoe

import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import com.uber.rib.core.BasicComposeRouter
import com.uber.rib.core.ComposePresenter

class TicTacToeRouter(
  presenter: ComposePresenter,
  interactor: TicTacToeInteractor,
  slot: MutableState<@Composable () -> Unit>,
) : BasicComposeRouter<TicTacToeInteractor>(presenter, interactor, slot)


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/tictactoe/TicTacToeScope.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin.tictactoe

import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import com.uber.rib.compose.root.main.AuthInfo
import com.uber.rib.compose.util.EventStream
import com.uber.rib.compose.util.StateStream
import com.uber.rib.core.ComposePresenter

@motif.Scope
interface TicTacToeScope {
  fun router(): TicTacToeRouter

  @motif.Objects
  abstract class Objects {
    abstract fun router(): TicTacToeRouter

    abstract fun interactor(): TicTacToeInteractor

    fun presenter(
      stateStream: StateStream<TicTacToeViewModel>,
      eventStream: EventStream<TicTacToeEvent>,
    ): ComposePresenter {
      return object : ComposePresenter() {
        override val composable =
          @Composable {
            TicTacToeView(
              stateStream.observe().collectAsState(initial = stateStream.current()),
              eventStream,
            )
          }
      }
    }

    fun eventStream() = EventStream<TicTacToeEvent>()

    fun stateStream(authInfo: AuthInfo) =
      StateStream(TicTacToeViewModel(authInfo.playerOne, Board()))
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/tictactoe/TicTacToeView.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin.tictactoe

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.uber.rib.compose.util.EventStream

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun TicTacToeView(viewModel: State<TicTacToeViewModel>, eventStream: EventStream<TicTacToeEvent>) {
  Column(
    horizontalAlignment = Alignment.CenterHorizontally,
    verticalArrangement = Arrangement.Top,
    modifier = Modifier.fillMaxSize().background(Color.Blue),
  ) {
    Text("Current Player: ${viewModel.value.currentPlayer}", color = Color.White)
    Box(
      modifier = Modifier.aspectRatio(1f).fillMaxSize(),
    ) {
      LazyVerticalGrid(columns = GridCells.Fixed(3), modifier = Modifier.fillMaxSize()) {
        val board = viewModel.value.board
        items(9) { i ->
          val row = i / 3
          val col = i % 3
          Text(
            text =
              when (board.cells[row][col]) {
                Board.MarkerType.CROSS -> "X"
                Board.MarkerType.NOUGHT -> "O"
                else -> " "
              },
            textAlign = TextAlign.Center,
            modifier =
              Modifier.fillMaxWidth()
                .aspectRatio(1f)
                .padding(16.dp)
                .background(Color.LightGray)
                .clickable(
                  enabled = board.cells[row][col] == null,
                  onClick = {
                    eventStream.notify(TicTacToeEvent.BoardClick(BoardCoordinate(row, col)))
                  },
                )
                .padding(32.dp),
          )
        }
      }
    }
  }
}

@Preview
@Composable
fun ProductSelectionViewPreview() {
  val board = Board()
  board.cells[0][2] = Board.MarkerType.CROSS
  board.cells[1][0] = Board.MarkerType.NOUGHT
  board.cells[2][1] = Board.MarkerType.CROSS
  val viewModel = remember { mutableStateOf(TicTacToeViewModel("James", board)) }
  TicTacToeView(viewModel, EventStream())
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/tictactoe/TicTacToeViewModel.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedin.tictactoe

data class TicTacToeViewModel(
  val currentPlayer: String,
  val board: Board,
)


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedout/LoggedOutEvent.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedout

sealed class LoggedOutEvent {
  class PlayerNameChanged(val name: String, val num: Int) : LoggedOutEvent()
  object LogInClick : LoggedOutEvent()
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedout/LoggedOutInteractor.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedout

import com.uber.rib.compose.root.main.AuthInfo
import com.uber.rib.compose.root.main.AuthStream
import com.uber.rib.compose.util.EventStream
import com.uber.rib.compose.util.StateStream
import com.uber.rib.core.BasicInteractor
import com.uber.rib.core.Bundle
import com.uber.rib.core.ComposePresenter
import com.uber.rib.core.coroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach

class LoggedOutInteractor(
  presenter: ComposePresenter,
  private val authStream: AuthStream,
  private val eventStream: EventStream<LoggedOutEvent>,
  private val stateStream: StateStream<LoggedOutViewModel>,
) : BasicInteractor<ComposePresenter, LoggedOutRouter>(presenter) {
  override fun didBecomeActive(savedInstanceState: Bundle?) {
    super.didBecomeActive(savedInstanceState)
    eventStream
      .observe()
      .onEach {
        when (it) {
          is LoggedOutEvent.PlayerNameChanged -> {
            with(stateStream) {
              dispatch(
                current()
                  .copy(
                    playerOne = if (it.num == 1) it.name else current().playerOne,
                    playerTwo = if (it.num == 2) it.name else current().playerTwo,
                  ),
              )
            }
          }
          LoggedOutEvent.LogInClick -> {
            val currentState = stateStream.current()
            authStream.accept(AuthInfo(true, currentState.playerOne, currentState.playerTwo))
          }
        }
      }
      .launchIn(coroutineScope)
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedout/LoggedOutRouter.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedout

import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import com.uber.rib.core.BasicComposeRouter
import com.uber.rib.core.ComposePresenter

class LoggedOutRouter(
  presenter: ComposePresenter,
  interactor: LoggedOutInteractor,
  slot: MutableState<@Composable () -> Unit>,
) : BasicComposeRouter<LoggedOutInteractor>(presenter, interactor, slot)


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedout/LoggedOutScope.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedout

import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import com.uber.rib.compose.util.EventStream
import com.uber.rib.compose.util.StateStream
import com.uber.rib.core.ComposePresenter

@motif.Scope
interface LoggedOutScope {
  fun router(): LoggedOutRouter

  @motif.Objects
  abstract class Objects {
    abstract fun router(): LoggedOutRouter

    abstract fun interactor(): LoggedOutInteractor

    fun presenter(
      stateStream: StateStream<LoggedOutViewModel>,
      eventStream: EventStream<LoggedOutEvent>,
    ): ComposePresenter {
      return object : ComposePresenter() {
        override val composable =
          @Composable {
            LoggedOutView(
              stateStream.observe().collectAsState(initial = stateStream.current()),
              eventStream,
            )
          }
      }
    }

    fun eventStream() = EventStream<LoggedOutEvent>()

    fun stateStream() = StateStream(LoggedOutViewModel())
  }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedout/LoggedOutView.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedout

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.uber.rib.compose.util.EventStream

@Composable
fun LoggedOutView(viewModel: State<LoggedOutViewModel>, eventStream: EventStream<LoggedOutEvent>) {
  Column(
    modifier = Modifier.fillMaxSize().padding(16.dp),
    verticalArrangement = Arrangement.spacedBy(16.dp, alignment = Alignment.Bottom),
  ) {
    TextField(
      value = viewModel.value.playerOne,
      onValueChange = { eventStream.notify(LoggedOutEvent.PlayerNameChanged(it, 1)) },
      placeholder = { Text(text = "Player One Name") },
      modifier = Modifier.fillMaxWidth(),
    )
    TextField(
      value = viewModel.value.playerTwo,
      onValueChange = { eventStream.notify(LoggedOutEvent.PlayerNameChanged(it, 2)) },
      placeholder = { Text(text = "Player Two Name") },
      modifier = Modifier.fillMaxWidth(),
    )
    Button(
      colors =
        ButtonDefaults.buttonColors(
          backgroundColor = Color.Black,
          contentColor = Color.White,
        ),
      onClick = { eventStream.notify(LoggedOutEvent.LogInClick) },
      modifier = Modifier.fillMaxWidth(),
    ) {
      Text(text = "LOGIN")
    }
  }
}

@Preview
@Composable
fun LoggedOutViewPreview() {
  val viewModel = remember { mutableStateOf(LoggedOutViewModel("James", "Alejandro")) }
  LoggedOutView(viewModel, EventStream())
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedout/LoggedOutViewModel.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.root.main.loggedout

data class LoggedOutViewModel(
  val playerOne: String = "",
  val playerTwo: String = "",
)


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/util/AnalyticsClient.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.util

import android.app.Application
import android.util.Log
import android.widget.Toast

class AnalyticsClientImpl(private val application: Application) : AnalyticsClient {
  override fun trackClick(id: String) {
    track(id, EventType.CLICK)
  }

  override fun trackImpression(id: String) {
    track(id, EventType.IMPRESSION)
  }

  private fun track(id: String, type: EventType) {
    val message = "$type for $id @ ${System.currentTimeMillis()}"
    Toast.makeText(application.applicationContext, message, Toast.LENGTH_SHORT).show()
    Log.d(this::class.java.simpleName, message)
  }

  enum class EventType {
    CLICK,
    IMPRESSION,
  }
}

object NoOpAnalyticsClient : AnalyticsClient {
  override fun trackClick(id: String) = Unit
  override fun trackImpression(id: String) = Unit
}

interface AnalyticsClient {
  fun trackClick(id: String)
  fun trackImpression(id: String)
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/util/CustomButton.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.util

import androidx.compose.foundation.layout.RowScope
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color

@Composable
fun CustomButton(
  onClick: () -> Unit,
  modifier: Modifier = Modifier,
  analyticsId: String? = null,
  content: @Composable RowScope.() -> Unit,
) {
  val analyticsClient = AnalyticsLocal.current
  val onClickWrapper: () -> Unit = {
    analyticsId?.let { analyticsClient.trackClick(it) }
    onClick()
  }
  Button(
    onClick = onClickWrapper,
    modifier = modifier,
    colors = ButtonDefaults.buttonColors(backgroundColor = Color.Black, contentColor = Color.White),
    content = content,
  )
  LaunchedEffect(null) { analyticsId?.let { analyticsClient.trackImpression(it) } }
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/util/CustomClientProvider.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.util

import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.staticCompositionLocalOf

val AnalyticsLocal = staticCompositionLocalOf<AnalyticsClient> { NoOpAnalyticsClient }
val ExperimentsLocal = staticCompositionLocalOf<ExperimentClient> { NoOpExperimentClient }
val LoggerLocal = staticCompositionLocalOf<LoggerClient> { NoOpLoggerClient }

@Composable
fun CustomClientProvider(
  analyticsClient: AnalyticsClient,
  experimentClient: ExperimentClient,
  loggerClient: LoggerClient,
  content: @Composable () -> Unit,
) {
  CompositionLocalProvider(
    AnalyticsLocal provides analyticsClient,
    ExperimentsLocal provides experimentClient,
    LoggerLocal provides loggerClient,
    content = content,
  )
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/util/EventStream.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.util

import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow

class EventStream<T> {
  private val _sharedFlow = MutableSharedFlow<T>(extraBufferCapacity = 1)
  private val sharedFlow = _sharedFlow.asSharedFlow()

  fun notify(event: T) = _sharedFlow.tryEmit(event)

  fun observe() = sharedFlow
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/util/ExperimentClient.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.util

import android.app.Application
import android.util.Log
import android.widget.Toast
import java.lang.Math.random

class ExperimentClientImpl(private val application: Application) : ExperimentClient {
  override fun isTreated(id: String): Boolean {
    val result = random() > 0.5
    val message = "isTreated($id) = $result"
    Toast.makeText(application.applicationContext, message, Toast.LENGTH_SHORT).show()
    Log.d(this::class.java.simpleName, message)
    return result
  }
}

object NoOpExperimentClient : ExperimentClient {
  override fun isTreated(id: String) = false
}

interface ExperimentClient {
  fun isTreated(id: String): Boolean
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/util/LoggerClient.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.util

import android.app.Application
import android.util.Log
import android.widget.Toast

class LoggerClientImpl(private val application: Application) : LoggerClient {
  override fun log(message: String) {
    Toast.makeText(application.applicationContext, message, Toast.LENGTH_SHORT).show()
    Log.d(this::class.java.simpleName, message)
  }
}

object NoOpLoggerClient : LoggerClient {
  override fun log(message: String) = Unit
}

interface LoggerClient {
  fun log(message: String)
}


================================================
FILE: demos/compose/src/main/kotlin/com/uber/rib/compose/util/StateStream.kt
================================================
/*
 * Copyright (C) 2021. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.compose.util

import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update

class StateStream<T : Any>(default: T) {
  private val _stateFlow = MutableStateFlow(default)
  private val stateFlow = _stateFlow.asStateFlow()

  fun dispatch(viewModel: T) = _stateFlow.update { viewModel }

  fun observe() = stateFlow

  fun current() = stateFlow.value
}


================================================
FILE: demos/compose/src/main/res/drawable/ic_launcher_background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#3DDC84"
        android:pathData="M0,0h108v108h-108z" />
    <path
        android:fillColor="#00000000"
        android:pathData="M9,0L9,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,0L19,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M29,0L29,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M39,0L39,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M49,0L49,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M59,0L59,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M69,0L69,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M79,0L79,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M89,0L89,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M99,0L99,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,9L108,9"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,19L108,19"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,29L108,29"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,39L108,39"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,49L108,49"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,59L108,59"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,69L108,69"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,79L108,79"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,89L108,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,99L108,99"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,29L89,29"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,39L89,39"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,49L89,49"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,59L89,59"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,69L89,69"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,79L89,79"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M29,19L29,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M39,19L39,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M49,19L49,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M59,19L59,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M69,19L69,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M79,19L79,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
</vector>


================================================
FILE: demos/compose/src/main/res/drawable-v24/ic_launcher_foreground.xml
================================================
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
        <aapt:attr name="android:fillColor">
            <gradient
                android:endX="85.84757"
                android:endY="92.4963"
                android:startX="42.9492"
                android:startY="49.59793"
                android:type="linear">
                <item
                    android:color="#44000000"
                    android:offset="0.0" />
                <item
                    android:color="#00000000"
                    android:offset="1.0" />
            </gradient>
        </aapt:attr>
    </path>
    <path
        android:fillColor="#FFFFFF"
        android:fillType="nonZero"
        android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
        android:strokeWidth="1"
        android:strokeColor="#00000000" />
</vector>

================================================
FILE: demos/compose/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@drawable/ic_launcher_background" />
    <foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

================================================
FILE: demos/compose/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@drawable/ic_launcher_background" />
    <foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

================================================
FILE: demos/compose/src/main/res/values/ids.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
</resources>

================================================
FILE: demos/compose/src/main/res/values/strings.xml
================================================
<resources>
    <string name="app_name">Compose RIBs</string>
</resources>

================================================
FILE: demos/compose/src/main/res/values/themes.xml
================================================
<resources xmlns:tools="http://schemas.android.com/tools">
    <style name="Theme.Android" parent="Theme.AppCompat.NoActionBar">
         <!-- Customize your theme here. -->
        <item name="android:windowActionBar">false</item>
        <item name="android:windowNoTitle">true</item>
    </style>
</resources>

================================================
FILE: demos/flipper/README.md
================================================

# RIB Demo: Flipper Debugging Tool

## Goal

This demo shows off RIBs plugin for Flipper Debugging Tool. It re-uses one of our tutorial application, and integrates
it with Flipper tool and our Flipper RIBs plugin.

## Integration

To integrate Flipper to your app, please refer to [Flipper official documentation](https://fbflipper.com/docs/getting-started/android-native)

Then, to enable RIBs plugin, simply add it to the list of used plugin during Flipper initialization.

In summary, your application ```onCreate()``` method should look similar to the one below:

```
public class SampleApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        SoLoader.init(this, false);

        if (BuildConfig.DEBUG && FlipperUtils.shouldEnableFlipper(this)) {
            final FlipperClient client = AndroidFlipperClient.getInstance(this);
            client.addPlugin(new RibTreePlugin());
            client.start();
        }
    }
}
```


================================================
FILE: demos/flipper/build.gradle.kts
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
plugins {
    id("ribs.android.application")
    alias(libs.plugins.kotlin.kapt)
    alias(libs.plugins.kotlin.ksp)
}

android {
    namespace = "com.uber.rib.flipper"

    defaultConfig {
        applicationId = "com.uber.rib.flipper"
    }

    buildFeatures {
        buildConfig = true
    }
}

dependencies {
    ksp(libs.dagger.compiler)
    kapt(project(":libraries:rib-compiler-test"))
    implementation(project(":libraries:rib-android"))
    implementation(libs.androidx.appcompat)
    implementation(libs.dagger.library)
    implementation(libs.rxbinding)
    implementation(appLibs.percent)
    compileOnly(appLibs.jsr250)
    testImplementation(project(":libraries:rib-test"))

    // Flipper Debug tool integration
    debugImplementation(libs.flipper)
    debugImplementation(appLibs.soloader)
    releaseImplementation(libs.flipper.noop)

    // Flipper RIBs plugin
    implementation(project(":tooling:rib-flipper-plugin"))
}


================================================
FILE: demos/flipper/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools">

    <uses-feature android:required="true" android:glEsVersion='0x00020000'/>

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

    <application
        android:name="com.uber.rib.SampleApplication"
        android:allowBackup="false"
        android:icon="@drawable/ub__ic_launcher"
        android:label="@string/app_name"
        android:screenOrientation="portrait">
        <activity
            android:name="com.uber.rib.RootActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/RootActivity.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib;

import android.view.ViewGroup;
import com.uber.rib.core.RibActivity;
import com.uber.rib.core.ViewRouter;
import com.uber.rib.root.RootBuilder;

/** The sample app's single activity. */
public class RootActivity extends RibActivity {

  @SuppressWarnings("unchecked")
  @Override
  protected ViewRouter<?, ?> createRouter(ViewGroup parentViewGroup) {
    RootBuilder rootBuilder = new RootBuilder(new RootBuilder.ParentComponent() {});
    return rootBuilder.build(parentViewGroup);
  }
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/SampleApplication.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib;

import android.app.Application;
import com.facebook.flipper.android.AndroidFlipperClient;
import com.facebook.flipper.android.utils.FlipperUtils;
import com.facebook.flipper.core.FlipperClient;
import com.facebook.soloader.SoLoader;
import com.uber.rib.flipper.BuildConfig;
import com.uber.rib.flipper.RibTreePlugin;

public class SampleApplication extends Application {

  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, false);

    if (BuildConfig.DEBUG && FlipperUtils.shouldEnableFlipper(this)) {
      final FlipperClient client = AndroidFlipperClient.getInstance(this);
      client.addPlugin(new RibTreePlugin());
      client.start();
    }
  }
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/RootBuilder.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root;

import static java.lang.annotation.RetentionPolicy.CLASS;

import android.view.LayoutInflater;
import android.view.ViewGroup;
import com.uber.rib.core.InteractorBaseComponent;
import com.uber.rib.core.ViewBuilder;
import com.uber.rib.flipper.R;
import com.uber.rib.root.loggedin.LoggedInBuilder;
import com.uber.rib.root.loggedout.LoggedOutBuilder;
import com.uber.rib.root.loggedout.LoggedOutInteractor;
import dagger.Binds;
import dagger.BindsInstance;
import dagger.Provides;
import java.lang.annotation.Retention;
import javax.inject.Scope;

/** Builder for the {@link RootScope}. */
public class RootBuilder extends ViewBuilder<RootView, RootRouter, RootBuilder.ParentComponent> {

  public RootBuilder(ParentComponent dependency) {
    super(dependency);
  }

  /**
   * Builds a new {@link RootRouter}.
   *
   * @param parentViewGroup parent view group that this router's view will be added to.
   * @return a new {@link RootRouter}.
   */
  public RootRouter build(ViewGroup parentViewGroup) {
    RootView view = createView(parentViewGroup);
    RootInteractor interactor = new RootInteractor();
    Component component =
        DaggerRootBuilder_Component.builder()
            .parentComponent(getDependency())
            .view(view)
            .interactor(interactor)
            .build();
    return component.rootRouter();
  }

  @Override
  protected RootView inflateView(LayoutInflater inflater, ViewGroup parentViewGroup) {
    return (RootView) inflater.inflate(R.layout.root_rib, parentViewGroup, false);
  }

  public interface ParentComponent {
    // Define dependencies required from your parent interactor here.
  }

  @dagger.Module
  public abstract static class Module {

    @RootScope
    @Provides
    static LoggedOutInteractor.Listener loggedOutListener(RootInteractor rootInteractor) {
      return rootInteractor.new LoggedOutListener();
    }

    @RootScope
    @Binds
    abstract RootInteractor.RootPresenter presenter(RootView view);

    @RootScope
    @Provides
    static RootRouter router(Component component, RootView view, RootInteractor interactor) {
      return new RootRouter(
          view,
          interactor,
          component,
          new LoggedOutBuilder(component),
          new LoggedInBuilder(component));
    }
  }

  @RootScope
  @dagger.Component(modules = Module.class, dependencies = ParentComponent.class)
  interface Component
      extends InteractorBaseComponent<RootInteractor>,
          LoggedOutBuilder.ParentComponent,
          LoggedInBuilder.ParentComponent,
          BuilderComponent {

    @dagger.Component.Builder
    interface Builder {

      @BindsInstance
      Builder interactor(RootInteractor interactor);

      @BindsInstance
      Builder view(RootView view);

      Builder parentComponent(ParentComponent component);

      Component build();
    }
  }

  interface BuilderComponent {

    RootRouter rootRouter();
  }

  @Scope
  @Retention(CLASS)
  @interface RootScope {}
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/RootInteractor.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root;

import androidx.annotation.Nullable;
import com.uber.rib.core.Bundle;
import com.uber.rib.core.Interactor;
import com.uber.rib.core.RibInteractor;
import com.uber.rib.root.loggedout.LoggedOutInteractor;
import javax.inject.Inject;

/** Coordinates Business Logic for {@link RootBuilder.RootScope}. */
@RibInteractor
public class RootInteractor extends Interactor<RootInteractor.RootPresenter, RootRouter> {

  @Inject RootPresenter presenter;

  @Override
  protected void didBecomeActive(@Nullable Bundle savedInstanceState) {
    super.didBecomeActive(savedInstanceState);
    getRouter().attachLoggedOut();
  }

  class LoggedOutListener implements LoggedOutInteractor.Listener {

    @Override
    public void login(String userNameA, String userNameB) {
      // Switch to logged in. Let’s just ignore userName for now.
      getRouter().detachLoggedOut();
      getRouter().attachLoggedIn();
    }
  }

  /** Presenter interface implemented by this RIB's view. */
  interface RootPresenter {}
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/RootRouter.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root;

import androidx.annotation.Nullable;
import com.uber.rib.core.ViewRouter;
import com.uber.rib.root.loggedin.LoggedInBuilder;
import com.uber.rib.root.loggedout.LoggedOutBuilder;
import com.uber.rib.root.loggedout.LoggedOutRouter;

/** Adds and removes children of {@link RootBuilder.RootScope}. */
public class RootRouter extends ViewRouter<RootView, RootInteractor> {

  private final LoggedOutBuilder loggedOutBuilder;
  private final LoggedInBuilder loggedInBuilder;
  @Nullable private LoggedOutRouter loggedOutRouter;

  RootRouter(
      RootView view,
      RootInteractor interactor,
      RootBuilder.Component component,
      LoggedOutBuilder loggedOutBuilder,
      LoggedInBuilder loggedInBuilder) {
    super(view, interactor, component);
    this.loggedOutBuilder = loggedOutBuilder;
    this.loggedInBuilder = loggedInBuilder;
  }

  void attachLoggedOut() {
    loggedOutRouter = loggedOutBuilder.build(getView());
    attachChild(loggedOutRouter);
    getView().addView(loggedOutRouter.getView());
  }

  void detachLoggedOut() {
    if (loggedOutRouter != null) {
      detachChild(loggedOutRouter);
      getView().removeView(loggedOutRouter.getView());
      loggedOutRouter = null;
    }
  }

  void attachLoggedIn() {
    attachChild(loggedInBuilder.build());
  }
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/RootView.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import androidx.annotation.Nullable;

/** Top level view for {@link RootBuilder.RootScope}. */
public class RootView extends FrameLayout implements RootInteractor.RootPresenter {

  public RootView(Context context) {
    this(context, null);
  }

  public RootView(Context context, @Nullable AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public RootView(Context context, @Nullable AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/LoggedInBuilder.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root.loggedin;

import static java.lang.annotation.RetentionPolicy.CLASS;

import com.uber.rib.core.Builder;
import com.uber.rib.core.EmptyPresenter;
import com.uber.rib.core.InteractorBaseComponent;
import com.uber.rib.root.RootView;
import com.uber.rib.root.loggedin.offgame.OffGameBuilder;
import com.uber.rib.root.loggedin.offgame.OffGameInteractor;
import com.uber.rib.root.loggedin.tictactoe.TicTacToeBuilder;
import dagger.BindsInstance;
import dagger.Provides;
import java.lang.annotation.Retention;
import javax.inject.Qualifier;
import javax.inject.Scope;

public class LoggedInBuilder extends Builder<LoggedInRouter, LoggedInBuilder.ParentComponent> {

  public LoggedInBuilder(ParentComponent dependency) {
    super(dependency);
  }

  /**
   * Builds a new {@link LoggedInRouter}.
   *
   * @return a new {@link LoggedInRouter}.
   */
  public LoggedInRouter build() {
    LoggedInInteractor interactor = new LoggedInInteractor();
    Component component =
        DaggerLoggedInBuilder_Component.builder()
            .parentComponent(getDependency())
            .interactor(interactor)
            .build();

    return component.loggedinRouter();
  }

  public interface ParentComponent {

    RootView rootView();
  }

  @dagger.Module
  public abstract static class Module {

    @LoggedInScope
    @Provides
    static EmptyPresenter presenter() {
      return new EmptyPresenter();
    }

    @LoggedInScope
    @Provides
    static LoggedInRouter router(
        Component component, LoggedInInteractor interactor, RootView rootView) {
      return new LoggedInRouter(
          interactor,
          component,
          rootView,
          new OffGameBuilder(component),
          new TicTacToeBuilder(component));
    }

    @LoggedInScope
    @Provides
    static OffGameInteractor.Listener listener(LoggedInInteractor interactor) {
      return interactor.new OffGameListener();
    }
  }

  @LoggedInScope
  @dagger.Component(modules = Module.class, dependencies = ParentComponent.class)
  public interface Component
      extends InteractorBaseComponent<LoggedInInteractor>,
          BuilderComponent,
          OffGameBuilder.ParentComponent,
          TicTacToeBuilder.ParentComponent {

    @dagger.Component.Builder
    interface Builder {

      @BindsInstance
      Builder interactor(LoggedInInteractor interactor);

      Builder parentComponent(ParentComponent component);

      Component build();
    }
  }

  interface BuilderComponent {

    LoggedInRouter loggedinRouter();
  }

  @Scope
  @Retention(CLASS)
  @interface LoggedInScope {}

  @Qualifier
  @Retention(CLASS)
  @interface LoggedInInternal {}
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/LoggedInInteractor.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root.loggedin;

import androidx.annotation.Nullable;
import com.uber.rib.core.Bundle;
import com.uber.rib.core.EmptyPresenter;
import com.uber.rib.core.Interactor;
import com.uber.rib.core.RibInteractor;
import com.uber.rib.root.loggedin.offgame.OffGameInteractor;

/** Coordinates Business Logic for {@link LoggedInScope}. */
@RibInteractor
public class LoggedInInteractor extends Interactor<EmptyPresenter, LoggedInRouter> {

  @Override
  protected void didBecomeActive(@Nullable Bundle savedInstanceState) {
    super.didBecomeActive(savedInstanceState);

    // when first logging in we should be in the OffGame state
    getRouter().attachOffGame();
  }

  class OffGameListener implements OffGameInteractor.Listener {

    @Override
    public void onStartGame() {
      getRouter().detachOffGame();
      getRouter().attachTicTacToe();
    }
  }
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/LoggedInRouter.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root.loggedin;

import android.view.ViewGroup;
import com.uber.rib.core.Router;
import com.uber.rib.root.loggedin.offgame.OffGameBuilder;
import com.uber.rib.root.loggedin.offgame.OffGameRouter;
import com.uber.rib.root.loggedin.tictactoe.TicTacToeBuilder;
import com.uber.rib.root.loggedin.tictactoe.TicTacToeRouter;

/** Adds and removes children of {@link LoggedInBuilder.LoggedInScope}. */
public class LoggedInRouter extends Router<LoggedInInteractor> {

  private final ViewGroup parentView;
  private final OffGameBuilder offGameBuilder;
  private final TicTacToeBuilder ticTacToeBuilder;
  private OffGameRouter offGameRouter;
  private TicTacToeRouter ticTacToeRouter;

  LoggedInRouter(
      LoggedInInteractor interactor,
      LoggedInBuilder.Component component,
      ViewGroup parentView,
      OffGameBuilder offGameBuilder,
      TicTacToeBuilder ticTacToeBuilder) {
    super(interactor, component);
    this.parentView = parentView;
    this.offGameBuilder = offGameBuilder;
    this.ticTacToeBuilder = ticTacToeBuilder;
  }

  @Override
  protected void willDetach() {
    super.willDetach();
    detachOffGame();
    detachTicTacToe();
  }

  void attachOffGame() {
    offGameRouter = offGameBuilder.build(parentView);
    attachChild(offGameRouter);
    parentView.addView(offGameRouter.getView());
  }

  void detachOffGame() {
    if (offGameRouter != null) {
      detachChild(offGameRouter);
      parentView.removeView(offGameRouter.getView());
      offGameRouter = null;
    }
  }

  void attachTicTacToe() {
    ticTacToeRouter = ticTacToeBuilder.build(parentView);
    attachChild(ticTacToeRouter);
    parentView.addView(ticTacToeRouter.getView());
  }

  void detachTicTacToe() {
    if (ticTacToeRouter != null) {
      detachChild(ticTacToeRouter);
      parentView.removeView(ticTacToeRouter.getView());
      ticTacToeRouter = null;
    }
  }
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameBuilder.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root.loggedin.offgame;

import static java.lang.annotation.RetentionPolicy.CLASS;

import android.view.LayoutInflater;
import android.view.ViewGroup;
import com.uber.rib.core.InteractorBaseComponent;
import com.uber.rib.core.ViewBuilder;
import com.uber.rib.flipper.R;
import dagger.Binds;
import dagger.BindsInstance;
import dagger.Provides;
import java.lang.annotation.Retention;
import javax.inject.Qualifier;
import javax.inject.Scope;

/** Builder for the {@link OffGameScope}. */
public class OffGameBuilder
    extends ViewBuilder<OffGameView, OffGameRouter, OffGameBuilder.ParentComponent> {

  public OffGameBuilder(ParentComponent dependency) {
    super(dependency);
  }

  /**
   * Builds a new {@link OffGameRouter}.
   *
   * @param parentViewGroup parent view group that this router's view will be added to.
   * @return a new {@link OffGameRouter}.
   */
  public OffGameRouter build(ViewGroup parentViewGroup) {
    OffGameView view = createView(parentViewGroup);
    OffGameInteractor interactor = new OffGameInteractor();
    Component component =
        DaggerOffGameBuilder_Component.builder()
            .parentComponent(getDependency())
            .view(view)
            .interactor(interactor)
            .build();
    return component.offgameRouter();
  }

  @Override
  protected OffGameView inflateView(LayoutInflater inflater, ViewGroup parentViewGroup) {
    return (OffGameView) inflater.inflate(R.layout.off_game_rib, parentViewGroup, false);
  }

  public interface ParentComponent {

    OffGameInteractor.Listener listener();
  }

  @dagger.Module
  public abstract static class Module {

    @OffGameScope
    @Binds
    abstract OffGameInteractor.OffGamePresenter presenter(OffGameView view);

    @OffGameScope
    @Provides
    static OffGameRouter router(
        Component component, OffGameView view, OffGameInteractor interactor) {
      return new OffGameRouter(view, interactor, component);
    }
  }

  @OffGameScope
  @dagger.Component(modules = Module.class, dependencies = ParentComponent.class)
  interface Component extends InteractorBaseComponent<OffGameInteractor>, BuilderComponent {

    @dagger.Component.Builder
    interface Builder {

      @BindsInstance
      Builder interactor(OffGameInteractor interactor);

      @BindsInstance
      Builder view(OffGameView view);

      Builder parentComponent(ParentComponent component);

      Component build();
    }
  }

  interface BuilderComponent {

    OffGameRouter offgameRouter();
  }

  @Scope
  @Retention(CLASS)
  @interface OffGameScope {}

  @Qualifier
  @Retention(CLASS)
  @interface OffGameInternal {}
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameInteractor.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root.loggedin.offgame;

import androidx.annotation.Nullable;
import com.uber.rib.core.Bundle;
import com.uber.rib.core.Interactor;
import com.uber.rib.core.RibInteractor;
import io.reactivex.Observable;
import io.reactivex.functions.Consumer;
import javax.inject.Inject;

/** Coordinates Business Logic for {@link OffGameScope}. */
@RibInteractor
public class OffGameInteractor
    extends Interactor<OffGameInteractor.OffGamePresenter, OffGameRouter> {

  @Inject Listener listener;
  @Inject OffGamePresenter presenter;

  @Override
  protected void didBecomeActive(@Nullable Bundle savedInstanceState) {
    super.didBecomeActive(savedInstanceState);

    presenter
        .startGameRequest()
        .subscribe(
            new Consumer<Object>() {
              @Override
              public void accept(Object object) throws Exception {
                listener.onStartGame();
              }
            });
  }

  public interface Listener {

    void onStartGame();
  }

  /** Presenter interface implemented by this RIB's view. */
  interface OffGamePresenter {

    Observable<Object> startGameRequest();
  }
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameRouter.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root.loggedin.offgame;

import com.uber.rib.core.ViewRouter;

/** Adds and removes children of {@link OffGameBuilder.OffGameScope}. */
public class OffGameRouter extends ViewRouter<OffGameView, OffGameInteractor> {

  public OffGameRouter(
      OffGameView view, OffGameInteractor interactor, OffGameBuilder.Component component) {
    super(view, interactor, component);
  }
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameView.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root.loggedin.offgame;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.jakewharton.rxbinding2.view.RxView;
import com.uber.rib.core.Initializer;
import com.uber.rib.flipper.R;
import io.reactivex.Observable;

/** Top level view for {@link OffGameBuilder.OffGameScope}. */
public class OffGameView extends LinearLayout implements OffGameInteractor.OffGamePresenter {

  private Button button;
  private TextView playerOneName;
  private TextView playerTwoName;
  private TextView playerOneScore;
  private TextView playerTwoScore;

  public OffGameView(Context context) {
    this(context, null);
  }

  public OffGameView(Context context, @Nullable AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public OffGameView(Context context, @Nullable AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  @Initializer
  @Override
  protected void onFinishInflate() {
    super.onFinishInflate();
    button = (Button) findViewById(R.id.start_game_button);
    playerOneName = (TextView) findViewById(R.id.player_one_name);
    playerTwoName = (TextView) findViewById(R.id.player_two_name);
    playerOneScore = (TextView) findViewById(R.id.player_one_win_count);
    playerTwoScore = (TextView) findViewById(R.id.player_two_win_count);
  }

  @Override
  public Observable<Object> startGameRequest() {
    return RxView.clicks(button);
  }
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/Board.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root.loggedin.tictactoe;

import javax.inject.Inject;

class Board {

  static final int ROWS = 3;
  static final int COLS = 3;

  MarkerType[][] cells;
  int currentRow;
  int currentCol;

  @Inject
  Board() {
    cells = new MarkerType[ROWS][COLS];
    for (int row = 0; row < ROWS; ++row) {
      for (int col = 0; col < COLS; ++col) {
        cells[row][col] = null;
      }
    }
  }

  /** Return true if it is a draw (i.e., no more EMPTY cell) */
  boolean isDraw() {
    for (int row = 0; row < ROWS; ++row) {
      for (int col = 0; col < COLS; ++col) {
        if (cells[row][col] == null) {
          return false;
        }
      }
    }
    return !hasWon(MarkerType.CROSS) && !hasWon(MarkerType.NOUGHT);
  }

  /** Return true if the player with "theSeed" has won after placing at (currentRow, currentCol) */
  boolean hasWon(MarkerType theSeed) {
    return ((cells[currentRow][0] == theSeed
            && cells[currentRow][1] == theSeed
            && cells[currentRow][2] == theSeed)
        || (cells[0][currentCol] == theSeed
            && cells[1][currentCol] == theSeed
            && cells[2][currentCol] == theSeed)
        || (currentRow == currentCol
            && cells[0][0] == theSeed
            && cells[1][1] == theSeed
            && cells[2][2] == theSeed)
        || (currentRow + currentCol == 2
            && cells[0][2] == theSeed
            && cells[1][1] == theSeed
            && cells[2][0] == theSeed));
  }

  enum MarkerType {
    CROSS,
    NOUGHT
  }
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/BoardCoordinate.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root.loggedin.tictactoe;

class BoardCoordinate {

  private final int x;
  private final int y;

  BoardCoordinate(int x, int y) {
    this.x = x;
    this.y = y;
  }

  int getX() {
    return x;
  }

  int getY() {
    return y;
  }
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeBuilder.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root.loggedin.tictactoe;

import static java.lang.annotation.RetentionPolicy.CLASS;

import android.view.LayoutInflater;
import android.view.ViewGroup;
import com.uber.rib.core.InteractorBaseComponent;
import com.uber.rib.core.ViewBuilder;
import com.uber.rib.flipper.R;
import dagger.Binds;
import dagger.BindsInstance;
import dagger.Provides;
import java.lang.annotation.Retention;
import javax.inject.Qualifier;
import javax.inject.Scope;

/** Builder for the {@link TicTacToeScope}. */
public class TicTacToeBuilder
    extends ViewBuilder<TicTacToeView, TicTacToeRouter, TicTacToeBuilder.ParentComponent> {

  public TicTacToeBuilder(ParentComponent dependency) {
    super(dependency);
  }

  /**
   * Builds a new {@link TicTacToeRouter}.
   *
   * @param parentViewGroup parent view group that this router's view will be added to.
   * @return a new {@link TicTacToeRouter}.
   */
  public TicTacToeRouter build(ViewGroup parentViewGroup) {
    TicTacToeView view = createView(parentViewGroup);
    TicTacToeInteractor interactor = new TicTacToeInteractor();
    Component component =
        DaggerTicTacToeBuilder_Component.builder()
            .parentComponent(getDependency())
            .view(view)
            .interactor(interactor)
            .build();
    return component.tictactoeRouter();
  }

  @Override
  protected TicTacToeView inflateView(LayoutInflater inflater, ViewGroup parentViewGroup) {
    return (TicTacToeView) inflater.inflate(R.layout.tic_tac_toe_rib, parentViewGroup, false);
  }

  public interface ParentComponent {
    // TODO: Define dependencies required from your parent interactor here.
  }

  @dagger.Module
  public abstract static class Module {

    @TicTacToeScope
    @Binds
    abstract TicTacToeInteractor.TicTacToePresenter presenter(TicTacToeView view);

    @TicTacToeScope
    @Provides
    static TicTacToeRouter router(
        Component component, TicTacToeView view, TicTacToeInteractor interactor) {
      return new TicTacToeRouter(view, interactor, component);
    }
  }

  @TicTacToeScope
  @dagger.Component(modules = Module.class, dependencies = ParentComponent.class)
  interface Component extends InteractorBaseComponent<TicTacToeInteractor>, BuilderComponent {

    @dagger.Component.Builder
    interface Builder {

      @BindsInstance
      Builder interactor(TicTacToeInteractor interactor);

      @BindsInstance
      Builder view(TicTacToeView view);

      Builder parentComponent(ParentComponent component);

      Component build();
    }
  }

  interface BuilderComponent {

    TicTacToeRouter tictactoeRouter();
  }

  @Scope
  @Retention(CLASS)
  @interface TicTacToeScope {}

  @Qualifier
  @Retention(CLASS)
  @interface TicTacToeInternal {}
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeInteractor.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root.loggedin.tictactoe;

import androidx.annotation.Nullable;
import com.uber.rib.core.Bundle;
import com.uber.rib.core.Interactor;
import com.uber.rib.core.RibInteractor;
import com.uber.rib.root.loggedin.tictactoe.Board.MarkerType;
import io.reactivex.Observable;
import io.reactivex.functions.Consumer;
import javax.inject.Inject;

/** Coordinates Business Logic for {@link TicTacToeScope}. */
@RibInteractor
public class TicTacToeInteractor
    extends Interactor<TicTacToeInteractor.TicTacToePresenter, TicTacToeRouter> {

  @Inject Board board;
  @Inject TicTacToePresenter presenter;

  private final String playerOne = "Fake name 1";
  private final String playerTwo = "Fake name 2";

  private MarkerType currentPlayer = MarkerType.CROSS;

  @Override
  protected void didBecomeActive(@Nullable Bundle savedInstanceState) {
    super.didBecomeActive(savedInstanceState);

    presenter
        .squareClicks()
        .subscribe(
            new Consumer<BoardCoordinate>() {
              @Override
              public void accept(BoardCoordinate xy) throws Exception {
                if (board.cells[xy.getX()][xy.getY()] == null) {
                  if (currentPlayer == MarkerType.CROSS) {
                    board.cells[xy.getX()][xy.getY()] = MarkerType.CROSS;
                    board.currentRow = xy.getX();
                    board.currentCol = xy.getY();
                    presenter.addCross(xy);
                    currentPlayer = MarkerType.NOUGHT;
                  } else {
                    board.cells[xy.getX()][xy.getY()] = MarkerType.NOUGHT;
                    board.currentRow = xy.getX();
                    board.currentCol = xy.getY();
                    presenter.addNought(xy);
                    currentPlayer = MarkerType.CROSS;
                  }
                }
                if (board.hasWon(MarkerType.CROSS)) {
                  presenter.setPlayerWon(playerOne);
                } else if (board.hasWon(MarkerType.NOUGHT)) {
                  presenter.setPlayerWon(playerTwo);
                } else if (board.isDraw()) {
                  presenter.setPlayerTie();
                } else {
                  updateCurrentPlayer();
                }
              }
            });
    updateCurrentPlayer();
  }

  private void updateCurrentPlayer() {
    if (currentPlayer == MarkerType.CROSS) {
      presenter.setCurrentPlayerName(playerOne);
    } else {
      presenter.setCurrentPlayerName(playerTwo);
    }
  }

  /** Presenter interface implemented by this RIB's view. */
  interface TicTacToePresenter {
    Observable<BoardCoordinate> squareClicks();

    void setCurrentPlayerName(String currentPlayer);

    void setPlayerWon(String playerName);

    void setPlayerTie();

    void addCross(BoardCoordinate xy);

    void addNought(BoardCoordinate xy);
  }

  public interface Listener {}
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeRouter.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root.loggedin.tictactoe;

import com.uber.rib.core.ViewRouter;

/** Adds and removes children of {@link TicTacToeBuilder.TicTacToeScope}. */
public class TicTacToeRouter extends ViewRouter<TicTacToeView, TicTacToeInteractor> {

  public TicTacToeRouter(
      TicTacToeView view, TicTacToeInteractor interactor, TicTacToeBuilder.Component component) {
    super(view, interactor, component);
  }
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeView.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root.loggedin.tictactoe;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.percentlayout.widget.PercentRelativeLayout;
import com.jakewharton.rxbinding2.view.RxView;
import com.uber.rib.core.Initializer;
import com.uber.rib.flipper.R;
import io.reactivex.Observable;
import io.reactivex.functions.Function;
import java.util.ArrayList;

/** Top level view for {@link TicTacToeBuilder.TicTacToeScope}. */
public class TicTacToeView extends PercentRelativeLayout
    implements TicTacToeInteractor.TicTacToePresenter {

  private TextView[][] imageButtons;
  private TextView titleView;

  public TicTacToeView(Context context) {
    this(context, null);
  }

  public TicTacToeView(Context context, @Nullable AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public TicTacToeView(Context context, @Nullable AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  @Initializer
  @Override
  protected void onFinishInflate() {
    super.onFinishInflate();
    imageButtons = new TextView[3][];
    imageButtons[0] =
        new TextView[] {
          (TextView) findViewById(R.id.button11),
          (TextView) findViewById(R.id.button12),
          (TextView) findViewById(R.id.button13)
        };
    imageButtons[1] =
        new TextView[] {
          (TextView) findViewById(R.id.button21),
          (TextView) findViewById(R.id.button22),
          (TextView) findViewById(R.id.button23)
        };
    imageButtons[2] =
        new TextView[] {
          (TextView) findViewById(R.id.button31),
          (TextView) findViewById(R.id.button32),
          (TextView) findViewById(R.id.button33)
        };
    titleView = (TextView) findViewById(R.id.title);
  }

  @Override
  public Observable<BoardCoordinate> squareClicks() {
    ArrayList<Observable<BoardCoordinate>> observables = new ArrayList<>();
    for (int i = 0; i < 3; i++) {
      for (int j = 0; j < 3; j++) {
        final int finalI = i;
        final int finalJ = j;
        observables.add(
            RxView.clicks(imageButtons[i][j])
                .map(
                    new Function<Object, BoardCoordinate>() {
                      @Override
                      public BoardCoordinate apply(Object irrelevant) throws Exception {
                        return new BoardCoordinate(finalI, finalJ);
                      }
                    }));
      }
    }
    return Observable.merge(observables);
  }

  @Override
  public void addCross(BoardCoordinate xy) {
    TextView textView = imageButtons[xy.getX()][xy.getY()];
    textView.setText("x");
    textView.setClickable(false);
  }

  @Override
  public void addNought(BoardCoordinate xy) {
    TextView textView = imageButtons[xy.getX()][xy.getY()];
    textView.setText("O");
    textView.setClickable(false);
  }

  @Override
  public void setCurrentPlayerName(String currentPlayer) {
    titleView.setText("Current Player: " + currentPlayer);
  }

  @Override
  public void setPlayerWon(String playerName) {
    titleView.setText("Player won: " + playerName + "!!!");
  }

  @Override
  public void setPlayerTie() {
    titleView.setText("Tie game!");
  }
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedout/LoggedOutBuilder.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root.loggedout;

import static java.lang.annotation.RetentionPolicy.CLASS;

import android.view.LayoutInflater;
import android.view.ViewGroup;
import com.uber.rib.core.InteractorBaseComponent;
import com.uber.rib.core.ViewBuilder;
import com.uber.rib.flipper.R;
import dagger.Binds;
import dagger.BindsInstance;
import dagger.Provides;
import java.lang.annotation.Retention;
import javax.inject.Qualifier;
import javax.inject.Scope;

/** Builder for the {@link LoggedOutScope}. */
public class LoggedOutBuilder
    extends ViewBuilder<LoggedOutView, LoggedOutRouter, LoggedOutBuilder.ParentComponent> {

  public LoggedOutBuilder(ParentComponent dependency) {
    super(dependency);
  }

  /**
   * Builds a new {@link LoggedOutRouter}.
   *
   * @param parentViewGroup parent view group that this router's view will be added to.
   * @return a new {@link LoggedOutRouter}.
   */
  public LoggedOutRouter build(ViewGroup parentViewGroup) {
    LoggedOutView view = createView(parentViewGroup);
    LoggedOutInteractor interactor = new LoggedOutInteractor();
    Component component =
        DaggerLoggedOutBuilder_Component.builder()
            .parentComponent(getDependency())
            .view(view)
            .interactor(interactor)
            .build();
    return component.loggedoutRouter();
  }

  @Override
  protected LoggedOutView inflateView(LayoutInflater inflater, ViewGroup parentViewGroup) {
    return (LoggedOutView) inflater.inflate(R.layout.logged_out_rib, parentViewGroup, false);
  }

  public interface ParentComponent {

    LoggedOutInteractor.Listener listener();
  }

  @dagger.Module
  public abstract static class Module {

    @LoggedOutScope
    @Binds
    abstract LoggedOutInteractor.LoggedOutPresenter presenter(LoggedOutView view);

    @LoggedOutScope
    @Provides
    static LoggedOutRouter router(
        Component component, LoggedOutView view, LoggedOutInteractor interactor) {
      return new LoggedOutRouter(view, interactor, component);
    }

    // TODO: Create provider methods for dependencies created by this Rib. These should be static.
  }

  @LoggedOutScope
  @dagger.Component(modules = Module.class, dependencies = ParentComponent.class)
  interface Component extends InteractorBaseComponent<LoggedOutInteractor>, BuilderComponent {

    @dagger.Component.Builder
    interface Builder {

      @BindsInstance
      Builder interactor(LoggedOutInteractor interactor);

      @BindsInstance
      Builder view(LoggedOutView view);

      Builder parentComponent(ParentComponent component);

      Component build();
    }
  }

  interface BuilderComponent {

    LoggedOutRouter loggedoutRouter();
  }

  @Scope
  @Retention(CLASS)
  @interface LoggedOutScope {}

  @Qualifier
  @Retention(CLASS)
  @interface LoggedOutInternal {}
}


================================================
FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedout/LoggedOutInteractor.java
================================================
/*
 * Copyright (C) 2017. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uber.rib.root.loggedout;

import androidx.annotation.Nullable;
import androidx.core.util.Pair;
import com.uber.rib.core.Bundle;
import com.uber.rib.core.Interactor;
import com.uber.rib.core.RibInteractor;
import com.uber.rib.root.loggedout.LoggedOutBuilder.LoggedOutScope;
import io.reactivex.Observable;
import io.reactivex.functions.Consumer;
import javax.inject.Inject;

/** Coordinates Business Logic for {@link LoggedOutScope}. */
@RibInteractor
public class LoggedOutInteractor
    extends Interactor<LoggedOutInteractor.LoggedOutPresenter, LoggedOutRouter> {

  @Inject Listener listener;
  @Inject LoggedOutPresenter presenter;

  @Override
  protected void didBecomeActive(@Nullable Bundle savedInstanceState) {
    super.didBecomeActive(savedInstanceState);
    presenter
        .loginName()
        .subscribe(
            new Consumer<Pair<String, String>>() {
              @Override
              public void accept(Pair<String, String> names) throws Exception {
                if (!isEmpty(names.first) && !isEmpty(names.second)) {
                  listener.login(names.first, names.second);
                }
              }
            });
  }

  private boolean isEmpty(@Nullable String string) {
    return string == null || string.length() == 0;
  }

  /** Presenter interface implemented by this RIB's vi
Download .txt
gitextract_os7hyq2r/

├── .github/
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       └── android.yml
├── .gitignore
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE.txt
├── README.md
├── RELEASING.md
├── build.gradle.kts
├── config/
│   ├── lint/
│   │   └── lint.xml
│   └── spotless/
│       ├── copyright.java
│       └── copyright.kt
├── conventions/
│   ├── build.gradle.kts
│   ├── settings.gradle.kts
│   └── src/
│       └── main/
│           └── kotlin/
│               ├── Extensions.kt
│               ├── ribs.android.application.errorprone.gradle.kts
│               ├── ribs.android.application.gradle.kts
│               ├── ribs.android.library.gradle.kts
│               ├── ribs.kotlin.library.gradle.kts
│               └── ribs.spotless.gradle.kts
├── demos/
│   ├── compose/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── kotlin/
│   │           │   └── com/
│   │           │       └── uber/
│   │           │           └── rib/
│   │           │               └── compose/
│   │           │                   ├── ComposeApplication.kt
│   │           │                   ├── root/
│   │           │                   │   ├── RootActivity.kt
│   │           │                   │   ├── RootInteractor.kt
│   │           │                   │   ├── RootRouter.kt
│   │           │                   │   ├── RootScope.kt
│   │           │                   │   ├── RootView.kt
│   │           │                   │   └── main/
│   │           │                   │       ├── AuthStream.kt
│   │           │                   │       ├── MainInteractor.kt
│   │           │                   │       ├── MainRouter.kt
│   │           │                   │       ├── MainScope.kt
│   │           │                   │       ├── MainView.kt
│   │           │                   │       ├── loggedin/
│   │           │                   │       │   ├── LoggedInEvent.kt
│   │           │                   │       │   ├── LoggedInInteractor.kt
│   │           │                   │       │   ├── LoggedInRouter.kt
│   │           │                   │       │   ├── LoggedInScope.kt
│   │           │                   │       │   ├── LoggedInView.kt
│   │           │                   │       │   ├── ScoreStream.kt
│   │           │                   │       │   ├── offgame/
│   │           │                   │       │   │   ├── OffGameEvent.kt
│   │           │                   │       │   │   ├── OffGameInteractor.kt
│   │           │                   │       │   │   ├── OffGameRouter.kt
│   │           │                   │       │   │   ├── OffGameScope.kt
│   │           │                   │       │   │   ├── OffGameView.kt
│   │           │                   │       │   │   └── OffGameViewModel.kt
│   │           │                   │       │   └── tictactoe/
│   │           │                   │       │       ├── Board.kt
│   │           │                   │       │       ├── BoardCoordinate.kt
│   │           │                   │       │       ├── TicTacToeEvent.kt
│   │           │                   │       │       ├── TicTacToeInteractor.kt
│   │           │                   │       │       ├── TicTacToeRouter.kt
│   │           │                   │       │       ├── TicTacToeScope.kt
│   │           │                   │       │       ├── TicTacToeView.kt
│   │           │                   │       │       └── TicTacToeViewModel.kt
│   │           │                   │       └── loggedout/
│   │           │                   │           ├── LoggedOutEvent.kt
│   │           │                   │           ├── LoggedOutInteractor.kt
│   │           │                   │           ├── LoggedOutRouter.kt
│   │           │                   │           ├── LoggedOutScope.kt
│   │           │                   │           ├── LoggedOutView.kt
│   │           │                   │           └── LoggedOutViewModel.kt
│   │           │                   └── util/
│   │           │                       ├── AnalyticsClient.kt
│   │           │                       ├── CustomButton.kt
│   │           │                       ├── CustomClientProvider.kt
│   │           │                       ├── EventStream.kt
│   │           │                       ├── ExperimentClient.kt
│   │           │                       ├── LoggerClient.kt
│   │           │                       └── StateStream.kt
│   │           └── res/
│   │               ├── drawable/
│   │               │   └── ic_launcher_background.xml
│   │               ├── drawable-v24/
│   │               │   └── ic_launcher_foreground.xml
│   │               ├── mipmap-anydpi-v26/
│   │               │   ├── ic_launcher.xml
│   │               │   └── ic_launcher_round.xml
│   │               └── values/
│   │                   ├── ids.xml
│   │                   ├── strings.xml
│   │                   └── themes.xml
│   ├── flipper/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── uber/
│   │           │           └── rib/
│   │           │               ├── RootActivity.java
│   │           │               ├── SampleApplication.java
│   │           │               └── root/
│   │           │                   ├── RootBuilder.java
│   │           │                   ├── RootInteractor.java
│   │           │                   ├── RootRouter.java
│   │           │                   ├── RootView.java
│   │           │                   ├── loggedin/
│   │           │                   │   ├── LoggedInBuilder.java
│   │           │                   │   ├── LoggedInInteractor.java
│   │           │                   │   ├── LoggedInRouter.java
│   │           │                   │   ├── offgame/
│   │           │                   │   │   ├── OffGameBuilder.java
│   │           │                   │   │   ├── OffGameInteractor.java
│   │           │                   │   │   ├── OffGameRouter.java
│   │           │                   │   │   └── OffGameView.java
│   │           │                   │   └── tictactoe/
│   │           │                   │       ├── Board.java
│   │           │                   │       ├── BoardCoordinate.java
│   │           │                   │       ├── TicTacToeBuilder.java
│   │           │                   │       ├── TicTacToeInteractor.java
│   │           │                   │       ├── TicTacToeRouter.java
│   │           │                   │       └── TicTacToeView.java
│   │           │                   └── loggedout/
│   │           │                       ├── LoggedOutBuilder.java
│   │           │                       ├── LoggedOutInteractor.java
│   │           │                       ├── LoggedOutRouter.java
│   │           │                       └── LoggedOutView.java
│   │           └── res/
│   │               ├── layout/
│   │               │   ├── logged_out_rib.xml
│   │               │   ├── off_game_rib.xml
│   │               │   ├── root_rib.xml
│   │               │   └── tic_tac_toe_rib.xml
│   │               └── values/
│   │                   └── ub__strings.xml
│   ├── intellij/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── uber/
│   │           │           └── rib/
│   │           │               ├── RootActivity.java
│   │           │               ├── SampleApplication.java
│   │           │               └── root/
│   │           │                   ├── RootBuilder.java
│   │           │                   ├── RootInteractor.java
│   │           │                   ├── RootRouter.java
│   │           │                   ├── RootView.java
│   │           │                   ├── loggedin/
│   │           │                   │   ├── LoggedInBuilder.java
│   │           │                   │   ├── LoggedInInteractor.java
│   │           │                   │   ├── LoggedInRouter.java
│   │           │                   │   ├── offgame/
│   │           │                   │   │   ├── OffGameBuilder.java
│   │           │                   │   │   ├── OffGameInteractor.java
│   │           │                   │   │   ├── OffGameRouter.java
│   │           │                   │   │   └── OffGameView.java
│   │           │                   │   └── tictactoe/
│   │           │                   │       ├── Board.java
│   │           │                   │       ├── BoardCoordinate.java
│   │           │                   │       ├── TicTacToeBuilder.java
│   │           │                   │       ├── TicTacToeInteractor.java
│   │           │                   │       ├── TicTacToeRouter.java
│   │           │                   │       └── TicTacToeView.java
│   │           │                   └── loggedout/
│   │           │                       ├── LoggedOutBuilder.java
│   │           │                       ├── LoggedOutInteractor.java
│   │           │                       ├── LoggedOutRouter.java
│   │           │                       └── LoggedOutView.java
│   │           └── res/
│   │               ├── layout/
│   │               │   ├── logged_out_rib.xml
│   │               │   ├── off_game_rib.xml
│   │               │   ├── root_rib.xml
│   │               │   └── tic_tac_toe_rib.xml
│   │               └── values/
│   │                   └── ub__strings.xml
│   ├── memory-leaks/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── uber/
│   │           │           └── rib/
│   │           │               ├── RootActivity.java
│   │           │               ├── SampleApplication.java
│   │           │               └── root/
│   │           │                   ├── RootBuilder.java
│   │           │                   ├── RootInteractor.java
│   │           │                   ├── RootRouter.java
│   │           │                   ├── RootView.java
│   │           │                   ├── loggedin/
│   │           │                   │   ├── LoggedInBuilder.java
│   │           │                   │   ├── LoggedInInteractor.java
│   │           │                   │   └── LoggedInRouter.java
│   │           │                   └── loggedout/
│   │           │                       ├── LoggedOutBuilder.java
│   │           │                       ├── LoggedOutInteractor.java
│   │           │                       ├── LoggedOutRouter.java
│   │           │                       └── LoggedOutView.java
│   │           └── res/
│   │               ├── layout/
│   │               │   ├── logged_out_rib.xml
│   │               │   └── root_rib.xml
│   │               └── values/
│   │                   └── ub__strings.xml
│   └── rib-workers/
│       ├── README.md
│       ├── build.gradle.kts
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── kotlin/
│               │   └── com/
│               │       └── uber/
│               │           └── rib/
│               │               └── workers/
│               │                   ├── ComposeApplication.kt
│               │                   ├── root/
│               │                   │   ├── RootActivity.kt
│               │                   │   ├── RootInteractor.kt
│               │                   │   ├── RootRouter.kt
│               │                   │   ├── RootScope.kt
│               │                   │   ├── RootView.kt
│               │                   │   ├── logger/
│               │                   │   │   └── ApplicationLevelWorkerLogger.kt
│               │                   │   └── main/
│               │                   │       ├── MainInteractor.kt
│               │                   │       ├── MainRouter.kt
│               │                   │       ├── MainScope.kt
│               │                   │       ├── MainView.kt
│               │                   │       ├── ribworkerselection/
│               │                   │       │   ├── RibWorkerBindTypeClickType.kt
│               │                   │       │   ├── RibWorkerSelectionInteractor.kt
│               │                   │       │   ├── RibWorkerSelectionRouter.kt
│               │                   │       │   ├── RibWorkerSelectionScope.kt
│               │                   │       │   ├── RibWorkerSelectionView.kt
│               │                   │       │   └── RibWorkerSelectionViewModel.kt
│               │                   │       └── workers/
│               │                   │           ├── BackgroundWorker.kt
│               │                   │           ├── DefaultRibCoroutineWorker.kt
│               │                   │           ├── DefaultWorker.kt
│               │                   │           ├── IoWorker.kt
│               │                   │           └── UiWorker.kt
│               │                   └── util/
│               │                       ├── EventStream.kt
│               │                       └── StateStream.kt
│               └── res/
│                   ├── drawable/
│                   │   └── ic_launcher_background.xml
│                   ├── drawable-v24/
│                   │   └── ic_launcher_foreground.xml
│                   ├── mipmap-anydpi-v26/
│                   │   ├── ic_launcher.xml
│                   │   └── ic_launcher_round.xml
│                   └── values/
│                       ├── strings.xml
│                       └── themes.xml
├── gradle/
│   ├── app-libs.versions.toml
│   ├── japicmp.gradle
│   ├── libs.versions.toml
│   ├── test-libs.versions.toml
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── libraries/
│   ├── rib-android/
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── core/
│   │       │                       ├── ActivityContext.kt
│   │       │                       ├── ActivityStarter.kt
│   │       │                       ├── BasicViewRouter.kt
│   │       │                       ├── IntentCreator.kt
│   │       │                       ├── IntentCreatorImpl.kt
│   │       │                       ├── IntentFactory.kt
│   │       │                       ├── RibActivity.kt
│   │       │                       ├── RibDebugOverlay.kt
│   │       │                       ├── RxActivityEvents.kt
│   │       │                       ├── ViewBuilder.kt
│   │       │                       ├── ViewPresenter.kt
│   │       │                       ├── ViewRouter.kt
│   │       │                       ├── XRay.kt
│   │       │                       └── lifecycle/
│   │       │                           ├── ActivityCallbackEvent.kt
│   │       │                           ├── ActivityEvent.kt
│   │       │                           └── ActivityLifecycleEvent.kt
│   │       └── test/
│   │           ├── kotlin/
│   │           │   └── com/
│   │           │       └── uber/
│   │           │           └── rib/
│   │           │               └── core/
│   │           │                   ├── BundleTest.kt
│   │           │                   ├── RibActivityTest.kt
│   │           │                   ├── ViewBuilderTest.kt
│   │           │                   └── XRayTest.kt
│   │           └── resources/
│   │               └── robolectric.properties
│   ├── rib-android-compose/
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       └── main/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── core/
│   │                               ├── BasicComposeRouter.kt
│   │                               └── ComposePresenter.kt
│   ├── rib-android-core/
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── core/
│   │       │                       ├── ActivityDelegate.kt
│   │       │                       ├── CoreAppCompatActivity.kt
│   │       │                       └── HasActivityDelegate.kt
│   │       └── test/
│   │           └── resources/
│   │               └── robolectric.properties
│   ├── rib-base/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── core/
│   │       │                       ├── BasicInteractor.kt
│   │       │                       ├── BasicRouter.kt
│   │       │                       ├── Builder.kt
│   │       │                       ├── Bundle.kt
│   │       │                       ├── EmptyPresenter.kt
│   │       │                       ├── FlowAsScope.kt
│   │       │                       ├── Initializer.kt
│   │       │                       ├── Interactor.kt
│   │       │                       ├── InteractorAndViewModule.kt
│   │       │                       ├── InteractorBaseComponent.kt
│   │       │                       ├── InteractorComponent.kt
│   │       │                       ├── InteractorModule.kt
│   │       │                       ├── InteractorType.kt
│   │       │                       ├── LazyBackingProperty.kt
│   │       │                       ├── Presenter.kt
│   │       │                       ├── Rib.kt
│   │       │                       ├── RibBuilder.kt
│   │       │                       ├── RibCoroutineWorker.kt
│   │       │                       ├── RibEventType.kt
│   │       │                       ├── RibEvents.kt
│   │       │                       ├── RibInteractor.kt
│   │       │                       ├── RibRefWatcher.kt
│   │       │                       ├── RibRouterEvent.kt
│   │       │                       ├── Router.kt
│   │       │                       ├── Worker.kt
│   │       │                       ├── WorkerBinder.kt
│   │       │                       ├── WorkerScopeProvider.kt
│   │       │                       ├── WorkerUnbinder.kt
│   │       │                       ├── internal/
│   │       │                       │   └── CoreFriendModuleApi.kt
│   │       │                       └── lifecycle/
│   │       │                           ├── InteractorEvent.kt
│   │       │                           ├── PresenterEvent.kt
│   │       │                           └── WorkerEvent.kt
│   │       └── test/
│   │           └── kotlin/
│   │               ├── android/
│   │               │   └── os/
│   │               │       ├── Bundle.kt
│   │               │       └── Parcelable.kt
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── core/
│   │                               ├── InteractorAndRouterTest.kt
│   │                               ├── LazyBackingPropertyTest.kt
│   │                               ├── RecordingObserver.kt
│   │                               ├── RibCoroutineWorkerTest.kt
│   │                               ├── RibEventsTest.kt
│   │                               ├── RibEventsUtils.kt
│   │                               ├── RibRefWatcherTest.kt
│   │                               ├── RouterTest.kt
│   │                               ├── WorkerBinderTest.kt
│   │                               ├── WorkerScopeProviderTest.kt
│   │                               └── WorkerTest.kt
│   ├── rib-compiler-app/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── compiler/
│   │       │                       ├── AnnotatedClass.kt
│   │       │                       ├── AnnotationVerifier.kt
│   │       │                       ├── CompilerUtils.kt
│   │       │                       ├── Constants.kt
│   │       │                       ├── ErrorReporter.kt
│   │       │                       ├── Generator.kt
│   │       │                       ├── InteractorAnnotatedClass.kt
│   │       │                       ├── InteractorAnnotationVerifier.kt
│   │       │                       ├── ProcessContext.kt
│   │       │                       ├── ProcessorPipeline.kt
│   │       │                       ├── RibInteractorProcessorPipeline.kt
│   │       │                       ├── RibProcessor.kt
│   │       │                       ├── TypeProcessorPipeline.kt
│   │       │                       └── VerificationFailedException.kt
│   │       └── test/
│   │           ├── kotlin/
│   │           │   └── com/
│   │           │       └── uber/
│   │           │           └── rib/
│   │           │               └── compiler/
│   │           │                   ├── InteractorAnnotationVerifierTest.kt
│   │           │                   └── InteractorProcessorTestBase.kt
│   │           └── resources/
│   │               └── fixtures/
│   │                   ├── AnnotatedInteractor.java
│   │                   ├── AnnotatedInteractorNoSuffix.java
│   │                   ├── AnnotatedNonInteractor.java
│   │                   └── CustomConstructorInteractor.java
│   ├── rib-compiler-test/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   ├── libs/
│   │   │   └── tools.jar
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── compiler/
│   │       │                       ├── Constants.kt
│   │       │                       ├── InteractorTestGenerator.kt
│   │       │                       └── RibTestProcessor.kt
│   │       └── test/
│   │           ├── kotlin/
│   │           │   └── com/
│   │           │       └── uber/
│   │           │           └── rib/
│   │           │               └── compiler/
│   │           │                   ├── InteractorTestGeneratorProcessorTestBase.kt
│   │           │                   └── InteractorTestGeneratorTest.kt
│   │           └── resources/
│   │               └── fixtures/
│   │                   ├── AnnotatedBasicInteractor.java
│   │                   ├── AnnotatedInteractor.java
│   │                   ├── TestAnnotatedBasicInteractor.java
│   │                   ├── TestAnnotatedInteractor.java
│   │                   └── TestForcedBasicInteractor.java
│   ├── rib-coroutines/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── core/
│   │       │                       ├── RibCoroutineScopes.kt
│   │       │                       ├── RibCoroutinesConfig.kt
│   │       │                       ├── RibDispatchers.kt
│   │       │                       └── internal/
│   │       │                           └── CoroutinesFriendModuleApi.kt
│   │       └── test/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── core/
│   │                               └── RibCoroutineScopesTest.kt
│   ├── rib-coroutines-test/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── core/
│   │       │                       ├── RibCoroutinesRule.kt
│   │       │                       ├── TestRibCoroutineScopes.kt
│   │       │                       └── TestRibDispatchers.kt
│   │       └── test/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── core/
│   │                               ├── RibCoroutinesRuleTest.kt
│   │                               ├── RibDispatchersTest.kt
│   │                               └── RibScopesTest.kt
│   ├── rib-debug-utils/
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       └── main/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── core/
│   │                               └── RouterDebugUtils.kt
│   ├── rib-router-navigator/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── core/
│   │       │                       ├── RouterAndState.kt
│   │       │                       ├── RouterNavigator.kt
│   │       │                       ├── RouterNavigatorEvent.kt
│   │       │                       ├── RouterNavigatorEventType.kt
│   │       │                       ├── RouterNavigatorEvents.kt
│   │       │                       ├── RouterNavigatorFactory.kt
│   │       │                       ├── RouterNavigatorState.kt
│   │       │                       └── StackRouterNavigator.kt
│   │       └── test/
│   │           └── kotlin/
│   │               ├── com/
│   │               │   └── uber/
│   │               │       └── rib/
│   │               │           └── core/
│   │               │               ├── RouterAndStateTest.kt
│   │               │               └── StackRouterNavigatorTest.kt
│   │               └── os/
│   │                   ├── Bundle.kt
│   │                   └── Parcelable.kt
│   ├── rib-screen-stack-base/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       └── main/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── core/
│   │                               └── screenstack/
│   │                                   ├── ScreenStackBase.kt
│   │                                   ├── ViewProvider.kt
│   │                                   └── lifecycle/
│   │                                       └── ScreenStackEvent.kt
│   ├── rib-test/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       └── main/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── core/
│   │                               ├── AndroidRecordingRx2Observer.kt
│   │                               ├── FakeComponent.kt
│   │                               ├── FakeInteractor.kt
│   │                               ├── FakePresenter.kt
│   │                               ├── FakeRouter.kt
│   │                               ├── FakeWorker.kt
│   │                               ├── InteractorHelper.kt
│   │                               ├── PresenterHelper.kt
│   │                               ├── RibTestBasePlaceholder.kt
│   │                               ├── RouterHelper.kt
│   │                               ├── TestRibCoroutineWorker.kt
│   │                               └── WorkerHelper.kt
│   ├── rib-workflow/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── gradle.properties
│   │   └── src/
│   │       ├── main/
│   │       │   └── kotlin/
│   │       │       └── com/
│   │       │           └── uber/
│   │       │               └── rib/
│   │       │                   └── workflow/
│   │       │                       └── core/
│   │       │                           ├── ActionableItem.kt
│   │       │                           ├── Step.kt
│   │       │                           ├── Workflow.kt
│   │       │                           └── internal/
│   │       │                               └── WorkflowFriendModuleApi.kt
│   │       └── test/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── workflow/
│   │                               └── core/
│   │                                   ├── AndroidSchedulersRule.kt
│   │                                   ├── DelegatingScheduler.kt
│   │                                   ├── StepTest.kt
│   │                                   └── WorkflowTest.kt
│   └── rib-workflow-test/
│       ├── build.gradle.kts
│       ├── gradle.properties
│       └── src/
│           └── main/
│               └── kotlin/
│                   └── com/
│                       └── uber/
│                           └── rib/
│                               └── workflow/
│                                   └── core/
│                                       └── StepTester.kt
├── releasing.sh
├── settings.gradle
├── tooling/
│   ├── rib-flipper-plugin/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── desktop/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   └── src/
│   │   │       ├── TreeChart.js
│   │   │       ├── index.js
│   │   │       └── utils.js
│   │   ├── gradle.properties
│   │   └── src/
│   │       └── main/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── uber/
│   │                       └── rib/
│   │                           └── flipper/
│   │                               ├── RibEventPayload.kt
│   │                               ├── RibTreeMessageType.kt
│   │                               └── RibTreePlugin.kt
│   ├── rib-intellij-plugin/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   ├── deploy/
│   │   │   └── rib-intellij-plugin.jar
│   │   ├── gradle.properties
│   │   ├── native/
│   │   │   ├── gradle.properties
│   │   │   └── intellij-broadcast-rib/
│   │   │       ├── README.md
│   │   │       ├── build.gradle.kts
│   │   │       └── src/
│   │   │           └── main/
│   │   │               └── java/
│   │   │                   └── com/
│   │   │                       └── uber/
│   │   │                           └── debug/
│   │   │                               └── broadcast/
│   │   │                                   └── rib/
│   │   │                                       ├── RibHierarchyDebugBroadcastHandler.java
│   │   │                                       ├── RibHierarchyPayload.java
│   │   │                                       ├── RibHierarchyUtils.java
│   │   │                                       └── RibHierarchyWithSelectionPayload.java
│   │   └── src/
│   │       ├── main/
│   │       │   ├── java/
│   │       │   │   └── com/
│   │       │   │       └── uber/
│   │       │   │           └── presidio/
│   │       │   │               └── intellij_plugin/
│   │       │   │                   ├── action/
│   │       │   │                   │   └── rib/
│   │       │   │                   │       ├── GenerateAction.java
│   │       │   │                   │       ├── GenerateRibAction.java
│   │       │   │                   │       ├── GenerateRibDialog.form
│   │       │   │                   │       ├── GenerateRibDialog.java
│   │       │   │                   │       └── Generators.java
│   │       │   │                   └── generator/
│   │       │   │                       ├── Generator.java
│   │       │   │                       ├── GeneratorPair.java
│   │       │   │                       └── rib/
│   │       │   │                           ├── BuilderGenerator.java
│   │       │   │                           ├── InteractorWithEmptyPresenterGenerator.java
│   │       │   │                           ├── InteractorWithEmptyPresenterTestGenerator.java
│   │       │   │                           ├── InteractorWithPresenterGenerator.java
│   │       │   │                           ├── InteractorWithPresenterTestGenerator.java
│   │       │   │                           ├── RouterGenerator.java
│   │       │   │                           ├── RouterTestGenerator.java
│   │       │   │                           ├── ViewBuilderGenerator.java
│   │       │   │                           ├── ViewGenerator.java
│   │       │   │                           ├── ViewRouterGenerator.java
│   │       │   │                           └── ViewRouterTestGenerator.java
│   │       │   ├── kotlin/
│   │       │   │   └── com/
│   │       │   │       └── uber/
│   │       │   │           └── intellij/
│   │       │   │               └── plugin/
│   │       │   │                   └── android/
│   │       │   │                       └── rib/
│   │       │   │                           ├── AndroidDeviceRepository.kt
│   │       │   │                           ├── AttachRibProjectServiceActivity.kt
│   │       │   │                           ├── CommandLineUtils.kt
│   │       │   │                           ├── RibHierarchyBrowser.kt
│   │       │   │                           ├── RibHierarchyPanel.kt
│   │       │   │                           ├── RibHierarchyUtils.kt
│   │       │   │                           ├── RibIcons.kt
│   │       │   │                           ├── RibProjectService.kt
│   │       │   │                           ├── RibViewBrowser.kt
│   │       │   │                           ├── io/
│   │       │   │                           │   ├── AckRequest.kt
│   │       │   │                           │   ├── LogcatMessageDecoder.kt
│   │       │   │                           │   ├── LogcatRequestProcessor.kt
│   │       │   │                           │   ├── Request.kt
│   │       │   │                           │   ├── RequestProcessor.kt
│   │       │   │                           │   ├── Response.kt
│   │       │   │                           │   ├── RibHierarchyRequest.kt
│   │       │   │                           │   ├── RibHighlightRequest.kt
│   │       │   │                           │   └── RibLocateRequest.kt
│   │       │   │                           └── ui/
│   │       │   │                               ├── HierarchyBrowserBase.kt
│   │       │   │                               ├── RibHierarchyActivityDescriptor.kt
│   │       │   │                               ├── RibHierarchyApplicationDescriptor.kt
│   │       │   │                               ├── RibHierarchyDescriptor.kt
│   │       │   │                               ├── RibHierarchyNodeDescriptor.kt
│   │       │   │                               ├── RibHierarchyRootNodeDescriptor.kt
│   │       │   │                               ├── RibHierarchyTreeStructure.kt
│   │       │   │                               ├── RibViewNodeDescriptor.kt
│   │       │   │                               └── RibViewRootNodeDescriptor.kt
│   │       │   └── resources/
│   │       │       ├── META-INF/
│   │       │       │   └── plugin.xml
│   │       │       ├── partials/
│   │       │       │   ├── ExampleInteractorTest.java.partial
│   │       │       │   ├── ExampleRouterTest.java.partial
│   │       │       │   ├── RibInteractorDidBecomeActive.java.partial
│   │       │       │   └── RibInteractorWillResignActive.java.partial
│   │       │       └── templates/
│   │       │           ├── java/
│   │       │           │   ├── RibBuilder.java.template
│   │       │           │   ├── RibInteractorWithEmptyPresenter.java.template
│   │       │           │   ├── RibInteractorWithEmptyPresenterTest.java.template
│   │       │           │   ├── RibInteractorWithPresenter.java.template
│   │       │           │   ├── RibInteractorWithPresenterTest.java.template
│   │       │           │   ├── RibRouter.java.template
│   │       │           │   ├── RibRouterTest.java.template
│   │       │           │   ├── RibView.java.template
│   │       │           │   ├── RibViewBuilder.java.template
│   │       │           │   ├── RibViewRouter.java.template
│   │       │           │   └── RibViewRouterTest.java.template
│   │       │           └── kotlin/
│   │       │               ├── RibBuilder.kt.template
│   │       │               ├── RibInteractorWithEmptyPresenter.kt.template
│   │       │               ├── RibInteractorWithEmptyPresenterTest.kt.template
│   │       │               ├── RibInteractorWithPresenter.kt.template
│   │       │               ├── RibInteractorWithPresenterTest.kt.template
│   │       │               ├── RibRouter.kt.template
│   │       │               ├── RibRouterTest.kt.template
│   │       │               ├── RibView.kt.template
│   │       │               ├── RibViewBuilder.kt.template
│   │       │               ├── RibViewRouter.kt.template
│   │       │               └── RibViewRouterTest.kt.template
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── uber/
│   │                       └── presidio/
│   │                           └── intellij_plugin/
│   │                               └── action/
│   │                                   └── rib/
│   │                                       └── RibGeneratorsTest.java
│   └── utils/
│       └── intellij-broadcast-core/
│           ├── README.md
│           ├── build.gradle.kts
│           ├── gradle.properties
│           └── src/
│               └── main/
│                   └── java/
│                       └── com/
│                           └── uber/
│                               └── debug/
│                                   └── broadcast/
│                                       └── core/
│                                           ├── AckDebugBroadcastHandler.java
│                                           ├── DebugBroadcastReceiver.java
│                                           ├── DebugBroadcastRequest.java
│                                           └── DebugBroadcastResponse.java
└── tutorials/
    ├── tutorial1/
    │   ├── README.md
    │   ├── build.gradle.kts
    │   └── src/
    │       ├── main/
    │       │   ├── AndroidManifest.xml
    │       │   ├── java/
    │       │   │   └── com/
    │       │   │       └── uber/
    │       │   │           └── rib/
    │       │   │               ├── RootActivity.java
    │       │   │               ├── SampleApplication.java
    │       │   │               └── root/
    │       │   │                   ├── RootBuilder.java
    │       │   │                   ├── RootInteractor.java
    │       │   │                   ├── RootRouter.java
    │       │   │                   └── RootView.java
    │       │   └── res/
    │       │       ├── layout/
    │       │       │   └── root_rib.xml
    │       │       └── values/
    │       │           └── ub__strings.xml
    │       └── test/
    │           └── java/
    │               └── com/
    │                   └── uber/
    │                       └── rib/
    │                           └── root/
    │                               ├── RootInteractorTest.java
    │                               └── RootRouterTest.java
    ├── tutorial2/
    │   ├── README.md
    │   ├── build.gradle.kts
    │   └── src/
    │       ├── main/
    │       │   ├── AndroidManifest.xml
    │       │   ├── java/
    │       │   │   └── com/
    │       │   │       └── uber/
    │       │   │           └── rib/
    │       │   │               ├── RootActivity.java
    │       │   │               ├── SampleApplication.java
    │       │   │               └── root/
    │       │   │                   ├── RootBuilder.java
    │       │   │                   ├── RootInteractor.java
    │       │   │                   ├── RootRouter.java
    │       │   │                   ├── RootView.java
    │       │   │                   ├── loggedin/
    │       │   │                   │   ├── offgame/
    │       │   │                   │   │   ├── OffGameBuilder.java
    │       │   │                   │   │   ├── OffGameInteractor.java
    │       │   │                   │   │   ├── OffGameRouter.java
    │       │   │                   │   │   └── OffGameView.java
    │       │   │                   │   └── tictactoe/
    │       │   │                   │       ├── Board.java
    │       │   │                   │       ├── BoardCoordinate.java
    │       │   │                   │       ├── TicTacToeBuilder.java
    │       │   │                   │       ├── TicTacToeInteractor.java
    │       │   │                   │       ├── TicTacToeRouter.java
    │       │   │                   │       └── TicTacToeView.java
    │       │   │                   └── loggedout/
    │       │   │                       ├── LoggedOutBuilder.java
    │       │   │                       ├── LoggedOutInteractor.java
    │       │   │                       ├── LoggedOutRouter.java
    │       │   │                       └── LoggedOutView.java
    │       │   └── res/
    │       │       ├── layout/
    │       │       │   ├── logged_out_rib.xml
    │       │       │   ├── off_game_rib.xml
    │       │       │   ├── root_rib.xml
    │       │       │   └── tic_tac_toe_rib.xml
    │       │       └── values/
    │       │           └── ub__strings.xml
    │       └── test/
    │           └── java/
    │               └── com/
    │                   └── uber/
    │                       └── rib/
    │                           └── root/
    │                               ├── RootInteractorTest.java
    │                               ├── RootRouterTest.java
    │                               └── loggedout/
    │                                   ├── LoggedOutInteractorTest.java
    │                                   └── LoggedOutRouterTest.java
    ├── tutorial3/
    │   ├── README.md
    │   ├── build.gradle.kts
    │   └── src/
    │       ├── main/
    │       │   ├── AndroidManifest.xml
    │       │   ├── java/
    │       │   │   └── com/
    │       │   │       └── uber/
    │       │   │           └── rib/
    │       │   │               ├── RootActivity.java
    │       │   │               ├── SampleApplication.java
    │       │   │               └── root/
    │       │   │                   ├── RootBuilder.java
    │       │   │                   ├── RootInteractor.java
    │       │   │                   ├── RootRouter.java
    │       │   │                   ├── RootView.java
    │       │   │                   ├── loggedin/
    │       │   │                   │   ├── LoggedInBuilder.java
    │       │   │                   │   ├── LoggedInInteractor.java
    │       │   │                   │   ├── LoggedInRouter.java
    │       │   │                   │   ├── offgame/
    │       │   │                   │   │   ├── OffGameBuilder.java
    │       │   │                   │   │   ├── OffGameInteractor.java
    │       │   │                   │   │   ├── OffGameRouter.java
    │       │   │                   │   │   └── OffGameView.java
    │       │   │                   │   └── tictactoe/
    │       │   │                   │       ├── Board.java
    │       │   │                   │       ├── BoardCoordinate.java
    │       │   │                   │       ├── TicTacToeBuilder.java
    │       │   │                   │       ├── TicTacToeInteractor.java
    │       │   │                   │       ├── TicTacToeRouter.java
    │       │   │                   │       └── TicTacToeView.java
    │       │   │                   └── loggedout/
    │       │   │                       ├── LoggedOutBuilder.java
    │       │   │                       ├── LoggedOutInteractor.java
    │       │   │                       ├── LoggedOutRouter.java
    │       │   │                       └── LoggedOutView.java
    │       │   └── res/
    │       │       ├── layout/
    │       │       │   ├── logged_out_rib.xml
    │       │       │   ├── off_game_rib.xml
    │       │       │   ├── root_rib.xml
    │       │       │   └── tic_tac_toe_rib.xml
    │       │       └── values/
    │       │           └── ub__strings.xml
    │       └── test/
    │           └── java/
    │               └── com/
    │                   └── uber/
    │                       └── rib/
    │                           └── root/
    │                               ├── RootInteractorTest.java
    │                               ├── RootRouterTest.java
    │                               ├── loggedin/
    │                               │   ├── LoggedInInteractorTest.java
    │                               │   ├── LoggedInRouterTest.java
    │                               │   ├── offgame/
    │                               │   │   ├── OffGameInteractorTest.java
    │                               │   │   └── OffGameRouterTest.java
    │                               │   └── tictactoe/
    │                               │       ├── TicTacToeInteractorTest.java
    │                               │       └── TicTacToeRouterTest.java
    │                               └── loggedout/
    │                                   ├── LoggedOutInteractorTest.java
    │                                   └── LoggedOutRouterTest.java
    ├── tutorial3-completed/
    │   ├── README.md
    │   ├── build.gradle.kts
    │   └── src/
    │       ├── main/
    │       │   ├── AndroidManifest.xml
    │       │   ├── java/
    │       │   │   └── com/
    │       │   │       └── uber/
    │       │   │           └── rib/
    │       │   │               ├── RootActivity.java
    │       │   │               ├── SampleApplication.java
    │       │   │               └── root/
    │       │   │                   ├── RootBuilder.java
    │       │   │                   ├── RootInteractor.java
    │       │   │                   ├── RootRouter.java
    │       │   │                   ├── RootView.java
    │       │   │                   ├── loggedin/
    │       │   │                   │   ├── LoggedInBuilder.java
    │       │   │                   │   ├── LoggedInInteractor.java
    │       │   │                   │   ├── LoggedInRouter.java
    │       │   │                   │   ├── MutableScoreStream.java
    │       │   │                   │   ├── ScoreStream.java
    │       │   │                   │   ├── offgame/
    │       │   │                   │   │   ├── OffGameBuilder.java
    │       │   │                   │   │   ├── OffGameInteractor.java
    │       │   │                   │   │   ├── OffGameRouter.java
    │       │   │                   │   │   └── OffGameView.java
    │       │   │                   │   └── tictactoe/
    │       │   │                   │       ├── Board.java
    │       │   │                   │       ├── BoardCoordinate.java
    │       │   │                   │       ├── TicTacToeBuilder.java
    │       │   │                   │       ├── TicTacToeInteractor.java
    │       │   │                   │       ├── TicTacToeRouter.java
    │       │   │                   │       └── TicTacToeView.java
    │       │   │                   └── loggedout/
    │       │   │                       ├── LoggedOutBuilder.java
    │       │   │                       ├── LoggedOutInteractor.java
    │       │   │                       ├── LoggedOutRouter.java
    │       │   │                       └── LoggedOutView.java
    │       │   └── res/
    │       │       ├── layout/
    │       │       │   ├── logged_out_rib.xml
    │       │       │   ├── off_game_rib.xml
    │       │       │   ├── root_rib.xml
    │       │       │   └── tic_tac_toe_rib.xml
    │       │       └── values/
    │       │           └── ub__strings.xml
    │       └── test/
    │           └── java/
    │               └── com/
    │                   └── uber/
    │                       └── rib/
    │                           └── root/
    │                               ├── RootInteractorTest.java
    │                               ├── RootRouterTest.java
    │                               ├── loggedin/
    │                               │   ├── LoggedInInteractorTest.java
    │                               │   ├── LoggedInRouterTest.java
    │                               │   ├── offgame/
    │                               │   │   ├── OffGameInteractorTest.java
    │                               │   │   └── OffGameRouterTest.java
    │                               │   └── tictactoe/
    │                               │       ├── TicTacToeInteractorTest.java
    │                               │       └── TicTacToeRouterTest.java
    │                               └── loggedout/
    │                                   ├── LoggedOutInteractorTest.java
    │                                   └── LoggedOutRouterTest.java
    └── tutorial4/
        ├── README.md
        ├── build.gradle.kts
        └── src/
            └── main/
                ├── AndroidManifest.xml
                ├── java/
                │   └── com/
                │       └── uber/
                │           └── rib/
                │               ├── RootActivity.java
                │               ├── SampleApplication.java
                │               └── root/
                │                   ├── RootActionableItem.java
                │                   ├── RootBuilder.java
                │                   ├── RootInteractor.java
                │                   ├── RootRouter.java
                │                   ├── RootView.java
                │                   ├── RootWorkflow.java
                │                   ├── RootWorkflowModel.java
                │                   ├── UserName.kt
                │                   ├── WorkflowFactory.java
                │                   ├── loggedin/
                │                   │   ├── GameKey.java
                │                   │   ├── GameProvider.java
                │                   │   ├── LoggedInActionableItem.java
                │                   │   ├── LoggedInBuilder.java
                │                   │   ├── LoggedInInteractor.java
                │                   │   ├── LoggedInRouter.java
                │                   │   ├── MutableScoreStream.java
                │                   │   ├── ScoreStream.java
                │                   │   ├── offgame/
                │                   │   │   ├── OffGameBuilder.java
                │                   │   │   ├── OffGameInteractor.java
                │                   │   │   ├── OffGameRouter.java
                │                   │   │   └── OffGameView.java
                │                   │   ├── randomWinner/
                │                   │   │   ├── RandomWinnerBuilder.java
                │                   │   │   ├── RandomWinnerInteractor.java
                │                   │   │   ├── RandomWinnerRouter.java
                │                   │   │   └── RandomWinnerView.java
                │                   │   └── tictactoe/
                │                   │       ├── Board.java
                │                   │       ├── BoardCoordinate.java
                │                   │       ├── TicTacToeBuilder.java
                │                   │       ├── TicTacToeInteractor.java
                │                   │       ├── TicTacToeRouter.java
                │                   │       └── TicTacToeView.java
                │                   └── loggedout/
                │                       ├── LoggedOutBuilder.java
                │                       ├── LoggedOutInteractor.java
                │                       ├── LoggedOutRouter.java
                │                       └── LoggedOutView.java
                └── res/
                    ├── layout/
                    │   ├── game_button.xml
                    │   ├── logged_out_rib.xml
                    │   ├── off_game_rib.xml
                    │   ├── root_rib.xml
                    │   └── tic_tac_toe_rib.xml
                    └── values/
                        └── ub__strings.xml
Download .txt
SYMBOL INDEX (1478 symbols across 233 files)

FILE: demos/flipper/src/main/java/com/uber/rib/RootActivity.java
  class RootActivity (line 24) | public class RootActivity extends RibActivity {
    method createRouter (line 26) | @SuppressWarnings("unchecked")

FILE: demos/flipper/src/main/java/com/uber/rib/SampleApplication.java
  class SampleApplication (line 26) | public class SampleApplication extends Application {
    method onCreate (line 28) | @Override

FILE: demos/flipper/src/main/java/com/uber/rib/root/RootBuilder.java
  class RootBuilder (line 35) | public class RootBuilder extends ViewBuilder<RootView, RootRouter, RootB...
    method RootBuilder (line 37) | public RootBuilder(ParentComponent dependency) {
    method build (line 47) | public RootRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 59) | @Override
    type ParentComponent (line 64) | public interface ParentComponent {
    class Module (line 68) | @dagger.Module
      method loggedOutListener (line 71) | @RootScope
      method presenter (line 77) | @RootScope
      method router (line 81) | @RootScope
    type Component (line 93) | @RootScope
      type Builder (line 101) | @dagger.Component.Builder
        method interactor (line 104) | @BindsInstance
        method view (line 107) | @BindsInstance
        method parentComponent (line 110) | Builder parentComponent(ParentComponent component);
        method build (line 112) | Component build();
    type BuilderComponent (line 116) | interface BuilderComponent {
      method rootRouter (line 118) | RootRouter rootRouter();

FILE: demos/flipper/src/main/java/com/uber/rib/root/RootInteractor.java
  class RootInteractor (line 26) | @RibInteractor
    method didBecomeActive (line 31) | @Override
    class LoggedOutListener (line 37) | class LoggedOutListener implements LoggedOutInteractor.Listener {
      method login (line 39) | @Override
    type RootPresenter (line 48) | interface RootPresenter {}

FILE: demos/flipper/src/main/java/com/uber/rib/root/RootRouter.java
  class RootRouter (line 25) | public class RootRouter extends ViewRouter<RootView, RootInteractor> {
    method RootRouter (line 31) | RootRouter(
    method attachLoggedOut (line 42) | void attachLoggedOut() {
    method detachLoggedOut (line 48) | void detachLoggedOut() {
    method attachLoggedIn (line 56) | void attachLoggedIn() {

FILE: demos/flipper/src/main/java/com/uber/rib/root/RootView.java
  class RootView (line 24) | public class RootView extends FrameLayout implements RootInteractor.Root...
    method RootView (line 26) | public RootView(Context context) {
    method RootView (line 30) | public RootView(Context context, @Nullable AttributeSet attrs) {
    method RootView (line 34) | public RootView(Context context, @Nullable AttributeSet attrs, int def...

FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/LoggedInBuilder.java
  class LoggedInBuilder (line 33) | public class LoggedInBuilder extends Builder<LoggedInRouter, LoggedInBui...
    method LoggedInBuilder (line 35) | public LoggedInBuilder(ParentComponent dependency) {
    method build (line 44) | public LoggedInRouter build() {
    type ParentComponent (line 55) | public interface ParentComponent {
      method rootView (line 57) | RootView rootView();
    class Module (line 60) | @dagger.Module
      method presenter (line 63) | @LoggedInScope
      method router (line 69) | @LoggedInScope
      method listener (line 81) | @LoggedInScope
    type Component (line 88) | @LoggedInScope
      type Builder (line 96) | @dagger.Component.Builder
        method interactor (line 99) | @BindsInstance
        method parentComponent (line 102) | Builder parentComponent(ParentComponent component);
        method build (line 104) | Component build();
    type BuilderComponent (line 108) | interface BuilderComponent {
      method loggedinRouter (line 110) | LoggedInRouter loggedinRouter();

FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/LoggedInInteractor.java
  class LoggedInInteractor (line 26) | @RibInteractor
    method didBecomeActive (line 29) | @Override
    class OffGameListener (line 37) | class OffGameListener implements OffGameInteractor.Listener {
      method onStartGame (line 39) | @Override

FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/LoggedInRouter.java
  class LoggedInRouter (line 26) | public class LoggedInRouter extends Router<LoggedInInteractor> {
    method LoggedInRouter (line 34) | LoggedInRouter(
    method willDetach (line 46) | @Override
    method attachOffGame (line 53) | void attachOffGame() {
    method detachOffGame (line 59) | void detachOffGame() {
    method attachTicTacToe (line 67) | void attachTicTacToe() {
    method detachTicTacToe (line 73) | void detachTicTacToe() {

FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameBuilder.java
  class OffGameBuilder (line 33) | public class OffGameBuilder
    method OffGameBuilder (line 36) | public OffGameBuilder(ParentComponent dependency) {
    method build (line 46) | public OffGameRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 58) | @Override
    type ParentComponent (line 63) | public interface ParentComponent {
      method listener (line 65) | OffGameInteractor.Listener listener();
    class Module (line 68) | @dagger.Module
      method presenter (line 71) | @OffGameScope
      method router (line 75) | @OffGameScope
    type Component (line 83) | @OffGameScope
      type Builder (line 87) | @dagger.Component.Builder
        method interactor (line 90) | @BindsInstance
        method view (line 93) | @BindsInstance
        method parentComponent (line 96) | Builder parentComponent(ParentComponent component);
        method build (line 98) | Component build();
    type BuilderComponent (line 102) | interface BuilderComponent {
      method offgameRouter (line 104) | OffGameRouter offgameRouter();

FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameInteractor.java
  class OffGameInteractor (line 27) | @RibInteractor
    method didBecomeActive (line 34) | @Override
    type Listener (line 49) | public interface Listener {
      method onStartGame (line 51) | void onStartGame();
    type OffGamePresenter (line 55) | interface OffGamePresenter {
      method startGameRequest (line 57) | Observable<Object> startGameRequest();

FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameRouter.java
  class OffGameRouter (line 21) | public class OffGameRouter extends ViewRouter<OffGameView, OffGameIntera...
    method OffGameRouter (line 23) | public OffGameRouter(

FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameView.java
  class OffGameView (line 30) | public class OffGameView extends LinearLayout implements OffGameInteract...
    method OffGameView (line 38) | public OffGameView(Context context) {
    method OffGameView (line 42) | public OffGameView(Context context, @Nullable AttributeSet attrs) {
    method OffGameView (line 46) | public OffGameView(Context context, @Nullable AttributeSet attrs, int ...
    method onFinishInflate (line 50) | @Initializer
    method startGameRequest (line 61) | @Override

FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/Board.java
  class Board (line 20) | class Board {
    method Board (line 29) | @Inject
    method isDraw (line 40) | boolean isDraw() {
    method hasWon (line 52) | boolean hasWon(MarkerType theSeed) {
    type MarkerType (line 69) | enum MarkerType {

FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/BoardCoordinate.java
  class BoardCoordinate (line 18) | class BoardCoordinate {
    method BoardCoordinate (line 23) | BoardCoordinate(int x, int y) {
    method getX (line 28) | int getX() {
    method getY (line 32) | int getY() {

FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeBuilder.java
  class TicTacToeBuilder (line 33) | public class TicTacToeBuilder
    method TicTacToeBuilder (line 36) | public TicTacToeBuilder(ParentComponent dependency) {
    method build (line 46) | public TicTacToeRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 58) | @Override
    type ParentComponent (line 63) | public interface ParentComponent {
    class Module (line 67) | @dagger.Module
      method presenter (line 70) | @TicTacToeScope
      method router (line 74) | @TicTacToeScope
    type Component (line 82) | @TicTacToeScope
      type Builder (line 86) | @dagger.Component.Builder
        method interactor (line 89) | @BindsInstance
        method view (line 92) | @BindsInstance
        method parentComponent (line 95) | Builder parentComponent(ParentComponent component);
        method build (line 97) | Component build();
    type BuilderComponent (line 101) | interface BuilderComponent {
      method tictactoeRouter (line 103) | TicTacToeRouter tictactoeRouter();

FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeInteractor.java
  class TicTacToeInteractor (line 28) | @RibInteractor
    method didBecomeActive (line 40) | @Override
    method updateCurrentPlayer (line 79) | private void updateCurrentPlayer() {
    type TicTacToePresenter (line 88) | interface TicTacToePresenter {
      method squareClicks (line 89) | Observable<BoardCoordinate> squareClicks();
      method setCurrentPlayerName (line 91) | void setCurrentPlayerName(String currentPlayer);
      method setPlayerWon (line 93) | void setPlayerWon(String playerName);
      method setPlayerTie (line 95) | void setPlayerTie();
      method addCross (line 97) | void addCross(BoardCoordinate xy);
      method addNought (line 99) | void addNought(BoardCoordinate xy);
    type Listener (line 102) | public interface Listener {}

FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeRouter.java
  class TicTacToeRouter (line 21) | public class TicTacToeRouter extends ViewRouter<TicTacToeView, TicTacToe...
    method TicTacToeRouter (line 23) | public TicTacToeRouter(

FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeView.java
  class TicTacToeView (line 31) | public class TicTacToeView extends PercentRelativeLayout
    method TicTacToeView (line 37) | public TicTacToeView(Context context) {
    method TicTacToeView (line 41) | public TicTacToeView(Context context, @Nullable AttributeSet attrs) {
    method TicTacToeView (line 45) | public TicTacToeView(Context context, @Nullable AttributeSet attrs, in...
    method onFinishInflate (line 49) | @Initializer
    method squareClicks (line 75) | @Override
    method addCross (line 96) | @Override
    method addNought (line 103) | @Override
    method setCurrentPlayerName (line 110) | @Override
    method setPlayerWon (line 115) | @Override
    method setPlayerTie (line 120) | @Override

FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedout/LoggedOutBuilder.java
  class LoggedOutBuilder (line 33) | public class LoggedOutBuilder
    method LoggedOutBuilder (line 36) | public LoggedOutBuilder(ParentComponent dependency) {
    method build (line 46) | public LoggedOutRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 58) | @Override
    type ParentComponent (line 63) | public interface ParentComponent {
      method listener (line 65) | LoggedOutInteractor.Listener listener();
    class Module (line 68) | @dagger.Module
      method presenter (line 71) | @LoggedOutScope
      method router (line 75) | @LoggedOutScope
    type Component (line 85) | @LoggedOutScope
      type Builder (line 89) | @dagger.Component.Builder
        method interactor (line 92) | @BindsInstance
        method view (line 95) | @BindsInstance
        method parentComponent (line 98) | Builder parentComponent(ParentComponent component);
        method build (line 100) | Component build();
    type BuilderComponent (line 104) | interface BuilderComponent {
      method loggedoutRouter (line 106) | LoggedOutRouter loggedoutRouter();

FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedout/LoggedOutInteractor.java
  class LoggedOutInteractor (line 29) | @RibInteractor
    method didBecomeActive (line 36) | @Override
    method isEmpty (line 52) | private boolean isEmpty(@Nullable String string) {
    type LoggedOutPresenter (line 57) | interface LoggedOutPresenter {
      method loginName (line 59) | Observable<Pair<String, String>> loginName();
    type Listener (line 62) | public interface Listener {
      method login (line 63) | void login(String userNameA, String userNameB);

FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedout/LoggedOutRouter.java
  class LoggedOutRouter (line 21) | public class LoggedOutRouter extends ViewRouter<LoggedOutView, LoggedOut...
    method LoggedOutRouter (line 23) | public LoggedOutRouter(

FILE: demos/flipper/src/main/java/com/uber/rib/root/loggedout/LoggedOutView.java
  class LoggedOutView (line 30) | public class LoggedOutView extends LinearLayout implements LoggedOutInte...
    method LoggedOutView (line 32) | public LoggedOutView(Context context) {
    method LoggedOutView (line 36) | public LoggedOutView(Context context, @Nullable AttributeSet attrs) {
    method LoggedOutView (line 40) | public LoggedOutView(Context context, @Nullable AttributeSet attrs, in...
    method loginName (line 44) | @Override

FILE: demos/intellij/src/main/java/com/uber/rib/RootActivity.java
  class RootActivity (line 24) | public class RootActivity extends RibActivity {
    method createRouter (line 26) | @SuppressWarnings("unchecked")

FILE: demos/intellij/src/main/java/com/uber/rib/SampleApplication.java
  class SampleApplication (line 25) | public class SampleApplication extends Application {
    method onCreate (line 27) | @Override

FILE: demos/intellij/src/main/java/com/uber/rib/root/RootBuilder.java
  class RootBuilder (line 35) | public class RootBuilder extends ViewBuilder<RootView, RootRouter, RootB...
    method RootBuilder (line 37) | public RootBuilder(ParentComponent dependency) {
    method build (line 47) | public RootRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 59) | @Override
    type ParentComponent (line 64) | public interface ParentComponent {
    class Module (line 68) | @dagger.Module
      method loggedOutListener (line 71) | @RootScope
      method presenter (line 77) | @RootScope
      method router (line 81) | @RootScope
    type Component (line 93) | @RootScope
      type Builder (line 101) | @dagger.Component.Builder
        method interactor (line 104) | @BindsInstance
        method view (line 107) | @BindsInstance
        method parentComponent (line 110) | Builder parentComponent(ParentComponent component);
        method build (line 112) | Component build();
    type BuilderComponent (line 116) | interface BuilderComponent {
      method rootRouter (line 118) | RootRouter rootRouter();

FILE: demos/intellij/src/main/java/com/uber/rib/root/RootInteractor.java
  class RootInteractor (line 26) | @RibInteractor
    method didBecomeActive (line 31) | @Override
    class LoggedOutListener (line 37) | class LoggedOutListener implements LoggedOutInteractor.Listener {
      method login (line 39) | @Override
    type RootPresenter (line 48) | interface RootPresenter {}

FILE: demos/intellij/src/main/java/com/uber/rib/root/RootRouter.java
  class RootRouter (line 25) | public class RootRouter extends ViewRouter<RootView, RootInteractor> {
    method RootRouter (line 31) | RootRouter(
    method attachLoggedOut (line 42) | void attachLoggedOut() {
    method detachLoggedOut (line 48) | void detachLoggedOut() {
    method attachLoggedIn (line 56) | void attachLoggedIn() {

FILE: demos/intellij/src/main/java/com/uber/rib/root/RootView.java
  class RootView (line 24) | public class RootView extends FrameLayout implements RootInteractor.Root...
    method RootView (line 26) | public RootView(Context context) {
    method RootView (line 30) | public RootView(Context context, @Nullable AttributeSet attrs) {
    method RootView (line 34) | public RootView(Context context, @Nullable AttributeSet attrs, int def...

FILE: demos/intellij/src/main/java/com/uber/rib/root/loggedin/LoggedInBuilder.java
  class LoggedInBuilder (line 33) | public class LoggedInBuilder extends Builder<LoggedInRouter, LoggedInBui...
    method LoggedInBuilder (line 35) | public LoggedInBuilder(ParentComponent dependency) {
    method build (line 44) | public LoggedInRouter build() {
    type ParentComponent (line 55) | public interface ParentComponent {
      method rootView (line 57) | RootView rootView();
    class Module (line 60) | @dagger.Module
      method presenter (line 63) | @LoggedInScope
      method router (line 69) | @LoggedInScope
      method listener (line 81) | @LoggedInScope
    type Component (line 88) | @LoggedInScope
      type Builder (line 96) | @dagger.Component.Builder
        method interactor (line 99) | @BindsInstance
        method parentComponent (line 102) | Builder parentComponent(ParentComponent component);
        method build (line 104) | Component build();
    type BuilderComponent (line 108) | interface BuilderComponent {
      method loggedinRouter (line 110) | LoggedInRouter loggedinRouter();

FILE: demos/intellij/src/main/java/com/uber/rib/root/loggedin/LoggedInInteractor.java
  class LoggedInInteractor (line 26) | @RibInteractor
    method didBecomeActive (line 29) | @Override
    class OffGameListener (line 37) | class OffGameListener implements OffGameInteractor.Listener {
      method onStartGame (line 39) | @Override

FILE: demos/intellij/src/main/java/com/uber/rib/root/loggedin/LoggedInRouter.java
  class LoggedInRouter (line 26) | public class LoggedInRouter extends Router<LoggedInInteractor> {
    method LoggedInRouter (line 34) | LoggedInRouter(
    method willDetach (line 46) | @Override
    method attachOffGame (line 53) | void attachOffGame() {
    method detachOffGame (line 59) | void detachOffGame() {
    method attachTicTacToe (line 67) | void attachTicTacToe() {
    method detachTicTacToe (line 73) | void detachTicTacToe() {

FILE: demos/intellij/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameBuilder.java
  class OffGameBuilder (line 33) | public class OffGameBuilder
    method OffGameBuilder (line 36) | public OffGameBuilder(ParentComponent dependency) {
    method build (line 46) | public OffGameRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 58) | @Override
    type ParentComponent (line 63) | public interface ParentComponent {
      method listener (line 65) | OffGameInteractor.Listener listener();
    class Module (line 68) | @dagger.Module
      method presenter (line 71) | @OffGameScope
      method router (line 75) | @OffGameScope
    type Component (line 83) | @OffGameScope
      type Builder (line 87) | @dagger.Component.Builder
        method interactor (line 90) | @BindsInstance
        method view (line 93) | @BindsInstance
        method parentComponent (line 96) | Builder parentComponent(ParentComponent component);
        method build (line 98) | Component build();
    type BuilderComponent (line 102) | interface BuilderComponent {
      method offgameRouter (line 104) | OffGameRouter offgameRouter();

FILE: demos/intellij/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameInteractor.java
  class OffGameInteractor (line 27) | @RibInteractor
    method didBecomeActive (line 34) | @Override
    type Listener (line 49) | public interface Listener {
      method onStartGame (line 51) | void onStartGame();
    type OffGamePresenter (line 55) | interface OffGamePresenter {
      method startGameRequest (line 57) | Observable<Object> startGameRequest();

FILE: demos/intellij/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameRouter.java
  class OffGameRouter (line 21) | public class OffGameRouter extends ViewRouter<OffGameView, OffGameIntera...
    method OffGameRouter (line 23) | public OffGameRouter(

FILE: demos/intellij/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameView.java
  class OffGameView (line 30) | public class OffGameView extends LinearLayout implements OffGameInteract...
    method OffGameView (line 38) | public OffGameView(Context context) {
    method OffGameView (line 42) | public OffGameView(Context context, @Nullable AttributeSet attrs) {
    method OffGameView (line 46) | public OffGameView(Context context, @Nullable AttributeSet attrs, int ...
    method onFinishInflate (line 50) | @Initializer
    method startGameRequest (line 61) | @Override

FILE: demos/intellij/src/main/java/com/uber/rib/root/loggedin/tictactoe/Board.java
  class Board (line 20) | class Board {
    method Board (line 29) | @Inject
    method isDraw (line 40) | boolean isDraw() {
    method hasWon (line 52) | boolean hasWon(MarkerType theSeed) {
    type MarkerType (line 69) | enum MarkerType {

FILE: demos/intellij/src/main/java/com/uber/rib/root/loggedin/tictactoe/BoardCoordinate.java
  class BoardCoordinate (line 18) | class BoardCoordinate {
    method BoardCoordinate (line 23) | BoardCoordinate(int x, int y) {
    method getX (line 28) | int getX() {
    method getY (line 32) | int getY() {

FILE: demos/intellij/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeBuilder.java
  class TicTacToeBuilder (line 33) | public class TicTacToeBuilder
    method TicTacToeBuilder (line 36) | public TicTacToeBuilder(ParentComponent dependency) {
    method build (line 46) | public TicTacToeRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 58) | @Override
    type ParentComponent (line 63) | public interface ParentComponent {
    class Module (line 67) | @dagger.Module
      method presenter (line 70) | @TicTacToeScope
      method router (line 74) | @TicTacToeScope
    type Component (line 82) | @TicTacToeScope
      type Builder (line 86) | @dagger.Component.Builder
        method interactor (line 89) | @BindsInstance
        method view (line 92) | @BindsInstance
        method parentComponent (line 95) | Builder parentComponent(ParentComponent component);
        method build (line 97) | Component build();
    type BuilderComponent (line 101) | interface BuilderComponent {
      method tictactoeRouter (line 103) | TicTacToeRouter tictactoeRouter();

FILE: demos/intellij/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeInteractor.java
  class TicTacToeInteractor (line 28) | @RibInteractor
    method didBecomeActive (line 40) | @Override
    method updateCurrentPlayer (line 79) | private void updateCurrentPlayer() {
    type TicTacToePresenter (line 88) | interface TicTacToePresenter {
      method squareClicks (line 89) | Observable<BoardCoordinate> squareClicks();
      method setCurrentPlayerName (line 91) | void setCurrentPlayerName(String currentPlayer);
      method setPlayerWon (line 93) | void setPlayerWon(String playerName);
      method setPlayerTie (line 95) | void setPlayerTie();
      method addCross (line 97) | void addCross(BoardCoordinate xy);
      method addNought (line 99) | void addNought(BoardCoordinate xy);
    type Listener (line 102) | public interface Listener {}

FILE: demos/intellij/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeRouter.java
  class TicTacToeRouter (line 21) | public class TicTacToeRouter extends ViewRouter<TicTacToeView, TicTacToe...
    method TicTacToeRouter (line 23) | public TicTacToeRouter(

FILE: demos/intellij/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeView.java
  class TicTacToeView (line 31) | public class TicTacToeView extends PercentRelativeLayout
    method TicTacToeView (line 37) | public TicTacToeView(Context context) {
    method TicTacToeView (line 41) | public TicTacToeView(Context context, @Nullable AttributeSet attrs) {
    method TicTacToeView (line 45) | public TicTacToeView(Context context, @Nullable AttributeSet attrs, in...
    method onFinishInflate (line 49) | @Initializer
    method squareClicks (line 75) | @Override
    method addCross (line 96) | @Override
    method addNought (line 103) | @Override
    method setCurrentPlayerName (line 110) | @Override
    method setPlayerWon (line 115) | @Override
    method setPlayerTie (line 120) | @Override

FILE: demos/intellij/src/main/java/com/uber/rib/root/loggedout/LoggedOutBuilder.java
  class LoggedOutBuilder (line 33) | public class LoggedOutBuilder
    method LoggedOutBuilder (line 36) | public LoggedOutBuilder(ParentComponent dependency) {
    method build (line 46) | public LoggedOutRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 58) | @Override
    type ParentComponent (line 63) | public interface ParentComponent {
      method listener (line 65) | LoggedOutInteractor.Listener listener();
    class Module (line 68) | @dagger.Module
      method presenter (line 71) | @LoggedOutScope
      method router (line 75) | @LoggedOutScope
    type Component (line 85) | @LoggedOutScope
      type Builder (line 89) | @dagger.Component.Builder
        method interactor (line 92) | @BindsInstance
        method view (line 95) | @BindsInstance
        method parentComponent (line 98) | Builder parentComponent(ParentComponent component);
        method build (line 100) | Component build();
    type BuilderComponent (line 104) | interface BuilderComponent {
      method loggedoutRouter (line 106) | LoggedOutRouter loggedoutRouter();

FILE: demos/intellij/src/main/java/com/uber/rib/root/loggedout/LoggedOutInteractor.java
  class LoggedOutInteractor (line 29) | @RibInteractor
    method didBecomeActive (line 36) | @Override
    method isEmpty (line 52) | private boolean isEmpty(@Nullable String string) {
    type LoggedOutPresenter (line 57) | interface LoggedOutPresenter {
      method loginName (line 59) | Observable<Pair<String, String>> loginName();
    type Listener (line 62) | public interface Listener {
      method login (line 63) | void login(String userNameA, String userNameB);

FILE: demos/intellij/src/main/java/com/uber/rib/root/loggedout/LoggedOutRouter.java
  class LoggedOutRouter (line 21) | public class LoggedOutRouter extends ViewRouter<LoggedOutView, LoggedOut...
    method LoggedOutRouter (line 23) | public LoggedOutRouter(

FILE: demos/intellij/src/main/java/com/uber/rib/root/loggedout/LoggedOutView.java
  class LoggedOutView (line 30) | public class LoggedOutView extends LinearLayout implements LoggedOutInte...
    method LoggedOutView (line 32) | public LoggedOutView(Context context) {
    method LoggedOutView (line 36) | public LoggedOutView(Context context, @Nullable AttributeSet attrs) {
    method LoggedOutView (line 40) | public LoggedOutView(Context context, @Nullable AttributeSet attrs, in...
    method loginName (line 44) | @Override

FILE: demos/memory-leaks/src/main/java/com/uber/rib/RootActivity.java
  class RootActivity (line 24) | public class RootActivity extends RibActivity {
    method createRouter (line 28) | @SuppressWarnings("unchecked")

FILE: demos/memory-leaks/src/main/java/com/uber/rib/SampleApplication.java
  class SampleApplication (line 25) | public class SampleApplication extends Application implements HasActivit...
    method onCreate (line 29) | @Override
    method installLeakCanary (line 37) | private static void installLeakCanary() {
    method activityDelegate (line 56) | @Override
    class SampleActivityDelegate (line 61) | private static final class SampleActivityDelegate implements ActivityD...

FILE: demos/memory-leaks/src/main/java/com/uber/rib/root/RootBuilder.java
  class RootBuilder (line 35) | public class RootBuilder extends ViewBuilder<RootView, RootRouter, RootB...
    method RootBuilder (line 37) | public RootBuilder(ParentComponent dependency) {
    method build (line 47) | public RootRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 59) | @Override
    type ParentComponent (line 64) | public interface ParentComponent {
    class Module (line 68) | @dagger.Module
      method loggedOutListener (line 71) | @RootScope
      method presenter (line 77) | @RootScope
      method router (line 81) | @RootScope
    type Component (line 93) | @RootScope
      type Builder (line 101) | @dagger.Component.Builder
        method interactor (line 104) | @BindsInstance
        method view (line 107) | @BindsInstance
        method parentComponent (line 110) | Builder parentComponent(ParentComponent component);
        method build (line 112) | Component build();
    type BuilderComponent (line 116) | interface BuilderComponent {
      method rootRouter (line 118) | RootRouter rootRouter();

FILE: demos/memory-leaks/src/main/java/com/uber/rib/root/RootInteractor.java
  class RootInteractor (line 26) | @RibInteractor
    method didBecomeActive (line 31) | @Override
    class LoggedOutListener (line 37) | class LoggedOutListener implements LoggedOutInteractor.Listener {
      method login (line 39) | @Override
    type RootPresenter (line 48) | interface RootPresenter {}

FILE: demos/memory-leaks/src/main/java/com/uber/rib/root/RootRouter.java
  class RootRouter (line 25) | public class RootRouter extends ViewRouter<RootView, RootInteractor> {
    method RootRouter (line 31) | RootRouter(
    method attachLoggedOut (line 42) | void attachLoggedOut() {
    method detachLoggedOut (line 48) | void detachLoggedOut() {
    method attachLoggedIn (line 56) | void attachLoggedIn() {

FILE: demos/memory-leaks/src/main/java/com/uber/rib/root/RootView.java
  class RootView (line 24) | public class RootView extends FrameLayout implements RootInteractor.Root...
    method RootView (line 26) | public RootView(Context context) {
    method RootView (line 30) | public RootView(Context context, @Nullable AttributeSet attrs) {
    method RootView (line 34) | public RootView(Context context, @Nullable AttributeSet attrs, int def...

FILE: demos/memory-leaks/src/main/java/com/uber/rib/root/loggedin/LoggedInBuilder.java
  class LoggedInBuilder (line 30) | public class LoggedInBuilder extends Builder<LoggedInRouter, LoggedInBui...
    method LoggedInBuilder (line 32) | public LoggedInBuilder(ParentComponent dependency) {
    method build (line 41) | public LoggedInRouter build() {
    type ParentComponent (line 52) | public interface ParentComponent {
      method rootView (line 53) | RootView rootView();
    class Module (line 56) | @dagger.Module
      method presenter (line 59) | @LoggedInScope
      method router (line 65) | @LoggedInScope
    type Component (line 72) | @LoggedInScope
      type Builder (line 76) | @dagger.Component.Builder
        method interactor (line 79) | @BindsInstance
        method parentComponent (line 82) | Builder parentComponent(ParentComponent component);
        method build (line 84) | Component build();
    type BuilderComponent (line 88) | interface BuilderComponent {
      method loggedinRouter (line 89) | LoggedInRouter loggedinRouter();

FILE: demos/memory-leaks/src/main/java/com/uber/rib/root/loggedin/LoggedInInteractor.java
  class LoggedInInteractor (line 24) | @RibInteractor

FILE: demos/memory-leaks/src/main/java/com/uber/rib/root/loggedin/LoggedInRouter.java
  class LoggedInRouter (line 21) | public class LoggedInRouter extends Router<LoggedInInteractor> {
    method LoggedInRouter (line 22) | LoggedInRouter(LoggedInInteractor interactor, LoggedInBuilder.Componen...

FILE: demos/memory-leaks/src/main/java/com/uber/rib/root/loggedout/LoggedOutBuilder.java
  class LoggedOutBuilder (line 33) | public class LoggedOutBuilder
    method LoggedOutBuilder (line 36) | public LoggedOutBuilder(ParentComponent dependency) {
    method build (line 46) | public LoggedOutRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 58) | @Override
    type ParentComponent (line 63) | public interface ParentComponent {
      method listener (line 65) | LoggedOutInteractor.Listener listener();
    class Module (line 68) | @dagger.Module
      method presenter (line 71) | @LoggedOutScope
      method router (line 75) | @LoggedOutScope
    type Component (line 85) | @LoggedOutScope
      type Builder (line 89) | @dagger.Component.Builder
        method interactor (line 92) | @BindsInstance
        method view (line 95) | @BindsInstance
        method parentComponent (line 98) | Builder parentComponent(ParentComponent component);
        method build (line 100) | Component build();
    type BuilderComponent (line 104) | interface BuilderComponent {
      method loggedoutRouter (line 106) | LoggedOutRouter loggedoutRouter();

FILE: demos/memory-leaks/src/main/java/com/uber/rib/root/loggedout/LoggedOutInteractor.java
  class LoggedOutInteractor (line 30) | @RibInteractor
    method didBecomeActive (line 37) | @SuppressWarnings("AutoDispose")
    method isEmpty (line 65) | private boolean isEmpty(@Nullable String string) {
    type LoggedOutPresenter (line 70) | interface LoggedOutPresenter {
      method loginName (line 72) | Observable<String> loginName();
    type Listener (line 75) | public interface Listener {
      method login (line 77) | void login(String userName);

FILE: demos/memory-leaks/src/main/java/com/uber/rib/root/loggedout/LoggedOutRouter.java
  class LoggedOutRouter (line 21) | public class LoggedOutRouter extends ViewRouter<LoggedOutView, LoggedOut...
    method LoggedOutRouter (line 23) | public LoggedOutRouter(

FILE: demos/memory-leaks/src/main/java/com/uber/rib/root/loggedout/LoggedOutView.java
  class LoggedOutView (line 29) | public class LoggedOutView extends LinearLayout implements LoggedOutInte...
    method LoggedOutView (line 31) | public LoggedOutView(Context context) {
    method LoggedOutView (line 35) | public LoggedOutView(Context context, @Nullable AttributeSet attrs) {
    method LoggedOutView (line 39) | public LoggedOutView(Context context, @Nullable AttributeSet attrs, in...
    method loginName (line 43) | @Override

FILE: libraries/rib-compiler-app/src/test/resources/fixtures/AnnotatedInteractor.java
  class AnnotatedInteractor (line 23) | @RibInteractor

FILE: libraries/rib-compiler-app/src/test/resources/fixtures/AnnotatedInteractorNoSuffix.java
  class AnnotatedInteractorNoSuffix (line 23) | @RibInteractor

FILE: libraries/rib-compiler-app/src/test/resources/fixtures/AnnotatedNonInteractor.java
  class AnnotatedNonInteractor (line 20) | @RibInteractor

FILE: libraries/rib-compiler-app/src/test/resources/fixtures/CustomConstructorInteractor.java
  class CustomConstructorInteractor (line 24) | @RibInteractor
    method CustomConstructorInteractor (line 27) | public CustomConstructorInteractor(String a, InteractorComponent depen...

FILE: libraries/rib-compiler-test/src/test/resources/fixtures/AnnotatedBasicInteractor.java
  class AnnotatedBasicInteractor (line 10) | @RibInteractor
    method AnnotatedBasicInteractor (line 16) | public AnnotatedBasicInteractor(Presenter presenter, Boolean fieldOne,...

FILE: libraries/rib-compiler-test/src/test/resources/fixtures/AnnotatedInteractor.java
  class AnnotatedInteractor (line 10) | @RibInteractor

FILE: libraries/rib-compiler-test/src/test/resources/fixtures/TestAnnotatedBasicInteractor.java
  class TestAnnotatedBasicInteractor (line 7) | public class TestAnnotatedBasicInteractor {
    method TestAnnotatedBasicInteractor (line 8) | private TestAnnotatedBasicInteractor() {
    method create (line 11) | public static AnnotatedBasicInteractor create(final Presenter presente...

FILE: libraries/rib-compiler-test/src/test/resources/fixtures/TestAnnotatedInteractor.java
  class TestAnnotatedInteractor (line 6) | public class TestAnnotatedInteractor {
    method TestAnnotatedInteractor (line 7) | private TestAnnotatedInteractor() {
    method create (line 10) | public static AnnotatedInteractor create(final Boolean fieldOne, final...

FILE: libraries/rib-compiler-test/src/test/resources/fixtures/TestForcedBasicInteractor.java
  class TestForcedBasicInteractor (line 7) | public class TestForcedBasicInteractor {
    method TestForcedBasicInteractor (line 8) | private TestForcedBasicInteractor() {
    method create (line 11) | public static ForcedBasicInteractor create(final Presenter presenter, ...

FILE: tooling/rib-flipper-plugin/desktop/src/TreeChart.js
  class TreeChart (line 7) | class TreeChart extends Component {
    method constructor (line 9) | constructor(props) {
    method componentDidMount (line 14) | componentDidMount() {
    method componentDidUpdate (line 18) | componentDidUpdate() {
    method getTextOpacity (line 22) | getTextOpacity(d) {
    method renderTree (line 29) | renderTree() {
    method render (line 127) | render() {

FILE: tooling/rib-flipper-plugin/desktop/src/index.js
  class RibTree (line 26) | class RibTree extends FlipperPlugin {
    method constructor (line 28) | constructor(props) {
    method componentDidMount (line 147) | componentDidMount() {
    method componentWillUnmount (line 151) | componentWillUnmount() {
    method onWindowResize (line 154) | onWindowResize() {
    method onNodeClick (line 158) | async onNodeClick(node) {
    method onEditLayout (line 170) | onEditLayout(node) {
    method onNodeMouseOver (line 174) | onNodeMouseOver(node) {
    method onNodeMouseOut (line 184) | onNodeMouseOut(node) {
    method onValueChanged (line 194) | onValueChanged(e) {
    method render (line 199) | render() {

FILE: tooling/rib-flipper-plugin/desktop/src/utils.js
  function getHostForNode (line 2) | function getHostForNode(node) {
  function getHostForNodeRecursive (line 10) | function getHostForNodeRecursive(node, fromParent) {

FILE: tooling/rib-intellij-plugin/native/intellij-broadcast-rib/src/main/java/com/uber/debug/broadcast/rib/RibHierarchyDebugBroadcastHandler.java
  class RibHierarchyDebugBroadcastHandler (line 56) | public class RibHierarchyDebugBroadcastHandler
    method RibHierarchyDebugBroadcastHandler (line 82) | @SuppressWarnings("RxJavaSubscribeInConstructor")
    method canHandle (line 89) | @Override
    method handle (line 96) | @Override
    method onSubscribe (line 120) | @Override
    method onNext (line 123) | @Override
    method onError (line 156) | @Override
    method onComplete (line 159) | @Override
    method buildRibHierarchyPayload (line 162) | private synchronized RibHierarchyPayload buildRibHierarchyPayload() {
    method buildRibHierarchyPayload (line 166) | private synchronized RibHierarchyPayload buildRibHierarchyPayload(
    method buildRibViewRecursive (line 190) | private synchronized RibView buildRibViewRecursive(
    method buildRibView (line 209) | private synchronized RibView buildRibView(View view) {
    method buildTreeRecursive (line 218) | private synchronized void buildTreeRecursive(
    method getRouterId (line 243) | @Nullable
    method getRouterFromId (line 248) | @Nullable
    method getViewFromId (line 258) | @Nullable
    method getView (line 268) | @Nullable
    method addChild (line 282) | private synchronized void addChild(UUID parentId, UUID childId) {
    method removeChild (line 304) | private synchronized void removeChild(UUID parentId, UUID childId) {
    method setOverlayVisibility (line 328) | private boolean setOverlayVisibility(UUID id, boolean isVisible) {
    method getActivity (line 361) | @Nullable
    method getActivityRecursive (line 376) | @Nullable
    method getCurrentProcessName (line 397) | private static String getCurrentProcessName(Context context) {
    method createRouterIdIfNeeded (line 411) | private UUID createRouterIdIfNeeded(Router router) {
    method createViewIdIfNeeded (line 415) | private UUID createViewIdIfNeeded(View view) {
    method computeUuidIfAbsent (line 419) | private static <T> UUID computeUuidIfAbsent(Map<T, UUID> map, T key) {
    method setTouchOverlayVisibility (line 430) | private void setTouchOverlayVisibility(boolean active) {
    class TargetInfo (line 452) | static class TargetInfo {
      method TargetInfo (line 461) | public TargetInfo(int x, int y) {
      method setNode (line 467) | public void setNode(RibNode node, int depth) {
      method setView (line 472) | public void setView(RibView view, int depth) {
      method nodeId (line 477) | public String nodeId() {
      method viewId (line 481) | public String viewId() {
    class RibTouchOverlayView (line 486) | @SuppressWarnings("UViewExtends")
      method RibTouchOverlayView (line 489) | public RibTouchOverlayView(Context context) {
      method onTouchEvent (line 494) | @Override

FILE: tooling/rib-intellij-plugin/native/intellij-broadcast-rib/src/main/java/com/uber/debug/broadcast/rib/RibHierarchyPayload.java
  class RibHierarchyPayload (line 24) | public class RibHierarchyPayload {
    method RibHierarchyPayload (line 29) | public RibHierarchyPayload(String name, RibApplication application) {
    method getApplication (line 34) | public RibApplication getApplication() {
    class RibApplication (line 38) | public static class RibApplication {
      method RibApplication (line 42) | public RibApplication(String name) {
      method addActivity (line 47) | public void addActivity(RibActivity activity) {
      method getActivities (line 54) | public List<RibActivity> getActivities() {
    class RibActivity (line 59) | public static class RibActivity {
      method RibActivity (line 63) | public RibActivity(Activity activity, RibNode rootRib) {
      method getRootRib (line 68) | public RibNode getRootRib() {
    class RibNode (line 73) | public static class RibNode {
      method RibNode (line 79) | public RibNode(String name, UUID id, @Nullable RibView view) {
      method getName (line 86) | public String getName() {
      method getId (line 90) | public UUID getId() {
      method getChildren (line 94) | public List<RibNode> getChildren() {
      method addChildren (line 98) | public void addChildren(RibNode childNode) {
      method getView (line 102) | @Nullable
    class RibView (line 108) | public static class RibView {
      method RibView (line 115) | public RibView(String name, UUID id, String viewId, String layoutId) {
      method getName (line 123) | public String getName() {
      method getId (line 127) | public UUID getId() {
      method getChildren (line 131) | public List<RibView> getChildren() {
      method addChildren (line 135) | public void addChildren(RibView childNode) {

FILE: tooling/rib-intellij-plugin/native/intellij-broadcast-rib/src/main/java/com/uber/debug/broadcast/rib/RibHierarchyUtils.java
  class RibHierarchyUtils (line 22) | public class RibHierarchyUtils {
    method RibHierarchyUtils (line 24) | private RibHierarchyUtils() {}
    method getFriendlyResourceId (line 33) | static String getFriendlyResourceId(Resources res, int resourceId) {
    method viewIncludesTarget (line 49) | static boolean viewIncludesTarget(View view, int targetX, int targetY) {

FILE: tooling/rib-intellij-plugin/native/intellij-broadcast-rib/src/main/java/com/uber/debug/broadcast/rib/RibHierarchyWithSelectionPayload.java
  class RibHierarchyWithSelectionPayload (line 19) | public class RibHierarchyWithSelectionPayload extends RibHierarchyPayload {
    method RibHierarchyWithSelectionPayload (line 24) | public RibHierarchyWithSelectionPayload(

FILE: tooling/rib-intellij-plugin/src/main/java/com/uber/presidio/intellij_plugin/action/rib/GenerateAction.java
  class GenerateAction (line 54) | public abstract class GenerateAction extends AnAction {
    method suitableTestSourceFolders (line 58) | private static SourceFolder suitableTestSourceFolders(Project project,...
    method createSourceFile (line 82) | private static void createSourceFile(
    method update (line 93) | @Override
    method generate (line 109) | protected void generate(
    method getPackageName (line 156) | protected final String getPackageName() {
    method isAvailable (line 178) | private boolean isAvailable(DataContext dataContext) {
    method checkPackageExists (line 207) | private boolean checkPackageExists(PsiDirectory directory) {

FILE: tooling/rib-intellij-plugin/src/main/java/com/uber/presidio/intellij_plugin/action/rib/GenerateRibAction.java
  class GenerateRibAction (line 24) | public class GenerateRibAction extends GenerateAction implements Generat...
    method actionPerformed (line 26) | @Override
    method onGenerateClicked (line 32) | @Override

FILE: tooling/rib-intellij-plugin/src/main/java/com/uber/presidio/intellij_plugin/action/rib/GenerateRibDialog.java
  class GenerateRibDialog (line 27) | public class GenerateRibDialog extends DialogWrapper {
    method GenerateRibDialog (line 35) | public GenerateRibDialog(final Listener listener) {
    method createCenterPanel (line 44) | @Nullable
    method doOKAction (line 50) | @Override
    type Listener (line 61) | public interface Listener {
      method onGenerateClicked (line 70) | void onGenerateClicked(

FILE: tooling/rib-intellij-plugin/src/main/java/com/uber/presidio/intellij_plugin/action/rib/Generators.java
  class Generators (line 33) | public final class Generators {
    method Generators (line 35) | private Generators() {}
    method getGeneratorsForRibWithPresenterAndView (line 42) | public static GeneratorPair getGeneratorsForRibWithPresenterAndView(
    method getGeneratorsForRibWithoutPresenterAndView (line 69) | public static GeneratorPair getGeneratorsForRibWithoutPresenterAndView(

FILE: tooling/rib-intellij-plugin/src/main/java/com/uber/presidio/intellij_plugin/generator/Generator.java
  class Generator (line 46) | public abstract class Generator {
    method Generator (line 63) | public Generator(String packageName, String ribName, boolean isKotlin,...
    method getClassName (line 113) | public abstract String getClassName();
    method getPackageName (line 118) | public final String getPackageName() {
    method getRibName (line 125) | public final String getRibName() {
    method getFileExtension (line 129) | public final String getFileExtension() {
    method getTemplateValuesMap (line 141) | protected final Map<String, String> getTemplateValuesMap() {
    method generate (line 148) | public final String generate() {
    method getResourceListing (line 166) | String[] getResourceListing(Class clazz, String path) throws URISyntax...

FILE: tooling/rib-intellij-plugin/src/main/java/com/uber/presidio/intellij_plugin/generator/GeneratorPair.java
  class GeneratorPair (line 20) | public class GeneratorPair {
    method GeneratorPair (line 25) | public GeneratorPair(
    method getMainSourceSetGenerators (line 31) | public List<Generator> getMainSourceSetGenerators() {
    method getTestSourceSetGenerators (line 35) | public List<Generator> getTestSourceSetGenerators() {

FILE: tooling/rib-intellij-plugin/src/main/java/com/uber/presidio/intellij_plugin/generator/rib/BuilderGenerator.java
  class BuilderGenerator (line 20) | public class BuilderGenerator extends Generator {
    method BuilderGenerator (line 24) | public BuilderGenerator(String packageName, String ribName, boolean is...
    method getClassName (line 28) | @Override

FILE: tooling/rib-intellij-plugin/src/main/java/com/uber/presidio/intellij_plugin/generator/rib/InteractorWithEmptyPresenterGenerator.java
  class InteractorWithEmptyPresenterGenerator (line 20) | public class InteractorWithEmptyPresenterGenerator extends Generator {
    method InteractorWithEmptyPresenterGenerator (line 24) | public InteractorWithEmptyPresenterGenerator(
    method getClassName (line 29) | @Override

FILE: tooling/rib-intellij-plugin/src/main/java/com/uber/presidio/intellij_plugin/generator/rib/InteractorWithEmptyPresenterTestGenerator.java
  class InteractorWithEmptyPresenterTestGenerator (line 20) | public class InteractorWithEmptyPresenterTestGenerator extends Generator {
    method InteractorWithEmptyPresenterTestGenerator (line 24) | public InteractorWithEmptyPresenterTestGenerator(
    method getClassName (line 29) | @Override

FILE: tooling/rib-intellij-plugin/src/main/java/com/uber/presidio/intellij_plugin/generator/rib/InteractorWithPresenterGenerator.java
  class InteractorWithPresenterGenerator (line 20) | public class InteractorWithPresenterGenerator extends Generator {
    method InteractorWithPresenterGenerator (line 24) | public InteractorWithPresenterGenerator(
    method getClassName (line 30) | @Override

FILE: tooling/rib-intellij-plugin/src/main/java/com/uber/presidio/intellij_plugin/generator/rib/InteractorWithPresenterTestGenerator.java
  class InteractorWithPresenterTestGenerator (line 20) | public class InteractorWithPresenterTestGenerator extends Generator {
    method InteractorWithPresenterTestGenerator (line 24) | public InteractorWithPresenterTestGenerator(
    method getClassName (line 29) | @Override

FILE: tooling/rib-intellij-plugin/src/main/java/com/uber/presidio/intellij_plugin/generator/rib/RouterGenerator.java
  class RouterGenerator (line 20) | public class RouterGenerator extends Generator {
    method RouterGenerator (line 24) | public RouterGenerator(String packageName, String ribName, boolean isK...
    method getClassName (line 28) | @Override

FILE: tooling/rib-intellij-plugin/src/main/java/com/uber/presidio/intellij_plugin/generator/rib/RouterTestGenerator.java
  class RouterTestGenerator (line 20) | public class RouterTestGenerator extends Generator {
    method RouterTestGenerator (line 24) | public RouterTestGenerator(String packageName, String ribName, boolean...
    method getClassName (line 28) | @Override

FILE: tooling/rib-intellij-plugin/src/main/java/com/uber/presidio/intellij_plugin/generator/rib/ViewBuilderGenerator.java
  class ViewBuilderGenerator (line 20) | public class ViewBuilderGenerator extends Generator {
    method ViewBuilderGenerator (line 24) | public ViewBuilderGenerator(String packageName, String ribName, boolea...
    method getClassName (line 28) | @Override

FILE: tooling/rib-intellij-plugin/src/main/java/com/uber/presidio/intellij_plugin/generator/rib/ViewGenerator.java
  class ViewGenerator (line 21) | public class ViewGenerator extends Generator {
    method ViewGenerator (line 25) | public ViewGenerator(String packageName, String ribName, boolean isKot...
    method getClassName (line 29) | @Override

FILE: tooling/rib-intellij-plugin/src/main/java/com/uber/presidio/intellij_plugin/generator/rib/ViewRouterGenerator.java
  class ViewRouterGenerator (line 20) | public class ViewRouterGenerator extends Generator {
    method ViewRouterGenerator (line 24) | public ViewRouterGenerator(String packageName, String ribName, boolean...
    method getClassName (line 28) | @Override

FILE: tooling/rib-intellij-plugin/src/main/java/com/uber/presidio/intellij_plugin/generator/rib/ViewRouterTestGenerator.java
  class ViewRouterTestGenerator (line 20) | public class ViewRouterTestGenerator extends Generator {
    method ViewRouterTestGenerator (line 24) | public ViewRouterTestGenerator(String packageName, String ribName, boo...
    method getClassName (line 28) | @Override

FILE: tooling/rib-intellij-plugin/src/test/java/com/uber/presidio/intellij_plugin/action/rib/RibGeneratorsTest.java
  class RibGeneratorsTest (line 33) | public class RibGeneratorsTest {
    method ribGenerators_shouldGenerateClassesThatCompiler (line 38) | @Test
    method viewRibGenerators_shouldGenerateClassesThatCompile (line 46) | @Test
    method testWithGenerators (line 56) | private static void testWithGenerators(@NonNull GeneratorPair generato...
    method generateSourceFiles (line 69) | private static void generateSourceFiles(

FILE: tooling/utils/intellij-broadcast-core/src/main/java/com/uber/debug/broadcast/core/AckDebugBroadcastHandler.java
  class AckDebugBroadcastHandler (line 23) | public class AckDebugBroadcastHandler implements Handler<String> {
    method AckDebugBroadcastHandler (line 27) | public AckDebugBroadcastHandler() {}
    method canHandle (line 29) | @Override
    method handle (line 34) | @Override

FILE: tooling/utils/intellij-broadcast-core/src/main/java/com/uber/debug/broadcast/core/DebugBroadcastReceiver.java
  class DebugBroadcastReceiver (line 33) | public class DebugBroadcastReceiver extends BroadcastReceiver {
    method initWithDefaults (line 40) | public static void initWithDefaults(Context context, List<Handler> ini...
    method onReceive (line 49) | @Override
    method isAppInForeground (line 73) | private boolean isAppInForeground(Context context) {
    type Handler (line 90) | public interface Handler<T> {
      method canHandle (line 92) | boolean canHandle(DebugBroadcastRequest request);
      method handle (line 94) | void handle(DebugBroadcastRequest request);

FILE: tooling/utils/intellij-broadcast-core/src/main/java/com/uber/debug/broadcast/core/DebugBroadcastRequest.java
  class DebugBroadcastRequest (line 27) | public class DebugBroadcastRequest {
    method DebugBroadcastRequest (line 40) | protected DebugBroadcastRequest(int sequence, @Nullable String command...
    method from (line 50) | static DebugBroadcastRequest from(Intent intent) {
    method getCommand (line 62) | public String getCommand() {
    method isCommand (line 72) | public boolean isCommand(String cmd) {
    method getStringExtra (line 82) | public String getStringExtra(String name) {
    method isValid (line 94) | public boolean isValid() {
    method respond (line 103) | public void respond(Object payload) {
    method error (line 112) | public void error(String description) {
    method getTag (line 122) | static String getTag(int sequence) {
    method writeResponse (line 134) | @SuppressWarnings({"LogCat", "LogConditional"})

FILE: tooling/utils/intellij-broadcast-core/src/main/java/com/uber/debug/broadcast/core/DebugBroadcastResponse.java
  class DebugBroadcastResponse (line 23) | public class DebugBroadcastResponse<T> {
    method DebugBroadcastResponse (line 32) | public DebugBroadcastResponse(T payload) {
    method setErrorDescription (line 39) | public void setErrorDescription(String errorDescription) {
    method getPayload (line 44) | @Nullable

FILE: tutorials/tutorial1/src/main/java/com/uber/rib/RootActivity.java
  class RootActivity (line 24) | public class RootActivity extends RibActivity {
    method createRouter (line 26) | @SuppressWarnings("unchecked")

FILE: tutorials/tutorial1/src/main/java/com/uber/rib/SampleApplication.java
  class SampleApplication (line 20) | public class SampleApplication extends Application {}

FILE: tutorials/tutorial1/src/main/java/com/uber/rib/root/RootBuilder.java
  class RootBuilder (line 32) | public class RootBuilder extends ViewBuilder<RootView, RootRouter, RootB...
    method RootBuilder (line 34) | public RootBuilder(ParentComponent dependency) {
    method build (line 44) | public RootRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 56) | @Override
    type ParentComponent (line 61) | public interface ParentComponent {
    class Module (line 65) | @dagger.Module
      method presenter (line 68) | @RootScope
      method router (line 72) | @RootScope
    type Component (line 79) | @RootScope
      type Builder (line 83) | @dagger.Component.Builder
        method interactor (line 85) | @BindsInstance
        method view (line 88) | @BindsInstance
        method parentComponent (line 91) | Builder parentComponent(ParentComponent component);
        method build (line 93) | Component build();
    type BuilderComponent (line 97) | interface BuilderComponent {
      method rootRouter (line 98) | RootRouter rootRouter();

FILE: tutorials/tutorial1/src/main/java/com/uber/rib/root/RootInteractor.java
  class RootInteractor (line 25) | @RibInteractor
    method didBecomeActive (line 30) | @Override
    type RootPresenter (line 38) | interface RootPresenter {}

FILE: tutorials/tutorial1/src/main/java/com/uber/rib/root/RootRouter.java
  class RootRouter (line 21) | public class RootRouter extends ViewRouter<RootView, RootInteractor> {
    method RootRouter (line 23) | RootRouter(RootView view, RootInteractor interactor, RootBuilder.Compo...

FILE: tutorials/tutorial1/src/main/java/com/uber/rib/root/RootView.java
  class RootView (line 24) | public class RootView extends FrameLayout implements RootInteractor.Root...
    method RootView (line 26) | public RootView(Context context) {
    method RootView (line 30) | public RootView(Context context, @Nullable AttributeSet attrs) {
    method RootView (line 34) | public RootView(Context context, @Nullable AttributeSet attrs, int def...

FILE: tutorials/tutorial1/src/test/java/com/uber/rib/root/RootInteractorTest.java
  class RootInteractorTest (line 22) | @SuppressWarnings("NullAway")
    method setup (line 30) | @Before

FILE: tutorials/tutorial1/src/test/java/com/uber/rib/root/RootRouterTest.java
  class RootRouterTest (line 22) | @SuppressWarnings("NullAway")
    method setup (line 31) | @Before

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/RootActivity.java
  class RootActivity (line 24) | public class RootActivity extends RibActivity {
    method createRouter (line 26) | @SuppressWarnings("unchecked")

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/SampleApplication.java
  class SampleApplication (line 20) | public class SampleApplication extends Application {}

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/RootBuilder.java
  class RootBuilder (line 33) | public class RootBuilder extends ViewBuilder<RootView, RootRouter, RootB...
    method RootBuilder (line 35) | public RootBuilder(ParentComponent dependency) {
    method build (line 45) | public RootRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 57) | @Override
    type ParentComponent (line 62) | public interface ParentComponent {
    class Module (line 66) | @dagger.Module
      method presenter (line 69) | @RootScope
      method router (line 73) | @RootScope
    type Component (line 80) | @RootScope
      type Builder (line 87) | @dagger.Component.Builder
        method interactor (line 89) | @BindsInstance
        method view (line 92) | @BindsInstance
        method parentComponent (line 95) | Builder parentComponent(ParentComponent component);
        method build (line 97) | Component build();
    type BuilderComponent (line 101) | interface BuilderComponent {
      method rootRouter (line 102) | RootRouter rootRouter();

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/RootInteractor.java
  class RootInteractor (line 25) | @RibInteractor
    method didBecomeActive (line 30) | @Override
    type RootPresenter (line 37) | interface RootPresenter {}

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/RootRouter.java
  class RootRouter (line 24) | public class RootRouter extends ViewRouter<RootView, RootInteractor> {
    method RootRouter (line 30) | RootRouter(
    method attachLoggedOut (line 39) | void attachLoggedOut() {
    method attachLoggedIn (line 45) | public void attachLoggedIn() {}
    method detachLoggedOut (line 47) | public void detachLoggedOut() {}

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/RootView.java
  class RootView (line 24) | public class RootView extends FrameLayout implements RootInteractor.Root...
    method RootView (line 26) | public RootView(Context context) {
    method RootView (line 30) | public RootView(Context context, @Nullable AttributeSet attrs) {
    method RootView (line 34) | public RootView(Context context, @Nullable AttributeSet attrs, int def...

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameBuilder.java
  class OffGameBuilder (line 33) | public class OffGameBuilder
    method OffGameBuilder (line 36) | public OffGameBuilder(ParentComponent dependency) {
    method build (line 46) | public OffGameRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 58) | @Override
    type ParentComponent (line 63) | public interface ParentComponent {
      method listener (line 65) | OffGameInteractor.Listener listener();
    class Module (line 68) | @dagger.Module
      method presenter (line 71) | @OffGameScope
      method router (line 75) | @OffGameScope
    type Component (line 83) | @OffGameScope
      type Builder (line 87) | @dagger.Component.Builder
        method interactor (line 90) | @BindsInstance
        method view (line 93) | @BindsInstance
        method parentComponent (line 96) | Builder parentComponent(ParentComponent component);
        method build (line 98) | Component build();
    type BuilderComponent (line 102) | interface BuilderComponent {
      method offgameRouter (line 104) | OffGameRouter offgameRouter();

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameInteractor.java
  class OffGameInteractor (line 27) | @RibInteractor
    method didBecomeActive (line 34) | @Override
    type Listener (line 49) | public interface Listener {
      method onStartGame (line 51) | void onStartGame();
    type OffGamePresenter (line 55) | interface OffGamePresenter {
      method startGameRequest (line 57) | Observable<Object> startGameRequest();

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameRouter.java
  class OffGameRouter (line 21) | public class OffGameRouter extends ViewRouter<OffGameView, OffGameIntera...
    method OffGameRouter (line 23) | public OffGameRouter(

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameView.java
  class OffGameView (line 29) | public class OffGameView extends LinearLayout implements OffGameInteract...
    method OffGameView (line 33) | public OffGameView(Context context) {
    method OffGameView (line 37) | public OffGameView(Context context, @Nullable AttributeSet attrs) {
    method OffGameView (line 41) | public OffGameView(Context context, @Nullable AttributeSet attrs, int ...
    method onFinishInflate (line 45) | @Initializer
    method startGameRequest (line 52) | @Override

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/loggedin/tictactoe/Board.java
  class Board (line 20) | class Board {
    method Board (line 29) | @Inject
    method isDraw (line 40) | boolean isDraw() {
    method hasWon (line 52) | boolean hasWon(MarkerType theSeed) {
    type MarkerType (line 69) | enum MarkerType {

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/loggedin/tictactoe/BoardCoordinate.java
  class BoardCoordinate (line 18) | class BoardCoordinate {
    method BoardCoordinate (line 23) | BoardCoordinate(int x, int y) {
    method getX (line 28) | int getX() {
    method getY (line 32) | int getY() {

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeBuilder.java
  class TicTacToeBuilder (line 33) | public class TicTacToeBuilder
    method TicTacToeBuilder (line 36) | public TicTacToeBuilder(ParentComponent dependency) {
    method build (line 46) | public TicTacToeRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 58) | @Override
    type ParentComponent (line 63) | public interface ParentComponent {
    class Module (line 67) | @dagger.Module
      method presenter (line 70) | @TicTacToeScope
      method router (line 74) | @TicTacToeScope
    type Component (line 82) | @TicTacToeScope
      type Builder (line 86) | @dagger.Component.Builder
        method interactor (line 89) | @BindsInstance
        method view (line 92) | @BindsInstance
        method parentComponent (line 95) | Builder parentComponent(ParentComponent component);
        method build (line 97) | Component build();
    type BuilderComponent (line 101) | interface BuilderComponent {
      method tictactoeRouter (line 103) | TicTacToeRouter tictactoeRouter();

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeInteractor.java
  class TicTacToeInteractor (line 28) | @RibInteractor
    method didBecomeActive (line 40) | @Override
    method updateCurrentPlayer (line 79) | private void updateCurrentPlayer() {
    type TicTacToePresenter (line 88) | interface TicTacToePresenter {
      method squareClicks (line 89) | Observable<BoardCoordinate> squareClicks();
      method setCurrentPlayerName (line 91) | void setCurrentPlayerName(String currentPlayer);
      method setPlayerWon (line 93) | void setPlayerWon(String playerName);
      method setPlayerTie (line 95) | void setPlayerTie();
      method addCross (line 97) | void addCross(BoardCoordinate xy);
      method addNought (line 99) | void addNought(BoardCoordinate xy);
    type Listener (line 102) | public interface Listener {}

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeRouter.java
  class TicTacToeRouter (line 21) | public class TicTacToeRouter extends ViewRouter<TicTacToeView, TicTacToe...
    method TicTacToeRouter (line 23) | public TicTacToeRouter(

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeView.java
  class TicTacToeView (line 31) | public class TicTacToeView extends PercentRelativeLayout
    method TicTacToeView (line 37) | public TicTacToeView(Context context) {
    method TicTacToeView (line 41) | public TicTacToeView(Context context, @Nullable AttributeSet attrs) {
    method TicTacToeView (line 45) | public TicTacToeView(Context context, @Nullable AttributeSet attrs, in...
    method onFinishInflate (line 49) | @Initializer
    method squareClicks (line 75) | @Override
    method addCross (line 96) | @Override
    method addNought (line 103) | @Override
    method setCurrentPlayerName (line 110) | @Override
    method setPlayerWon (line 115) | @Override
    method setPlayerTie (line 120) | @Override

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/loggedout/LoggedOutBuilder.java
  class LoggedOutBuilder (line 33) | public class LoggedOutBuilder
    method LoggedOutBuilder (line 36) | public LoggedOutBuilder(ParentComponent dependency) {
    method build (line 46) | public LoggedOutRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 58) | @Override
    type ParentComponent (line 63) | public interface ParentComponent {
    class Module (line 67) | @dagger.Module
      method presenter (line 70) | @LoggedOutScope
      method router (line 74) | @LoggedOutScope
    type Component (line 84) | @LoggedOutScope
      type Builder (line 88) | @dagger.Component.Builder
        method interactor (line 90) | @BindsInstance
        method view (line 93) | @BindsInstance
        method parentComponent (line 96) | Builder parentComponent(ParentComponent component);
        method build (line 98) | Component build();
    type BuilderComponent (line 102) | interface BuilderComponent {
      method loggedoutRouter (line 103) | LoggedOutRouter loggedoutRouter();

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/loggedout/LoggedOutInteractor.java
  class LoggedOutInteractor (line 29) | @RibInteractor
    method didBecomeActive (line 35) | @Override
    type LoggedOutPresenter (line 50) | interface LoggedOutPresenter {
      method loginName (line 51) | Observable<String> loginName();

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/loggedout/LoggedOutRouter.java
  class LoggedOutRouter (line 21) | public class LoggedOutRouter extends ViewRouter<LoggedOutView, LoggedOut...
    method LoggedOutRouter (line 23) | public LoggedOutRouter(

FILE: tutorials/tutorial2/src/main/java/com/uber/rib/root/loggedout/LoggedOutView.java
  class LoggedOutView (line 29) | public class LoggedOutView extends LinearLayout implements LoggedOutInte...
    method LoggedOutView (line 31) | public LoggedOutView(Context context) {
    method LoggedOutView (line 35) | public LoggedOutView(Context context, @Nullable AttributeSet attrs) {
    method LoggedOutView (line 39) | public LoggedOutView(Context context, @Nullable AttributeSet attrs, in...
    method loginName (line 43) | @Override

FILE: tutorials/tutorial2/src/test/java/com/uber/rib/root/RootInteractorTest.java
  class RootInteractorTest (line 22) | @SuppressWarnings("NullAway")
    method setup (line 30) | @Before

FILE: tutorials/tutorial2/src/test/java/com/uber/rib/root/RootRouterTest.java
  class RootRouterTest (line 23) | @SuppressWarnings("NullAway")
    method setup (line 32) | @Before

FILE: tutorials/tutorial2/src/test/java/com/uber/rib/root/loggedout/LoggedOutInteractorTest.java
  class LoggedOutInteractorTest (line 24) | @SuppressWarnings("NullAway")
    method setup (line 32) | @Before
    method anExampleTest_withSomeConditions_shouldPass (line 40) | @Test

FILE: tutorials/tutorial2/src/test/java/com/uber/rib/root/loggedout/LoggedOutRouterTest.java
  class LoggedOutRouterTest (line 23) | @SuppressWarnings("NullAway")
    method setup (line 32) | @Before

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/RootActivity.java
  class RootActivity (line 24) | public class RootActivity extends RibActivity {
    method createRouter (line 26) | @SuppressWarnings("unchecked")

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/SampleApplication.java
  class SampleApplication (line 20) | public class SampleApplication extends Application {}

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/RootBuilder.java
  class RootBuilder (line 35) | public class RootBuilder extends ViewBuilder<RootView, RootRouter, RootB...
    method RootBuilder (line 37) | public RootBuilder(ParentComponent dependency) {
    method build (line 47) | public RootRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 59) | @Override
    type ParentComponent (line 64) | public interface ParentComponent {
    class Module (line 68) | @dagger.Module
      method loggedOutListener (line 71) | @RootScope
      method presenter (line 77) | @RootScope
      method router (line 81) | @RootScope
    type Component (line 93) | @RootScope
      type Builder (line 101) | @dagger.Component.Builder
        method interactor (line 104) | @BindsInstance
        method view (line 107) | @BindsInstance
        method parentComponent (line 110) | Builder parentComponent(ParentComponent component);
        method build (line 112) | Component build();
    type BuilderComponent (line 116) | interface BuilderComponent {
      method rootRouter (line 118) | RootRouter rootRouter();

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/RootInteractor.java
  class RootInteractor (line 26) | @RibInteractor
    method didBecomeActive (line 31) | @Override
    class LoggedOutListener (line 37) | class LoggedOutListener implements LoggedOutInteractor.Listener {
      method requestLogin (line 39) | @Override
    type RootPresenter (line 48) | interface RootPresenter {}

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/RootRouter.java
  class RootRouter (line 25) | public class RootRouter extends ViewRouter<RootView, RootInteractor> {
    method RootRouter (line 31) | RootRouter(
    method attachLoggedOut (line 42) | void attachLoggedOut() {
    method detachLoggedOut (line 48) | void detachLoggedOut() {
    method attachLoggedIn (line 56) | void attachLoggedIn(String playerOne, String playerTwo) {

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/RootView.java
  class RootView (line 24) | public class RootView extends FrameLayout implements RootInteractor.Root...
    method RootView (line 26) | public RootView(Context context) {
    method RootView (line 30) | public RootView(Context context, @Nullable AttributeSet attrs) {
    method RootView (line 34) | public RootView(Context context, @Nullable AttributeSet attrs, int def...

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedin/LoggedInBuilder.java
  class LoggedInBuilder (line 36) | public class LoggedInBuilder extends Builder<LoggedInRouter, LoggedInBui...
    method LoggedInBuilder (line 38) | public LoggedInBuilder(ParentComponent dependency) {
    method build (line 47) | public LoggedInRouter build(String playerOne, String playerTwo) {
    type ParentComponent (line 60) | public interface ParentComponent {
      method rootView (line 62) | RootView rootView();
    class Module (line 65) | @dagger.Module
      method presenter (line 68) | @LoggedInScope
      method router (line 74) | @LoggedInScope
      method mutableScoreStream (line 86) | @LoggedInScope
      method listener (line 94) | @LoggedInScope
      method ticTacToeListener (line 100) | @LoggedInScope
      method scoreStream (line 106) | @LoggedInScope
    type Component (line 111) | @LoggedInScope
      type Builder (line 119) | @dagger.Component.Builder
        method interactor (line 122) | @BindsInstance
        method parentComponent (line 125) | Builder parentComponent(ParentComponent component);
        method build (line 127) | Component build();
        method playerOne (line 129) | @BindsInstance
        method playerTwo (line 132) | @BindsInstance
    type BuilderComponent (line 137) | interface BuilderComponent {
      method loggedinRouter (line 139) | LoggedInRouter loggedinRouter();

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedin/LoggedInInteractor.java
  class LoggedInInteractor (line 28) | @RibInteractor
    method didBecomeActive (line 33) | @Override
    method willResignActive (line 41) | @Override
    class OffGameListener (line 48) | class OffGameListener implements OffGameInteractor.Listener {
      method onStartGame (line 50) | @Override
    class TicTacToeListener (line 57) | class TicTacToeListener implements TicTacToeInteractor.Listener {
      method gameWon (line 59) | @Override

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedin/LoggedInRouter.java
  class LoggedInRouter (line 26) | public class LoggedInRouter extends Router<LoggedInInteractor> {
    method LoggedInRouter (line 34) | LoggedInRouter(
    method willDetach (line 46) | @Override
    method attachOffGame (line 53) | void attachOffGame() {
    method detachOffGame (line 59) | void detachOffGame() {
    method attachTicTacToe (line 67) | void attachTicTacToe() {
    method detachTicTacToe (line 73) | void detachTicTacToe() {

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedin/MutableScoreStream.java
  class MutableScoreStream (line 23) | class MutableScoreStream implements ScoreStream {
    method MutableScoreStream (line 27) | MutableScoreStream(String playerOne, String playerTwo) {
    method addVictory (line 31) | void addVictory(String userName) {
    method scores (line 46) | @Override

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedin/ScoreStream.java
  type ScoreStream (line 21) | public interface ScoreStream {
    method scores (line 22) | Observable<ImmutableMap<String, Integer>> scores();

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameBuilder.java
  class OffGameBuilder (line 35) | public class OffGameBuilder
    method OffGameBuilder (line 38) | public OffGameBuilder(ParentComponent dependency) {
    method build (line 48) | public OffGameRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 60) | @Override
    type ParentComponent (line 65) | public interface ParentComponent {
      method playerOne (line 67) | @Named("player_one")
      method playerTwo (line 70) | @Named("player_two")
      method listener (line 73) | OffGameInteractor.Listener listener();
      method scoreStream (line 75) | ScoreStream scoreStream();
    class Module (line 78) | @dagger.Module
      method presenter (line 81) | @OffGameScope
      method router (line 85) | @OffGameScope
    type Component (line 93) | @OffGameScope
      type Builder (line 97) | @dagger.Component.Builder
        method interactor (line 100) | @BindsInstance
        method view (line 103) | @BindsInstance
        method parentComponent (line 106) | Builder parentComponent(ParentComponent component);
        method build (line 108) | Component build();
    type BuilderComponent (line 112) | interface BuilderComponent {
      method offgameRouter (line 114) | OffGameRouter offgameRouter();

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameInteractor.java
  class OffGameInteractor (line 31) | @RibInteractor
    method didBecomeActive (line 47) | @Override
    type Listener (line 76) | public interface Listener {
      method onStartGame (line 78) | void onStartGame();
    type OffGamePresenter (line 82) | interface OffGamePresenter {
      method setPlayerNames (line 84) | void setPlayerNames(String playerOne, String playerTwo);
      method setScores (line 86) | void setScores(Integer playerOneScore, Integer playerTwoScore);
      method startGameRequest (line 88) | Observable<Object> startGameRequest();

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameRouter.java
  class OffGameRouter (line 21) | public class OffGameRouter extends ViewRouter<OffGameView, OffGameIntera...
    method OffGameRouter (line 23) | public OffGameRouter(

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameView.java
  class OffGameView (line 31) | public class OffGameView extends LinearLayout implements OffGameInteract...
    method OffGameView (line 39) | public OffGameView(Context context) {
    method OffGameView (line 43) | public OffGameView(Context context, @Nullable AttributeSet attrs) {
    method OffGameView (line 47) | public OffGameView(Context context, @Nullable AttributeSet attrs, int ...
    method onFinishInflate (line 51) | @Initializer
    method setPlayerNames (line 62) | @Override
    method setScores (line 68) | @Override
    method startGameRequest (line 76) | @Override

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedin/tictactoe/Board.java
  class Board (line 20) | class Board {
    method Board (line 29) | @Inject
    method isDraw (line 40) | boolean isDraw() {
    method hasWon (line 52) | boolean hasWon(MarkerType theSeed) {
    type MarkerType (line 69) | enum MarkerType {

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedin/tictactoe/BoardCoordinate.java
  class BoardCoordinate (line 18) | class BoardCoordinate {
    method BoardCoordinate (line 23) | BoardCoordinate(int x, int y) {
    method getX (line 28) | int getX() {
    method getY (line 32) | int getY() {

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeBuilder.java
  class TicTacToeBuilder (line 34) | public class TicTacToeBuilder
    method TicTacToeBuilder (line 37) | public TicTacToeBuilder(ParentComponent dependency) {
    method build (line 47) | public TicTacToeRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 59) | @Override
    type ParentComponent (line 64) | public interface ParentComponent {
      method ticTacToeListener (line 66) | TicTacToeInteractor.Listener ticTacToeListener();
      method playerOne (line 68) | @Named("player_one")
      method playerTwo (line 71) | @Named("player_two")
    class Module (line 75) | @dagger.Module
      method presenter (line 78) | @TicTacToeScope
      method router (line 82) | @TicTacToeScope
    type Component (line 90) | @TicTacToeScope
      type Builder (line 94) | @dagger.Component.Builder
        method interactor (line 97) | @BindsInstance
        method view (line 100) | @BindsInstance
        method parentComponent (line 103) | Builder parentComponent(ParentComponent component);
        method build (line 105) | Component build();
    type BuilderComponent (line 109) | interface BuilderComponent {
      method tictactoeRouter (line 111) | TicTacToeRouter tictactoeRouter();

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeInteractor.java
  class TicTacToeInteractor (line 29) | @RibInteractor
    method didBecomeActive (line 47) | @Override
    method updateCurrentPlayer (line 89) | private void updateCurrentPlayer() {
    type TicTacToePresenter (line 98) | interface TicTacToePresenter {
      method squareClicks (line 99) | Observable<BoardCoordinate> squareClicks();
      method setCurrentPlayerName (line 101) | void setCurrentPlayerName(String currentPlayer);
      method setPlayerWon (line 103) | void setPlayerWon(String playerName);
      method setPlayerTie (line 105) | void setPlayerTie();
      method addCross (line 107) | void addCross(BoardCoordinate xy);
      method addNought (line 109) | void addNought(BoardCoordinate xy);
    type Listener (line 112) | public interface Listener {
      method gameWon (line 119) | void gameWon(@Nullable String winner);

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeRouter.java
  class TicTacToeRouter (line 21) | public class TicTacToeRouter extends ViewRouter<TicTacToeView, TicTacToe...
    method TicTacToeRouter (line 23) | public TicTacToeRouter(

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeView.java
  class TicTacToeView (line 31) | public class TicTacToeView extends PercentRelativeLayout
    method TicTacToeView (line 37) | public TicTacToeView(Context context) {
    method TicTacToeView (line 41) | public TicTacToeView(Context context, @Nullable AttributeSet attrs) {
    method TicTacToeView (line 45) | public TicTacToeView(Context context, @Nullable AttributeSet attrs, in...
    method onFinishInflate (line 49) | @Initializer
    method squareClicks (line 75) | @Override
    method addCross (line 96) | @Override
    method addNought (line 103) | @Override
    method setCurrentPlayerName (line 110) | @Override
    method setPlayerWon (line 115) | @Override
    method setPlayerTie (line 120) | @Override

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedout/LoggedOutBuilder.java
  class LoggedOutBuilder (line 33) | public class LoggedOutBuilder
    method LoggedOutBuilder (line 36) | public LoggedOutBuilder(ParentComponent dependency) {
    method build (line 46) | public LoggedOutRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 58) | @Override
    type ParentComponent (line 63) | public interface ParentComponent {
      method listener (line 65) | LoggedOutInteractor.Listener listener();
    class Module (line 68) | @dagger.Module
      method presenter (line 71) | @LoggedOutScope
      method router (line 75) | @LoggedOutScope
    type Component (line 85) | @LoggedOutScope
      type Builder (line 89) | @dagger.Component.Builder
        method interactor (line 92) | @BindsInstance
        method view (line 95) | @BindsInstance
        method parentComponent (line 98) | Builder parentComponent(ParentComponent component);
        method build (line 100) | Component build();
    type BuilderComponent (line 104) | interface BuilderComponent {
      method loggedoutRouter (line 106) | LoggedOutRouter loggedoutRouter();

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedout/LoggedOutInteractor.java
  class LoggedOutInteractor (line 29) | @RibInteractor
    method didBecomeActive (line 36) | @Override
    method isEmpty (line 52) | private boolean isEmpty(@Nullable String string) {
    type LoggedOutPresenter (line 57) | interface LoggedOutPresenter {
      method playerNames (line 59) | Observable<Pair<String, String>> playerNames();
    type Listener (line 62) | public interface Listener {
      method requestLogin (line 64) | void requestLogin(String playerOne, String playerTwo);

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedout/LoggedOutRouter.java
  class LoggedOutRouter (line 21) | public class LoggedOutRouter extends ViewRouter<LoggedOutView, LoggedOut...
    method LoggedOutRouter (line 23) | public LoggedOutRouter(

FILE: tutorials/tutorial3-completed/src/main/java/com/uber/rib/root/loggedout/LoggedOutView.java
  class LoggedOutView (line 32) | public class LoggedOutView extends LinearLayout implements LoggedOutInte...
    method LoggedOutView (line 38) | public LoggedOutView(Context context) {
    method LoggedOutView (line 42) | public LoggedOutView(Context context, @Nullable AttributeSet attrs) {
    method LoggedOutView (line 46) | public LoggedOutView(Context context, @Nullable AttributeSet attrs, in...
    method onFinishInflate (line 50) | @Initializer
    method playerNames (line 59) | @Override

FILE: tutorials/tutorial3-completed/src/test/java/com/uber/rib/root/RootInteractorTest.java
  class RootInteractorTest (line 22) | public class RootInteractorTest {
    method setup (line 29) | @Before

FILE: tutorials/tutorial3-completed/src/test/java/com/uber/rib/root/RootRouterTest.java
  class RootRouterTest (line 24) | public class RootRouterTest {
    method setup (line 32) | @Before

FILE: tutorials/tutorial3-completed/src/test/java/com/uber/rib/root/loggedin/LoggedInInteractorTest.java
  class LoggedInInteractorTest (line 24) | public class LoggedInInteractorTest extends RibTestBasePlaceholder {
    method setup (line 32) | @Before

FILE: tutorials/tutorial3-completed/src/test/java/com/uber/rib/root/loggedin/LoggedInRouterTest.java
  class LoggedInRouterTest (line 26) | public class LoggedInRouterTest extends RibTestBasePlaceholder {
    method setup (line 36) | @Before

FILE: tutorials/tutorial3-completed/src/test/java/com/uber/rib/root/loggedin/offgame/OffGameInteractorTest.java
  class OffGameInteractorTest (line 24) | public class OffGameInteractorTest extends RibTestBasePlaceholder {
    method setup (line 36) | @Before

FILE: tutorials/tutorial3-completed/src/test/java/com/uber/rib/root/loggedin/offgame/OffGameRouterTest.java
  class OffGameRouterTest (line 23) | public class OffGameRouterTest extends RibTestBasePlaceholder {
    method setup (line 31) | @Before

FILE: tutorials/tutorial3-completed/src/test/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeInteractorTest.java
  class TicTacToeInteractorTest (line 23) | public class TicTacToeInteractorTest extends RibTestBasePlaceholder {
    method setup (line 35) | @Before

FILE: tutorials/tutorial3-completed/src/test/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeRouterTest.java
  class TicTacToeRouterTest (line 23) | public class TicTacToeRouterTest extends RibTestBasePlaceholder {
    method setup (line 31) | @Before

FILE: tutorials/tutorial3-completed/src/test/java/com/uber/rib/root/loggedout/LoggedOutInteractorTest.java
  class LoggedOutInteractorTest (line 32) | public class LoggedOutInteractorTest extends RibTestBasePlaceholder {
    method setup (line 40) | @Before
    method attach_whenViewEmitsName_shouldCallListener (line 47) | @Test
    method attach_whenViewEmitsEmptyName_shouldNotCallListener (line 58) | @Test

FILE: tutorials/tutorial3-completed/src/test/java/com/uber/rib/root/loggedout/LoggedOutRouterTest.java
  class LoggedOutRouterTest (line 23) | public class LoggedOutRouterTest extends RibTestBasePlaceholder {
    method setup (line 31) | @Before

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/RootActivity.java
  class RootActivity (line 24) | public class RootActivity extends RibActivity {
    method createRouter (line 26) | @SuppressWarnings("unchecked")

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/SampleApplication.java
  class SampleApplication (line 20) | public class SampleApplication extends Application {}

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/RootBuilder.java
  class RootBuilder (line 35) | public class RootBuilder extends ViewBuilder<RootView, RootRouter, RootB...
    method RootBuilder (line 37) | public RootBuilder(ParentComponent dependency) {
    method build (line 47) | public RootRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 59) | @Override
    type ParentComponent (line 64) | public interface ParentComponent {
    class Module (line 68) | @dagger.Module
      method loggedOutListener (line 71) | @RootScope
      method presenter (line 77) | @RootScope
      method router (line 81) | @RootScope
    type Component (line 93) | @RootScope
      type Builder (line 101) | @dagger.Component.Builder
        method interactor (line 104) | @BindsInstance
        method view (line 107) | @BindsInstance
        method parentComponent (line 110) | Builder parentComponent(ParentComponent component);
        method build (line 112) | Component build();
    type BuilderComponent (line 116) | interface BuilderComponent {
      method rootRouter (line 118) | RootRouter rootRouter();

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/RootInteractor.java
  class RootInteractor (line 26) | @RibInteractor
    method didBecomeActive (line 31) | @Override
    class LoggedOutListener (line 37) | class LoggedOutListener implements LoggedOutInteractor.Listener {
      method login (line 39) | @Override
    type RootPresenter (line 48) | interface RootPresenter {}

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/RootRouter.java
  class RootRouter (line 25) | public class RootRouter extends ViewRouter<RootView, RootInteractor> {
    method RootRouter (line 31) | RootRouter(
    method attachLoggedOut (line 42) | void attachLoggedOut() {
    method detachLoggedOut (line 48) | void detachLoggedOut() {
    method attachLoggedIn (line 56) | void attachLoggedIn() {

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/RootView.java
  class RootView (line 24) | public class RootView extends FrameLayout implements RootInteractor.Root...
    method RootView (line 26) | public RootView(Context context) {
    method RootView (line 30) | public RootView(Context context, @Nullable AttributeSet attrs) {
    method RootView (line 34) | public RootView(Context context, @Nullable AttributeSet attrs, int def...

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/loggedin/LoggedInBuilder.java
  class LoggedInBuilder (line 33) | public class LoggedInBuilder extends Builder<LoggedInRouter, LoggedInBui...
    method LoggedInBuilder (line 35) | public LoggedInBuilder(ParentComponent dependency) {
    method build (line 44) | public LoggedInRouter build() {
    type ParentComponent (line 55) | public interface ParentComponent {
      method rootView (line 57) | RootView rootView();
    class Module (line 60) | @dagger.Module
      method presenter (line 63) | @LoggedInScope
      method router (line 69) | @LoggedInScope
      method listener (line 81) | @LoggedInScope
    type Component (line 88) | @LoggedInScope
      type Builder (line 96) | @dagger.Component.Builder
        method interactor (line 99) | @BindsInstance
        method parentComponent (line 102) | Builder parentComponent(ParentComponent component);
        method build (line 104) | Component build();
    type BuilderComponent (line 108) | interface BuilderComponent {
      method loggedinRouter (line 110) | LoggedInRouter loggedinRouter();

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/loggedin/LoggedInInteractor.java
  class LoggedInInteractor (line 26) | @RibInteractor
    method didBecomeActive (line 29) | @Override
    class OffGameListener (line 37) | class OffGameListener implements OffGameInteractor.Listener {
      method onStartGame (line 39) | @Override

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/loggedin/LoggedInRouter.java
  class LoggedInRouter (line 26) | public class LoggedInRouter extends Router<LoggedInInteractor> {
    method LoggedInRouter (line 34) | LoggedInRouter(
    method willDetach (line 46) | @Override
    method attachOffGame (line 53) | void attachOffGame() {
    method detachOffGame (line 59) | void detachOffGame() {
    method attachTicTacToe (line 67) | void attachTicTacToe() {
    method detachTicTacToe (line 73) | void detachTicTacToe() {

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameBuilder.java
  class OffGameBuilder (line 33) | public class OffGameBuilder
    method OffGameBuilder (line 36) | public OffGameBuilder(ParentComponent dependency) {
    method build (line 46) | public OffGameRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 58) | @Override
    type ParentComponent (line 63) | public interface ParentComponent {
      method listener (line 65) | OffGameInteractor.Listener listener();
    class Module (line 68) | @dagger.Module
      method presenter (line 71) | @OffGameScope
      method router (line 75) | @OffGameScope
    type Component (line 83) | @OffGameScope
      type Builder (line 87) | @dagger.Component.Builder
        method interactor (line 90) | @BindsInstance
        method view (line 93) | @BindsInstance
        method parentComponent (line 96) | Builder parentComponent(ParentComponent component);
        method build (line 98) | Component build();
    type BuilderComponent (line 102) | interface BuilderComponent {
      method offgameRouter (line 104) | OffGameRouter offgameRouter();

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameInteractor.java
  class OffGameInteractor (line 27) | @RibInteractor
    method didBecomeActive (line 34) | @Override
    type Listener (line 49) | public interface Listener {
      method onStartGame (line 51) | void onStartGame();
    type OffGamePresenter (line 55) | interface OffGamePresenter {
      method startGameRequest (line 57) | Observable<Object> startGameRequest();

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameRouter.java
  class OffGameRouter (line 21) | public class OffGameRouter extends ViewRouter<OffGameView, OffGameIntera...
    method OffGameRouter (line 23) | public OffGameRouter(

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameView.java
  class OffGameView (line 30) | public class OffGameView extends LinearLayout implements OffGameInteract...
    method OffGameView (line 38) | public OffGameView(Context context) {
    method OffGameView (line 42) | public OffGameView(Context context, @Nullable AttributeSet attrs) {
    method OffGameView (line 46) | public OffGameView(Context context, @Nullable AttributeSet attrs, int ...
    method onFinishInflate (line 50) | @Initializer
    method startGameRequest (line 61) | @Override

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/loggedin/tictactoe/Board.java
  class Board (line 20) | class Board {
    method Board (line 29) | @Inject
    method isDraw (line 40) | boolean isDraw() {
    method hasWon (line 52) | boolean hasWon(MarkerType theSeed) {
    type MarkerType (line 69) | enum MarkerType {

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/loggedin/tictactoe/BoardCoordinate.java
  class BoardCoordinate (line 18) | class BoardCoordinate {
    method BoardCoordinate (line 23) | BoardCoordinate(int x, int y) {
    method getX (line 28) | int getX() {
    method getY (line 32) | int getY() {

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeBuilder.java
  class TicTacToeBuilder (line 33) | public class TicTacToeBuilder
    method TicTacToeBuilder (line 36) | public TicTacToeBuilder(ParentComponent dependency) {
    method build (line 46) | public TicTacToeRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 58) | @Override
    type ParentComponent (line 63) | public interface ParentComponent {
    class Module (line 67) | @dagger.Module
      method presenter (line 70) | @TicTacToeScope
      method router (line 74) | @TicTacToeScope
    type Component (line 82) | @TicTacToeScope
      type Builder (line 86) | @dagger.Component.Builder
        method interactor (line 89) | @BindsInstance
        method view (line 92) | @BindsInstance
        method parentComponent (line 95) | Builder parentComponent(ParentComponent component);
        method build (line 97) | Component build();
    type BuilderComponent (line 101) | interface BuilderComponent {
      method tictactoeRouter (line 103) | TicTacToeRouter tictactoeRouter();

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeInteractor.java
  class TicTacToeInteractor (line 28) | @RibInteractor
    method didBecomeActive (line 40) | @Override
    method updateCurrentPlayer (line 79) | private void updateCurrentPlayer() {
    type TicTacToePresenter (line 88) | interface TicTacToePresenter {
      method squareClicks (line 89) | Observable<BoardCoordinate> squareClicks();
      method setCurrentPlayerName (line 91) | void setCurrentPlayerName(String currentPlayer);
      method setPlayerWon (line 93) | void setPlayerWon(String playerName);
      method setPlayerTie (line 95) | void setPlayerTie();
      method addCross (line 97) | void addCross(BoardCoordinate xy);
      method addNought (line 99) | void addNought(BoardCoordinate xy);
    type Listener (line 102) | public interface Listener {}

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeRouter.java
  class TicTacToeRouter (line 21) | public class TicTacToeRouter extends ViewRouter<TicTacToeView, TicTacToe...
    method TicTacToeRouter (line 23) | public TicTacToeRouter(

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeView.java
  class TicTacToeView (line 31) | public class TicTacToeView extends PercentRelativeLayout
    method TicTacToeView (line 37) | public TicTacToeView(Context context) {
    method TicTacToeView (line 41) | public TicTacToeView(Context context, @Nullable AttributeSet attrs) {
    method TicTacToeView (line 45) | public TicTacToeView(Context context, @Nullable AttributeSet attrs, in...
    method onFinishInflate (line 49) | @Initializer
    method squareClicks (line 75) | @Override
    method addCross (line 96) | @Override
    method addNought (line 103) | @Override
    method setCurrentPlayerName (line 110) | @Override
    method setPlayerWon (line 115) | @Override
    method setPlayerTie (line 120) | @Override

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/loggedout/LoggedOutBuilder.java
  class LoggedOutBuilder (line 33) | public class LoggedOutBuilder
    method LoggedOutBuilder (line 36) | public LoggedOutBuilder(ParentComponent dependency) {
    method build (line 46) | public LoggedOutRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 58) | @Override
    type ParentComponent (line 63) | public interface ParentComponent {
      method listener (line 65) | LoggedOutInteractor.Listener listener();
    class Module (line 68) | @dagger.Module
      method presenter (line 71) | @LoggedOutScope
      method router (line 75) | @LoggedOutScope
    type Component (line 85) | @LoggedOutScope
      type Builder (line 89) | @dagger.Component.Builder
        method interactor (line 92) | @BindsInstance
        method view (line 95) | @BindsInstance
        method parentComponent (line 98) | Builder parentComponent(ParentComponent component);
        method build (line 100) | Component build();
    type BuilderComponent (line 104) | interface BuilderComponent {
      method loggedoutRouter (line 106) | LoggedOutRouter loggedoutRouter();

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/loggedout/LoggedOutInteractor.java
  class LoggedOutInteractor (line 29) | @RibInteractor
    method didBecomeActive (line 36) | @Override
    method isEmpty (line 52) | private boolean isEmpty(@Nullable String string) {
    type LoggedOutPresenter (line 57) | interface LoggedOutPresenter {
      method loginName (line 59) | Observable<Pair<String, String>> loginName();
    type Listener (line 62) | public interface Listener {
      method login (line 63) | void login(String userNameA, String userNameB);

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/loggedout/LoggedOutRouter.java
  class LoggedOutRouter (line 21) | public class LoggedOutRouter extends ViewRouter<LoggedOutView, LoggedOut...
    method LoggedOutRouter (line 23) | public LoggedOutRouter(

FILE: tutorials/tutorial3/src/main/java/com/uber/rib/root/loggedout/LoggedOutView.java
  class LoggedOutView (line 30) | public class LoggedOutView extends LinearLayout implements LoggedOutInte...
    method LoggedOutView (line 32) | public LoggedOutView(Context context) {
    method LoggedOutView (line 36) | public LoggedOutView(Context context, @Nullable AttributeSet attrs) {
    method LoggedOutView (line 40) | public LoggedOutView(Context context, @Nullable AttributeSet attrs, in...
    method loginName (line 44) | @Override

FILE: tutorials/tutorial3/src/test/java/com/uber/rib/root/RootInteractorTest.java
  class RootInteractorTest (line 22) | public class RootInteractorTest {
    method setup (line 29) | @Before

FILE: tutorials/tutorial3/src/test/java/com/uber/rib/root/RootRouterTest.java
  class RootRouterTest (line 24) | public class RootRouterTest {
    method setup (line 32) | @Before

FILE: tutorials/tutorial3/src/test/java/com/uber/rib/root/loggedin/LoggedInInteractorTest.java
  class LoggedInInteractorTest (line 24) | public class LoggedInInteractorTest extends RibTestBasePlaceholder {
    method setup (line 31) | @Before

FILE: tutorials/tutorial3/src/test/java/com/uber/rib/root/loggedin/LoggedInRouterTest.java
  class LoggedInRouterTest (line 26) | public class LoggedInRouterTest extends RibTestBasePlaceholder {
    method setup (line 36) | @Before

FILE: tutorials/tutorial3/src/test/java/com/uber/rib/root/loggedin/offgame/OffGameInteractorTest.java
  class OffGameInteractorTest (line 23) | public class OffGameInteractorTest extends RibTestBasePlaceholder {
    method setup (line 31) | @Before

FILE: tutorials/tutorial3/src/test/java/com/uber/rib/root/loggedin/offgame/OffGameRouterTest.java
  class OffGameRouterTest (line 23) | public class OffGameRouterTest extends RibTestBasePlaceholder {
    method setup (line 31) | @Before

FILE: tutorials/tutorial3/src/test/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeInteractorTest.java
  class TicTacToeInteractorTest (line 23) | public class TicTacToeInteractorTest extends RibTestBasePlaceholder {
    method setup (line 31) | @Before

FILE: tutorials/tutorial3/src/test/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeRouterTest.java
  class TicTacToeRouterTest (line 23) | public class TicTacToeRouterTest extends RibTestBasePlaceholder {
    method setup (line 31) | @Before

FILE: tutorials/tutorial3/src/test/java/com/uber/rib/root/loggedout/LoggedOutInteractorTest.java
  class LoggedOutInteractorTest (line 32) | public class LoggedOutInteractorTest extends RibTestBasePlaceholder {
    method setup (line 40) | @Before
    method attach_whenViewEmitsName_shouldCallListener (line 47) | @Test
    method attach_whenViewEmitsEmptyName_shouldNotCallListener (line 56) | @Test

FILE: tutorials/tutorial3/src/test/java/com/uber/rib/root/loggedout/LoggedOutRouterTest.java
  class LoggedOutRouterTest (line 23) | public class LoggedOutRouterTest extends RibTestBasePlaceholder {
    method setup (line 31) | @Before

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/RootActivity.java
  class RootActivity (line 34) | public class RootActivity extends RibActivity {
    method createRouter (line 38) | @SuppressWarnings("unchecked")
    method onCreate (line 47) | @Override
    method handleDeepLink (line 55) | private void handleDeepLink(Intent intent) {
    class RootReturnValue (line 70) | private class RootReturnValue {}

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/SampleApplication.java
  class SampleApplication (line 20) | public class SampleApplication extends Application {}

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/RootActionableItem.java
  type RootActionableItem (line 20) | public interface RootActionableItem extends ActionableItem {}

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/RootBuilder.java
  class RootBuilder (line 35) | public class RootBuilder extends ViewBuilder<RootView, RootRouter, RootB...
    method RootBuilder (line 37) | public RootBuilder(ParentComponent dependency) {
    method build (line 47) | public RootRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 59) | @Override
    type ParentComponent (line 64) | public interface ParentComponent {
    class Module (line 68) | @dagger.Module
      method loggedOutListener (line 71) | @RootScope
      method presenter (line 77) | @RootScope
      method router (line 81) | @RootScope
    type Component (line 93) | @RootScope
      type Builder (line 101) | @dagger.Component.Builder
        method interactor (line 104) | @BindsInstance
        method view (line 107) | @BindsInstance
        method parentComponent (line 110) | Builder parentComponent(ParentComponent component);
        method build (line 112) | Component build();
    type BuilderComponent (line 116) | interface BuilderComponent {
      method rootRouter (line 118) | RootRouter rootRouter();

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/RootInteractor.java
  class RootInteractor (line 26) | @RibInteractor
    method didBecomeActive (line 32) | @Override
    class LoggedOutListener (line 38) | class LoggedOutListener implements LoggedOutInteractor.Listener {
      method requestLogin (line 40) | @Override
    type RootPresenter (line 49) | interface RootPresenter {}

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/RootRouter.java
  class RootRouter (line 29) | public class RootRouter extends ViewRouter<RootView, RootInteractor> {
    method RootRouter (line 38) | RootRouter(
    method attachLoggedOut (line 49) | void attachLoggedOut() {
    method detachLoggedOut (line 55) | void detachLoggedOut() {
    method attachLoggedIn (line 63) | LoggedInActionableItem attachLoggedIn(UserName playerOne, UserName pla...

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/RootView.java
  class RootView (line 24) | public class RootView extends FrameLayout implements RootInteractor.Root...
    method RootView (line 26) | public RootView(Context context) {
    method RootView (line 30) | public RootView(Context context, @Nullable AttributeSet attrs) {
    method RootView (line 34) | public RootView(Context context, @Nullable AttributeSet attrs, int def...

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/RootWorkflow.java
  class RootWorkflow (line 29) | public abstract class RootWorkflow<TWorkflowReturnType, TDeepLinkModel e...
    method RootWorkflow (line 39) | public RootWorkflow(Intent deepLinkIntent) {
    method RootWorkflow (line 48) | public RootWorkflow(TDeepLinkModel deepLinkModel) {
    method getSteps (line 52) | @Override
    method getDeepLinkModel (line 60) | public TDeepLinkModel getDeepLinkModel() {
    method getSteps (line 69) | protected abstract Step<TWorkflowReturnType, ?> getSteps(
    method parseDeepLinkIntent (line 78) | protected abstract TDeepLinkModel parseDeepLinkIntent(Intent deepLinkI...

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/RootWorkflowModel.java
  type RootWorkflowModel (line 21) | public interface RootWorkflowModel extends Serializable {}

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/WorkflowFactory.java
  class WorkflowFactory (line 21) | public class WorkflowFactory {
    method getWorkflow (line 22) | @Nullable

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/GameKey.java
  type GameKey (line 18) | public interface GameKey {
    method gameName (line 19) | String gameName();

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/GameProvider.java
  type GameProvider (line 21) | public interface GameProvider extends GameKey {
    method gameName (line 22) | String gameName();
    method viewRouter (line 24) | ViewRouter viewRouter(ViewGroup viewGroup);

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/LoggedInActionableItem.java
  type LoggedInActionableItem (line 20) | public interface LoggedInActionableItem extends ActionableItem {}

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/LoggedInBuilder.java
  class LoggedInBuilder (line 43) | public class LoggedInBuilder extends Builder<LoggedInRouter, LoggedInBui...
    method LoggedInBuilder (line 45) | public LoggedInBuilder(ParentComponent dependency) {
    method build (line 54) | public LoggedInRouter build(UserName playerOne, UserName playerTwo) {
    type ParentComponent (line 67) | public interface ParentComponent {
      method rootView (line 69) | RootView rootView();
    class Module (line 72) | @dagger.Module
      method presenter (line 75) | @LoggedInScope
      method router (line 81) | @LoggedInScope
      method mutableScoreStream (line 93) | @LoggedInScope
      method listener (line 101) | @LoggedInScope
      method randomWinnerListener (line 107) | @LoggedInScope
      method ticTacToeGameListener (line 112) | @LoggedInScope
      method ticTacToeListener (line 117) | @LoggedInScope
      method scoreStream (line 123) | @LoggedInScope
      method gameProviders (line 127) | @LoggedInInternal
      method gameKeys (line 158) | @LoggedInScope
    type Component (line 163) | @LoggedInScope
      type Builder (line 172) | @dagger.Component.Builder
        method interactor (line 175) | @BindsInstance
        method parentComponent (line 178) | Builder parentComponent(ParentComponent component);
        method build (line 180) | Component build();
        method playerOne (line 182) | @BindsInstance
        method playerTwo (line 185) | @BindsInstance
    type BuilderComponent (line 190) | interface BuilderComponent {
      method loggedinRouter (line 191) | LoggedInRouter loggedinRouter();

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/LoggedInInteractor.java
  class LoggedInInteractor (line 32) | @RibInteractor
    method didBecomeActive (line 39) | @Override
    class OffGameListener (line 47) | class OffGameListener implements OffGameInteractor.Listener {
      method onStartGame (line 49) | @Override
    class GameListener (line 60) | class GameListener implements TicTacToeInteractor.Listener, RandomWinn...
      method gameWon (line 62) | @Override

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/LoggedInRouter.java
  class LoggedInRouter (line 26) | public class LoggedInRouter extends Router<LoggedInInteractor> {
    method LoggedInRouter (line 34) | LoggedInRouter(
    method willDetach (line 46) | @Override
    method attachOffGame (line 53) | void attachOffGame() {
    method detachOffGame (line 59) | void detachOffGame() {
    method attachGame (line 67) | void attachGame(GameProvider gameProvider) {
    method detachGame (line 73) | void detachGame() {

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/MutableScoreStream.java
  class MutableScoreStream (line 24) | class MutableScoreStream implements ScoreStream {
    method MutableScoreStream (line 28) | MutableScoreStream(UserName playerOne, UserName playerTwo) {
    method addVictory (line 32) | void addVictory(UserName userName) {
    method scores (line 47) | @Override

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/ScoreStream.java
  type ScoreStream (line 22) | public interface ScoreStream {
    method scores (line 23) | Observable<ImmutableMap<UserName, Integer>> scores();

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameBuilder.java
  class OffGameBuilder (line 38) | public class OffGameBuilder
    method OffGameBuilder (line 41) | public OffGameBuilder(ParentComponent dependency) {
    method build (line 51) | public OffGameRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 63) | @Override
    type ParentComponent (line 68) | public interface ParentComponent {
      method playerOne (line 69) | @Named("player_one")
      method playerTwo (line 72) | @Named("player_two")
      method listener (line 75) | OffGameInteractor.Listener listener();
      method scoreStream (line 77) | ScoreStream scoreStream();
      method gameKeys (line 79) | List<? extends GameKey> gameKeys();
    class Module (line 82) | @dagger.Module
      method presenter (line 85) | @OffGameScope
      method router (line 89) | @OffGameScope
    type Component (line 97) | @OffGameScope
      type Builder (line 101) | @dagger.Component.Builder
        method interactor (line 104) | @BindsInstance
        method view (line 107) | @BindsInstance
        method parentComponent (line 110) | Builder parentComponent(ParentComponent component);
        method build (line 112) | Component build();
    type BuilderComponent (line 116) | interface BuilderComponent {
      method offgameRouter (line 117) | OffGameRouter offgameRouter();

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameInteractor.java
  class OffGameInteractor (line 33) | @RibInteractor
    method didBecomeActive (line 50) | @Override
    type Listener (line 79) | public interface Listener {
      method onStartGame (line 81) | void onStartGame(GameKey gameKey);
    type OffGamePresenter (line 85) | interface OffGamePresenter {
      method setPlayerNames (line 87) | void setPlayerNames(String playerOne, String playerTwo);
      method setScores (line 89) | void setScores(Integer playerOneScore, Integer playerTwoScore);
      method startGameRequest (line 91) | Observable<GameKey> startGameRequest(List<? extends GameKey> gameKeys);

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameRouter.java
  class OffGameRouter (line 21) | public class OffGameRouter extends ViewRouter<OffGameView, OffGameIntera...
    method OffGameRouter (line 23) | public OffGameRouter(

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameView.java
  class OffGameView (line 36) | public class OffGameView extends LinearLayout implements OffGameInteract...
    method OffGameView (line 43) | public OffGameView(Context context) {
    method OffGameView (line 47) | public OffGameView(Context context, @Nullable AttributeSet attrs) {
    method OffGameView (line 51) | public OffGameView(Context context, @Nullable AttributeSet attrs, int ...
    method onFinishInflate (line 55) | @Initializer
    method setPlayerNames (line 65) | @Override
    method setScores (line 71) | @Override
    method startGameRequest (line 79) | @Override

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/randomWinner/RandomWinnerBuilder.java
  class RandomWinnerBuilder (line 37) | public class RandomWinnerBuilder
    method RandomWinnerBuilder (line 40) | public RandomWinnerBuilder(ParentComponent dependency) {
    method build (line 50) | public RandomWinnerRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 62) | @Override
    type ParentComponent (line 68) | public interface ParentComponent {
      method randomWinnerListener (line 69) | RandomWinnerInteractor.Listener randomWinnerListener();
      method playerOne (line 71) | @Named("player_one")
      method playerTwo (line 74) | @Named("player_two")
    class Module (line 78) | @dagger.Module
      method presenter (line 81) | @RandomWinnerScope
      method router (line 85) | @RandomWinnerScope
    type Component (line 93) | @RandomWinnerScope
      type Builder (line 97) | @dagger.Component.Builder
        method interactor (line 99) | @BindsInstance
        method view (line 102) | @BindsInstance
        method parentComponent (line 105) | Builder parentComponent(ParentComponent component);
        method build (line 107) | Component build();
    type BuilderComponent (line 111) | interface BuilderComponent {
      method randomwinnerRouter (line 112) | RandomWinnerRouter randomwinnerRouter();

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/randomWinner/RandomWinnerInteractor.java
  class RandomWinnerInteractor (line 27) | @RibInteractor
    method didBecomeActive (line 41) | @Override
    type RandomWinnerPresenter (line 52) | interface RandomWinnerPresenter {}
    type Listener (line 54) | public interface Listener {
      method gameWon (line 61) | void gameWon(UserName winner);

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/randomWinner/RandomWinnerRouter.java
  class RandomWinnerRouter (line 25) | public class RandomWinnerRouter extends ViewRouter<RandomWinnerView, Ran...
    method RandomWinnerRouter (line 27) | public RandomWinnerRouter(

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/randomWinner/RandomWinnerView.java
  class RandomWinnerView (line 24) | class RandomWinnerView extends FrameLayout implements RandomWinnerIntera...
    method RandomWinnerView (line 26) | public RandomWinnerView(Context context) {
    method RandomWinnerView (line 30) | public RandomWinnerView(Context context, @Nullable AttributeSet attrs) {
    method RandomWinnerView (line 34) | public RandomWinnerView(Context context, @Nullable AttributeSet attrs,...

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/tictactoe/Board.java
  class Board (line 20) | class Board {
    method Board (line 29) | @Inject
    method isDraw (line 40) | boolean isDraw() {
    method hasWon (line 52) | boolean hasWon(MarkerType theSeed) {
    type MarkerType (line 69) | enum MarkerType {

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/tictactoe/BoardCoordinate.java
  class BoardCoordinate (line 18) | class BoardCoordinate {
    method BoardCoordinate (line 23) | BoardCoordinate(int x, int y) {
    method getX (line 28) | int getX() {
    method getY (line 32) | int getY() {

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeBuilder.java
  class TicTacToeBuilder (line 35) | public class TicTacToeBuilder
    method TicTacToeBuilder (line 38) | public TicTacToeBuilder(ParentComponent dependency) {
    method build (line 48) | public TicTacToeRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 60) | @Override
    type ParentComponent (line 65) | public interface ParentComponent {
      method ticTacToeListener (line 66) | TicTacToeInteractor.Listener ticTacToeListener();
      method playerOne (line 68) | @Named("player_one")
      method playerTwo (line 71) | @Named("player_two")
    class Module (line 75) | @dagger.Module
      method presenter (line 78) | @TicTacToeScope
      method router (line 82) | @TicTacToeScope
    type Component (line 90) | @TicTacToeScope
      type Builder (line 94) | @dagger.Component.Builder
        method interactor (line 97) | @BindsInstance
        method view (line 100) | @BindsInstance
        method parentComponent (line 103) | Builder parentComponent(ParentComponent component);
        method build (line 105) | Component build();
    type BuilderComponent (line 109) | interface BuilderComponent {
      method tictactoeRouter (line 111) | TicTacToeRouter tictactoeRouter();

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeInteractor.java
  class TicTacToeInteractor (line 30) | @RibInteractor
    method didBecomeActive (line 48) | @Override
    method updateCurrentPlayer (line 90) | private void updateCurrentPlayer() {
    type TicTacToePresenter (line 99) | interface TicTacToePresenter {
      method squareClicks (line 100) | Observable<BoardCoordinate> squareClicks();
      method setCurrentPlayerName (line 102) | void setCurrentPlayerName(String currentPlayer);
      method setPlayerWon (line 104) | void setPlayerWon(String playerName);
      method setPlayerTie (line 106) | void setPlayerTie();
      method addCross (line 108) | void addCross(BoardCoordinate xy);
      method addNought (line 110) | void addNought(BoardCoordinate xy);
    type Listener (line 113) | public interface Listener {
      method gameWon (line 120) | void gameWon(UserName winner);

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeRouter.java
  class TicTacToeRouter (line 21) | public class TicTacToeRouter extends ViewRouter<TicTacToeView, TicTacToe...
    method TicTacToeRouter (line 23) | public TicTacToeRouter(

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeView.java
  class TicTacToeView (line 31) | public class TicTacToeView extends PercentRelativeLayout
    method TicTacToeView (line 37) | public TicTacToeView(Context context) {
    method TicTacToeView (line 41) | public TicTacToeView(Context context, @Nullable AttributeSet attrs) {
    method TicTacToeView (line 45) | public TicTacToeView(Context context, @Nullable AttributeSet attrs, in...
    method onFinishInflate (line 49) | @Initializer
    method squareClicks (line 75) | @Override
    method addCross (line 96) | @Override
    method addNought (line 103) | @Override
    method setCurrentPlayerName (line 110) | @Override
    method setPlayerWon (line 115) | @Override
    method setPlayerTie (line 120) | @Override

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedout/LoggedOutBuilder.java
  class LoggedOutBuilder (line 33) | public class LoggedOutBuilder
    method LoggedOutBuilder (line 36) | public LoggedOutBuilder(ParentComponent dependency) {
    method build (line 46) | public LoggedOutRouter build(ViewGroup parentViewGroup) {
    method inflateView (line 58) | @Override
    type ParentComponent (line 63) | public interface ParentComponent {
      method listener (line 65) | LoggedOutInteractor.Listener listener();
    class Module (line 68) | @dagger.Module
      method presenter (line 71) | @LoggedOutScope
      method router (line 75) | @LoggedOutScope
    type Component (line 85) | @LoggedOutScope
      type Builder (line 89) | @dagger.Component.Builder
        method interactor (line 92) | @BindsInstance
        method view (line 95) | @BindsInstance
        method parentComponent (line 98) | Builder parentComponent(ParentComponent component);
        method build (line 100) | Component build();
    type BuilderComponent (line 104) | interface BuilderComponent {
      method loggedoutRouter (line 106) | LoggedOutRouter loggedoutRouter();

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedout/LoggedOutInteractor.java
  class LoggedOutInteractor (line 30) | @RibInteractor
    method didBecomeActive (line 37) | @Override
    method isEmpty (line 53) | private boolean isEmpty(@Nullable String string) {
    type LoggedOutPresenter (line 58) | interface LoggedOutPresenter {
      method playerNames (line 60) | Observable<Pair<String, String>> playerNames();
    type Listener (line 63) | public interface Listener {
      method requestLogin (line 65) | void requestLogin(UserName playerOne, UserName playerTwo);

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedout/LoggedOutRouter.java
  class LoggedOutRouter (line 21) | public class LoggedOutRouter extends ViewRouter<LoggedOutView, LoggedOut...
    method LoggedOutRouter (line 23) | public LoggedOutRouter(

FILE: tutorials/tutorial4/src/main/java/com/uber/rib/root/loggedout/LoggedOutView.java
  class LoggedOutView (line 32) | public class LoggedOutView extends LinearLayout implements LoggedOutInte...
    method LoggedOutView (line 38) | public LoggedOutView(Context context) {
    method LoggedOutView (line 42) | public LoggedOutView(Context context, @Nullable AttributeSet attrs) {
    method LoggedOutView (line 46) | public LoggedOutView(Context context, @Nullable AttributeSet attrs, in...
    method onFinishInflate (line 50) | @Initializer
    method playerNames (line 59) | @Override
Condensed preview — 665 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,445K chars).
[
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 694,
    "preview": "<!--\nThank you for contributing to RIBs. Before pressing the \"Create Pull Request\" button, please consider the following"
  },
  {
    "path": ".github/workflows/android.yml",
    "chars": 1338,
    "preview": "name: CI Android\n\non: [push, pull_request]\n\njobs:\n  build:\n    name: JDK ${{ matrix.java_version }}\n    runs-on: ubuntu-"
  },
  {
    "path": ".gitignore",
    "chars": 1624,
    "preview": "###OSX###\n\n.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must ends with two \\r.\nIcon\n\n\n# Thumbnails\n._*\n\n# Files that might"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 7113,
    "preview": "# Changelog\n\n### Version 0.1.0\n\n* Initial release\n\n### Version 0.9.2\n\n* Fix forked Workflow invoking didComplete multipl"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 3224,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 2520,
    "preview": "# Contributing to RIBs\n\nUber welcomes contributions of all kinds and sizes. This includes everything from from simple bu"
  },
  {
    "path": "LICENSE.txt",
    "chars": 11986,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "README.md",
    "chars": 6380,
    "preview": "<p align=\"center\">\n<img src=\"https://github.com/uber/ribs/blob/assets/rib_horizontal_black.png\" width=\"60%\" height=\"60%\""
  },
  {
    "path": "RELEASING.md",
    "chars": 626,
    "preview": "Releasing\n=========\n\nAndroid\n-------\n\n 1. Change the version in `gradle.properties` to a non-SNAPSHOT version.\n 2. Updat"
  },
  {
    "path": "build.gradle.kts",
    "chars": 1166,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "config/lint/lint.xml",
    "chars": 116,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<lint>\n    <issue id=\"GoogleAppIndexingWarning\" severity=\"ignore\" />\n</lint>\n"
  },
  {
    "path": "config/spotless/copyright.java",
    "chars": 606,
    "preview": "/*\n * Copyright (C) $YEAR. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * yo"
  },
  {
    "path": "config/spotless/copyright.kt",
    "chars": 606,
    "preview": "/*\n * Copyright (C) $YEAR. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * yo"
  },
  {
    "path": "conventions/build.gradle.kts",
    "chars": 1816,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "conventions/settings.gradle.kts",
    "chars": 860,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "conventions/src/main/kotlin/Extensions.kt",
    "chars": 1556,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "conventions/src/main/kotlin/ribs.android.application.errorprone.gradle.kts",
    "chars": 1271,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "conventions/src/main/kotlin/ribs.android.application.gradle.kts",
    "chars": 2144,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "conventions/src/main/kotlin/ribs.android.library.gradle.kts",
    "chars": 1716,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "conventions/src/main/kotlin/ribs.kotlin.library.gradle.kts",
    "chars": 988,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "conventions/src/main/kotlin/ribs.spotless.gradle.kts",
    "chars": 1723,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/README.md",
    "chars": 2711,
    "preview": "The Uber RIBs Compose Demo showcases the integration of RIBs with Jetpack Compose, an Android UI toolkit for building na"
  },
  {
    "path": "demos/compose/build.gradle.kts",
    "chars": 1962,
    "preview": "/*\n * Copyright (C) 2025. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/AndroidManifest.xml",
    "chars": 874,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <appli"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/ComposeApplication.kt",
    "chars": 1469,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/RootActivity.kt",
    "chars": 1245,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/RootInteractor.kt",
    "chars": 830,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/RootRouter.kt",
    "chars": 1267,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/RootScope.kt",
    "chars": 1940,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/RootView.kt",
    "chars": 1132,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/AuthStream.kt",
    "chars": 1121,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/MainInteractor.kt",
    "chars": 1556,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/MainRouter.kt",
    "chars": 2322,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/MainScope.kt",
    "chars": 1809,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/MainView.kt",
    "chars": 1881,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/LoggedInEvent.kt",
    "chars": 725,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/LoggedInInteractor.kt",
    "chars": 2225,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/LoggedInRouter.kt",
    "chars": 2257,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/LoggedInScope.kt",
    "chars": 2374,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/LoggedInView.kt",
    "chars": 2362,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/ScoreStream.kt",
    "chars": 1466,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/offgame/OffGameEvent.kt",
    "chars": 729,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/offgame/OffGameInteractor.kt",
    "chars": 2069,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/offgame/OffGameRouter.kt",
    "chars": 1040,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/offgame/OffGameScope.kt",
    "chars": 1807,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/offgame/OffGameView.kt",
    "chars": 2510,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/offgame/OffGameViewModel.kt",
    "chars": 814,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/tictactoe/Board.kt",
    "chars": 2104,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/tictactoe/BoardCoordinate.kt",
    "chars": 716,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/tictactoe/TicTacToeEvent.kt",
    "chars": 810,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/tictactoe/TicTacToeInteractor.kt",
    "chars": 3276,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/tictactoe/TicTacToeRouter.kt",
    "chars": 1048,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/tictactoe/TicTacToeScope.kt",
    "chars": 1744,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/tictactoe/TicTacToeView.kt",
    "chars": 3589,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedin/tictactoe/TicTacToeViewModel.kt",
    "chars": 747,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedout/LoggedOutEvent.kt",
    "chars": 804,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedout/LoggedOutInteractor.kt",
    "chars": 2176,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedout/LoggedOutRouter.kt",
    "chars": 1039,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedout/LoggedOutScope.kt",
    "chars": 1637,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedout/LoggedOutView.kt",
    "chars": 2757,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/root/main/loggedout/LoggedOutViewModel.kt",
    "chars": 749,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/util/AnalyticsClient.kt",
    "chars": 1525,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/util/CustomButton.kt",
    "chars": 1551,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/util/CustomClientProvider.kt",
    "chars": 1426,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/util/EventStream.kt",
    "chars": 971,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/util/ExperimentClient.kt",
    "chars": 1290,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/util/LoggerClient.kt",
    "chars": 1124,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/kotlin/com/uber/rib/compose/util/StateStream.kt",
    "chars": 1046,
    "preview": "/*\n * Copyright (C) 2021. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/compose/src/main/res/drawable/ic_launcher_background.xml",
    "chars": 5606,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:wi"
  },
  {
    "path": "demos/compose/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "chars": 1702,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    "
  },
  {
    "path": "demos/compose/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "chars": 272,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "demos/compose/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "chars": 272,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "demos/compose/src/main/res/values/ids.xml",
    "chars": 63,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n</resources>"
  },
  {
    "path": "demos/compose/src/main/res/values/strings.xml",
    "chars": 74,
    "preview": "<resources>\n    <string name=\"app_name\">Compose RIBs</string>\n</resources>"
  },
  {
    "path": "demos/compose/src/main/res/values/themes.xml",
    "chars": 312,
    "preview": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <style name=\"Theme.Android\" parent=\"Theme.AppCompat.NoAct"
  },
  {
    "path": "demos/flipper/README.md",
    "chars": 990,
    "preview": "\n# RIB Demo: Flipper Debugging Tool\n\n## Goal\n\nThis demo shows off RIBs plugin for Flipper Debugging Tool. It re-uses one"
  },
  {
    "path": "demos/flipper/build.gradle.kts",
    "chars": 1549,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/AndroidManifest.xml",
    "chars": 994,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          x"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/RootActivity.java",
    "chars": 1118,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/SampleApplication.java",
    "chars": 1320,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/RootBuilder.java",
    "chars": 3614,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/RootInteractor.java",
    "chars": 1634,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/RootRouter.java",
    "chars": 1923,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/RootView.java",
    "chars": 1207,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/loggedin/LoggedInBuilder.java",
    "chars": 3279,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/loggedin/LoggedInInteractor.java",
    "chars": 1483,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/loggedin/LoggedInRouter.java",
    "chars": 2511,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameBuilder.java",
    "chars": 3256,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameInteractor.java",
    "chars": 1751,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameRouter.java",
    "chars": 1005,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameView.java",
    "chars": 2162,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/Board.java",
    "chars": 2132,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/BoardCoordinate.java",
    "chars": 865,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeBuilder.java",
    "chars": 3359,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeInteractor.java",
    "chars": 3494,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeRouter.java",
    "chars": 1025,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeView.java",
    "chars": 3868,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/loggedout/LoggedOutBuilder.java",
    "chars": 3419,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/loggedout/LoggedOutInteractor.java",
    "chars": 2130,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/loggedout/LoggedOutRouter.java",
    "chars": 1016,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/java/com/uber/rib/root/loggedout/LoggedOutView.java",
    "chars": 2111,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/flipper/src/main/res/layout/logged_out_rib.xml",
    "chars": 1079,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.uber.rib.root.loggedout.LoggedOutView\n    xmlns:android=\"http://schemas.andr"
  },
  {
    "path": "demos/flipper/src/main/res/layout/off_game_rib.xml",
    "chars": 2116,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.uber.rib.root.loggedin.offgame.OffGameView\n    xmlns:android=\"http://schemas"
  },
  {
    "path": "demos/flipper/src/main/res/layout/root_rib.xml",
    "chars": 213,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.uber.rib.root.RootView\n    xmlns:android=\"http://schemas.android.com/apk/res"
  },
  {
    "path": "demos/flipper/src/main/res/layout/tic_tac_toe_rib.xml",
    "chars": 3681,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.uber.rib.root.loggedin.tictactoe.TicTacToeView\n    xmlns:android=\"http://sch"
  },
  {
    "path": "demos/flipper/src/main/res/values/ub__strings.xml",
    "chars": 438,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"app_name\">Flipper Demo</string>\n    <string name=\"p"
  },
  {
    "path": "demos/intellij/README.md",
    "chars": 763,
    "preview": "\n# RIB Demo: RIBs Tree IntelliJ plugin.\n\n## Goal\n\nThis demo shows off integration for the RIBs tree IntelliJ plugin.\n\n##"
  },
  {
    "path": "demos/intellij/build.gradle.kts",
    "chars": 1429,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/AndroidManifest.xml",
    "chars": 994,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          x"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/RootActivity.java",
    "chars": 1118,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/SampleApplication.java",
    "chars": 1319,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/RootBuilder.java",
    "chars": 3615,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/RootInteractor.java",
    "chars": 1634,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/RootRouter.java",
    "chars": 1923,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/RootView.java",
    "chars": 1207,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/loggedin/LoggedInBuilder.java",
    "chars": 3279,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/loggedin/LoggedInInteractor.java",
    "chars": 1483,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/loggedin/LoggedInRouter.java",
    "chars": 2511,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameBuilder.java",
    "chars": 3257,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameInteractor.java",
    "chars": 1751,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameRouter.java",
    "chars": 1005,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/loggedin/offgame/OffGameView.java",
    "chars": 2163,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/loggedin/tictactoe/Board.java",
    "chars": 2132,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/loggedin/tictactoe/BoardCoordinate.java",
    "chars": 865,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeBuilder.java",
    "chars": 3360,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeInteractor.java",
    "chars": 3494,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeRouter.java",
    "chars": 1025,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/loggedin/tictactoe/TicTacToeView.java",
    "chars": 3869,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/loggedout/LoggedOutBuilder.java",
    "chars": 3420,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/loggedout/LoggedOutInteractor.java",
    "chars": 2130,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/loggedout/LoggedOutRouter.java",
    "chars": 1016,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/java/com/uber/rib/root/loggedout/LoggedOutView.java",
    "chars": 2112,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/intellij/src/main/res/layout/logged_out_rib.xml",
    "chars": 1079,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.uber.rib.root.loggedout.LoggedOutView\n    xmlns:android=\"http://schemas.andr"
  },
  {
    "path": "demos/intellij/src/main/res/layout/off_game_rib.xml",
    "chars": 2116,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.uber.rib.root.loggedin.offgame.OffGameView\n    xmlns:android=\"http://schemas"
  },
  {
    "path": "demos/intellij/src/main/res/layout/root_rib.xml",
    "chars": 213,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.uber.rib.root.RootView\n    xmlns:android=\"http://schemas.android.com/apk/res"
  },
  {
    "path": "demos/intellij/src/main/res/layout/tic_tac_toe_rib.xml",
    "chars": 3681,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.uber.rib.root.loggedin.tictactoe.TicTacToeView\n    xmlns:android=\"http://sch"
  },
  {
    "path": "demos/intellij/src/main/res/values/ub__strings.xml",
    "chars": 439,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"app_name\">Intellij Demo</string>\n    <string name=\""
  },
  {
    "path": "demos/memory-leaks/README.md",
    "chars": 2538,
    "preview": "\n# RIB Demo: Memory Leaks\n\n## Goal\n\nThis demo shows off some memory leak tooling for RIBs.\n\n## Leak Canary\n\nThe `LoggedI"
  },
  {
    "path": "demos/memory-leaks/build.gradle.kts",
    "chars": 1712,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/memory-leaks/src/main/AndroidManifest.xml",
    "chars": 994,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          x"
  },
  {
    "path": "demos/memory-leaks/src/main/java/com/uber/rib/RootActivity.java",
    "chars": 1146,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/memory-leaks/src/main/java/com/uber/rib/SampleApplication.java",
    "chars": 2157,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/memory-leaks/src/main/java/com/uber/rib/root/RootBuilder.java",
    "chars": 3618,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/memory-leaks/src/main/java/com/uber/rib/root/RootInteractor.java",
    "chars": 1615,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/memory-leaks/src/main/java/com/uber/rib/root/RootRouter.java",
    "chars": 1923,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/memory-leaks/src/main/java/com/uber/rib/root/RootView.java",
    "chars": 1207,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/memory-leaks/src/main/java/com/uber/rib/root/loggedin/LoggedInBuilder.java",
    "chars": 2674,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/memory-leaks/src/main/java/com/uber/rib/root/loggedin/LoggedInInteractor.java",
    "chars": 989,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/memory-leaks/src/main/java/com/uber/rib/root/loggedin/LoggedInRouter.java",
    "chars": 944,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/memory-leaks/src/main/java/com/uber/rib/root/loggedout/LoggedOutBuilder.java",
    "chars": 3423,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/memory-leaks/src/main/java/com/uber/rib/root/loggedout/LoggedOutInteractor.java",
    "chars": 2518,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/memory-leaks/src/main/java/com/uber/rib/root/loggedout/LoggedOutRouter.java",
    "chars": 1016,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/memory-leaks/src/main/java/com/uber/rib/root/loggedout/LoggedOutView.java",
    "chars": 1871,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/memory-leaks/src/main/res/layout/logged_out_rib.xml",
    "chars": 858,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.uber.rib.root.loggedout.LoggedOutView\n    xmlns:android=\"http://schemas.andr"
  },
  {
    "path": "demos/memory-leaks/src/main/res/layout/root_rib.xml",
    "chars": 213,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.uber.rib.root.RootView\n    xmlns:android=\"http://schemas.android.com/apk/res"
  },
  {
    "path": "demos/memory-leaks/src/main/res/values/ub__strings.xml",
    "chars": 322,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"app_name\">Memory Leak Demo</string>\n    <string nam"
  },
  {
    "path": "demos/rib-workers/README.md",
    "chars": 347,
    "preview": "The RIBs Workers Demo app showcases:\n\n1. Binding of [com.uber.rib.core.Worker] with different [CoroutineContext]\n2. Bind"
  },
  {
    "path": "demos/rib-workers/build.gradle.kts",
    "chars": 1891,
    "preview": "/*\n * Copyright (C) 2025. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/AndroidManifest.xml",
    "chars": 834,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <appli"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/ComposeApplication.kt",
    "chars": 1580,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/RootActivity.kt",
    "chars": 1348,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/RootInteractor.kt",
    "chars": 833,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/RootRouter.kt",
    "chars": 1267,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/RootScope.kt",
    "chars": 1167,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/RootView.kt",
    "chars": 896,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/logger/ApplicationLevelWorkerLogger.kt",
    "chars": 3042,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/main/MainInteractor.kt",
    "chars": 1155,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/main/MainRouter.kt",
    "chars": 1838,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/main/MainScope.kt",
    "chars": 1626,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/main/MainView.kt",
    "chars": 1763,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/main/ribworkerselection/RibWorkerBindTypeClickType.kt",
    "chars": 955,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/main/ribworkerselection/RibWorkerSelectionInteractor.kt",
    "chars": 4399,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/main/ribworkerselection/RibWorkerSelectionRouter.kt",
    "chars": 1144,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/main/ribworkerselection/RibWorkerSelectionScope.kt",
    "chars": 2364,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/main/ribworkerselection/RibWorkerSelectionView.kt",
    "chars": 3798,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/main/ribworkerselection/RibWorkerSelectionViewModel.kt",
    "chars": 738,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/main/workers/BackgroundWorker.kt",
    "chars": 1056,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/main/workers/DefaultRibCoroutineWorker.kt",
    "chars": 956,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/main/workers/DefaultWorker.kt",
    "chars": 925,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/main/workers/IoWorker.kt",
    "chars": 1750,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/root/main/workers/UiWorker.kt",
    "chars": 1381,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/util/EventStream.kt",
    "chars": 971,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/kotlin/com/uber/rib/workers/util/StateStream.kt",
    "chars": 1046,
    "preview": "/*\n * Copyright (C) 2023. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "demos/rib-workers/src/main/res/drawable/ic_launcher_background.xml",
    "chars": 5606,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:wi"
  },
  {
    "path": "demos/rib-workers/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "chars": 1702,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    "
  },
  {
    "path": "demos/rib-workers/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "chars": 272,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "demos/rib-workers/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "chars": 272,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "demos/rib-workers/src/main/res/values/strings.xml",
    "chars": 78,
    "preview": "<resources>\n    <string name=\"app_name\">Rib Workers Demo</string>\n</resources>"
  },
  {
    "path": "demos/rib-workers/src/main/res/values/themes.xml",
    "chars": 312,
    "preview": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <style name=\"Theme.Android\" parent=\"Theme.AppCompat.NoAct"
  },
  {
    "path": "gradle/app-libs.versions.toml",
    "chars": 1556,
    "preview": "[versions]\nandroidx-activity = \"1.8.2\"\nautodispose = \"1.4.1\"\ncompose-libraries = \"1.6.8\" # If changing this, change also"
  },
  {
    "path": "gradle/japicmp.gradle",
    "chars": 4042,
    "preview": "import me.champeau.gradle.japicmp.JapicmpTask\n\next.javaBaselineVersion = \"0.10.1\"\n\nbuildscript {\n    repositories {\n    "
  },
  {
    "path": "gradle/libs.versions.toml",
    "chars": 5562,
    "preview": "[versions]\nandroid-api = \"4.1.1.4\"\nandroid-studio = \"2023.3.1.20\"\nandroidx-annotation = \"1.9.1\"\nandroidx-appcompat = \"1."
  },
  {
    "path": "gradle/test-libs.versions.toml",
    "chars": 860,
    "preview": "[versions]\ncompile-testing = \"0.23.0\"\njunit = \"4.13.2\"\nkotlinx-coroutines = \"1.10.2\"\nmockito = \"3.12.4\"\nmockito-kotlin ="
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 233,
    "preview": "#Wed Apr 12 10:45:00 PDT 2017\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "gradle.properties",
    "chars": 1529,
    "preview": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will o"
  },
  {
    "path": "gradlew",
    "chars": 4971,
    "preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start "
  },
  {
    "path": "gradlew.bat",
    "chars": 2314,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem "
  },
  {
    "path": "libraries/rib-android/build.gradle.kts",
    "chars": 1420,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  },
  {
    "path": "libraries/rib-android/gradle.properties",
    "chars": 664,
    "preview": "#\n# Copyright (C) 2017. Uber Technologies\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may "
  },
  {
    "path": "libraries/rib-android/src/main/kotlin/com/uber/rib/core/ActivityContext.kt",
    "chars": 807,
    "preview": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you"
  }
]

// ... and 465 more files (download for full content)

About this extraction

This page contains the full source code of the uber/RIBs GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 665 files (18.8 MB), approximately 335.1k tokens, and a symbol index with 1478 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!