├── Barf ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── badoo │ │ └── barf │ │ ├── mvp │ │ ├── MvpView.java │ │ ├── FlowListener.java │ │ ├── MvpPresenter.java │ │ ├── BaseRxPresenter.java │ │ └── PresenterFactory.java │ │ ├── usecase │ │ ├── UseCase.java │ │ └── UseCaseOld.java │ │ ├── data │ │ └── repo │ │ │ ├── Query.java │ │ │ ├── annotations │ │ │ ├── Handles.java │ │ │ └── HandlesUtil.java │ │ │ ├── Repository.java │ │ │ └── DelegatingRepository.java │ │ └── rx │ │ └── ScheduleOn.java ├── proguard-rules.pro └── build.gradle ├── Chateau ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── badoo │ │ └── chateau │ │ ├── data │ │ └── models │ │ │ ├── payloads │ │ │ ├── Payload.java │ │ │ ├── TimestampPayload.java │ │ │ ├── TextPayload.java │ │ │ └── ImagePayload.java │ │ │ ├── BaseUser.java │ │ │ └── BaseConversation.java │ │ └── ui │ │ ├── chat │ │ ├── info │ │ │ ├── ChatInfoPresenter.java │ │ │ └── BaseChatInfoPresenter.java │ │ ├── typing │ │ │ ├── IsTypingPresenter.java │ │ │ └── BaseIsTypingPresenter.java │ │ ├── input │ │ │ ├── ChatInputPresenter.java │ │ │ └── BaseChatInputPresenter.java │ │ ├── photos │ │ │ ├── BasePhotoPresenter.java │ │ │ └── PhotoPresenter.java │ │ └── messages │ │ │ └── MessageListPresenter.java │ │ └── conversations │ │ ├── create │ │ ├── namegroup │ │ │ ├── NameGroupPresenter.java │ │ │ └── NameGroupPresenterImpl.java │ │ └── selectusers │ │ │ └── UserListPresenter.java │ │ └── list │ │ └── ConversationListPresenter.java ├── proguard-rules.pro └── build.gradle ├── ChateauCore ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── badoo │ │ └── chateau │ │ └── core │ │ ├── model │ │ ├── User.java │ │ ├── Message.java │ │ └── Conversation.java │ │ ├── usecases │ │ ├── messages │ │ │ ├── GetFailedToDeliverMessages.java │ │ │ ├── SendMessage.java │ │ │ ├── SubscribeToMessageUpdates.java │ │ │ └── LoadMessages.java │ │ ├── users │ │ │ └── GetUsers.java │ │ ├── conversations │ │ │ ├── SubscribeToConversationUpdates.java │ │ │ ├── MarkConversationRead.java │ │ │ ├── GetConversation.java │ │ │ ├── CreateConversation.java │ │ │ ├── DeleteConversations.java │ │ │ ├── CreateGroupConversation.java │ │ │ └── LoadConversations.java │ │ └── istyping │ │ │ ├── SendUserIsTyping.java │ │ │ └── SubscribeToUsersTyping.java │ │ └── repos │ │ ├── istyping │ │ └── IsTypingDataSource.java │ │ └── users │ │ ├── UserDataSource.java │ │ └── UserQueries.java ├── proguard-rules.pro └── build.gradle ├── ExampleApp ├── .gitignore ├── backend │ └── parse_data.zip ├── src │ ├── main │ │ ├── res │ │ │ ├── drawable-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_notification.png │ │ │ ├── drawable-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_notification.png │ │ │ ├── drawable-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_notification.png │ │ │ ├── drawable-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_notification.png │ │ │ │ ├── bg_chat_bubble_left.9.png │ │ │ │ └── bg_chat_bubble_right.9.png │ │ │ ├── drawable-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_notification.png │ │ │ ├── drawable │ │ │ │ ├── badge_unread.xml │ │ │ │ ├── image_placeholder.xml │ │ │ │ ├── ic_error_small.xml │ │ │ │ ├── ic_send.xml │ │ │ │ ├── selectable_background.xml │ │ │ │ ├── ic_done.xml │ │ │ │ ├── textinput_dropshadow.xml │ │ │ │ ├── ic_delete.xml │ │ │ │ ├── ic_notification_new_message.xml │ │ │ │ ├── ic_upload_failed.xml │ │ │ │ ├── ic_photo.xml │ │ │ │ ├── ic_create_chat.xml │ │ │ │ ├── ic_camera_alt.xml │ │ │ │ └── ic_group_chat.xml │ │ │ ├── menu │ │ │ │ ├── conversation_actions.xml │ │ │ │ └── input_actions.xml │ │ │ ├── layout │ │ │ │ ├── activity_view_image.xml │ │ │ │ ├── item_input_action.xml │ │ │ │ ├── control_timestamp.xml │ │ │ │ ├── toolbar_actionbar_with_headerbar.xml │ │ │ │ ├── list_item_chat_day.xml │ │ │ │ ├── list_item_loading.xml │ │ │ │ ├── list_item_user.xml │ │ │ │ ├── activity_chat.xml │ │ │ │ ├── activity_name_group.xml │ │ │ │ ├── list_item_chat_text_message.xml │ │ │ │ ├── activity_conversations.xml │ │ │ │ ├── activity_create_conversation.xml │ │ │ │ └── list_item_chat_image_message.xml │ │ │ ├── values │ │ │ │ ├── dimens.xml │ │ │ │ ├── attrs.xml │ │ │ │ ├── colors.xml │ │ │ │ ├── styles.xml │ │ │ │ └── strings.xml │ │ │ ├── values-w820dp │ │ │ │ └── dimens.xml │ │ │ └── drawable-v21 │ │ │ │ └── selectable_background.xml │ │ └── java │ │ │ ├── com │ │ │ └── badoo │ │ │ │ └── chateau │ │ │ │ ├── example │ │ │ │ ├── ui │ │ │ │ │ ├── chat │ │ │ │ │ │ ├── istyping │ │ │ │ │ │ │ ├── ExampleIsTypingPresenter.java │ │ │ │ │ │ │ ├── ExampleIsTypingPresenterImpl.java │ │ │ │ │ │ │ └── ExampleIsTypingViewImpl.java │ │ │ │ │ │ ├── messages │ │ │ │ │ │ │ ├── ExampleMessageListView.java │ │ │ │ │ │ │ ├── ItemPreProcessor.java │ │ │ │ │ │ │ ├── ExampleMessageListPresenter.java │ │ │ │ │ │ │ ├── viewholders │ │ │ │ │ │ │ │ ├── TextMessageViewHolder.java │ │ │ │ │ │ │ │ ├── TimestampViewHolder.java │ │ │ │ │ │ │ │ └── ChatBubbleViewHolder.java │ │ │ │ │ │ │ ├── BaseItemClickListener.java │ │ │ │ │ │ │ ├── TimeStampPreProcessor.java │ │ │ │ │ │ │ └── ExampleMessageListPresenterImpl.java │ │ │ │ │ │ ├── info │ │ │ │ │ │ │ ├── ExampleChatInfoPresenter.java │ │ │ │ │ │ │ ├── ExampleChatInfoPresenterImpl.java │ │ │ │ │ │ │ └── ExampleChatInfoViewImpl.java │ │ │ │ │ │ ├── input │ │ │ │ │ │ │ ├── ExampleChatInputPresenter.java │ │ │ │ │ │ │ ├── ExampleChatInputPresenterImpl.java │ │ │ │ │ │ │ └── ChatInputViewImpl.java │ │ │ │ │ │ ├── photos │ │ │ │ │ │ │ └── PhotoViewImpl.java │ │ │ │ │ │ └── FullScreenImageActivity.java │ │ │ │ │ ├── widgets │ │ │ │ │ │ └── SimpleTextWatcher.java │ │ │ │ │ ├── conversations │ │ │ │ │ │ ├── list │ │ │ │ │ │ │ ├── CreateConversationPresenterImpl.java │ │ │ │ │ │ │ ├── CreateConversationPresenter.java │ │ │ │ │ │ │ └── CreateConversationViewImpl.java │ │ │ │ │ │ └── create │ │ │ │ │ │ │ └── namegroup │ │ │ │ │ │ │ └── NameGroupViewImpl.java │ │ │ │ │ ├── Injector.java │ │ │ │ │ ├── LandingActivity.java │ │ │ │ │ ├── session │ │ │ │ │ │ ├── login │ │ │ │ │ │ │ ├── LoginPresenter.java │ │ │ │ │ │ │ └── LoginPresenterImpl.java │ │ │ │ │ │ └── register │ │ │ │ │ │ │ └── RegistrationPresenter.java │ │ │ │ │ ├── util │ │ │ │ │ │ ├── recycle │ │ │ │ │ │ │ └── AboveFabItemDecoration.java │ │ │ │ │ │ └── MessageViewHolder.java │ │ │ │ │ └── ExampleConfiguration.java │ │ │ │ ├── data │ │ │ │ │ ├── model │ │ │ │ │ │ ├── ExampleUser.java │ │ │ │ │ │ └── ExampleConversation.java │ │ │ │ │ └── repos │ │ │ │ │ │ ├── messages │ │ │ │ │ │ └── cache │ │ │ │ │ │ │ └── MessageMemoryCache.java │ │ │ │ │ │ ├── session │ │ │ │ │ │ ├── SessionDataSource.java │ │ │ │ │ │ └── ParseSessionDataSource.java │ │ │ │ │ │ └── user │ │ │ │ │ │ └── ParseUserDataSource.java │ │ │ │ └── usecases │ │ │ │ │ └── session │ │ │ │ │ ├── SignOut.java │ │ │ │ │ ├── SignIn.java │ │ │ │ │ └── Register.java │ │ │ │ └── ui │ │ │ │ └── conversations │ │ │ │ └── list │ │ │ │ └── ConversationByLastMessageComparator.java │ │ │ └── android │ │ │ └── support │ │ │ └── v7 │ │ │ └── widget │ │ │ └── AppCompatBackgroundHelper2.java │ ├── test │ │ └── java │ │ │ ├── com │ │ │ └── badoo │ │ │ │ ├── unittest │ │ │ │ ├── rx │ │ │ │ │ ├── SchedulerFactory.java │ │ │ │ │ ├── ImmediateSchedulerFactory.java │ │ │ │ │ ├── TrackingSchedulerFactory.java │ │ │ │ │ └── BaseRxTestCase.java │ │ │ │ └── MapMatchers.java │ │ │ │ ├── chateau │ │ │ │ ├── example │ │ │ │ │ ├── usecases │ │ │ │ │ │ └── session │ │ │ │ │ │ │ ├── SignOutTest.java │ │ │ │ │ │ │ ├── SignInTest.java │ │ │ │ │ │ │ └── RegisterTest.java │ │ │ │ │ └── ui │ │ │ │ │ │ ├── utils │ │ │ │ │ │ └── TestUtils.java │ │ │ │ │ │ └── conversations │ │ │ │ │ │ └── list │ │ │ │ │ │ └── ConversationByLastMessageComparatorTest.java │ │ │ │ └── core │ │ │ │ │ └── usecases │ │ │ │ │ ├── istyping │ │ │ │ │ ├── SendUserIsTypingTest.java │ │ │ │ │ └── SubscribeToUsersTypingQueryTest.java │ │ │ │ │ ├── conversations │ │ │ │ │ ├── SubscribeToUpdatesQueryTest.java │ │ │ │ │ ├── MarkConversationReadTest.java │ │ │ │ │ ├── GetConversationTest.java │ │ │ │ │ ├── CreateConversationTest.java │ │ │ │ │ ├── CreateGroupConversationTest.java │ │ │ │ │ └── LoadConversationsTest.java │ │ │ │ │ ├── users │ │ │ │ │ └── GetUsersTest.java │ │ │ │ │ └── messages │ │ │ │ │ └── SendMessagesTest.java │ │ │ │ └── barf │ │ │ │ └── data │ │ │ │ └── repo │ │ │ │ └── BaseRepoTest.java │ │ │ └── rx │ │ │ └── plugins │ │ │ └── RxTestSchedulerProxy.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── badoo │ │ └── chateau │ │ └── example │ │ └── ApplicationTest.java └── proguard-rules.pro ├── ChateauExtras ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ ├── res │ │ ├── drawable-hdpi │ │ │ ├── ic_mess_bubble_right.9.png │ │ │ └── ic_mess_bubble_circle.9.png │ │ ├── drawable-mdpi │ │ │ ├── ic_mess_bubble_right.9.png │ │ │ └── ic_mess_bubble_circle.9.png │ │ ├── drawable-xhdpi │ │ │ ├── ic_mess_bubble_circle.9.png │ │ │ └── ic_mess_bubble_right.9.png │ │ ├── drawable-xxhdpi │ │ │ ├── ic_mess_bubble_right.9.png │ │ │ └── ic_mess_bubble_circle.9.png │ │ ├── drawable-xxxhdpi │ │ │ ├── ic_mess_bubble_circle.9.png │ │ │ └── ic_mess_bubble_right.9.png │ │ └── layout │ │ │ └── list_item_loading.xml │ │ └── java │ │ └── com │ │ └── badoo │ │ └── chateau │ │ └── extras │ │ └── recycle │ │ ├── ViewHolderFactory.java │ │ ├── BindableViewHolder.java │ │ └── WrappingAdapter.java ├── proguard-rules.pro └── build.gradle ├── doc ├── cleanarc.png ├── chat-screenshot.png └── conversations-screenshot.png ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── versions.gradle ├── .gitignore ├── gradle.properties └── LICENSE.md /Barf/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /Chateau/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /ChateauCore/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /ExampleApp/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /ChateauExtras/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /doc/cleanarc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/doc/cleanarc.png -------------------------------------------------------------------------------- /doc/chat-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/doc/chat-screenshot.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':Chateau', ':Barf', ':ChateauCore', ':ExampleApp', ':ChateauExtras' 2 | -------------------------------------------------------------------------------- /doc/conversations-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/doc/conversations-screenshot.png -------------------------------------------------------------------------------- /ExampleApp/backend/parse_data.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ExampleApp/backend/parse_data.zip -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /Barf/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ExampleApp/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ExampleApp/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ExampleApp/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Chateau/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable-hdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ExampleApp/src/main/res/drawable-hdpi/ic_notification.png -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable-mdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ExampleApp/src/main/res/drawable-mdpi/ic_notification.png -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ExampleApp/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ExampleApp/src/main/res/drawable-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ChateauCore/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable-xhdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ExampleApp/src/main/res/drawable-xhdpi/ic_notification.png -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable-xxhdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ExampleApp/src/main/res/drawable-xxhdpi/ic_notification.png -------------------------------------------------------------------------------- /ChateauExtras/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable-xxxhdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ExampleApp/src/main/res/drawable-xxxhdpi/ic_notification.png -------------------------------------------------------------------------------- /Barf/src/main/java/com/badoo/barf/mvp/MvpView.java: -------------------------------------------------------------------------------- 1 | package com.badoo.barf.mvp; 2 | 3 | /** 4 | * Interface definition of a MVP View 5 | */ 6 | public interface MvpView { 7 | } 8 | -------------------------------------------------------------------------------- /ChateauExtras/src/main/res/drawable-hdpi/ic_mess_bubble_right.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ChateauExtras/src/main/res/drawable-hdpi/ic_mess_bubble_right.9.png -------------------------------------------------------------------------------- /ChateauExtras/src/main/res/drawable-mdpi/ic_mess_bubble_right.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ChateauExtras/src/main/res/drawable-mdpi/ic_mess_bubble_right.9.png -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable-xxhdpi/bg_chat_bubble_left.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ExampleApp/src/main/res/drawable-xxhdpi/bg_chat_bubble_left.9.png -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable-xxhdpi/bg_chat_bubble_right.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ExampleApp/src/main/res/drawable-xxhdpi/bg_chat_bubble_right.9.png -------------------------------------------------------------------------------- /versions.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | chateauLibraryVersionName = '1.0.0-preview3' 3 | chateauExampleAppVersionName = '1.0.0-preview3' 4 | chateauExampleAppVersionCode = 4 5 | } 6 | -------------------------------------------------------------------------------- /ChateauExtras/src/main/res/drawable-hdpi/ic_mess_bubble_circle.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ChateauExtras/src/main/res/drawable-hdpi/ic_mess_bubble_circle.9.png -------------------------------------------------------------------------------- /ChateauExtras/src/main/res/drawable-mdpi/ic_mess_bubble_circle.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ChateauExtras/src/main/res/drawable-mdpi/ic_mess_bubble_circle.9.png -------------------------------------------------------------------------------- /ChateauExtras/src/main/res/drawable-xhdpi/ic_mess_bubble_circle.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ChateauExtras/src/main/res/drawable-xhdpi/ic_mess_bubble_circle.9.png -------------------------------------------------------------------------------- /ChateauExtras/src/main/res/drawable-xhdpi/ic_mess_bubble_right.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ChateauExtras/src/main/res/drawable-xhdpi/ic_mess_bubble_right.9.png -------------------------------------------------------------------------------- /ChateauExtras/src/main/res/drawable-xxhdpi/ic_mess_bubble_right.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ChateauExtras/src/main/res/drawable-xxhdpi/ic_mess_bubble_right.9.png -------------------------------------------------------------------------------- /ChateauExtras/src/main/res/drawable-xxhdpi/ic_mess_bubble_circle.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ChateauExtras/src/main/res/drawable-xxhdpi/ic_mess_bubble_circle.9.png -------------------------------------------------------------------------------- /ChateauExtras/src/main/res/drawable-xxxhdpi/ic_mess_bubble_circle.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ChateauExtras/src/main/res/drawable-xxxhdpi/ic_mess_bubble_circle.9.png -------------------------------------------------------------------------------- /ChateauExtras/src/main/res/drawable-xxxhdpi/ic_mess_bubble_right.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badoo/Chateau/HEAD/ChateauExtras/src/main/res/drawable-xxxhdpi/ic_mess_bubble_right.9.png -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/model/User.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.model; 2 | 3 | /** 4 | * Marker interface for users. 5 | */ 6 | public interface User { 7 | } 8 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/model/Message.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.model; 2 | 3 | /** 4 | * Marker interface for messages 5 | */ 6 | public interface Message { 7 | } 8 | -------------------------------------------------------------------------------- /Barf/src/main/java/com/badoo/barf/usecase/UseCase.java: -------------------------------------------------------------------------------- 1 | package com.badoo.barf.usecase; 2 | 3 | /** 4 | * Annotation use to mark a class as a use case. A use 5 | */ 6 | public @interface UseCase { 7 | } 8 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/model/Conversation.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.model; 2 | 3 | /** 4 | * Marker interface for conversations 5 | */ 6 | public interface Conversation { 7 | } 8 | -------------------------------------------------------------------------------- /Chateau/src/main/java/com/badoo/chateau/data/models/payloads/Payload.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.data.models.payloads; 2 | 3 | /** 4 | * Marker interface for base message payloads. 5 | */ 6 | public interface Payload { 7 | } 8 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable/badge_unread.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Mar 30 17:54:14 BST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip 7 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable/image_placeholder.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/menu/conversation_actions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable/ic_error_small.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/layout/activity_view_image.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16dp 3 | 72dp 4 | 5 | 8dp 6 | 7 | 16dp 8 | 16dp 9 | 10 | 24dp 11 | 12 | -------------------------------------------------------------------------------- /ExampleApp/src/test/java/com/badoo/unittest/rx/SchedulerFactory.java: -------------------------------------------------------------------------------- 1 | package com.badoo.unittest.rx; 2 | 3 | import rx.Scheduler; 4 | 5 | public interface SchedulerFactory { 6 | Scheduler createIOScheduler(); 7 | 8 | Scheduler createComputationScheduler(); 9 | 10 | Scheduler createNewThreadScheduler(); 11 | 12 | Scheduler createMainThreadScheduler(); 13 | } 14 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable/ic_send.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable/selectable_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable/ic_done.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /ChateauExtras/src/main/java/com/badoo/chateau/extras/recycle/ViewHolderFactory.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.extras.recycle; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.ViewGroup; 6 | 7 | public interface ViewHolderFactory { 8 | 9 | @NonNull 10 | T create(@NonNull ViewGroup parent); 11 | } 12 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable/textinput_dropshadow.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/menu/input_actions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable/ic_delete.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable/ic_notification_new_message.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /Barf/src/main/java/com/badoo/barf/data/repo/Query.java: -------------------------------------------------------------------------------- 1 | package com.badoo.barf.data.repo; 2 | 3 | /** 4 | * A marker interface for repository queries. Any class implementing this must also provide implementations of equals() and hashCode() 5 | * otherwise you might risk having queries executed multiple times (concurrently) since we cannot deduplicate them. 6 | *

7 | * the expected return type for this query 8 | */ 9 | public interface Query { 10 | } 11 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/chat/istyping/ExampleIsTypingPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.chat.istyping; 2 | 3 | import com.badoo.chateau.example.data.model.ExampleUser; 4 | import com.badoo.chateau.ui.chat.typing.IsTypingPresenter; 5 | 6 | public interface ExampleIsTypingPresenter extends IsTypingPresenter { 7 | 8 | interface ExampleIsTypingView extends IsTypingView { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable/ic_upload_failed.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/chat/messages/ExampleMessageListView.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.chat.messages; 2 | 3 | import com.badoo.chateau.example.data.model.ExampleMessage; 4 | import com.badoo.chateau.ui.chat.messages.MessageListPresenter; 5 | 6 | /** 7 | * Extension of MessageListView for the example app. 8 | */ 9 | public interface ExampleMessageListView extends MessageListPresenter.MessageListView { 10 | } 11 | -------------------------------------------------------------------------------- /ExampleApp/src/androidTest/java/com/badoo/chateau/example/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/data/model/ExampleUser.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.data.model; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.annotation.Nullable; 5 | 6 | import com.badoo.chateau.data.models.BaseUser; 7 | 8 | public class ExampleUser extends BaseUser { 9 | 10 | public ExampleUser(@NonNull String userId, @Nullable String displayName) { 11 | super(userId, displayName); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/chat/info/ExampleChatInfoPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.chat.info; 2 | 3 | import com.badoo.chateau.example.data.model.ExampleConversation; 4 | import com.badoo.chateau.ui.chat.info.ChatInfoPresenter; 5 | 6 | public interface ExampleChatInfoPresenter extends ChatInfoPresenter { 7 | 8 | interface ExampleChatInfoView extends ChatInfoView { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/layout/item_input_action.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable/ic_photo.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable/ic_create_chat.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/chat/input/ExampleChatInputPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.chat.input; 2 | 3 | import com.badoo.chateau.example.data.model.ExampleMessage; 4 | import com.badoo.chateau.ui.chat.input.ChatInputPresenter; 5 | 6 | /** 7 | * Extension of ChatInputPresenter for the example app (just used to specify generic parameters for now) 8 | */ 9 | public interface ExampleChatInputPresenter extends ChatInputPresenter { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/layout/control_timestamp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/chat/messages/ItemPreProcessor.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.chat.messages; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.chateau.example.data.model.ExampleMessage; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Preprocessor that can add or remove items from the list of messages before it's displayed 11 | */ 12 | public interface ItemPreProcessor { 13 | 14 | List doProcess(@NonNull List input); 15 | } 16 | -------------------------------------------------------------------------------- /Barf/src/main/java/com/badoo/barf/mvp/FlowListener.java: -------------------------------------------------------------------------------- 1 | package com.badoo.barf.mvp; 2 | 3 | /** 4 | * An marker interface that is used in addition to the View for allowing the presenter to control navigation related functionality of the app. 5 | * This was introduced to solve issues that arose from separating the View implementation from the containing Fragment/Activity as well 6 | * as from the decision to split functionality into several View/Presenter pairs for each screen (based on areas or responsibility). 7 | */ 8 | public interface FlowListener { 9 | } 10 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/layout/toolbar_actionbar_with_headerbar.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Barf/src/main/java/com/badoo/barf/mvp/MvpPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.barf.mvp; 2 | 3 | import android.app.Activity; 4 | import android.app.Fragment; 5 | 6 | /** 7 | * Interface definition of a MVP Presenter. 8 | */ 9 | public interface MvpPresenter { 10 | 11 | /** 12 | * Lifecycle callback that is invoked from onStart of the Fragment/Activity managing the presenter 13 | */ 14 | void onStart(); 15 | 16 | /** 17 | * Lifecycle callback that is invoked from onStop of the Fragment/Activity managing the presenter 18 | */ 19 | void onStop(); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /Barf/src/main/java/com/badoo/barf/rx/ScheduleOn.java: -------------------------------------------------------------------------------- 1 | package com.badoo.barf.rx; 2 | 3 | import rx.Observable.Transformer; 4 | import rx.android.schedulers.AndroidSchedulers; 5 | import rx.schedulers.Schedulers; 6 | 7 | public class ScheduleOn { 8 | 9 | /** 10 | * Applies schedules such that the subscription is performed on the io thread, but the response is observed on the Android main thread. 11 | */ 12 | public static Transformer io() { 13 | return observable -> observable.subscribeOn(Schedulers.io()) 14 | .observeOn(AndroidSchedulers.mainThread()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ChateauExtras/src/main/java/com/badoo/chateau/extras/recycle/BindableViewHolder.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.extras.recycle; 2 | 3 | import android.support.annotation.CallSuper; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.View; 6 | 7 | public abstract class BindableViewHolder extends RecyclerView.ViewHolder { 8 | 9 | private T mItem; 10 | 11 | public BindableViewHolder(View itemView) { 12 | super(itemView); 13 | } 14 | 15 | @CallSuper 16 | public void bind(T item) { 17 | mItem = item; 18 | } 19 | 20 | public T getBoundItem() { 21 | return mItem; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/widgets/SimpleTextWatcher.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.widgets; 2 | 3 | import android.text.Editable; 4 | import android.text.TextWatcher; 5 | 6 | /** 7 | * Simple implementation of TextWatcher. 8 | */ 9 | class SimpleTextWatcher implements TextWatcher { 10 | @Override 11 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 12 | 13 | } 14 | 15 | @Override 16 | public void onTextChanged(CharSequence s, int start, int before, int count) { 17 | 18 | } 19 | 20 | @Override 21 | public void afterTextChanged(Editable s) { 22 | 23 | } 24 | } -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable/ic_camera_alt.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /Chateau/src/main/java/com/badoo/chateau/data/models/payloads/TimestampPayload.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.data.models.payloads; 2 | 3 | /** 4 | * Dummy payload for timestamps in the messages list (chat) 5 | */ 6 | public class TimestampPayload implements Payload { 7 | 8 | // All needed data is already provided by BaseMessage. We just need this class to be able to register a renderer 9 | 10 | // These two are needed for the stable id calculation 11 | @Override 12 | public boolean equals(Object o) { 13 | return o instanceof TimestampPayload; 14 | } 15 | 16 | @Override 17 | public int hashCode() { 18 | return 0; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #Buildt application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Android Studio captures folder 33 | captures/ 34 | 35 | # Intellij 36 | *.iml 37 | .idea 38 | 39 | # Keystore files 40 | *.jks 41 | 42 | # Oh Mac 43 | .DS_Store 44 | .AppleDouble 45 | .LSOverride 46 | -------------------------------------------------------------------------------- /ChateauExtras/src/main/java/com/badoo/chateau/extras/recycle/WrappingAdapter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.extras.recycle; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | 5 | /** 6 | * Interface to use when one adapter wraps another adapter. Can be used to get the wrapped adapter, and the modified position for that 7 | * adapter. 8 | */ 9 | public interface WrappingAdapter { 10 | 11 | /** 12 | * Assert if the current position is handled by the wrapped adapter. 13 | */ 14 | boolean isHandledByWrappedAdapter(int position); 15 | 16 | RecyclerView.Adapter getWrappedAdapter(); 17 | 18 | int getAdjustedPosition(int position); 19 | } 20 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/usecases/session/SignOut.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.usecases.session; 2 | 3 | import com.badoo.barf.data.repo.Repository; 4 | import com.badoo.barf.usecase.UseCase; 5 | import com.badoo.chateau.core.model.User; 6 | import com.badoo.chateau.example.data.repos.session.SessionQuery; 7 | 8 | import rx.Observable; 9 | 10 | @UseCase 11 | public class SignOut { 12 | 13 | private final Repository mRepository; 14 | 15 | public SignOut(Repository repository) { 16 | mRepository = repository; 17 | } 18 | 19 | public Observable execute() { 20 | return mRepository.query(new SessionQuery.SignOut()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable-v21/selectable_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Barf/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/erikandre/android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /Chateau/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/erikandre/android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /ChateauCore/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/erikandre/android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /ChateauExtras/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/erikandre/android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /ExampleApp/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/erikandre/android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/drawable/ic_group_chat.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /Chateau/src/main/java/com/badoo/chateau/ui/chat/info/ChatInfoPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.ui.chat.info; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.mvp.MvpPresenter; 6 | import com.badoo.barf.mvp.MvpView; 7 | import com.badoo.chateau.core.model.Conversation; 8 | 9 | /** 10 | * Presenter for handling information about a conversation other than the messages in it. 11 | */ 12 | public interface ChatInfoPresenter extends MvpPresenter { 13 | 14 | interface ChatInfoView extends MvpView { 15 | 16 | /** 17 | * Show information about the conversation 18 | */ 19 | void showConversation(@NonNull C conversation); 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/layout/list_item_chat_day.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | -------------------------------------------------------------------------------- /ExampleApp/src/test/java/com/badoo/unittest/rx/ImmediateSchedulerFactory.java: -------------------------------------------------------------------------------- 1 | package com.badoo.unittest.rx; 2 | 3 | import rx.Scheduler; 4 | import rx.schedulers.Schedulers; 5 | 6 | public class ImmediateSchedulerFactory implements SchedulerFactory { 7 | @Override 8 | public Scheduler createIOScheduler() { 9 | return Schedulers.immediate(); 10 | } 11 | 12 | @Override 13 | public Scheduler createComputationScheduler() { 14 | return Schedulers.immediate(); 15 | } 16 | 17 | @Override 18 | public Scheduler createNewThreadScheduler() { 19 | return Schedulers.immediate(); 20 | } 21 | 22 | @Override 23 | public Scheduler createMainThreadScheduler() { 24 | return Schedulers.immediate(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Barf/src/main/java/com/badoo/barf/data/repo/annotations/Handles.java: -------------------------------------------------------------------------------- 1 | package com.badoo.barf.data.repo.annotations; 2 | 3 | import com.badoo.barf.data.repo.DelegatingRepository; 4 | import com.badoo.barf.data.repo.Query; 5 | 6 | import java.lang.annotation.ElementType; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.annotation.Target; 10 | 11 | /** 12 | * Used to annotated methods on a data source so they can be registered on a {@link com.badoo.barf.data.repo.DelegatingRepository} using 13 | * {@link HandlesUtil#processClass(DelegatingRepository, Class, Object)}. 14 | */ 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Target(ElementType.METHOD) 17 | public @interface Handles { 18 | 19 | Class value(); 20 | } 21 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/chat/input/ExampleChatInputPresenterImpl.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.chat.input; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.chateau.core.usecases.messages.SendMessage; 6 | import com.badoo.chateau.example.data.model.ExampleMessage; 7 | import com.badoo.chateau.ui.chat.input.BaseChatInputPresenter; 8 | 9 | public class ExampleChatInputPresenterImpl extends BaseChatInputPresenter implements ExampleChatInputPresenter { 10 | 11 | public ExampleChatInputPresenterImpl(@NonNull String chatId, @NonNull ChatInputView view, 12 | @NonNull SendMessage sendMessage) { 13 | super(chatId, view, sendMessage); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ChateauExtras/src/main/res/layout/list_item_loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 18 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/usecases/messages/GetFailedToDeliverMessages.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.usecases.messages; 2 | 3 | import com.badoo.barf.data.repo.Repository; 4 | import com.badoo.barf.usecase.UseCase; 5 | import com.badoo.chateau.core.model.Message; 6 | import com.badoo.chateau.core.repos.messages.MessageQueries.GetUndeliveredQuery; 7 | 8 | import java.util.List; 9 | 10 | import rx.Observable; 11 | 12 | @UseCase 13 | public class GetFailedToDeliverMessages { 14 | 15 | private final Repository mRepo; 16 | 17 | public GetFailedToDeliverMessages(Repository repo) { 18 | mRepo = repo; 19 | } 20 | 21 | public Observable> execute() { 22 | return mRepo.query(new GetUndeliveredQuery<>()); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Chateau/src/main/java/com/badoo/chateau/ui/chat/typing/IsTypingPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.ui.chat.typing; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.mvp.MvpPresenter; 6 | import com.badoo.barf.mvp.MvpView; 7 | import com.badoo.chateau.core.model.User; 8 | 9 | /** 10 | * Presenter for handling the "is writing" statuses (for both the local and remote users) 11 | */ 12 | public interface IsTypingPresenter extends MvpPresenter { 13 | 14 | /** 15 | * Called when the user is typing a message, should be throttled (don't call for every keystroke) 16 | */ 17 | void onUserTyping(); 18 | 19 | interface IsTypingView extends MvpView { 20 | 21 | void showOtherUserTyping(@NonNull U user); 22 | 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Chateau/src/main/java/com/badoo/chateau/ui/chat/input/ChatInputPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.ui.chat.input; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.mvp.MvpPresenter; 6 | import com.badoo.barf.mvp.MvpView; 7 | import com.badoo.chateau.core.model.Message; 8 | 9 | /** 10 | * Presenter managing the text input part of the chat screen 11 | */ 12 | public interface ChatInputPresenter extends MvpPresenter { 13 | 14 | /** 15 | * Called when a message has been entered and is ready to be sent 16 | */ 17 | void onSendMessage(@NonNull M message); 18 | 19 | interface ChatInputView extends MvpView { 20 | 21 | /** 22 | * Clears the enter text in the text field 23 | */ 24 | void clearText(); 25 | 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/layout/list_item_loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /Chateau/src/main/java/com/badoo/chateau/ui/chat/photos/BasePhotoPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.ui.chat.photos; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.mvp.BaseRxPresenter; 6 | 7 | /** 8 | * Base implementation of the PhotoPresenter interface. 9 | */ 10 | public class BasePhotoPresenter extends BaseRxPresenter implements PhotoPresenter { 11 | 12 | @NonNull 13 | private final PhotoFlowListener mFlowListener; 14 | 15 | public BasePhotoPresenter(@NonNull PhotoFlowListener flowListener) { 16 | mFlowListener = flowListener; 17 | } 18 | 19 | @Override 20 | public void onPickPhoto() { 21 | mFlowListener.requestPickPhoto(); 22 | } 23 | 24 | @Override 25 | public void onTakePhoto() { 26 | mFlowListener.requestTakePhoto(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/usecases/session/SignIn.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.usecases.session; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.data.repo.Repository; 6 | import com.badoo.barf.usecase.UseCase; 7 | import com.badoo.chateau.core.model.User; 8 | import com.badoo.chateau.example.data.repos.session.SessionQuery; 9 | 10 | import rx.Observable; 11 | 12 | @UseCase 13 | public class SignIn { 14 | 15 | private final Repository mRepository; 16 | 17 | public SignIn(@NonNull Repository repository) { 18 | mRepository = repository; 19 | } 20 | 21 | public Observable execute(@NonNull String userName, @NonNull String password) { 22 | return mRepository.query(new SessionQuery.SignIn<>(userName, password)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Barf/src/main/java/com/badoo/barf/data/repo/Repository.java: -------------------------------------------------------------------------------- 1 | package com.badoo.barf.data.repo; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import rx.Observable; 6 | 7 | /** 8 | * A repository is a data store that can be used to both request and publish data. The repository may or may not be able to retrieve data 9 | * from local and/or remote sources, but if so, it should follow the mode specified by the {@link Query#getMode()}. 10 | */ 11 | public interface Repository { 12 | 13 | /** 14 | * Perform a query on the repository. 15 | * 16 | * @return an {@link Observable} that will only be completed one all the necessary information has been loaded based upon the 17 | * {@link Query#getMode()}. 18 | */ 19 | @NonNull 20 | Observable query(@NonNull Query query); 21 | } 22 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/usecases/users/GetUsers.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.usecases.users; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.data.repo.Repository; 6 | import com.badoo.barf.usecase.UseCase; 7 | import com.badoo.chateau.core.model.User; 8 | import com.badoo.chateau.core.repos.users.UserQueries; 9 | 10 | import java.util.List; 11 | 12 | import rx.Observable; 13 | 14 | /** 15 | * Use case for retrieving all users 16 | */ 17 | @UseCase 18 | public class GetUsers { 19 | 20 | private final Repository mRepository; 21 | 22 | public GetUsers(@NonNull Repository repository) { 23 | mRepository = repository; 24 | } 25 | 26 | public Observable> execute() { 27 | return mRepository.query(new UserQueries.GetAllUsersQuery<>()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/conversations/list/CreateConversationPresenterImpl.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.conversations.list; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.mvp.BaseRxPresenter; 6 | 7 | /** 8 | * Implementation of CreateConversationPresenter which delegates the operation to the flow listener 9 | */ 10 | class CreateConversationPresenterImpl extends BaseRxPresenter implements CreateConversationPresenter { 11 | 12 | private CreateConversationFlowListener mFlowListener; 13 | 14 | CreateConversationPresenterImpl(@NonNull CreateConversationFlowListener flowListener) { 15 | mFlowListener = flowListener; 16 | } 17 | 18 | @Override 19 | public void onCreateNewConversationClicked() { 20 | mFlowListener.requestCreateNewConversation(); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/chat/messages/ExampleMessageListPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.chat.messages; 2 | 3 | import android.net.Uri; 4 | import android.support.annotation.NonNull; 5 | 6 | import com.badoo.barf.mvp.FlowListener; 7 | import com.badoo.chateau.example.data.model.ExampleMessage; 8 | import com.badoo.chateau.ui.chat.messages.MessageListPresenter; 9 | 10 | /** 11 | * Extension of MessageListPresenter for the example app. 12 | */ 13 | public interface ExampleMessageListPresenter extends MessageListPresenter { 14 | 15 | /** 16 | * Notifies that an image has been clicked. 17 | */ 18 | void onImageClicked(@NonNull Uri uri); 19 | 20 | interface ExampleMessageListFlowListener extends FlowListener { 21 | 22 | void requestOpenImage(@NonNull Uri imageUri); 23 | 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/chat/info/ExampleChatInfoPresenterImpl.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.chat.info; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.chateau.core.usecases.conversations.GetConversation; 6 | import com.badoo.chateau.example.data.model.ExampleConversation; 7 | import com.badoo.chateau.ui.chat.info.BaseChatInfoPresenter; 8 | 9 | public class ExampleChatInfoPresenterImpl extends BaseChatInfoPresenter implements ExampleChatInfoPresenter { 10 | 11 | public ExampleChatInfoPresenterImpl(@NonNull ChatInfoView view, 12 | @NonNull String conversationId, 13 | @NonNull GetConversation getConversation) { 14 | super(view, conversationId, getConversation); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/usecases/session/Register.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.usecases.session; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.data.repo.Repository; 6 | import com.badoo.barf.usecase.UseCase; 7 | import com.badoo.chateau.core.model.User; 8 | import com.badoo.chateau.example.data.repos.session.SessionQuery; 9 | 10 | import rx.Observable; 11 | 12 | @UseCase 13 | public class Register { 14 | 15 | private final Repository mRepository; 16 | 17 | public Register(@NonNull Repository repository) { 18 | mRepository = repository; 19 | } 20 | 21 | public Observable execute(@NonNull String userName, @NonNull String displayName, @NonNull String password) { 22 | return mRepository.query(new SessionQuery.Register<>(userName, displayName, password)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | 21 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/chat/messages/viewholders/TextMessageViewHolder.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.chat.messages.viewholders; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | 7 | import com.badoo.chateau.data.models.payloads.TextPayload; 8 | import com.badoo.chateau.example.R; 9 | import com.badoo.chateau.example.data.model.ExampleMessage; 10 | 11 | public class TextMessageViewHolder extends ChatBubbleViewHolder { 12 | 13 | private final TextView mMessageText; 14 | 15 | public TextMessageViewHolder(@NonNull View itemView) { 16 | super(itemView); 17 | mMessageText = (TextView) itemView.findViewById(R.id.message_text); 18 | } 19 | 20 | @Override 21 | protected void bindPayload(ExampleMessage message, TextPayload payload) { 22 | mMessageText.setText((payload.getMessage())); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/layout/list_item_user.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 21 | 22 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/usecases/conversations/SubscribeToConversationUpdates.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.usecases.conversations; 2 | 3 | import com.badoo.barf.data.repo.Repository; 4 | import com.badoo.barf.usecase.UseCase; 5 | import com.badoo.chateau.core.model.Conversation; 6 | import com.badoo.chateau.core.repos.conversations.ConversationQueries; 7 | 8 | import rx.Observable; 9 | 10 | /** 11 | * Use case for subscribing to conversation updates 12 | */ 13 | @UseCase 14 | public class SubscribeToConversationUpdates { 15 | 16 | private Repository mConversationRepository; 17 | 18 | public SubscribeToConversationUpdates(Repository conversationRepository) { 19 | mConversationRepository = conversationRepository; 20 | } 21 | 22 | public Observable execute() { 23 | return mConversationRepository.query(new ConversationQueries.SubscribeToUpdatesQuery()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/usecases/istyping/SendUserIsTyping.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.usecases.istyping; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.data.repo.Repository; 6 | import com.badoo.barf.usecase.UseCase; 7 | import com.badoo.chateau.core.model.User; 8 | import com.badoo.chateau.core.repos.istyping.IsTypingQueries; 9 | 10 | import rx.Observable; 11 | 12 | /** 13 | * Use case to indicate that the user is typing a message in a chat. 14 | */ 15 | @UseCase 16 | public class SendUserIsTyping { 17 | 18 | private final Repository mRepository; 19 | 20 | public SendUserIsTyping(@NonNull Repository repository) { 21 | mRepository = repository; 22 | } 23 | 24 | public Observable execute(@NonNull String conversationId) { 25 | return mRepository.query(new IsTypingQueries.SendIsTyping(conversationId)).map(user -> null); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/data/repos/messages/cache/MessageMemoryCache.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.data.repos.messages.cache; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.chateau.example.data.model.ExampleMessage; 6 | 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | /** 12 | * Memory cache for messages 13 | */ 14 | public class MessageMemoryCache { 15 | 16 | private Map mCache = new HashMap<>(); 17 | 18 | public synchronized boolean hasData(@NonNull String conversationId) { 19 | return mCache.containsKey(conversationId); 20 | } 21 | 22 | @NonNull 23 | public synchronized CacheEntry get(@NonNull String conversationId) { 24 | if (!mCache.containsKey(conversationId)) { 25 | mCache.put(conversationId, new CacheEntry()); 26 | } 27 | return mCache.get(conversationId); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/usecases/messages/SendMessage.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.usecases.messages; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.data.repo.Repository; 6 | import com.badoo.barf.usecase.UseCase; 7 | import com.badoo.chateau.core.model.Message; 8 | import com.badoo.chateau.core.repos.messages.MessageQueries.SendQuery; 9 | 10 | import rx.Observable; 11 | 12 | /** 13 | * Use case for sending a new message 14 | */ 15 | @UseCase 16 | public class SendMessage { 17 | 18 | private final Repository mRepo; 19 | 20 | public SendMessage(Repository repo) { 21 | mRepo = repo; 22 | } 23 | 24 | public Observable execute(@NonNull String conversationId, @NonNull M message) { 25 | return mRepo.query(new SendQuery<>(conversationId, message)) 26 | .ignoreElements() 27 | .cast(Void.class); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/usecases/istyping/SubscribeToUsersTyping.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.usecases.istyping; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.data.repo.Repository; 6 | import com.badoo.barf.usecase.UseCase; 7 | import com.badoo.chateau.core.model.User; 8 | import com.badoo.chateau.core.repos.istyping.IsTypingQueries.SubscribeToUsersTypingQuery; 9 | 10 | import rx.Observable; 11 | 12 | /** 13 | * Use case to indicate that the user is typing a message in a chat. 14 | */ 15 | @UseCase 16 | public class SubscribeToUsersTyping { 17 | 18 | private final Repository mRepository; 19 | 20 | public SubscribeToUsersTyping(@NonNull Repository repository) { 21 | mRepository = repository; 22 | } 23 | 24 | public Observable execute(@NonNull String conversationId) { 25 | return mRepository.query(new SubscribeToUsersTypingQuery<>(conversationId)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/ui/conversations/list/ConversationByLastMessageComparator.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.ui.conversations.list; 2 | 3 | import com.badoo.chateau.example.data.model.ExampleConversation; 4 | 5 | import java.util.Comparator; 6 | 7 | /** 8 | * Sorts conversations in descending order 9 | */ 10 | public class ConversationByLastMessageComparator implements Comparator { 11 | 12 | @Override 13 | public int compare(ExampleConversation lhsConversation, ExampleConversation rhsConversation) { 14 | final long lhs = lhsConversation.getLastMessage() != null ? lhsConversation.getLastMessage().getTimestamp() : 0; 15 | final long rhs = rhsConversation.getLastMessage() != null ? rhsConversation.getLastMessage().getTimestamp() : 0; 16 | return lhs > rhs ? -1 : (lhs == rhs ? 0 : 1); 17 | } 18 | 19 | @Override 20 | public boolean equals(Object object) { 21 | return object == this; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/conversations/list/CreateConversationPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.conversations.list; 2 | 3 | import com.badoo.barf.mvp.FlowListener; 4 | import com.badoo.barf.mvp.MvpPresenter; 5 | import com.badoo.barf.mvp.MvpView; 6 | 7 | /** 8 | * Component presenter for handling creating new conversations (this is not handled by the base ConversationListPresenter as this is often 9 | * application dependent). 10 | */ 11 | interface CreateConversationPresenter extends MvpPresenter { 12 | 13 | /** 14 | * Called when a new conversation is requested. 15 | */ 16 | void onCreateNewConversationClicked(); 17 | 18 | interface CreateConversationFlowListener extends FlowListener { 19 | 20 | /** 21 | * Called when a new conversation is required. 22 | */ 23 | void requestCreateNewConversation(); 24 | } 25 | 26 | interface CreateConversationView extends MvpView { 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/Injector.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | public class Injector { 9 | 10 | private static Map, Configuration> sConfigurator = new HashMap<>(); 11 | 12 | public static void register(@NonNull Class cls, @NonNull Configuration config) { 13 | sConfigurator.put(cls, config); 14 | } 15 | 16 | public static void inject(T target) { 17 | //noinspection unchecked 18 | Configuration config = (Configuration) sConfigurator.get(target.getClass()); 19 | if (config == null) { 20 | throw new RuntimeException("No configuration specified for " + target.getClass().getSimpleName()); 21 | } 22 | config.inject(target); 23 | } 24 | 25 | public interface Configuration { 26 | 27 | void inject(T target); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/chat/istyping/ExampleIsTypingPresenterImpl.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.chat.istyping; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.chateau.core.usecases.istyping.SendUserIsTyping; 6 | import com.badoo.chateau.core.usecases.istyping.SubscribeToUsersTyping; 7 | import com.badoo.chateau.example.data.model.ExampleUser; 8 | import com.badoo.chateau.ui.chat.typing.BaseIsTypingPresenter; 9 | 10 | public class ExampleIsTypingPresenterImpl extends BaseIsTypingPresenter implements ExampleIsTypingPresenter { 11 | 12 | public ExampleIsTypingPresenterImpl(@NonNull IsTypingView view, @NonNull String conversationId, 13 | @NonNull SubscribeToUsersTyping subscribeToUsersTyping, 14 | @NonNull SendUserIsTyping sendUserIsTyping) { 15 | super(view, conversationId, subscribeToUsersTyping, sendUserIsTyping); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Barf/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'me.tatarka.retrolambda' 2 | apply plugin: 'com.android.library' 3 | 4 | android { 5 | compileSdkVersion 23 6 | buildToolsVersion "23.0.2" 7 | 8 | defaultConfig { 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionName chateauLibraryVersionName 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | compileOptions { 20 | sourceCompatibility JavaVersion.VERSION_1_8 21 | targetCompatibility JavaVersion.VERSION_1_8 22 | } 23 | } 24 | 25 | dependencies { 26 | compile 'com.android.support:appcompat-v7:23.1.1' 27 | compile 'io.reactivex:rxandroid:1.1.0@aar' 28 | compile 'io.reactivex:rxjava:1.1.0' 29 | testCompile 'junit:junit:4.12' 30 | testCompile 'org.mockito:mockito-core:1.10.19' 31 | } 32 | 33 | ext { 34 | artifactId = 'barf' 35 | } 36 | apply from: '../release.gradle' 37 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/repos/istyping/IsTypingDataSource.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.repos.istyping; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.data.repo.annotations.Handles; 6 | import com.badoo.chateau.core.model.User; 7 | 8 | import rx.Observable; 9 | 10 | /** 11 | * Defines a data source for providing information about whether a participant of a conversation is typing. 12 | */ 13 | public interface IsTypingDataSource { 14 | 15 | /** 16 | * Should be called when the user is typing a message. 17 | */ 18 | @Handles(IsTypingQueries.SendIsTyping.class) 19 | Observable sendUserIsTyping(@NonNull IsTypingQueries.SendIsTyping query); 20 | 21 | /** 22 | * Returns an observable that will be updated whenever a user is typing. 23 | */ 24 | @NonNull 25 | @Handles(IsTypingQueries.SubscribeToUsersTypingQuery.class) 26 | Observable subscribeToUsersTyping(@NonNull IsTypingQueries.SubscribeToUsersTypingQuery query); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /ChateauExtras/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'me.tatarka.retrolambda' 2 | apply plugin: 'com.android.library' 3 | 4 | android { 5 | compileSdkVersion 23 6 | buildToolsVersion "23.0.2" 7 | 8 | defaultConfig { 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionName chateauLibraryVersionName 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | compileOptions { 20 | sourceCompatibility JavaVersion.VERSION_1_8 21 | targetCompatibility JavaVersion.VERSION_1_8 22 | } 23 | } 24 | 25 | dependencies { 26 | compile project(':Barf') 27 | compile 'com.android.support:appcompat-v7:23.1.1' 28 | compile 'com.android.support:recyclerview-v7:23.1.1' 29 | testCompile 'junit:junit:4.12' 30 | testCompile 'org.mockito:mockito-core:1.9.5' 31 | } 32 | 33 | ext { 34 | artifactId = 'chateau-extras' 35 | } 36 | apply from: '../release.gradle' -------------------------------------------------------------------------------- /Chateau/src/main/java/com/badoo/chateau/ui/chat/photos/PhotoPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.ui.chat.photos; 2 | 3 | import com.badoo.barf.mvp.FlowListener; 4 | import com.badoo.barf.mvp.MvpPresenter; 5 | import com.badoo.barf.mvp.MvpView; 6 | 7 | /** 8 | * Presenter for sending different types of photos. 9 | */ 10 | public interface PhotoPresenter extends MvpPresenter { 11 | 12 | /** 13 | * Called when the user starts the "Send photo from album" flow 14 | */ 15 | void onPickPhoto(); 16 | 17 | /** 18 | * Called when the user starts the "Send photo from album" flow 19 | */ 20 | void onTakePhoto(); 21 | 22 | interface PhotoView extends MvpView{ 23 | 24 | } 25 | 26 | interface PhotoFlowListener extends FlowListener { 27 | 28 | /** 29 | * Request an image to be picked from gallery 30 | */ 31 | void requestPickPhoto(); 32 | 33 | /** 34 | * Request an image to be taken using the camera 35 | */ 36 | void requestTakePhoto(); 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ChateauCore/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'me.tatarka.retrolambda' 2 | apply plugin: 'com.android.library' 3 | 4 | android { 5 | compileSdkVersion 23 6 | buildToolsVersion "23.0.2" 7 | 8 | defaultConfig { 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionName chateauLibraryVersionName 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | compileOptions { 20 | sourceCompatibility JavaVersion.VERSION_1_8 21 | targetCompatibility JavaVersion.VERSION_1_8 22 | } 23 | } 24 | 25 | dependencies { 26 | compile project(':Barf') 27 | compile 'com.android.support:appcompat-v7:23.1.1' 28 | compile 'com.android.support:recyclerview-v7:23.1.1' 29 | testCompile 'junit:junit:4.12' 30 | testCompile 'org.mockito:mockito-core:1.9.5' 31 | } 32 | 33 | ext { 34 | artifactId = 'chateau-core' 35 | } 36 | apply from: '../release.gradle' 37 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/usecases/conversations/MarkConversationRead.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.usecases.conversations; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.data.repo.Repository; 6 | import com.badoo.barf.usecase.UseCase; 7 | import com.badoo.chateau.core.model.Conversation; 8 | import com.badoo.chateau.core.repos.conversations.ConversationQueries.MarkConversationReadQuery; 9 | 10 | import rx.Observable; 11 | 12 | /** 13 | * Use case for marking a conversation as read 14 | */ 15 | @UseCase 16 | public class MarkConversationRead { 17 | 18 | private final Repository mConversationRepository; 19 | 20 | public MarkConversationRead(Repository conversationRepository) { 21 | mConversationRepository = conversationRepository; 22 | } 23 | 24 | public Observable execute(@NonNull String conversationId) { 25 | return mConversationRepository.query(new MarkConversationReadQuery(conversationId)); 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/usecases/conversations/GetConversation.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.usecases.conversations; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.data.repo.Repository; 6 | import com.badoo.barf.usecase.UseCase; 7 | import com.badoo.chateau.core.model.Conversation; 8 | import com.badoo.chateau.core.repos.conversations.ConversationQueries; 9 | 10 | import rx.Observable; 11 | 12 | /** 13 | * Use case for retrieving data for a single conversation (not including the actual messages in it) 14 | */ 15 | @UseCase 16 | public class GetConversation { 17 | 18 | private final Repository mConversationRepository; 19 | 20 | public GetConversation(Repository conversationRepository) { 21 | mConversationRepository = conversationRepository; 22 | } 23 | 24 | public Observable execute(@NonNull String conversationId) { 25 | return mConversationRepository.query(new ConversationQueries.GetConversationQuery<>(conversationId)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Barf/src/main/java/com/badoo/barf/usecase/UseCaseOld.java: -------------------------------------------------------------------------------- 1 | package com.badoo.barf.usecase; 2 | 3 | import rx.Observable; 4 | import rx.android.schedulers.AndroidSchedulers; 5 | import rx.schedulers.Schedulers; 6 | 7 | /** 8 | * Base class that should be used for all user cases, ensure subscriptions to the observable returned view {@link #execute(Object)} are 9 | * published to on the main thread, and any work done occurs on a computation thread. 10 | */ 11 | public abstract class UseCaseOld { 12 | 13 | public Observable execute(P params) { 14 | return createObservable(params) 15 | .observeOn(AndroidSchedulers.mainThread()) 16 | .subscribeOn(Schedulers.computation()); 17 | } 18 | 19 | /** 20 | * Create a observer which will publish the result of the use case for the given params. 21 | */ 22 | protected abstract Observable createObservable(P params); 23 | 24 | /** 25 | * Can be used params type is no params are required. 26 | */ 27 | public enum NoParams { 28 | NONE 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /Chateau/src/main/java/com/badoo/chateau/ui/conversations/create/namegroup/NameGroupPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.ui.conversations.create.namegroup; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.mvp.FlowListener; 6 | import com.badoo.barf.mvp.MvpPresenter; 7 | import com.badoo.barf.mvp.MvpView; 8 | import com.badoo.chateau.core.model.Conversation; 9 | 10 | /** 11 | * Presenter which manages naming of a new chat group 12 | */ 13 | public interface NameGroupPresenter extends MvpPresenter { 14 | 15 | /** 16 | * Called when a name has been selected 17 | */ 18 | void onCreateGroupClicked(@NonNull String name); 19 | 20 | interface NameGroupFlowListener extends FlowListener { 21 | 22 | /** 23 | * Requests a conversation to be opened 24 | */ 25 | void requestOpenChat(@NonNull C conversationId); 26 | } 27 | 28 | interface NameGroupView extends MvpView { 29 | 30 | void showGroupNameEmptyError(); 31 | 32 | void clearErrors(); 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/chat/info/ExampleChatInfoViewImpl.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.chat.info; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.v7.app.ActionBar; 5 | 6 | import com.badoo.barf.mvp.PresenterFactory; 7 | import com.badoo.chateau.example.data.model.ExampleConversation; 8 | import com.badoo.chateau.example.ui.chat.info.ExampleChatInfoPresenter.ExampleChatInfoView; 9 | 10 | public class ExampleChatInfoViewImpl implements ExampleChatInfoView { 11 | 12 | 13 | private final ActionBar mSupportActionBar; 14 | 15 | public ExampleChatInfoViewImpl(@NonNull PresenterFactory presenterFactory, 16 | @NonNull ActionBar supportActionBar) { 17 | mSupportActionBar = supportActionBar; 18 | presenterFactory.init(this); 19 | } 20 | 21 | @Override 22 | public void showConversation(@NonNull ExampleConversation conversation) { 23 | mSupportActionBar.setTitle(conversation.getName()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/repos/users/UserDataSource.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.repos.users; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.data.repo.annotations.Handles; 6 | import com.badoo.chateau.core.model.User; 7 | import com.badoo.chateau.core.repos.users.UserQueries.GetAllUsersQuery; 8 | import com.badoo.chateau.core.repos.users.UserQueries.GetUserQuery; 9 | 10 | import java.util.List; 11 | 12 | import rx.Observable; 13 | 14 | /** 15 | * Defines a data source providing user data for the {@link UserRepository} 16 | */ 17 | public interface UserDataSource { 18 | 19 | /** 20 | * Returns an {@link Observable} which emits all the users 21 | */ 22 | @NonNull 23 | @Handles(GetAllUsersQuery.class) 24 | Observable> getAllUsers(GetAllUsersQuery query); 25 | 26 | /** 27 | * Returns an {@link Observable} which emits a single, specific user 28 | */ 29 | @NonNull 30 | @Handles(GetUserQuery.class) 31 | Observable getSingleUser(GetUserQuery query); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /Chateau/src/main/java/com/badoo/chateau/data/models/payloads/TextPayload.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.data.models.payloads; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | /** 6 | * Payload containing just text 7 | */ 8 | public class TextPayload implements Payload { 9 | 10 | private final String mMessage; 11 | 12 | public TextPayload(@NonNull String message) { 13 | mMessage = message; 14 | } 15 | 16 | @NonNull 17 | public String getMessage() { 18 | return mMessage; 19 | } 20 | 21 | @Override 22 | public boolean equals(Object o) { 23 | if (this == o) return true; 24 | if (!(o instanceof TextPayload)) return false; 25 | 26 | TextPayload that = (TextPayload) o; 27 | 28 | return mMessage.equals(that.mMessage); 29 | 30 | } 31 | 32 | @Override 33 | public int hashCode() { 34 | return mMessage.hashCode(); 35 | } 36 | 37 | @Override 38 | public String toString() { 39 | return "TextPayload{" + 40 | "mMessage='" + mMessage + '\'' + 41 | '}'; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/usecases/conversations/CreateConversation.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.usecases.conversations; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.data.repo.Repository; 6 | import com.badoo.barf.usecase.UseCase; 7 | import com.badoo.chateau.core.model.Conversation; 8 | import com.badoo.chateau.core.repos.conversations.ConversationQueries; 9 | 10 | import rx.Observable; 11 | 12 | /** 13 | * User case for creating a conversation with a single user. To create a conversation with multiple users (group chat) use {@link CreateGroupConversation} 14 | */ 15 | @UseCase 16 | public class CreateConversation { 17 | 18 | private final Repository mConversationRepository; 19 | 20 | public CreateConversation(Repository conversationRepository) { 21 | mConversationRepository = conversationRepository; 22 | } 23 | 24 | public Observable execute(@NonNull String userId) { 25 | return mConversationRepository.query(new ConversationQueries.CreateConversationQuery<>(userId)); 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/usecases/conversations/DeleteConversations.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.usecases.conversations; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.data.repo.Repository; 6 | import com.badoo.barf.usecase.UseCase; 7 | import com.badoo.chateau.core.model.Conversation; 8 | import com.badoo.chateau.core.repos.conversations.ConversationQueries; 9 | 10 | import java.util.List; 11 | 12 | import rx.Observable; 13 | 14 | /** 15 | * User case for deleting an existing conversation (either with a single user or a group) 16 | */ 17 | @UseCase 18 | public class DeleteConversations { 19 | 20 | private final Repository mConversationRepository; 21 | 22 | public DeleteConversations(Repository conversationRepository) { 23 | mConversationRepository = conversationRepository; 24 | } 25 | 26 | public Observable execute(@NonNull List conversations) { 27 | return mConversationRepository.query(new ConversationQueries.DeleteConversationsQuery<>(conversations)); 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /ExampleApp/src/test/java/com/badoo/unittest/MapMatchers.java: -------------------------------------------------------------------------------- 1 | package com.badoo.unittest; 2 | 3 | import org.hamcrest.Matcher; 4 | import org.hamcrest.collection.IsMapContaining; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | import static org.hamcrest.CoreMatchers.allOf; 11 | import static org.hamcrest.CoreMatchers.anyOf; 12 | 13 | public class MapMatchers { 14 | 15 | public static Matcher> matchesEntriesIn(Map map) { 16 | return allOf(buildMatcherArray(map)); 17 | } 18 | 19 | public static Matcher> matchesAnyEntryIn(Map map) { 20 | return anyOf(buildMatcherArray(map)); 21 | } 22 | 23 | @SuppressWarnings("unchecked") 24 | private static Matcher>[] buildMatcherArray(Map map) { 25 | List>> entries = new ArrayList<>(); 26 | for (K key : map.keySet()) { 27 | entries.add(IsMapContaining.hasEntry(key, map.get(key))); 28 | } 29 | return entries.toArray(new Matcher[entries.size()]); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/usecases/messages/SubscribeToMessageUpdates.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.usecases.messages; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.data.repo.Repository; 6 | import com.badoo.barf.usecase.UseCase; 7 | import com.badoo.chateau.core.model.Message; 8 | import com.badoo.chateau.core.repos.messages.MessageDataSource.Update; 9 | import com.badoo.chateau.core.repos.messages.MessageQueries; 10 | 11 | import rx.Observable; 12 | 13 | /** 14 | * Use case for subscribing to new messages in a conversation 15 | */ 16 | @UseCase 17 | public class SubscribeToMessageUpdates { 18 | 19 | private final Repository mRepo; 20 | 21 | public SubscribeToMessageUpdates(Repository repo) { 22 | mRepo = repo; 23 | } 24 | 25 | public Observable> forConversation(@NonNull String conversationId) { 26 | return mRepo.query(new MessageQueries.SubscribeQuery<>(conversationId)); 27 | } 28 | 29 | public Observable> all() { 30 | return mRepo.query(new MessageQueries.SubscribeQuery<>()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Badoo Development 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/chat/messages/BaseItemClickListener.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.chat.messages; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.v7.widget.RecyclerView; 5 | 6 | import com.badoo.chateau.data.models.BaseMessage; 7 | import com.badoo.chateau.example.data.model.ExampleMessage; 8 | 9 | public class BaseItemClickListener implements MessageListAdapter.ItemClickListener { 10 | 11 | @NonNull 12 | private final RecyclerView mRecyclerView; 13 | private MessageListAdapter mAdapter; 14 | 15 | BaseItemClickListener(@NonNull RecyclerView recyclerView, @NonNull MessageListAdapter adapter) { 16 | mRecyclerView = recyclerView; 17 | mAdapter = adapter; 18 | } 19 | 20 | @Override 21 | public void onClick(@NonNull ExampleMessage message) { 22 | if(!(mRecyclerView.isComputingLayout() || mRecyclerView.isAnimating())) { 23 | mAdapter.toggleTimestampForMessage(message); 24 | } 25 | } 26 | 27 | @Override 28 | public boolean onLongPress(@NonNull ExampleMessage message) { 29 | return true; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Barf/src/main/java/com/badoo/barf/mvp/BaseRxPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.barf.mvp; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import rx.Subscription; 7 | import rx.subscriptions.CompositeSubscription; 8 | 9 | /** 10 | * A base class for presenters to provider some utility functionality to manage rx subscriptions. When using this presenter it's important 11 | * that the lifecycle methods are called at the relevant times. 12 | */ 13 | public abstract class BaseRxPresenter implements MvpPresenter { 14 | 15 | private List mSubscriptions = new ArrayList<>(); 16 | 17 | /** 18 | * Add a subscription to be tracked such that when this presenter is destroyed the subscription will be unsubscribed from. 19 | */ 20 | public void manage(Subscription subscription) { 21 | mSubscriptions.add(subscription); 22 | } 23 | 24 | @Override 25 | public void onStart() { 26 | } 27 | 28 | @Override 29 | public void onStop() { 30 | for (Subscription subscription : mSubscriptions) { 31 | subscription.unsubscribe(); 32 | } 33 | mSubscriptions.clear(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/chat/messages/viewholders/TimestampViewHolder.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.chat.messages.viewholders; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.text.format.DateUtils; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | 8 | import com.badoo.chateau.example.R; 9 | import com.badoo.chateau.data.models.BaseMessage; 10 | import com.badoo.chateau.data.models.payloads.TimestampPayload; 11 | import com.badoo.chateau.example.data.model.ExampleMessage; 12 | import com.badoo.chateau.example.ui.util.MessageViewHolder; 13 | 14 | public class TimestampViewHolder extends MessageViewHolder { 15 | 16 | private final TextView mTimestamp; 17 | 18 | public TimestampViewHolder(@NonNull View itemView) { 19 | super(itemView); 20 | mTimestamp = (TextView) itemView.findViewById(R.id.day_timestamp); 21 | } 22 | 23 | @Override 24 | protected void bindPayload(ExampleMessage message, TimestampPayload payload) { 25 | mTimestamp.setText(DateUtils.getRelativeTimeSpanString(message.getTimestamp(), System.currentTimeMillis(), DateUtils.DAY_IN_MILLIS)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/conversations/list/CreateConversationViewImpl.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.conversations.list; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.design.widget.FloatingActionButton; 5 | 6 | import com.badoo.barf.mvp.MvpView; 7 | import com.badoo.barf.mvp.PresenterFactory; 8 | import com.badoo.chateau.example.R; 9 | import com.badoo.chateau.example.ui.conversations.list.CreateConversationPresenter.CreateConversationView; 10 | import com.badoo.chateau.extras.ViewFinder; 11 | 12 | class CreateConversationViewImpl implements CreateConversationView, MvpView { 13 | 14 | private final CreateConversationPresenter mPresenter; 15 | 16 | public CreateConversationViewImpl(@NonNull ViewFinder viewFinder, 17 | @NonNull PresenterFactory presenterFactory) { 18 | mPresenter = presenterFactory.init(this); 19 | FloatingActionButton startNewChat = viewFinder.findViewById(R.id.conversations_start_new_chat_button); 20 | startNewChat.setOnClickListener(v -> mPresenter.onCreateNewConversationClicked()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/usecases/conversations/CreateGroupConversation.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.usecases.conversations; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.data.repo.Repository; 6 | import com.badoo.barf.usecase.UseCase; 7 | import com.badoo.chateau.core.model.Conversation; 8 | import com.badoo.chateau.core.repos.conversations.ConversationQueries; 9 | 10 | import java.util.List; 11 | 12 | import rx.Observable; 13 | 14 | /** 15 | * User case for creating a conversation with multiple users (group chat). To create a conversation with a single user (group chat) use {@link CreateConversation} 16 | */ 17 | @UseCase 18 | public class CreateGroupConversation { 19 | 20 | private final Repository mConversationRepository; 21 | 22 | public CreateGroupConversation(Repository conversationRepository) { 23 | mConversationRepository = conversationRepository; 24 | } 25 | 26 | public Observable execute(@NonNull List userIds, @NonNull String name) { 27 | return mConversationRepository.query(new ConversationQueries.CreateGroupConversationQuery<>(userIds, name)); 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/chat/photos/PhotoViewImpl.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.chat.photos; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.mvp.PresenterFactory; 6 | import com.badoo.chateau.example.R; 7 | import com.badoo.chateau.example.ui.widgets.ChatTextInputView; 8 | import com.badoo.chateau.extras.ViewFinder; 9 | import com.badoo.chateau.ui.chat.photos.PhotoPresenter; 10 | 11 | public class PhotoViewImpl implements PhotoPresenter.PhotoView { 12 | 13 | public PhotoViewImpl(@NonNull ViewFinder viewFinder, 14 | @NonNull PresenterFactory presenterFactory) { 15 | PhotoPresenter presenter = presenterFactory.init(this); 16 | ChatTextInputView input = viewFinder.findViewById(R.id.chat_input); 17 | input.setOnActionItemClickedListener(item -> { 18 | if (item.getItemId() == R.id.action_attachPhoto) { 19 | presenter.onPickPhoto(); 20 | } 21 | else if (item.getItemId() == R.id.action_takePhoto) { 22 | presenter.onTakePhoto(); 23 | } 24 | return true; 25 | }); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/data/model/ExampleConversation.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.data.model; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.chateau.data.models.BaseConversation; 6 | import com.badoo.chateau.data.models.BaseUser; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Conversation model for the example app. Adds information about participants and the last message sent 12 | */ 13 | public class ExampleConversation extends BaseConversation { 14 | 15 | private List mParticipants; 16 | private ExampleMessage mLastMessage; 17 | 18 | public ExampleConversation(@NonNull String id, @NonNull String name, 19 | List participants, ExampleMessage lastMessage, int unreadCount) { 20 | super(id, name, unreadCount); 21 | mParticipants = participants; 22 | mLastMessage = lastMessage; 23 | } 24 | 25 | public ExampleConversation(@NonNull String id) { 26 | super(id); 27 | } 28 | 29 | public List getParticipants() { 30 | return mParticipants; 31 | } 32 | 33 | public ExampleMessage getLastMessage() { 34 | return mLastMessage; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Chateau/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'me.tatarka.retrolambda' 2 | apply plugin: 'com.android.library' 3 | 4 | android { 5 | compileSdkVersion 23 6 | buildToolsVersion "23.0.2" 7 | 8 | defaultConfig { 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionName chateauLibraryVersionName 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | compileOptions { 20 | sourceCompatibility JavaVersion.VERSION_1_8 21 | targetCompatibility JavaVersion.VERSION_1_8 22 | } 23 | } 24 | 25 | dependencies { 26 | compile project(':ChateauCore') 27 | compile 'com.android.support:appcompat-v7:23.1.1' 28 | compile 'com.android.support:recyclerview-v7:23.1.1' 29 | compile 'com.android.support:design:23.1.1' 30 | testCompile 'junit:junit:4.12' 31 | testCompile 'org.mockito:mockito-core:1.9.5' 32 | compile('com.facebook.fresco:fresco:0.9.0') { 33 | exclude module: 'bolts-android' 34 | exclude module: 'support-v4' 35 | } 36 | } 37 | 38 | ext { 39 | artifactId = 'chateau' 40 | } 41 | apply from: '../release.gradle' -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/data/repos/session/SessionDataSource.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.data.repos.session; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.data.repo.annotations.Handles; 6 | import com.badoo.chateau.data.models.BaseUser; 7 | 8 | import rx.Observable; 9 | 10 | /** 11 | * Defines a data source for providing session data for the {@link SessionRepository} 12 | */ 13 | public interface SessionDataSource { 14 | 15 | /** 16 | * Attempt to sign in as a user with a given name and password 17 | * 18 | * @return an {@link Observable} which emits the signed in in user. 19 | */ 20 | @NonNull 21 | @Handles(SessionQuery.SignIn.class) 22 | Observable signIn(@NonNull SessionQuery.SignIn query); 23 | 24 | /** 25 | * Signs out the currently signed in user. 26 | */ 27 | @Handles(SessionQuery.SignOut.class) 28 | Observable signOut(); 29 | 30 | /** 31 | * Attempt to register a user. 32 | *

33 | * @return an {@link Observable} which emits the registered user. 34 | */ 35 | @NonNull 36 | @Handles(SessionQuery.Register.class) 37 | Observable register(@NonNull SessionQuery.Register query); 38 | } 39 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/LandingActivity.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | 7 | import com.badoo.chateau.example.ui.conversations.list.ConversationListActivity; 8 | import com.badoo.chateau.example.ui.session.login.LoginActivity; 9 | import com.parse.ParseUser; 10 | 11 | public class LandingActivity extends AppCompatActivity { 12 | @Override 13 | public void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | 16 | if (ParseUser.getCurrentUser() != null) { 17 | openConversationsList(); 18 | } 19 | else { 20 | openLogin(); 21 | } 22 | finish(); 23 | } 24 | 25 | private void openConversationsList() { 26 | final Intent intent = new Intent(this, ConversationListActivity.class); 27 | intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 28 | startActivity(intent); 29 | } 30 | 31 | private void openLogin() { 32 | final Intent intent = new Intent(this, LoginActivity.class); 33 | intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 34 | startActivity(intent); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/usecases/messages/LoadMessages.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.usecases.messages; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.data.repo.Repository; 6 | import com.badoo.barf.usecase.UseCase; 7 | import com.badoo.chateau.core.model.Message; 8 | import com.badoo.chateau.core.repos.messages.MessageDataSource.LoadResult; 9 | import com.badoo.chateau.core.repos.messages.MessageQueries.LoadQuery; 10 | 11 | import rx.Observable; 12 | 13 | @UseCase 14 | public class LoadMessages { 15 | 16 | private final Repository mRepo; 17 | 18 | public LoadMessages(Repository repo) { 19 | mRepo = repo; 20 | } 21 | 22 | public Observable> all(@NonNull String conversationId) { 23 | return mRepo.query(new LoadQuery<>(conversationId, LoadQuery.Type.ALL, null, null)); 24 | } 25 | 26 | public Observable> older(@NonNull String conversationId) { 27 | return mRepo.query(new LoadQuery<>(conversationId, LoadQuery.Type.OLDER, null, null)); 28 | } 29 | 30 | public Observable> newer(@NonNull String conversationId) { 31 | return mRepo.query(new LoadQuery<>(conversationId, LoadQuery.Type.NEWER, null, null)); 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Chateau/src/main/java/com/badoo/chateau/ui/chat/input/BaseChatInputPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.ui.chat.input; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.mvp.BaseRxPresenter; 6 | import com.badoo.barf.rx.ScheduleOn; 7 | import com.badoo.chateau.core.model.Message; 8 | import com.badoo.chateau.core.usecases.messages.SendMessage; 9 | 10 | public class BaseChatInputPresenter extends BaseRxPresenter 11 | implements ChatInputPresenter { 12 | 13 | @NonNull 14 | private final ChatInputView mView; 15 | @NonNull 16 | private final SendMessage mSendMessage; 17 | private final String mChatId; 18 | 19 | public BaseChatInputPresenter(@NonNull String chatId, 20 | @NonNull ChatInputView view, 21 | @NonNull SendMessage sendMessage) { 22 | mChatId = chatId; 23 | mView = view; 24 | mSendMessage = sendMessage; 25 | } 26 | 27 | public String getChatId() { 28 | return mChatId; 29 | } 30 | 31 | @Override 32 | public void onSendMessage(@NonNull M message) { 33 | manage(mSendMessage.execute(mChatId, message) 34 | .compose(ScheduleOn.io()).subscribe()); 35 | mView.clearText(); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/session/login/LoginPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.session.login; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.annotation.Nullable; 5 | 6 | import com.badoo.barf.mvp.FlowListener; 7 | import com.badoo.barf.mvp.MvpPresenter; 8 | import com.badoo.barf.mvp.MvpView; 9 | 10 | public interface LoginPresenter extends MvpPresenter { 11 | 12 | void onSignIn(@NonNull String userName, @NonNull String password); 13 | 14 | void onNotRegistered(); 15 | 16 | interface LoginFlowListener extends FlowListener { 17 | 18 | void userLoggedIn(); 19 | 20 | void userNotRegistered(); 21 | } 22 | 23 | interface LoginView extends MvpView { 24 | 25 | void showUserNameEmptyError(); 26 | 27 | void showPasswordEmptyError(); 28 | 29 | /** 30 | * Show an error message to the user (if the error warrants it) 31 | * 32 | * @param fatal true if the error was fatal, false if it can be ignored while still maintaining some functionality. 33 | */ 34 | void showError(boolean fatal, @Nullable Throwable throwable); 35 | 36 | void clearAllErrors(); 37 | 38 | void displayProgress(); 39 | 40 | void hideProgress(); 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chateau/src/main/java/com/badoo/chateau/ui/chat/info/BaseChatInfoPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.ui.chat.info; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.mvp.BaseRxPresenter; 6 | import com.badoo.barf.rx.ScheduleOn; 7 | import com.badoo.chateau.core.model.Conversation; 8 | import com.badoo.chateau.core.usecases.conversations.GetConversation; 9 | 10 | /** 11 | */ 12 | public class BaseChatInfoPresenter extends BaseRxPresenter implements ChatInfoPresenter { 13 | 14 | @NonNull 15 | private final ChatInfoView mView; 16 | @NonNull 17 | private final String mConversationId; 18 | @NonNull 19 | private final GetConversation mGetConversation; 20 | 21 | public BaseChatInfoPresenter(@NonNull ChatInfoView view, 22 | @NonNull String conversationId, 23 | @NonNull GetConversation getConversation) { 24 | mView = view; 25 | mConversationId = conversationId; 26 | mGetConversation = getConversation; 27 | } 28 | 29 | @Override 30 | public void onStart() { 31 | super.onStart(); 32 | manage(mGetConversation.execute(mConversationId) 33 | .compose(ScheduleOn.io()) 34 | .subscribe(mView::showConversation)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/util/recycle/AboveFabItemDecoration.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.util.recycle; 2 | 3 | import android.graphics.Rect; 4 | import android.support.annotation.NonNull; 5 | import android.support.design.widget.FloatingActionButton; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.view.View; 8 | 9 | /** 10 | * Item decoration that ensures that enough padding is added to the last item in the list to ensure that it scrolls above the 11 | * floating action button. 12 | */ 13 | public final class AboveFabItemDecoration extends RecyclerView.ItemDecoration { 14 | 15 | private final FloatingActionButton mFab; 16 | 17 | public AboveFabItemDecoration(@NonNull FloatingActionButton fab) { 18 | mFab = fab; 19 | } 20 | 21 | @Override 22 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 23 | super.getItemOffsets(outRect, view, parent, state); 24 | 25 | final int itemPosition = parent.getChildAdapterPosition(view); 26 | if (itemPosition == RecyclerView.NO_POSITION) { 27 | return; 28 | } 29 | 30 | final int itemCount = state.getItemCount(); 31 | if (itemCount > 0 && itemPosition == itemCount - 1) { 32 | outRect.set(0, 0, 0, mFab.getHeight()); 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/session/register/RegistrationPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.session.register; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.annotation.Nullable; 5 | 6 | import com.badoo.barf.mvp.FlowListener; 7 | import com.badoo.barf.mvp.MvpPresenter; 8 | import com.badoo.barf.mvp.MvpView; 9 | 10 | public interface RegistrationPresenter extends MvpPresenter { 11 | 12 | void onRegister(@NonNull String userName, @NonNull String displayName, @NonNull String password); 13 | 14 | void onAlreadyRegistered(); 15 | 16 | interface RegistrationFlowListener extends FlowListener { 17 | 18 | void userRegistered(); 19 | 20 | void userAlreadyRegistered(); 21 | } 22 | 23 | interface RegistrationView extends MvpView { 24 | 25 | void showUserNameEmptyError(); 26 | 27 | void showDisplayNameEmptyError(); 28 | 29 | void showPasswordEmptyError(); 30 | 31 | /** 32 | * Show an error message to the user (if the error warrants it) 33 | * 34 | * @param fatal true if the error was fatal, false if it can be ignored while still maintaining some functionality. 35 | */ 36 | void showError(boolean fatal, @Nullable Throwable throwable); 37 | 38 | void clearAllErrors(); 39 | 40 | void showProgress(); 41 | 42 | void hideProgress(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Chateau/src/main/java/com/badoo/chateau/ui/conversations/create/selectusers/UserListPresenter.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.ui.conversations.create.selectusers; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.annotation.Nullable; 5 | 6 | import com.badoo.barf.mvp.FlowListener; 7 | import com.badoo.barf.mvp.MvpPresenter; 8 | import com.badoo.barf.mvp.MvpView; 9 | import com.badoo.chateau.core.model.Conversation; 10 | import com.badoo.chateau.core.model.User; 11 | 12 | import java.util.List; 13 | 14 | public interface UserListPresenter extends MvpPresenter { 15 | 16 | /** 17 | * To be invoked when the final selection of users has been made. 18 | */ 19 | void onUsersSelected(List userIds); 20 | 21 | interface UserListView extends MvpView { 22 | 23 | void showUsers(@NonNull List users); 24 | 25 | /** 26 | * Show an error message to the user (if the error warrants it) 27 | * 28 | * @param fatal true if the error was fatal, false if it can be ignored while still maintaining some functionality. 29 | */ 30 | void showError(boolean fatal, @Nullable Throwable throwable); 31 | 32 | } 33 | 34 | interface UserListFlowListener extends FlowListener { 35 | 36 | void requestOpenChat(@NonNull C conversation); 37 | 38 | void requestCreateGroupChat(@NonNull List users); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ExampleApp/src/main/java/com/badoo/chateau/example/ui/chat/input/ChatInputViewImpl.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.chat.input; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.mvp.MvpView; 6 | import com.badoo.barf.mvp.PresenterFactory; 7 | import com.badoo.chateau.example.R; 8 | import com.badoo.chateau.example.data.model.ExampleMessage; 9 | import com.badoo.chateau.example.ui.widgets.ChatTextInputView; 10 | import com.badoo.chateau.extras.ViewFinder; 11 | import com.badoo.chateau.ui.chat.input.ChatInputPresenter; 12 | 13 | import static com.badoo.chateau.ui.chat.input.ChatInputPresenter.ChatInputView; 14 | 15 | public class ChatInputViewImpl implements ChatInputView { 16 | 17 | private final ChatTextInputView mInput; 18 | @NonNull 19 | private final ChatInputPresenter mPresenter; 20 | 21 | public ChatInputViewImpl(@NonNull String conversationId, 22 | @NonNull ViewFinder viewFinder, 23 | @NonNull PresenterFactory> presenterFactory) { 24 | mPresenter = presenterFactory.init(this); 25 | mInput = viewFinder.findViewById(R.id.chat_input); 26 | mInput.setOnSendClickListener(v -> mPresenter.onSendMessage(ExampleMessage.createOutgoingTextMessage(conversationId, mInput.getText()))); 27 | } 28 | 29 | @Override 30 | public void clearText() { 31 | mInput.clearText(); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/layout/activity_chat.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 16 | 17 | 22 | 23 | 29 | 30 | 31 | 32 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /ExampleApp/src/test/java/com/badoo/chateau/example/usecases/session/SignOutTest.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.usecases.session; 2 | 3 | import com.badoo.barf.data.repo.Repository; 4 | import com.badoo.chateau.example.data.model.ExampleUser; 5 | import com.badoo.chateau.example.data.repos.session.SessionQuery; 6 | 7 | import com.badoo.unittest.rx.BaseRxTestCase; 8 | 9 | import org.junit.Before; 10 | import org.junit.Test; 11 | import org.junit.runner.RunWith; 12 | import org.mockito.Mock; 13 | import org.mockito.runners.MockitoJUnitRunner; 14 | 15 | import rx.Observable; 16 | 17 | import static org.mockito.Matchers.eq; 18 | import static org.mockito.Mockito.times; 19 | import static org.mockito.Mockito.verify; 20 | import static org.mockito.Mockito.when; 21 | 22 | @RunWith(MockitoJUnitRunner.class) 23 | public class SignOutTest extends BaseRxTestCase { 24 | 25 | @Mock 26 | private Repository mMockRepository; 27 | private SignOut mTarget; 28 | 29 | @Before 30 | public void beforeTest() { 31 | super.beforeTest(); 32 | mTarget = new SignOut(mMockRepository); 33 | } 34 | 35 | @Test 36 | public void whenMessagesForChatRequested_thenRepoIsQueriedForCorrectChatId() throws Exception { 37 | // Setup 38 | when(mMockRepository.query(eq(new SessionQuery.SignOut()))) 39 | .thenReturn(Observable.empty()); 40 | 41 | // Execute 42 | mTarget.execute(); 43 | 44 | // Assert 45 | verify(mMockRepository, times(1)).query(eq(new SessionQuery.SignOut())); 46 | } 47 | } -------------------------------------------------------------------------------- /ExampleApp/src/test/java/com/badoo/chateau/example/ui/utils/TestUtils.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.example.ui.utils; 2 | 3 | import android.database.Observable; 4 | import android.support.v7.widget.RecyclerView; 5 | 6 | import java.lang.reflect.Field; 7 | import java.util.ArrayList; 8 | 9 | import static org.mockito.Mockito.mock; 10 | 11 | public final class TestUtils { 12 | 13 | private TestUtils() {} 14 | 15 | /** 16 | * Fixes internal dependencies to android.database.Observable so that a RecyclerView.Adapter can be tested using regular unit tests while 17 | * observing changes to the data setIsTypingRepository. 18 | */ 19 | public static RecyclerView.AdapterDataObserver fixAdapterForTesting(RecyclerView.Adapter adapter) throws NoSuchFieldException, IllegalAccessException { 20 | // Observables are not mocked by default so we need to hook the adapter up to an observer so we can track changes 21 | Field observableField = RecyclerView.Adapter.class.getDeclaredField("mObservable"); 22 | observableField.setAccessible(true); 23 | Object observable = observableField.get(adapter); 24 | Field observersField = Observable.class.getDeclaredField("mObservers"); 25 | observersField.setAccessible(true); 26 | final ArrayList observers = new ArrayList<>(); 27 | RecyclerView.AdapterDataObserver dataObserver = mock(RecyclerView.AdapterDataObserver.class); 28 | observers.add(dataObserver); 29 | observersField.set(observable, observers); 30 | return dataObserver; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ChateauCore/src/main/java/com/badoo/chateau/core/usecases/conversations/LoadConversations.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.usecases.conversations; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.badoo.barf.data.repo.Repository; 6 | import com.badoo.barf.usecase.UseCase; 7 | import com.badoo.chateau.core.model.Conversation; 8 | import com.badoo.chateau.core.repos.conversations.ConversationDataSource.LoadResult; 9 | 10 | import rx.Observable; 11 | 12 | import static com.badoo.chateau.core.repos.conversations.ConversationQueries.LoadConversationsQuery; 13 | import static com.badoo.chateau.core.repos.conversations.ConversationQueries.LoadConversationsQuery.*; 14 | 15 | /** 16 | * Use case for retrieving all conversations that the current user is involved in. 17 | */ 18 | @UseCase 19 | public class LoadConversations { 20 | 21 | private Repository mConversationRepository; 22 | 23 | public LoadConversations(Repository conversationRepository) { 24 | mConversationRepository = conversationRepository; 25 | } 26 | 27 | public final Observable> all() { 28 | return execute(Type.ALL); 29 | } 30 | 31 | public final Observable> newer() { 32 | return execute(Type.NEWER); 33 | } 34 | 35 | public final Observable> older() { 36 | return execute(Type.OLDER); 37 | } 38 | 39 | protected Observable> execute(@NonNull Type type) { 40 | return mConversationRepository.query(new LoadConversationsQuery<>(type, null, null)); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /Chateau/src/main/java/com/badoo/chateau/data/models/BaseUser.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.data.models; 2 | 3 | import com.badoo.chateau.core.model.User; 4 | 5 | /** 6 | * Use model containing fields common to users 7 | */ 8 | public class BaseUser implements User { 9 | 10 | private final String mUserId; 11 | private final String mDisplayName; 12 | 13 | public BaseUser(String userId, String displayName) { 14 | mUserId = userId; 15 | mDisplayName = displayName; 16 | } 17 | 18 | public String getUserId() { 19 | return mUserId; 20 | } 21 | 22 | public String getDisplayName() { 23 | return mDisplayName; 24 | } 25 | 26 | @Override 27 | public boolean equals(Object o) { 28 | if (this == o) return true; 29 | if (o == null || getClass() != o.getClass()) return false; 30 | 31 | BaseUser baseUser = (BaseUser) o; 32 | 33 | if (mUserId != null ? !mUserId.equals(baseUser.mUserId) : baseUser.mUserId != null) return false; 34 | return mDisplayName != null ? mDisplayName.equals(baseUser.mDisplayName) : baseUser.mDisplayName == null; 35 | 36 | } 37 | 38 | @Override 39 | public int hashCode() { 40 | int result = mUserId != null ? mUserId.hashCode() : 0; 41 | result = 31 * result + (mDisplayName != null ? mDisplayName.hashCode() : 0); 42 | return result; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return "BaseUser{" + 48 | "mUserId='" + mUserId + '\'' + 49 | ", mDisplayName='" + mDisplayName + '\'' + 50 | '}'; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ExampleApp/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #c5cae9 4 | #3f51b5 5 | #303f9f 6 | 7 | #ff80ab 8 | #ff4081 9 | #f50057 10 | 11 | #fafafa 12 | #f5f5f5 13 | #eeeeee 14 | #e0e0e0 15 | #bdbdbd 16 | #9e9e9e 17 | #757575 18 | #616161 19 | #424242 20 | #212121 21 | 22 | 23 | #DE000000 24 | #8A000000 25 | #61000000 26 | #1F000000 27 | 28 | 29 | #B3FFFFFF 30 | #B3FFFFFF 31 | #80000000 32 | #1F000000 33 | 34 | #607d8b 35 | 36 | #80FF0000 37 | 38 | 39 | #400f58ff 40 | #60a0ffa0 41 | 42 | -------------------------------------------------------------------------------- /ExampleApp/src/test/java/com/badoo/chateau/core/usecases/istyping/SendUserIsTypingTest.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.usecases.istyping; 2 | 3 | import com.badoo.barf.data.repo.Repository; 4 | import com.badoo.chateau.core.repos.istyping.IsTypingQueries; 5 | import com.badoo.chateau.example.data.model.ExampleUser; 6 | import com.badoo.unittest.rx.BaseRxTestCase; 7 | 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.mockito.Mock; 12 | import org.mockito.runners.MockitoJUnitRunner; 13 | 14 | import rx.Observable; 15 | 16 | import static org.mockito.Matchers.eq; 17 | import static org.mockito.Mockito.times; 18 | import static org.mockito.Mockito.verify; 19 | import static org.mockito.Mockito.when; 20 | 21 | @RunWith(MockitoJUnitRunner.class) 22 | public class SendUserIsTypingTest extends BaseRxTestCase { 23 | 24 | private static final String CHAT_ID = "chat"; 25 | 26 | @Mock 27 | private Repository mMockRepository; 28 | private SendUserIsTyping mTarget; 29 | 30 | @Before 31 | public void beforeTest() { 32 | super.beforeTest(); 33 | mTarget = new SendUserIsTyping(mMockRepository); 34 | } 35 | 36 | @Test 37 | public void whenMessagesForChatRequested_thenRepoIsQueriedForCorrectChatId() throws Exception { 38 | // Setup 39 | when(mMockRepository.query(eq(new IsTypingQueries.SendIsTyping(CHAT_ID)))) 40 | .thenReturn(Observable.empty()); 41 | 42 | // Execute 43 | mTarget.execute(CHAT_ID); 44 | 45 | // Assert 46 | verify(mMockRepository, times(1)).query(eq(new IsTypingQueries.SendIsTyping(CHAT_ID))); 47 | } 48 | } -------------------------------------------------------------------------------- /ExampleApp/src/test/java/com/badoo/chateau/core/usecases/conversations/SubscribeToUpdatesQueryTest.java: -------------------------------------------------------------------------------- 1 | package com.badoo.chateau.core.usecases.conversations; 2 | 3 | import com.badoo.barf.data.repo.Repository; 4 | import com.badoo.chateau.core.repos.conversations.ConversationQueries; 5 | import com.badoo.chateau.example.data.model.ExampleConversation; 6 | import com.badoo.unittest.rx.BaseRxTestCase; 7 | 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.mockito.Mock; 12 | import org.mockito.runners.MockitoJUnitRunner; 13 | 14 | import rx.Observable; 15 | 16 | import static org.mockito.Matchers.eq; 17 | import static org.mockito.Mockito.times; 18 | import static org.mockito.Mockito.verify; 19 | import static org.mockito.Mockito.when; 20 | 21 | @RunWith(MockitoJUnitRunner.class) 22 | public class SubscribeToUpdatesQueryTest extends BaseRxTestCase { 23 | 24 | @Mock 25 | private Repository mMockRepository; 26 | private SubscribeToConversationUpdates mTarget; 27 | 28 | @Before 29 | public void beforeTest() { 30 | super.beforeTest(); 31 | mTarget = new SubscribeToConversationUpdates(mMockRepository); 32 | } 33 | 34 | @Test 35 | public void whenMessagesForChatRequested_thenRepoIsQueriedForCorrectChatId() throws Exception { 36 | // Setup 37 | when(mMockRepository.query(eq(new ConversationQueries.SubscribeToUpdatesQuery()))) 38 | .thenReturn(Observable.just(true)); 39 | 40 | // Execute 41 | mTarget.execute(); 42 | 43 | // Assert 44 | verify(mMockRepository, times(1)).query(eq(new ConversationQueries.SubscribeToUpdatesQuery())); 45 | } 46 | } -------------------------------------------------------------------------------- /ExampleApp/src/main/res/layout/activity_name_group.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 17 | 18 | 22 | 23 | 30 | 31 | 32 | 33 |