├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── data ├── build.gradle └── src │ ├── main │ └── java │ │ └── data │ │ ├── cache │ │ └── RxProviders.java │ │ ├── internal │ │ └── di │ │ │ └── DataModule.java │ │ ├── net │ │ └── RestApi.java │ │ ├── sections │ │ ├── DataRepository.java │ │ ├── UI.java │ │ └── user_demo │ │ │ └── UserDemoDataRepository.java │ │ └── storage │ │ └── RepositoryAdapter.java │ └── test │ └── java │ └── data │ ├── net │ └── RestApiTest.java │ └── user_demo │ └── UserDemoDataRepositoryTest.java ├── domain ├── build.gradle └── src │ ├── main │ └── java │ │ └── domain │ │ ├── foundation │ │ ├── BaseView.java │ │ ├── Presenter.java │ │ ├── Repository.java │ │ ├── UseCase.java │ │ ├── helpers │ │ │ └── ParserException.java │ │ └── schedulers │ │ │ ├── ObserveOn.java │ │ │ └── SubscribeOn.java │ │ ├── internal │ │ └── di │ │ │ └── DomainModule.java │ │ └── sections │ │ ├── UI.java │ │ ├── Wireframe.java │ │ ├── dashboard │ │ ├── DashboardItemsMenu.java │ │ ├── DashboardPresenter.java │ │ ├── DashboardView.java │ │ ├── GetMenuItemsUseCase.java │ │ └── ItemMenu.java │ │ ├── launch │ │ ├── LaunchPresenter.java │ │ └── LaunchView.java │ │ └── user_demo │ │ ├── UserDemoRepository.java │ │ ├── common │ │ └── UserView.java │ │ ├── detail │ │ ├── GetSelectedDemoUserListUseCase.java │ │ └── UserDemoPresenter.java │ │ ├── entities │ │ └── UserDemoEntity.java │ │ ├── list │ │ ├── GetUsersDemoUseCase.java │ │ ├── SaveUserDemoSelectedListUseCase.java │ │ ├── UsersDemoPresenter.java │ │ └── UsersView.java │ │ └── search │ │ ├── SearchUserDemoPresenter.java │ │ └── SearchUserDemoUseCase.java │ └── test │ └── java │ └── domain │ ├── common │ └── BaseTest.java │ ├── foundation │ ├── PresenterErrorsTest.java │ └── PresenterSubscriptionsTest.java │ └── sections │ ├── dashboard │ └── GetMenuItemsUseCaseTest.java │ └── user_demo │ ├── detail │ └── GetSelectedDemoUserListUseCaseTest.java │ ├── list │ ├── GetUsersDemoUseCaseTest.java │ └── SaveUserDemoSelectedListUseCaseTest.java │ └── search │ └── SearchUserDemoUseCaseTest.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── presentation ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── presentation │ │ ├── common │ │ ├── BaseTest.java │ │ ├── SuiteIntegration.java │ │ └── ViewActions.java │ │ └── sections │ │ ├── dashboard │ │ └── DashboardTest.java │ │ └── user_demo │ │ └── UsersTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── presentation │ │ ├── foundation │ │ ├── AppCare.java │ │ ├── BaseApp.java │ │ ├── BaseFragmentActivity.java │ │ ├── BasePresenterFragment.java │ │ ├── LayoutResActivity.java │ │ ├── LayoutResFragment.java │ │ └── SingleFragmentActivity.java │ │ ├── internal │ │ └── di │ │ │ ├── ApplicationComponent.java │ │ │ ├── ApplicationModule.java │ │ │ ├── DataPresentationModule.java │ │ │ └── DomainPresentationModule.java │ │ ├── sections │ │ ├── UIData.java │ │ ├── UIDomain.java │ │ ├── WireframeDomain.java │ │ ├── dashboard │ │ │ ├── DashBoardActivity.java │ │ │ ├── DashboardItemsMenuDomain.java │ │ │ └── ItemMenuViewGroup.java │ │ ├── launch │ │ │ └── LaunchActivity.java │ │ └── user_demo │ │ │ ├── UserViewGroup.java │ │ │ ├── detail │ │ │ └── UserFragment.java │ │ │ ├── list │ │ │ └── UsersFragment.java │ │ │ └── search │ │ │ └── SearchUserFragment.java │ │ └── utilities │ │ └── recyclerview_adapter │ │ ├── RecyclerViewAdapter.java │ │ └── ViewWrapper.java │ └── res │ ├── drawable-xxxhdpi │ ├── geek.jpg │ ├── ic_search.png │ ├── ic_user.png │ └── ic_users.png │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── sections │ ├── common │ │ └── layout │ │ │ ├── action_bar.xml │ │ │ ├── single_fragment_activity.xml │ │ │ └── toolbar.xml │ ├── dashboard │ │ └── layout │ │ │ ├── dashboard_activity.xml │ │ │ └── item_menu_view_group.xml │ └── user_demo │ │ └── layout │ │ ├── user_fragment.xml │ │ ├── user_search_fragment.xml │ │ ├── user_view_group.xml │ │ └── users_fragment.xml │ ├── values-sw600dp │ └── dimens.xml │ ├── values-sw720dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── ids.xml │ ├── strings.xml │ └── styles.xml ├── settings.gradle └── start_fresh ├── AndroidManifest ├── ApplicationComponent ├── DataModule ├── DomainPresentationModule ├── LICENSE ├── LaunchPresenter ├── README.md ├── RestApi ├── RxProviders ├── SuiteIntegration ├── Wireframe ├── WireframeDomain ├── build ├── build_presentation ├── strings └── styles /.gitignore: -------------------------------------------------------------------------------- 1 | # Built 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 | 15 | # Gradle files 16 | .gradle/ 17 | **/build/ 18 | 19 | # Local configuration file (sdk path, etc) 20 | local.properties 21 | 22 | # Proguard folder generated by Eclipse 23 | proguard/ 24 | 25 | # Log Files 26 | *.log 27 | 28 | # Android Studio 29 | .navigation/ 30 | .idea/ 31 | **/*.iml 32 | 33 | # Android Studio captures folder 34 | captures/ 35 | 36 | # .DS_Store files 37 | **/.DS_Store 38 | 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-base__app__android-green.svg?style=true)](https://android-arsenal.com/details/1/3040) 2 | 3 | Base App Android 4 | ================ 5 | 6 | Base skeleton structure to start every new project, based on the design patters suggested by Robert C. Martin *(aka Uncle Bob)* on his clean architecture. 7 | 8 | *base_app_android* is the project which we use at [Refineria Web](http://www.refineriaweb.com/servicios/desarrollo-apps-moviles/) to start any new Android project. It presents a structure of 3 layers, domain, data and presentation; this approach has been chosen with the purpose of creating an application that conducts unit testing and also allow the portability between platforms, mainly iOS. 9 | 10 | The project is divided in three modules: 11 | * **domain**: java library project. Every test is a unit test and all its dependencies are pure java libraries: dagger 2, rxjava, lombok, junit and mockito. 12 | * **data**: java library project. It’s the repository that supplies the data which will be consumed by the domain module. Dependencies: domain module, retrofit 2, dagger 2, rxjava, rxcache, lombok, junit, and mockito. 13 | * **presentation**: android app project. It links the two previous modules and implement all the views interfaces defined in domain module. Dependencies: domain and data module, dagger 2, rxAndroid, lombok, butterknife and espresso. 14 | 15 | The application implements a minimal example using the Github Api. The purpose is to illustrate in a simple way the natural workflow derived from this kind of architecture, using the classes created in the foundation packages in every one of the 3 layers. 16 | 17 | To facility the use of this project as a common base one for any new project, a gradle task called *freshStart* has been created. This task removes the earlier mentioned minimal example, leaving the appliaction in an optimal state to start any new project. 18 | 19 | Just run the next command from any terminal located at the root project: 20 | 21 | ```gradle 22 | $ ./gradlew freshStart 23 | ``` 24 | After that, build and clean project 25 | 26 | ## Some considerations: 27 | + [Lombok Plugin for IntelliJ IDEA](https://github.com/mplushnikov/lombok-intellij-plugin) is required in order to support the annotations generated by [Lombo library](https://github.com/rzwitserloot/lombok) 28 | + [Spoon](https://github.com/square/spoon) has a [Spoon Gradle Plugin](https://github.com/stanfy/spoon-gradle-plugin) that allows you running a specific test suite or a test class by passing a parameter, e.g: 29 | ```gradle 30 | $ ./gradlew clean build spoon -P classNameTestTuRun=fully.qualified.TestCase 31 | $ ./gradlew clean build spoon -P classNameTestTuRun=presentation.common.SuiteIntegration 32 | ``` 33 | 34 | + To use [Gradle Retrolambda Plugin](https://github.com/evant/gradle-retrolambda) you will need to install [JDK 8](http://www.oracle.com/technetwork/java/javase/overview/java8-2100321.html) and create JAVA8_HOME environment variable. The same for your previous JDK (e.g: JAVA7_HOME). So please make sure that JAVA8_HOME and JAVA7_HOME has been added to the path of the system 35 | ```bash 36 | $ nano ~/.bash_profile 37 | export JAVA8_HOME=/Library/Java/JavaVirtualMachines/jdk8_etc/Contents/Home 38 | export JAVA7_HOME=/Library/Java/JavaVirtualMachines/jdk7_etc/Contents/Home 39 | export PATH=$PATH:$JAVA8_HOME:$JAVA7_HOME 40 | ``` 41 | 42 | Also, specify in Android Studio the JDK Location pointing to jdk8 43 | /Library/Java/JavaVirtualMachines/jdk8_etc/Contents/Home 44 | -------------------------------------------------------------------------------- /data/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'me.tatarka.retrolambda' 3 | 4 | buildscript { 5 | repositories { 6 | mavenCentral() 7 | jcenter() 8 | maven { 9 | url "https://plugins.gradle.org/m2/" 10 | } 11 | } 12 | 13 | dependencies { 14 | classpath rootProject.ext.buildScriptDependencies.retrolambda 15 | classpath rootProject.ext.buildScriptDependencies.javaApt 16 | } 17 | } 18 | 19 | apply plugin: 'idea' 20 | apply plugin: "net.ltgt.apt" 21 | 22 | sourceCompatibility = JavaVersion.VERSION_1_8 23 | targetCompatibility = JavaVersion.VERSION_1_8 24 | 25 | configurations { 26 | provided 27 | } 28 | 29 | sourceSets { 30 | main { 31 | compileClasspath += configurations.provided 32 | runtimeClasspath += configurations.provided 33 | } 34 | } 35 | 36 | dependencies { 37 | compile fileTree(dir: 'libs', include: ['*.jar']) 38 | compile project(':domain') 39 | 40 | 41 | def dataDependencies = rootProject.ext.dataDependencies 42 | 43 | compile dataDependencies.retrofit 44 | compile dataDependencies.retrofitAdapterRxJava 45 | compile dataDependencies.retrofitConverterGson 46 | compile dataDependencies.rxCache 47 | 48 | apt dataDependencies.daggerCompiler 49 | compile dataDependencies.dagger 50 | 51 | provided dataDependencies.javaxAnnotation 52 | compile dataDependencies.rxJava 53 | 54 | provided dataDependencies.lombok 55 | apt dataDependencies.lombok 56 | 57 | def dataTestDependencies = rootProject.ext.dataTestDependencies 58 | testCompile dataTestDependencies.junit 59 | testCompile dataTestDependencies.mockito 60 | } 61 | 62 | retrolambda { 63 | jdk System.getenv("JAVA8_HOME") 64 | oldJdk System.getenv("JAVA7_HOME") 65 | javaVersion JavaVersion.VERSION_1_7 66 | } -------------------------------------------------------------------------------- /data/src/main/java/data/cache/RxProviders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package data.cache; 18 | 19 | import domain.sections.user_demo.entities.UserDemoEntity; 20 | import io.rx_cache.EvictProvider; 21 | import rx.Observable; 22 | 23 | /** 24 | * Providers for RxCache 25 | */ 26 | public interface RxProviders { 27 | Observable getSelectedUserDemoList(Observable oUserSelected, EvictProvider evictProvider); 28 | } 29 | -------------------------------------------------------------------------------- /data/src/main/java/data/internal/di/DataModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package data.internal.di; 18 | 19 | import javax.inject.Singleton; 20 | 21 | import dagger.Module; 22 | import dagger.Provides; 23 | import data.cache.RxProviders; 24 | import data.net.RestApi; 25 | import data.sections.user_demo.UserDemoDataRepository; 26 | import data.storage.RepositoryAdapter; 27 | import domain.sections.user_demo.UserDemoRepository; 28 | import io.rx_cache.internal.RxCache; 29 | import retrofit2.Retrofit; 30 | import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; 31 | import retrofit2.converter.gson.GsonConverterFactory; 32 | 33 | /** 34 | * Dagger module for data layer. {@link #provideRestApi} define the interface used by retrofit in order 35 | * to generate every endpoint required 36 | * 37 | * {@link #provideUserDemoDataRepository} is an example of repository. UserDemoDataRepository implements the interface defined 38 | * in the domain layer, it required to be able to launch the application. 39 | */ 40 | @Module 41 | public class DataModule { 42 | 43 | @Singleton @Provides RestApi provideRestApi() { 44 | return new Retrofit.Builder() 45 | .baseUrl(RestApi.URL_BASE) 46 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 47 | .addConverterFactory(GsonConverterFactory.create()) 48 | .build().create(RestApi.class); 49 | } 50 | 51 | @Singleton @Provides RxProviders provideRxProviders(RepositoryAdapter repositoryAdapter) { 52 | return new RxCache.Builder() 53 | .persistence(repositoryAdapter.cacheDirectory()) 54 | .using(RxProviders.class); 55 | } 56 | 57 | @Provides @Singleton public UserDemoRepository provideUserDemoDataRepository(UserDemoDataRepository userDemoDataRepository) { 58 | return userDemoDataRepository; 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /data/src/main/java/data/net/RestApi.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package data.net; 18 | 19 | import java.util.List; 20 | 21 | import domain.sections.user_demo.entities.UserDemoEntity; 22 | import retrofit2.Response; 23 | import retrofit2.http.GET; 24 | import retrofit2.http.Headers; 25 | import retrofit2.http.Path; 26 | import rx.Observable; 27 | 28 | 29 | /** 30 | * Definition for Retrofit of every endpoint required by the Api. 31 | * {@link #getUsers()} and {@link #getUser(String)} are both and example of endpoint} 32 | */ 33 | public interface RestApi { 34 | String URL_BASE = "https://api.github.com"; 35 | String HEADER_API_VERSION = "Accept: application/vnd.github.v3+json"; 36 | 37 | @Headers({HEADER_API_VERSION}) 38 | @GET("/users/{username}") Observable> getUser(@Path("username") String username); 39 | 40 | @Headers({HEADER_API_VERSION}) 41 | @GET("/users") Observable>> getUsers(); 42 | } 43 | -------------------------------------------------------------------------------- /data/src/main/java/data/sections/DataRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package data.sections; 18 | 19 | import com.google.gson.Gson; 20 | import com.google.gson.JsonParseException; 21 | 22 | import java.io.IOException; 23 | 24 | import data.cache.RxProviders; 25 | import data.net.RestApi; 26 | import domain.foundation.Repository; 27 | import lombok.Data; 28 | import retrofit2.Response; 29 | import rx.Observable; 30 | 31 | 32 | public abstract class DataRepository implements Repository { 33 | protected final RestApi restApi; 34 | protected final RxProviders rxProviders; 35 | protected final UI UI; 36 | 37 | public DataRepository(RestApi restApi, RxProviders rxProviders, UI ui) { 38 | this.restApi = restApi; 39 | this.rxProviders = rxProviders; 40 | this.UI = ui; 41 | } 42 | 43 | protected void handleError(Response response) { 44 | if (response.isSuccess()) return; 45 | 46 | try { 47 | ResponseError responseError = new Gson().fromJson(response.errorBody().string(), ResponseError.class); 48 | throw new RuntimeException(responseError.getMessage()); 49 | } catch (JsonParseException |IOException exception) { 50 | throw new RuntimeException(); 51 | } 52 | } 53 | 54 | @Data private static class ResponseError { 55 | private final String message; 56 | } 57 | 58 | protected Observable buildObservableError(String message) { 59 | return Observable.create(subscriber -> subscriber.onError(new RuntimeException(message))); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /data/src/main/java/data/sections/UI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package data.sections; 18 | 19 | import rx.Observable; 20 | 21 | public interface UI { 22 | Observable genericError(); 23 | } 24 | -------------------------------------------------------------------------------- /data/src/main/java/data/sections/user_demo/UserDemoDataRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package data.sections.user_demo; 18 | 19 | 20 | import java.util.List; 21 | 22 | import javax.inject.Inject; 23 | 24 | import data.cache.RxProviders; 25 | import data.net.RestApi; 26 | import data.sections.DataRepository; 27 | import data.sections.UI; 28 | import domain.sections.user_demo.UserDemoRepository; 29 | import domain.sections.user_demo.entities.UserDemoEntity; 30 | import io.rx_cache.EvictProvider; 31 | import rx.Observable; 32 | 33 | public class UserDemoDataRepository extends DataRepository implements UserDemoRepository { 34 | 35 | @Inject public UserDemoDataRepository(RestApi restApi, RxProviders rxProviders, UI ui) { 36 | super(restApi, rxProviders, ui); 37 | } 38 | 39 | @Override public Observable searchByUserName(final String username) { 40 | return restApi.getUser(username).map(response -> { 41 | handleError(response); 42 | final UserDemoEntity user = response.body(); 43 | return user; 44 | }); 45 | } 46 | 47 | @Override public Observable> askForUsers() { 48 | return restApi.getUsers().map(response -> { 49 | handleError(response); 50 | return response.body(); 51 | }); 52 | } 53 | 54 | @Override public Observable getSelectedUserDemoList() { 55 | return rxProviders.getSelectedUserDemoList(Observable.just(null), new EvictProvider(false)); 56 | } 57 | 58 | @Override public Observable saveSelectedUserDemoList(UserDemoEntity userSelected) { 59 | return rxProviders.getSelectedUserDemoList(Observable.just(userSelected), new EvictProvider(true)) 60 | .map(user-> true); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /data/src/main/java/data/storage/RepositoryAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package data.storage; 18 | 19 | import java.io.File; 20 | 21 | /** 22 | * Provides the file system which will be injected in the Persistence class through Dagger. 23 | * @see data.storage.Persistence 24 | * {@link #cacheDirectory()} will be provided by the presentation layer. 25 | */ 26 | public interface RepositoryAdapter { 27 | File cacheDirectory(); 28 | } 29 | -------------------------------------------------------------------------------- /data/src/test/java/data/net/RestApiTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package data.net; 18 | 19 | import org.junit.Before; 20 | import org.junit.FixMethodOrder; 21 | import org.junit.Test; 22 | import org.junit.runners.MethodSorters; 23 | 24 | import java.util.List; 25 | 26 | import domain.sections.user_demo.entities.UserDemoEntity; 27 | import retrofit2.Response; 28 | import retrofit2.Retrofit; 29 | import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; 30 | import retrofit2.converter.gson.GsonConverterFactory; 31 | import rx.observers.TestSubscriber; 32 | 33 | import static org.hamcrest.core.Is.is; 34 | import static org.hamcrest.core.IsNot.not; 35 | import static org.junit.Assert.assertNull; 36 | import static org.junit.Assert.assertThat; 37 | 38 | @FixMethodOrder(MethodSorters.NAME_ASCENDING) 39 | public class RestApiTest { 40 | private static final String VALID_USERNAME = "RefineriaWeb", INVALID_USERNAME = ""; 41 | private RestApi restApiUT; 42 | 43 | @Before public void setUp() { 44 | restApiUT = new Retrofit.Builder() 45 | .baseUrl(RestApi.URL_BASE) 46 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 47 | .addConverterFactory(GsonConverterFactory.create()) 48 | .build().create(RestApi.class); 49 | } 50 | 51 | @Test public void _1_When_Get_User_With_Valid_User_Name_Then_Get_UserDemo() { 52 | TestSubscriber> subscriber = new TestSubscriber<>(); 53 | restApiUT.getUser(VALID_USERNAME).subscribe(subscriber); 54 | 55 | subscriber.awaitTerminalEvent(); 56 | Response userDemo = subscriber.getOnNextEvents().get(0); 57 | assertThat(userDemo.body().getId(), is(not(0))); 58 | assertThat(subscriber.getOnNextEvents().size(), is(1)); 59 | } 60 | 61 | @Test public void _2_When_Get_User_With_Invalid_User_Name_Then_Throw_An_ExceptionOnSubscriber() { 62 | TestSubscriber> subscriber = new TestSubscriber<>(); 63 | restApiUT.getUser(INVALID_USERNAME).subscribe(subscriber); 64 | 65 | subscriber.awaitTerminalEvent(); 66 | Response userDemo = subscriber.getOnNextEvents().get(0); 67 | assertNull(userDemo.body()); 68 | } 69 | 70 | @Test public void _3_When_Get_Users_Then_Get_Users() { 71 | TestSubscriber>> subscriber = new TestSubscriber<>(); 72 | restApiUT.getUsers().subscribe(subscriber); 73 | 74 | subscriber.awaitTerminalEvent(); 75 | assertThat(subscriber.getOnNextEvents().size(), is(not(0))); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /data/src/test/java/data/user_demo/UserDemoDataRepositoryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package data.user_demo; 18 | 19 | import org.junit.Before; 20 | import org.junit.Test; 21 | import org.mockito.Mock; 22 | import org.mockito.MockitoAnnotations; 23 | 24 | import data.net.RestApi; 25 | import data.sections.UI; 26 | import data.sections.user_demo.UserDemoDataRepository; 27 | import domain.sections.user_demo.entities.UserDemoEntity; 28 | import retrofit2.Response; 29 | import rx.Observable; 30 | import rx.observers.TestSubscriber; 31 | 32 | import static org.hamcrest.CoreMatchers.is; 33 | import static org.junit.Assert.assertThat; 34 | import static org.mockito.Matchers.any; 35 | import static org.mockito.Mockito.mock; 36 | import static org.mockito.Mockito.when; 37 | 38 | public class UserDemoDataRepositoryTest { 39 | @Mock private RestApi restApiMock; 40 | @Mock private UI UIMock; 41 | private UserDemoDataRepository userDemoDataRepositoryUT; 42 | 43 | @Before public void setUp() { 44 | MockitoAnnotations.initMocks(this); 45 | userDemoDataRepositoryUT = new UserDemoDataRepository(restApiMock, null, UIMock); 46 | } 47 | 48 | @Test public void When_Search_With_Valid_User_Name_Then_Get_Demo_User() { 49 | Response response = Response.success(mock(UserDemoEntity.class)); 50 | when(restApiMock.getUser(any(String.class))).thenReturn(Observable.just(response)); 51 | 52 | TestSubscriber subscriber = new TestSubscriber<>(); 53 | userDemoDataRepositoryUT.searchByUserName(any(String.class)).subscribe(subscriber); 54 | subscriber.awaitTerminalEvent(); 55 | 56 | assertThat(subscriber.getOnNextEvents().size(), is(1)); 57 | } 58 | } -------------------------------------------------------------------------------- /domain/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'me.tatarka.retrolambda' 3 | 4 | buildscript { 5 | repositories { 6 | mavenCentral() 7 | jcenter() 8 | maven { 9 | url "https://plugins.gradle.org/m2/" 10 | } 11 | } 12 | 13 | dependencies { 14 | classpath rootProject.ext.buildScriptDependencies.retrolambda 15 | classpath rootProject.ext.buildScriptDependencies.javaApt 16 | } 17 | } 18 | 19 | apply plugin: 'idea' 20 | apply plugin: "net.ltgt.apt" 21 | 22 | sourceCompatibility = JavaVersion.VERSION_1_8 23 | targetCompatibility = JavaVersion.VERSION_1_8 24 | 25 | configurations { 26 | provided 27 | } 28 | 29 | sourceSets { 30 | main { 31 | compileClasspath += configurations.provided 32 | runtimeClasspath += configurations.provided 33 | } 34 | } 35 | 36 | dependencies { 37 | compile fileTree(dir: 'libs', include: ['*.jar']) 38 | 39 | def domainDependencies = rootProject.ext.domainDependencies 40 | 41 | compile domainDependencies.dagger 42 | apt domainDependencies.daggerCompiler 43 | provided domainDependencies.javaxAnnotation 44 | 45 | compile domainDependencies.rxJava 46 | 47 | provided domainDependencies.lombok 48 | apt domainDependencies.lombok 49 | 50 | def domainTestDependencies = rootProject.ext.domainTestDependencies 51 | 52 | testCompile domainTestDependencies.junit 53 | testCompile domainTestDependencies.mockito 54 | } 55 | 56 | retrolambda { 57 | jdk System.getenv("JAVA8_HOME") 58 | oldJdk System.getenv("JAVA7_HOME") 59 | javaVersion JavaVersion.VERSION_1_7 60 | } -------------------------------------------------------------------------------- /domain/src/main/java/domain/foundation/BaseView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.foundation; 18 | 19 | /** 20 | * Base interface for any interface of type view. These interfaces will be implemented for the pertinent 21 | * screen in the presentation layer 22 | */ 23 | public interface BaseView { 24 | } 25 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/foundation/Presenter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.foundation; 18 | 19 | import domain.foundation.helpers.ParserException; 20 | import domain.foundation.schedulers.ObserveOn; 21 | import domain.foundation.schedulers.SubscribeOn; 22 | import domain.sections.UI; 23 | import domain.sections.Wireframe; 24 | import rx.Observable; 25 | import rx.Subscription; 26 | import rx.subscriptions.CompositeSubscription; 27 | 28 | /** 29 | * Base class for any Presenter. 30 | * The presenter is responsible for linking the uses cases in order to create a logical unit 31 | * which will be represented as a screen in the application. 32 | * @param The view interface attached to this presenter. 33 | * @see BaseView 34 | */ 35 | public abstract class Presenter { 36 | protected V view; 37 | protected final Wireframe wireframe; 38 | private final SubscribeOn subscribeOn; 39 | private final ObserveOn observeOn; 40 | private final ParserException parserException; 41 | protected final UI ui; 42 | private final CompositeSubscription subscriptions; 43 | 44 | public Presenter(Wireframe wireframe, SubscribeOn subscribeOn, ObserveOn observeOn, ParserException parserException, UI ui) { 45 | this.wireframe = wireframe; 46 | this.subscribeOn = subscribeOn; 47 | this.observeOn = observeOn; 48 | this.parserException = parserException; 49 | this.ui = ui; 50 | this.subscriptions = new CompositeSubscription(); 51 | } 52 | 53 | /** 54 | * Called when view is required to initialize. On the Android lifecycle ecosystem, it would be onCreated. 55 | */ 56 | public void attachView(V view) { 57 | this.view = view; 58 | } 59 | 60 | /** 61 | * Called when view is required to resume. On the Android lifecycle ecosystem, it would be onResume. 62 | */ 63 | public void resumeView() {} 64 | 65 | /** 66 | * Handles observable subscriptions, not throw any exception and report it using feedback. 67 | */ 68 | protected Disposing safetyReportError(Observable observable) { 69 | Observable configured = schedulers(observable) 70 | .doOnError(throwable -> ui.showFeedback(parserException.with(throwable).react())) 71 | .onErrorResumeNext(throwable -> Observable.empty()); 72 | 73 | return new Disposing(configured, subscriptions); 74 | } 75 | 76 | /** 77 | * Handles observable subscriptions, not throw any exception and report it using anchoredScreenFeedback. 78 | */ 79 | protected Disposing safetyReportErrorAnchored(Observable observable) { 80 | Observable configured = schedulers(observable) 81 | .doOnError(throwable -> ui.showAnchoredScreenFeedback(parserException.with(throwable).react())) 82 | .onErrorResumeNext(throwable -> Observable.empty()); 83 | 84 | return new Disposing(configured, subscriptions); 85 | } 86 | 87 | /** 88 | * Handles observable subscriptions and not throw any exception. 89 | */ 90 | protected Disposing safety(Observable observable) { 91 | Observable configured = schedulers(observable) 92 | .onErrorResumeNext(throwable -> Observable.empty()); 93 | 94 | return new Disposing(configured, subscriptions); 95 | } 96 | 97 | /** 98 | * Handles observable schedulers. 99 | */ 100 | private Observable schedulers(Observable observable) { 101 | return observable.subscribeOn(subscribeOn.getScheduler()) 102 | .observeOn(observeOn.getScheduler()); 103 | } 104 | 105 | public void dispose() { 106 | if (!subscriptions.isUnsubscribed()) { 107 | subscriptions.clear(); 108 | } 109 | } 110 | 111 | /** 112 | * Wrapper to hold a reference to the observable and the expected subscription. 113 | */ 114 | protected static class Disposing { 115 | private Observable observable; 116 | private final CompositeSubscription subscriptions; 117 | 118 | private Disposing(Observable observable, CompositeSubscription subscriptions) { 119 | this.observable = observable; 120 | this.subscriptions = subscriptions; 121 | } 122 | 123 | public void disposable(Disposable disposable) { 124 | subscriptions.add(disposable.subscription(observable)); 125 | } 126 | 127 | public interface Disposable { 128 | Subscription subscription(Observable observable); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/foundation/Repository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.foundation; 18 | 19 | /** 20 | * Base interface for any repository. 21 | * These interfaces will be implemented in the data layer. 22 | */ 23 | public interface Repository { 24 | } 25 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/foundation/UseCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.foundation; 18 | 19 | import domain.sections.UI; 20 | import rx.Observable; 21 | 22 | /** 23 | * Base class for any UseCase. 24 | * The UseCase retrieves its data from an specific repository and 25 | * it is in charge of processing data for any presenter. 26 | * @see Repository 27 | */ 28 | 29 | public abstract class UseCase { 30 | protected final UI ui; 31 | 32 | public UseCase(UI ui) { 33 | this.ui = ui; 34 | } 35 | 36 | /** 37 | * Observable built for every use case 38 | */ 39 | public abstract Observable react(); 40 | } -------------------------------------------------------------------------------- /domain/src/main/java/domain/foundation/helpers/ParserException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.foundation.helpers; 18 | 19 | import javax.inject.Inject; 20 | 21 | import domain.foundation.UseCase; 22 | import domain.sections.UI; 23 | import rx.Observable; 24 | import rx.exceptions.CompositeException; 25 | 26 | /** 27 | * Created by victor on 09/03/16. 28 | */ 29 | public class ParserException extends UseCase { 30 | private Throwable throwable; 31 | 32 | @Inject public ParserException(UI ui) { 33 | super(ui); 34 | } 35 | 36 | public ParserException with(Throwable throwable) { 37 | this.throwable = throwable; 38 | return this; 39 | } 40 | 41 | @Override public Observable react() { 42 | String message = throwable.getMessage(); 43 | 44 | if (throwable instanceof CompositeException) { 45 | message += System.getProperty("line.separator"); 46 | CompositeException compositeException = (CompositeException) throwable; 47 | 48 | for (Throwable exception : compositeException.getExceptions()) { 49 | String exceptionName = exception.getClass().getSimpleName(); 50 | String exceptionMessage = exception.getMessage() != null ? exception.getMessage() : ""; 51 | message += exceptionName + " -> " + exceptionMessage + System.getProperty("line.separator"); 52 | } 53 | } 54 | 55 | return Observable.just(message); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/foundation/schedulers/ObserveOn.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.foundation.schedulers; 18 | 19 | import rx.Scheduler; 20 | 21 | /** 22 | * Provides the Scheduler for any Observable to observeOn 23 | * This interfaces is injected by dagger and implemented by 24 | */ 25 | public interface ObserveOn { 26 | Scheduler getScheduler(); 27 | } 28 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/foundation/schedulers/SubscribeOn.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.foundation.schedulers; 18 | 19 | import rx.Scheduler; 20 | 21 | /** 22 | * Provides the Scheduler for any Observable to subscribeOn 23 | * This interfaces is injected by dagger and implemented in the presentation layer. 24 | * For example, in Android system you can use AndroidSchedulers.mainThread() using RxAndroid library 25 | */ 26 | public interface SubscribeOn { 27 | Scheduler getScheduler(); 28 | } -------------------------------------------------------------------------------- /domain/src/main/java/domain/internal/di/DomainModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.internal.di; 18 | 19 | import javax.inject.Singleton; 20 | 21 | import domain.foundation.schedulers.SubscribeOn; 22 | import dagger.Module; 23 | import dagger.Provides; 24 | import rx.schedulers.Schedulers; 25 | 26 | /** 27 | * Dagger module for domain layer. 28 | */ 29 | @Module 30 | public class DomainModule { 31 | 32 | /** 33 | * Provides the Scheduler to be used by any subscriber on subscribing. 34 | * The operation will be executed in a new thread, this way the ui won't be block 35 | */ 36 | @Singleton @Provides SubscribeOn provideSubscribeOn() { 37 | return (() -> Schedulers.io()); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/UI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections; 18 | 19 | import rx.Observable; 20 | import rx.Subscription; 21 | 22 | public interface UI { 23 | Observable errorNonEmptyFields(); 24 | Subscription showFeedback(Observable oFeedback); 25 | Subscription showAnchoredScreenFeedback(Observable oFeedback); 26 | 27 | void showLoading(); 28 | void hideLoading(); 29 | } 30 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/Wireframe.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections; 18 | 19 | /** 20 | * Provides the routing for the application screens. Its behaviour is defined in the presentation layer. 21 | */ 22 | public interface Wireframe { 23 | void dashboard(); 24 | void searchUserScreen(); 25 | void userScreen(); 26 | void usersScreen(); 27 | void popCurrentScreen(); 28 | } 29 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/dashboard/DashboardItemsMenu.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.dashboard; 18 | 19 | public interface DashboardItemsMenu { 20 | void configureUsers(ItemMenu itemMenu); 21 | void configureUser(ItemMenu itemMenu); 22 | void configureSearchUser(ItemMenu itemMenu); 23 | } 24 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/dashboard/DashboardPresenter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.dashboard; 18 | 19 | import javax.inject.Inject; 20 | 21 | import domain.foundation.Presenter; 22 | import domain.foundation.helpers.ParserException; 23 | import domain.foundation.schedulers.ObserveOn; 24 | import domain.foundation.schedulers.SubscribeOn; 25 | import domain.sections.UI; 26 | import domain.sections.Wireframe; 27 | 28 | public class DashboardPresenter extends Presenter { 29 | private final GetMenuItemsUseCase useCase; 30 | 31 | @Inject public DashboardPresenter(Wireframe wireframe, SubscribeOn subscribeOn, ObserveOn observeOn, ParserException parserException, UI ui, GetMenuItemsUseCase useCase) { 32 | super(wireframe, subscribeOn, observeOn, parserException, ui); 33 | this.useCase = useCase; 34 | } 35 | 36 | @Override public void attachView(DashboardView view) { 37 | super.attachView(view); 38 | 39 | safetyReportError(useCase.react().doOnCompleted(view::showUsers)) 40 | .disposable(view::loadItemsMenu); 41 | } 42 | 43 | public void setSelectedItemMenu(ItemMenu itemMenu) { 44 | if (itemMenu.getId() == GetMenuItemsUseCase.ID_USERS) 45 | view.showUsers(); 46 | else if (itemMenu.getId() == GetMenuItemsUseCase.ID_USER) 47 | view.showUser(); 48 | else 49 | view.showUserSearch(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/dashboard/DashboardView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.dashboard; 18 | 19 | import java.util.List; 20 | 21 | import domain.foundation.BaseView; 22 | import rx.Observable; 23 | import rx.Subscription; 24 | 25 | public interface DashboardView extends BaseView { 26 | Subscription loadItemsMenu(Observable> oItemsMenu); 27 | void showUsers(); 28 | void showUser(); 29 | void showUserSearch(); 30 | } 31 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/dashboard/GetMenuItemsUseCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.dashboard; 18 | 19 | import java.util.Arrays; 20 | import java.util.List; 21 | 22 | import javax.inject.Inject; 23 | 24 | import domain.foundation.UseCase; 25 | import domain.sections.UI; 26 | import rx.Observable; 27 | 28 | public class GetMenuItemsUseCase extends UseCase> { 29 | public static final int ID_USERS = 1, ID_USER = 2, ID_SEARCH_USER = 3; 30 | private final DashboardItemsMenu dashboardItemsMenu; 31 | 32 | @Inject GetMenuItemsUseCase(DashboardItemsMenu dashboardItemsMenu, UI ui) { 33 | super(ui); 34 | this.dashboardItemsMenu = dashboardItemsMenu; 35 | } 36 | 37 | @Override public Observable> react() { 38 | ItemMenu users = new ItemMenu(ID_USERS); 39 | dashboardItemsMenu.configureUsers(users); 40 | 41 | ItemMenu user = new ItemMenu(ID_USER); 42 | dashboardItemsMenu.configureUser(user); 43 | 44 | ItemMenu searchUser = new ItemMenu(ID_SEARCH_USER); 45 | dashboardItemsMenu.configureSearchUser(searchUser); 46 | 47 | return Observable.just(Arrays.asList(users, user, searchUser)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/dashboard/ItemMenu.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.dashboard; 18 | 19 | import lombok.Data; 20 | 21 | @Data 22 | public class ItemMenu { 23 | public final int id; 24 | public String title; 25 | public Object imageResource; 26 | } 27 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/launch/LaunchPresenter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.launch; 18 | 19 | import javax.inject.Inject; 20 | 21 | import domain.foundation.Presenter; 22 | import domain.foundation.helpers.ParserException; 23 | import domain.foundation.schedulers.ObserveOn; 24 | import domain.foundation.schedulers.SubscribeOn; 25 | import domain.sections.UI; 26 | import domain.sections.Wireframe; 27 | 28 | public class LaunchPresenter extends Presenter { 29 | 30 | @Inject public LaunchPresenter(Wireframe wireframe, SubscribeOn subscribeOn, ObserveOn observeOn, ParserException parserException, UI ui) { 31 | super(wireframe, subscribeOn, observeOn, parserException, ui); 32 | } 33 | 34 | @Override public void attachView(LaunchView view) { 35 | super.attachView(view); 36 | wireframe.dashboard(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/launch/LaunchView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.launch; 18 | 19 | import domain.foundation.BaseView; 20 | 21 | 22 | public interface LaunchView extends BaseView {} 23 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/user_demo/UserDemoRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.user_demo; 18 | 19 | import java.util.List; 20 | 21 | import domain.foundation.Repository; 22 | import domain.sections.user_demo.entities.UserDemoEntity; 23 | import rx.Observable; 24 | 25 | public interface UserDemoRepository extends Repository { 26 | Observable searchByUserName(String nameUser); 27 | Observable> askForUsers(); 28 | Observable getSelectedUserDemoList(); 29 | Observable saveSelectedUserDemoList(UserDemoEntity user); 30 | } 31 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/user_demo/common/UserView.java: -------------------------------------------------------------------------------- 1 | package domain.sections.user_demo.common; 2 | 3 | import domain.foundation.BaseView; 4 | import domain.sections.user_demo.entities.UserDemoEntity; 5 | import rx.Observable; 6 | import rx.Subscription; 7 | 8 | /** 9 | * Created by victor on 01/02/16. 10 | */ 11 | public interface UserView extends BaseView { 12 | Subscription showUser(Observable user); 13 | } 14 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/user_demo/detail/GetSelectedDemoUserListUseCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.user_demo.detail; 18 | 19 | import javax.inject.Inject; 20 | 21 | import domain.foundation.UseCase; 22 | import domain.sections.UI; 23 | import domain.sections.user_demo.UserDemoRepository; 24 | import domain.sections.user_demo.entities.UserDemoEntity; 25 | import rx.Observable; 26 | 27 | public class GetSelectedDemoUserListUseCase extends UseCase { 28 | private final UserDemoRepository repository; 29 | 30 | @Inject public GetSelectedDemoUserListUseCase(UI ui, UserDemoRepository repository) { 31 | super(ui); 32 | this.repository = repository; 33 | } 34 | 35 | @Override public Observable react() { 36 | return repository.getSelectedUserDemoList(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/user_demo/detail/UserDemoPresenter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.user_demo.detail; 18 | 19 | import javax.inject.Inject; 20 | 21 | import domain.foundation.Presenter; 22 | import domain.foundation.helpers.ParserException; 23 | import domain.foundation.schedulers.ObserveOn; 24 | import domain.foundation.schedulers.SubscribeOn; 25 | import domain.sections.UI; 26 | import domain.sections.Wireframe; 27 | import domain.sections.user_demo.common.UserView; 28 | 29 | public class UserDemoPresenter extends Presenter { 30 | private final GetSelectedDemoUserListUseCase useCase; 31 | 32 | @Inject public UserDemoPresenter(Wireframe wireframe, SubscribeOn subscribeOn, ObserveOn observeOn, ParserException parserException, UI ui, GetSelectedDemoUserListUseCase useCase) { 33 | super(wireframe, subscribeOn, observeOn, parserException, ui); 34 | this.useCase = useCase; 35 | } 36 | 37 | @Override public void attachView(UserView view) { 38 | super.attachView(view); 39 | 40 | safetyReportError(useCase.react()).disposable(view::showUser); 41 | } 42 | 43 | public void goToSearchScreen() { 44 | wireframe.searchUserScreen(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/user_demo/entities/UserDemoEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.user_demo.entities; 18 | 19 | 20 | import lombok.AccessLevel; 21 | import lombok.AllArgsConstructor; 22 | import lombok.Data; 23 | 24 | @AllArgsConstructor(access = AccessLevel.PROTECTED) 25 | @Data 26 | public class UserDemoEntity { 27 | private final int id; 28 | private final String login; 29 | private String avatar_url = ""; 30 | 31 | public String getAvatarUrl() { 32 | if (avatar_url.isEmpty()) return avatar_url; 33 | return avatar_url.split("\\?")[0]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/user_demo/list/GetUsersDemoUseCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.user_demo.list; 18 | 19 | import java.util.List; 20 | 21 | import javax.inject.Inject; 22 | 23 | import domain.foundation.UseCase; 24 | import domain.sections.UI; 25 | import domain.sections.user_demo.UserDemoRepository; 26 | import domain.sections.user_demo.entities.UserDemoEntity; 27 | import rx.Observable; 28 | 29 | public class GetUsersDemoUseCase extends UseCase> { 30 | private final UserDemoRepository repository; 31 | 32 | @Inject public GetUsersDemoUseCase(UI ui, UserDemoRepository repository) { 33 | super(ui); 34 | this.repository = repository; 35 | } 36 | 37 | @Override public Observable> react() { 38 | return repository.askForUsers(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/user_demo/list/SaveUserDemoSelectedListUseCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.user_demo.list; 18 | 19 | import javax.inject.Inject; 20 | 21 | import domain.foundation.UseCase; 22 | import domain.sections.UI; 23 | import domain.sections.user_demo.UserDemoRepository; 24 | import domain.sections.user_demo.entities.UserDemoEntity; 25 | import rx.Observable; 26 | 27 | public class SaveUserDemoSelectedListUseCase extends UseCase { 28 | private final UserDemoRepository repository; 29 | private UserDemoEntity userDemoEntity; 30 | 31 | @Inject public SaveUserDemoSelectedListUseCase(UI ui, UserDemoRepository repository) { 32 | super(ui); 33 | this.repository = repository; 34 | } 35 | 36 | public SaveUserDemoSelectedListUseCase with(UserDemoEntity userDemoEntity) { 37 | this.userDemoEntity = userDemoEntity; 38 | return this; 39 | } 40 | 41 | @Override public Observable react() { 42 | assert userDemoEntity != null; 43 | return repository.saveSelectedUserDemoList(userDemoEntity); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/user_demo/list/UsersDemoPresenter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.user_demo.list; 18 | 19 | import javax.inject.Inject; 20 | 21 | import domain.foundation.Presenter; 22 | import domain.foundation.helpers.ParserException; 23 | import domain.foundation.schedulers.ObserveOn; 24 | import domain.foundation.schedulers.SubscribeOn; 25 | import domain.sections.UI; 26 | import domain.sections.Wireframe; 27 | import domain.sections.user_demo.entities.UserDemoEntity; 28 | 29 | public class UsersDemoPresenter extends Presenter { 30 | private final GetUsersDemoUseCase getUsersDemoUseCase; 31 | private final SaveUserDemoSelectedListUseCase saveUserDemoSelectedListUseCase; 32 | 33 | @Inject public UsersDemoPresenter(Wireframe wireframe, SubscribeOn subscribeOn, ObserveOn observeOn, ParserException parserException, UI ui, GetUsersDemoUseCase getUsersDemoUseCase, SaveUserDemoSelectedListUseCase saveUserDemoSelectedListUseCase) { 34 | super(wireframe, subscribeOn, observeOn, parserException, ui); 35 | this.getUsersDemoUseCase = getUsersDemoUseCase; 36 | this.saveUserDemoSelectedListUseCase = saveUserDemoSelectedListUseCase; 37 | } 38 | 39 | @Override public void attachView(UsersView view) { 40 | super.attachView(view); 41 | 42 | safetyReportError(getUsersDemoUseCase.react()) 43 | .disposable(view::showUsers); 44 | } 45 | 46 | public void goToDetail(UserDemoEntity user) { 47 | safetyReportError(saveUserDemoSelectedListUseCase.with(user).react()) 48 | .disposable(oSuccess -> oSuccess.subscribe(_I -> wireframe.userScreen())); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/user_demo/list/UsersView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.user_demo.list; 18 | 19 | import java.util.List; 20 | 21 | import domain.foundation.BaseView; 22 | import domain.sections.user_demo.entities.UserDemoEntity; 23 | import rx.Observable; 24 | import rx.Subscription; 25 | 26 | public interface UsersView extends BaseView { 27 | Subscription showUsers(Observable> users); 28 | } 29 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/user_demo/search/SearchUserDemoPresenter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.user_demo.search; 18 | 19 | import javax.inject.Inject; 20 | 21 | import domain.foundation.Presenter; 22 | import domain.foundation.helpers.ParserException; 23 | import domain.foundation.schedulers.ObserveOn; 24 | import domain.foundation.schedulers.SubscribeOn; 25 | import domain.sections.UI; 26 | import domain.sections.Wireframe; 27 | import domain.sections.user_demo.common.UserView; 28 | 29 | public class SearchUserDemoPresenter extends Presenter { 30 | private final SearchUserDemoUseCase useCase; 31 | 32 | @Inject public SearchUserDemoPresenter(Wireframe wireframe, SubscribeOn subscribeOn, ObserveOn observeOn, ParserException parserException, UI ui, SearchUserDemoUseCase useCase) { 33 | super(wireframe, subscribeOn, observeOn, parserException, ui); 34 | this.useCase = useCase; 35 | } 36 | 37 | @Override public void attachView(UserView view) { 38 | super.attachView(view); 39 | } 40 | 41 | public void getUserByUserName(String username) { 42 | useCase.setName(username); 43 | if (username == null || username.isEmpty()) { 44 | safetyReportErrorAnchored(ui.errorNonEmptyFields()).disposable(ui::showAnchoredScreenFeedback); 45 | } else { 46 | safetyReportErrorAnchored(useCase.react()).disposable(view::showUser); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /domain/src/main/java/domain/sections/user_demo/search/SearchUserDemoUseCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.user_demo.search; 18 | 19 | import javax.inject.Inject; 20 | 21 | import domain.foundation.UseCase; 22 | import domain.sections.UI; 23 | import domain.sections.user_demo.UserDemoRepository; 24 | import domain.sections.user_demo.entities.UserDemoEntity; 25 | import rx.Observable; 26 | 27 | public class SearchUserDemoUseCase extends UseCase { 28 | private final UserDemoRepository repository; 29 | private String name; 30 | 31 | @Inject public SearchUserDemoUseCase(UI ui, UserDemoRepository repository) { 32 | super(ui); 33 | this.repository = repository; 34 | } 35 | 36 | public void setName(String name) { 37 | this.name = name; 38 | } 39 | 40 | @Override public Observable react() { 41 | return repository.searchByUserName(name); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /domain/src/test/java/domain/common/BaseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.common; 18 | 19 | import org.junit.Before; 20 | import org.mockito.Mock; 21 | import org.mockito.MockitoAnnotations; 22 | 23 | import domain.foundation.schedulers.ObserveOn; 24 | import domain.foundation.schedulers.SubscribeOn; 25 | import domain.sections.UI; 26 | import rx.schedulers.Schedulers; 27 | 28 | import static org.mockito.Mockito.when; 29 | 30 | public abstract class BaseTest { 31 | protected final static int WAIT = 50; 32 | @Mock protected UI UIMock; 33 | @Mock protected ObserveOn observeOnMock; 34 | @Mock protected SubscribeOn subscribeOnMock; 35 | 36 | @Before public void setUp() { 37 | MockitoAnnotations.initMocks(this); 38 | when(observeOnMock.getScheduler()).thenReturn(Schedulers.newThread()); 39 | when(subscribeOnMock.getScheduler()).thenReturn(Schedulers.newThread()); 40 | } 41 | } -------------------------------------------------------------------------------- /domain/src/test/java/domain/foundation/PresenterErrorsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.foundation; 18 | 19 | import org.junit.Test; 20 | 21 | import domain.common.BaseTest; 22 | import domain.foundation.helpers.ParserException; 23 | import rx.Observable; 24 | import rx.observers.TestSubscriber; 25 | 26 | import static org.hamcrest.core.Is.is; 27 | import static org.junit.Assert.assertThat; 28 | import static org.mockito.Matchers.any; 29 | import static org.mockito.Mockito.times; 30 | import static org.mockito.Mockito.verify; 31 | import static org.mockito.Mockito.when; 32 | 33 | public class PresenterErrorsTest extends BaseTest { 34 | private final String SUCCESS = "success", FAILURE = "failure"; 35 | private PresenterUnderTest presenterUT; 36 | private UseCaseSuccessMock useCaseSuccessMock; 37 | private UseCaseFailureMock useCaseFailureMock; 38 | 39 | @Override public void setUp() { 40 | super.setUp(); 41 | presenterUT = new PresenterUnderTest(); 42 | useCaseSuccessMock = new UseCaseSuccessMock(); 43 | useCaseFailureMock = new UseCaseFailureMock(); 44 | } 45 | 46 | @Test public void When_Subscribe_Safety_Observable_Success_Get_Response() { 47 | TestSubscriber subscriberMock = new TestSubscriber<>(); 48 | presenterUT.safety(useCaseSuccessMock.react()) 49 | .disposable(oMock -> oMock.subscribe(subscriberMock)); 50 | subscriberMock.awaitTerminalEvent(); 51 | 52 | String response = subscriberMock.getOnNextEvents().get(0); 53 | assertThat(response, is(SUCCESS)); 54 | subscriberMock.assertNoErrors(); 55 | } 56 | 57 | @Test public void When_Subscribe_Safety_Observable_Failure_Nothing_Is_Emitted() { 58 | Observable oFeedback = Observable.just(FAILURE); 59 | when(UIMock.errorNonEmptyFields()).thenReturn(oFeedback); 60 | 61 | TestSubscriber subscriberMock = new TestSubscriber<>(); 62 | presenterUT.safety(useCaseFailureMock.react()) 63 | .disposable(oMock -> oMock.subscribe(subscriberMock)); 64 | subscriberMock.awaitTerminalEvent(); 65 | 66 | subscriberMock.assertNoErrors(); 67 | subscriberMock.assertNoValues(); 68 | 69 | verify(UIMock, times(0)).showFeedback(oFeedback); 70 | } 71 | 72 | @Test public void When_Subscribe_Safety_Report_Error_Observable_Failure_Nothing_Is_Emitted_And_UI_Show_Error_Is_Called() { 73 | TestSubscriber subscriberMock = new TestSubscriber<>(); 74 | presenterUT.safetyReportError(useCaseFailureMock.react()) 75 | .disposable(oMock -> oMock.subscribe(subscriberMock)); 76 | subscriberMock.awaitTerminalEvent(); 77 | 78 | subscriberMock.assertNoErrors(); 79 | subscriberMock.assertNoValues(); 80 | 81 | verify(UIMock, times(1)).showFeedback(any(Observable.class)); 82 | } 83 | 84 | private class PresenterUnderTest extends Presenter { 85 | final UseCaseSuccessMock useCaseSuccessMock; 86 | final UseCaseFailureMock useCaseFailureMock; 87 | 88 | public PresenterUnderTest() { 89 | super(null, subscribeOnMock, observeOnMock, new ParserException(UIMock), UIMock); 90 | useCaseSuccessMock = new UseCaseSuccessMock(); 91 | useCaseFailureMock = new UseCaseFailureMock(); 92 | } 93 | } 94 | 95 | private class UseCaseSuccessMock extends UseCase { 96 | public UseCaseSuccessMock() { 97 | super(UIMock); 98 | } 99 | 100 | @Override public Observable react() { 101 | return Observable.just(SUCCESS); 102 | } 103 | } 104 | 105 | private class UseCaseFailureMock extends UseCase { 106 | public UseCaseFailureMock() { 107 | super(UIMock); 108 | } 109 | 110 | @Override public Observable react() { 111 | return Observable.just(SUCCESS).map(message -> { 112 | throw new RuntimeException(FAILURE); 113 | }); 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /domain/src/test/java/domain/foundation/PresenterSubscriptionsTest.java: -------------------------------------------------------------------------------- 1 | package domain.foundation; 2 | 3 | import org.junit.Test; 4 | 5 | import domain.common.BaseTest; 6 | import domain.foundation.helpers.ParserException; 7 | import rx.Observable; 8 | import rx.observers.TestSubscriber; 9 | import rx.schedulers.Schedulers; 10 | 11 | /** 12 | * Created by victor on 01/02/16. 13 | */ 14 | public class PresenterSubscriptionsTest extends BaseTest { 15 | private Presenter presenterUT; 16 | 17 | @Override public void setUp() { 18 | super.setUp(); 19 | presenterUT = new Presenter(null, subscribeOnMock, observeOnMock, new ParserException(UIMock), UIMock) {}; 20 | } 21 | 22 | @Test public void When_Unsubscribe_Subscription_Do_Not_Get_Response() { 23 | TestSubscriber subscriberMock = new TestSubscriber(); 24 | 25 | presenterUT.safetyReportError(getExpensiveObservable()) 26 | .disposable(observable -> observable.subscribe(subscriberMock)); 27 | 28 | presenterUT.dispose(); 29 | 30 | waitForIt(); 31 | subscriberMock.assertNoValues(); 32 | } 33 | 34 | @Test public void When_No_Unsubscribe_Subscription_Get_Response() { 35 | TestSubscriber subscriberMock = new TestSubscriber(); 36 | 37 | presenterUT.safetyReportError(getExpensiveObservable()) 38 | .disposable(observable -> observable.subscribe(subscriberMock)); 39 | 40 | waitForIt(); 41 | subscriberMock.assertValueCount(1); 42 | } 43 | 44 | @Test public void When_No_Unsubscribe_Subscription_With_Several_Subscriptions_Get_Response() { 45 | TestSubscriber subscriberMock1 = new TestSubscriber(); 46 | presenterUT.safetyReportError(getExpensiveObservable()) 47 | .disposable(observable -> observable.subscribe(subscriberMock1)); 48 | 49 | TestSubscriber subscriberMock2 = new TestSubscriber(); 50 | presenterUT.safetyReportError(getExpensiveObservable()) 51 | .disposable(observable -> observable.subscribe(subscriberMock2)); 52 | 53 | waitForIt(); 54 | subscriberMock1.assertValueCount(1); 55 | subscriberMock2.assertValueCount(1); 56 | } 57 | 58 | @Test public void When_Unsubscribe_Subscription_With_Several_Subscriptions_Do_Not_Get_Response() { 59 | TestSubscriber subscriberMock1 = new TestSubscriber(); 60 | presenterUT.safetyReportError(getExpensiveObservable()) 61 | .disposable(observable -> observable.subscribe(subscriberMock1)); 62 | 63 | TestSubscriber subscriberMock2 = new TestSubscriber(); 64 | presenterUT.safetyReportError(getExpensiveObservable()) 65 | .disposable(observable -> observable.subscribe(subscriberMock1)); 66 | 67 | presenterUT.dispose(); 68 | 69 | waitForIt(); 70 | subscriberMock1.assertNoValues(); 71 | subscriberMock2.assertNoValues(); 72 | } 73 | 74 | private Observable getExpensiveObservable() { 75 | return Observable.create(subscriber -> { 76 | try { 77 | Thread.sleep(500); 78 | subscriber.onNext("Mock"); 79 | } catch (InterruptedException e) {} 80 | }).subscribeOn(Schedulers.newThread()); 81 | } 82 | 83 | private void waitForIt() { 84 | try { 85 | Thread.sleep(1000); 86 | } catch (InterruptedException e) { 87 | e.printStackTrace(); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /domain/src/test/java/domain/sections/dashboard/GetMenuItemsUseCaseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.dashboard; 18 | 19 | import org.junit.Test; 20 | import org.mockito.Mock; 21 | 22 | import java.util.List; 23 | 24 | import domain.common.BaseTest; 25 | import domain.sections.user_demo.entities.UserDemoEntity; 26 | import rx.observers.TestSubscriber; 27 | 28 | import static org.hamcrest.CoreMatchers.is; 29 | import static org.junit.Assert.assertThat; 30 | 31 | public class GetMenuItemsUseCaseTest extends BaseTest { 32 | private GetMenuItemsUseCase getMenuItemsUseCase; 33 | @Mock protected DashboardItemsMenu dashboardItemsMenuMock; 34 | @Mock protected UserDemoEntity userDemoEntityMock; 35 | 36 | @Override public void setUp() { 37 | super.setUp(); 38 | getMenuItemsUseCase = new GetMenuItemsUseCase(dashboardItemsMenuMock, UIMock); 39 | } 40 | 41 | @Test public void When_Execute_Get_Items_Menu() { 42 | TestSubscriber> subscriberMock = new TestSubscriber<>(); 43 | getMenuItemsUseCase.react().subscribe(subscriberMock); 44 | subscriberMock.awaitTerminalEvent(); 45 | 46 | assertThat(subscriberMock.getOnCompletedEvents().size(), is(1)); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /domain/src/test/java/domain/sections/user_demo/detail/GetSelectedDemoUserListUseCaseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.user_demo.detail; 18 | 19 | import org.junit.Test; 20 | import org.mockito.Mock; 21 | 22 | import domain.common.BaseTest; 23 | import domain.sections.user_demo.UserDemoRepository; 24 | import domain.sections.user_demo.entities.UserDemoEntity; 25 | import rx.Observable; 26 | import rx.observers.TestSubscriber; 27 | 28 | import static org.hamcrest.core.Is.is; 29 | import static org.junit.Assert.assertThat; 30 | import static org.mockito.Mockito.when; 31 | 32 | public class GetSelectedDemoUserListUseCaseTest extends BaseTest { 33 | private GetSelectedDemoUserListUseCase getSelectedDemoUserListUseCaseUT; 34 | @Mock protected UserDemoRepository userDemoRepositoryMock; 35 | @Mock protected UserDemoEntity userDemoEntityMock; 36 | 37 | @Override public void setUp() { 38 | super.setUp(); 39 | getSelectedDemoUserListUseCaseUT = new GetSelectedDemoUserListUseCase(UIMock, userDemoRepositoryMock); 40 | } 41 | 42 | @Test public void When_Execute_Get_User() { 43 | when(userDemoRepositoryMock.getSelectedUserDemoList()).thenReturn(Observable.just(userDemoEntityMock)); 44 | 45 | TestSubscriber subscriberMock = new TestSubscriber<>(); 46 | getSelectedDemoUserListUseCaseUT.react().subscribe(subscriberMock); 47 | subscriberMock.awaitTerminalEvent(); 48 | 49 | assertThat(subscriberMock.getOnCompletedEvents().size(), is(1)); 50 | } 51 | } -------------------------------------------------------------------------------- /domain/src/test/java/domain/sections/user_demo/list/GetUsersDemoUseCaseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.user_demo.list; 18 | 19 | import org.junit.Test; 20 | import org.mockito.Mock; 21 | 22 | import java.util.Arrays; 23 | import java.util.List; 24 | 25 | import domain.common.BaseTest; 26 | import domain.sections.user_demo.UserDemoRepository; 27 | import domain.sections.user_demo.entities.UserDemoEntity; 28 | import rx.Observable; 29 | import rx.observers.TestSubscriber; 30 | 31 | import static org.hamcrest.MatcherAssert.assertThat; 32 | import static org.hamcrest.core.Is.is; 33 | import static org.mockito.Mockito.when; 34 | 35 | public class GetUsersDemoUseCaseTest extends BaseTest { 36 | private GetUsersDemoUseCase getUsersDemoUseCaseUT; 37 | @Mock protected UserDemoRepository userDemoRepositoryMock; 38 | @Mock protected UserDemoEntity userDemoEntityMock; 39 | 40 | @Override public void setUp() { 41 | super.setUp(); 42 | getUsersDemoUseCaseUT = new GetUsersDemoUseCase(UIMock, userDemoRepositoryMock); 43 | } 44 | 45 | @Test public void When_Execute_Get_Users() { 46 | when(userDemoRepositoryMock.askForUsers()).thenReturn(Observable.just(Arrays.asList())); 47 | 48 | TestSubscriber> subscriberMock = new TestSubscriber<>(); 49 | getUsersDemoUseCaseUT.react().subscribe(subscriberMock); 50 | subscriberMock.awaitTerminalEvent(); 51 | 52 | assertThat(subscriberMock.getOnCompletedEvents().size(), is(1)); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /domain/src/test/java/domain/sections/user_demo/list/SaveUserDemoSelectedListUseCaseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.user_demo.list; 18 | 19 | import org.junit.Test; 20 | import org.mockito.Mock; 21 | 22 | import domain.common.BaseTest; 23 | import domain.sections.user_demo.UserDemoRepository; 24 | import domain.sections.user_demo.entities.UserDemoEntity; 25 | import rx.Observable; 26 | import rx.observers.TestSubscriber; 27 | 28 | import static org.hamcrest.MatcherAssert.assertThat; 29 | import static org.hamcrest.core.Is.is; 30 | import static org.mockito.Mockito.when; 31 | 32 | public class SaveUserDemoSelectedListUseCaseTest extends BaseTest { 33 | private SaveUserDemoSelectedListUseCase saveUserDemoSelectedListUseCaseUT; 34 | @Mock protected UserDemoRepository userDemoRepositoryMock; 35 | @Mock protected UserDemoEntity userDemoEntityMock; 36 | 37 | @Override public void setUp() { 38 | super.setUp(); 39 | saveUserDemoSelectedListUseCaseUT = new SaveUserDemoSelectedListUseCase(UIMock, userDemoRepositoryMock); 40 | } 41 | 42 | @Test public void When_Save_User_Then_Get_Boolean_Observable() { 43 | when(userDemoRepositoryMock.saveSelectedUserDemoList(userDemoEntityMock)).thenReturn(Observable.just(true)); 44 | 45 | saveUserDemoSelectedListUseCaseUT.with(userDemoEntityMock); 46 | 47 | TestSubscriber subscriberMock = new TestSubscriber<>(); 48 | saveUserDemoSelectedListUseCaseUT.react().subscribe(subscriberMock); 49 | subscriberMock.awaitTerminalEvent(); 50 | 51 | assertThat(subscriberMock.getOnCompletedEvents().size(), is(1)); 52 | } 53 | 54 | @Test(expected=AssertionError.class) 55 | public void When_Save_Null_Then_Throws_Assertion_Error() { 56 | TestSubscriber subscriberMock = new TestSubscriber<>(); 57 | saveUserDemoSelectedListUseCaseUT.react().subscribe(subscriberMock); 58 | subscriberMock.awaitTerminalEvent(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /domain/src/test/java/domain/sections/user_demo/search/SearchUserDemoUseCaseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package domain.sections.user_demo.search; 18 | 19 | import org.junit.Test; 20 | import org.mockito.Mock; 21 | 22 | import domain.common.BaseTest; 23 | import domain.sections.user_demo.UserDemoRepository; 24 | import domain.sections.user_demo.entities.UserDemoEntity; 25 | import rx.Observable; 26 | import rx.observers.TestSubscriber; 27 | 28 | import static org.hamcrest.core.Is.is; 29 | import static org.junit.Assert.assertThat; 30 | import static org.mockito.Mockito.when; 31 | 32 | public class SearchUserDemoUseCaseTest extends BaseTest { 33 | private SearchUserDemoUseCase searchUserDemoUseCaseUT; 34 | @Mock protected UserDemoRepository userDemoRepositoryMock; 35 | @Mock protected UserDemoEntity userDemoEntityMock; 36 | 37 | @Override public void setUp() { 38 | super.setUp(); 39 | searchUserDemoUseCaseUT = new SearchUserDemoUseCase(UIMock, userDemoRepositoryMock); 40 | } 41 | 42 | @Test public void When_Get_User_With_Valid_Name_Get_User() { 43 | when(userDemoRepositoryMock.searchByUserName("valid")).thenReturn(Observable.just(userDemoEntityMock)); 44 | 45 | TestSubscriber subscriberMock = new TestSubscriber<>(); 46 | searchUserDemoUseCaseUT.setName("valid"); 47 | searchUserDemoUseCaseUT.react().subscribe(subscriberMock); 48 | subscriberMock.awaitTerminalEvent(); 49 | 50 | assertThat(subscriberMock.getOnCompletedEvents().size(), is(1)); 51 | } 52 | 53 | @Test public void When_Get_User_With_Invalid_Name_Get_Error() { 54 | when(userDemoRepositoryMock.searchByUserName("invalid")).thenReturn(Observable.create(subscriber -> subscriber.onError(new RuntimeException()))); 55 | 56 | TestSubscriber subscriberMock = new TestSubscriber<>(); 57 | searchUserDemoUseCaseUT.setName("invalid"); 58 | searchUserDemoUseCaseUT.react().subscribe(subscriberMock); 59 | subscriberMock.awaitTerminalEvent(); 60 | 61 | assertThat(subscriberMock.getOnErrorEvents().size(), is(1)); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RefineriaWeb/base_app_android/47e586e66fedf572ee97956ab3885ba9f0a2755c/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Oct 29 13:23:29 CET 2015 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.4-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /presentation/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'android-apt' 3 | apply plugin: 'me.tatarka.retrolambda' 4 | apply plugin: 'spoon' 5 | 6 | 7 | buildscript { 8 | repositories { 9 | mavenCentral() 10 | jcenter() 11 | } 12 | 13 | dependencies { 14 | classpath rootProject.ext.buildScriptDependencies.androidApt 15 | classpath rootProject.ext.buildScriptDependencies.retrolambda 16 | classpath rootProject.ext.buildScriptDependencies.spoon 17 | } 18 | } 19 | 20 | spoon { 21 | debug = true 22 | if (project.hasProperty('classNameTestTuRun')) { 23 | className = project.classNameTestTuRun 24 | } 25 | } 26 | 27 | android { 28 | compileSdkVersion rootProject.ext.compileSdkVersion 29 | buildToolsVersion rootProject.ext.buildToolsVersion 30 | 31 | signingConfigs { 32 | release { 33 | storeFile file("keystore") 34 | storePassword "storePassword" 35 | keyAlias "keyAlias" 36 | keyPassword "keyPassword" 37 | } 38 | } 39 | 40 | defaultConfig { 41 | applicationId rootProject.ext.applicationId 42 | minSdkVersion rootProject.ext.minSdkVersion 43 | targetSdkVersion rootProject.ext.targetSdkVersion 44 | versionCode rootProject.ext.versionCode 45 | versionName rootProject.ext.versionName 46 | 47 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 48 | } 49 | 50 | buildTypes { 51 | release { 52 | minifyEnabled false 53 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 54 | } 55 | } 56 | 57 | sourceSets { 58 | main { 59 | res.srcDirs = 60 | [ 61 | 'src/main/res/sections/common', 62 | 'src/main/res/sections/user_demo', 63 | 'src/main/res/sections/dashboard', 64 | 'src/main/res/sections', 65 | 'src/main/res' 66 | ] 67 | } 68 | } 69 | 70 | //Retrolambda 71 | compileOptions { 72 | sourceCompatibility JavaVersion.VERSION_1_8 73 | targetCompatibility JavaVersion.VERSION_1_8 74 | } 75 | 76 | //Lint crash with retrolambda, prevent abort on error 77 | lintOptions { 78 | abortOnError false 79 | } 80 | } 81 | 82 | configurations.all { 83 | resolutionStrategy.force "com.android.support:support-annotations:${rootProject.ext.supportVersion}" 84 | } 85 | 86 | dependencies { 87 | compile fileTree(dir: 'libs', include: ['*.jar']) 88 | compile project(':data') 89 | compile project(':domain') 90 | 91 | def presentationDependencies = rootProject.ext.presentationDependencies 92 | 93 | apt presentationDependencies.daggerCompiler 94 | compile presentationDependencies.dagger 95 | provided presentationDependencies.javaxAnnotation 96 | 97 | compile presentationDependencies.rxJava 98 | compile presentationDependencies.rxAndroid 99 | 100 | compile presentationDependencies.supportAppCompat 101 | compile presentationDependencies.supportRecyclerview 102 | compile presentationDependencies.supportDesign 103 | compile presentationDependencies.picasso 104 | compile presentationDependencies.materialishProgress 105 | compile(presentationDependencies.materialDialog) { 106 | transitive = true 107 | } 108 | compile presentationDependencies.butterKnife 109 | 110 | def presentationTestDependencies = rootProject.ext.presentationTestDependencies 111 | 112 | androidTestCompile presentationTestDependencies.spoonScreenshots 113 | androidTestCompile presentationTestDependencies.supportTestRunner 114 | androidTestCompile presentationTestDependencies.supportTestRules 115 | androidTestCompile (presentationTestDependencies.espresso) { 116 | exclude module: 'support-annotations' 117 | exclude module: 'support-v4' 118 | exclude module: 'support-v13' 119 | exclude module: 'recyclerview-v7' 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /presentation/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/victor/Documents/AndroidStudio/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 | -------------------------------------------------------------------------------- /presentation/src/androidTest/java/presentation/common/BaseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.common; 18 | 19 | import android.app.Activity; 20 | import android.support.test.InstrumentationRegistry; 21 | import android.support.test.rule.ActivityTestRule; 22 | import android.support.test.runner.AndroidJUnit4; 23 | 24 | import com.squareup.spoon.Spoon; 25 | 26 | import org.junit.Before; 27 | import org.junit.Rule; 28 | import org.junit.runner.RunWith; 29 | 30 | import presentation.foundation.BaseApp; 31 | import presentation.sections.launch.LaunchActivity; 32 | 33 | @RunWith(AndroidJUnit4.class) 34 | public abstract class BaseTest { 35 | public static final long SHORT_WAIT = 1000; 36 | public static final long MEDIUM_WAIT = 2500; 37 | public static final long LONG_WAIT = 5000; 38 | 39 | public static void shortWait() { 40 | waitTime(SHORT_WAIT); 41 | } 42 | 43 | public static void mediumWait() { 44 | waitTime(MEDIUM_WAIT); 45 | } 46 | 47 | public static void longWait() { 48 | waitTime(LONG_WAIT); 49 | } 50 | 51 | private static void waitTime(long time) { 52 | try {Thread.sleep(time); 53 | } catch (InterruptedException e) { e.printStackTrace();} 54 | } 55 | 56 | @Rule public ActivityTestRule mActivityRule = new ActivityTestRule<>(LaunchActivity.class); 57 | 58 | @Before public void init() {} 59 | 60 | protected Activity getCurrentActivity() { 61 | BaseApp app = (BaseApp) InstrumentationRegistry.getTargetContext().getApplicationContext(); 62 | return app.getLiveActivity(); 63 | } 64 | 65 | protected void takeScreenShot(String name) { 66 | try { 67 | Spoon.screenshot(getCurrentActivity(), name); 68 | } catch (Exception ignore){} 69 | } 70 | } -------------------------------------------------------------------------------- /presentation/src/androidTest/java/presentation/common/SuiteIntegration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.common; 18 | 19 | import org.junit.runner.RunWith; 20 | import org.junit.runners.Suite; 21 | 22 | import presentation.sections.dashboard.DashboardTest; 23 | import presentation.sections.user_demo.UsersTest; 24 | 25 | @RunWith(Suite.class) 26 | @Suite.SuiteClasses({ 27 | DashboardTest.class, 28 | UsersTest.class 29 | 30 | }) 31 | public class SuiteIntegration { 32 | 33 | } 34 | -------------------------------------------------------------------------------- /presentation/src/androidTest/java/presentation/common/ViewActions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.common; 18 | 19 | import android.support.test.espresso.UiController; 20 | import android.support.test.espresso.ViewAction; 21 | import android.support.v4.view.GravityCompat; 22 | import android.support.v4.widget.DrawerLayout; 23 | import android.view.View; 24 | 25 | import org.hamcrest.Matcher; 26 | 27 | import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom; 28 | 29 | public class ViewActions { 30 | public static ViewAction actionOpenDrawer() { 31 | return new ViewAction() { 32 | @Override public Matcher getConstraints() { 33 | return isAssignableFrom(DrawerLayout.class); 34 | } 35 | 36 | @Override public String getDescription() { 37 | return "open drawer"; 38 | } 39 | 40 | @Override public void perform(UiController uiController, View view) { 41 | ((DrawerLayout) view).openDrawer(GravityCompat.START); 42 | } 43 | }; 44 | } 45 | 46 | public static ViewAction actionCloseDrawer() { 47 | return new ViewAction() { 48 | @Override public Matcher getConstraints() { 49 | return isAssignableFrom(DrawerLayout.class); 50 | } 51 | 52 | @Override public String getDescription() { 53 | return "close drawer"; 54 | } 55 | 56 | @Override public void perform(UiController uiController, View view) { 57 | ((DrawerLayout) view).closeDrawer(GravityCompat.START); 58 | } 59 | }; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /presentation/src/androidTest/java/presentation/sections/dashboard/DashboardTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.sections.dashboard; 18 | 19 | import android.support.test.espresso.contrib.RecyclerViewActions; 20 | 21 | import org.junit.Test; 22 | 23 | import base.app.android.R; 24 | import presentation.common.BaseTest; 25 | 26 | import static android.support.test.espresso.Espresso.onView; 27 | import static android.support.test.espresso.action.ViewActions.click; 28 | import static android.support.test.espresso.matcher.ViewMatchers.withId; 29 | import static presentation.common.ViewActions.actionCloseDrawer; 30 | import static presentation.common.ViewActions.actionOpenDrawer; 31 | 32 | public class DashboardTest extends BaseTest { 33 | 34 | @Test public void Open_And_Close_Users() { 35 | onView(withId(R.id.drawer_layout)).perform(actionOpenDrawer()); 36 | mediumWait(); 37 | onView(withId(R.id.rv_menu_items)).perform(RecyclerViewActions.actionOnItemAtPosition(0, click())); 38 | 39 | takeScreenShot("Users"); 40 | onView(withId(R.id.drawer_layout)).perform(actionCloseDrawer()); 41 | } 42 | 43 | @Test public void Open_And_Close_User() { 44 | onView(withId(R.id.drawer_layout)).perform(actionOpenDrawer()); 45 | mediumWait(); 46 | 47 | onView(withId(R.id.rv_menu_items)).perform(RecyclerViewActions.actionOnItemAtPosition(1, click())); 48 | 49 | takeScreenShot("User"); 50 | onView(withId(R.id.drawer_layout)).perform(actionCloseDrawer()); 51 | } 52 | 53 | @Test public void Open_And_Close_Search_User() { 54 | onView(withId(R.id.drawer_layout)).perform(actionOpenDrawer()); 55 | mediumWait(); 56 | 57 | onView(withId(R.id.rv_menu_items)).perform(RecyclerViewActions.actionOnItemAtPosition(2, click())); 58 | 59 | takeScreenShot("SearchUser"); 60 | onView(withId(R.id.drawer_layout)).perform(actionCloseDrawer()); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /presentation/src/androidTest/java/presentation/sections/user_demo/UsersTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.sections.user_demo; 18 | 19 | import android.support.test.espresso.contrib.RecyclerViewActions; 20 | 21 | import org.junit.FixMethodOrder; 22 | import org.junit.Test; 23 | import org.junit.runners.MethodSorters; 24 | 25 | import base.app.android.R; 26 | import presentation.common.BaseTest; 27 | 28 | import static android.support.test.espresso.Espresso.onView; 29 | import static android.support.test.espresso.action.ViewActions.click; 30 | import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard; 31 | import static android.support.test.espresso.action.ViewActions.replaceText; 32 | import static android.support.test.espresso.assertion.ViewAssertions.matches; 33 | import static android.support.test.espresso.matcher.ViewMatchers.withId; 34 | import static android.support.test.espresso.matcher.ViewMatchers.withText; 35 | 36 | @FixMethodOrder(MethodSorters.NAME_ASCENDING) 37 | public class UsersTest extends BaseTest { 38 | private static final int ID_USER = 21, INDEX_LIST = 11, ID_USER_REFINERIA = 8580307; 39 | private static final String USERNAME = "technoweenie"; 40 | private static final String USERNAME_REFINERIA = "RefineriaWeb"; 41 | 42 | @Test public void _1_Get_Users() { 43 | mediumWait(); 44 | onView(withId(R.id.rv_users)).perform(RecyclerViewActions.scrollToPosition(INDEX_LIST)); 45 | takeScreenShot("Users"); 46 | } 47 | 48 | @Test public void _2_Get_User() { 49 | mediumWait(); 50 | onView(withId(R.id.rv_users)).perform(RecyclerViewActions.scrollToPosition(INDEX_LIST)); 51 | 52 | mediumWait(); 53 | onView(withId(R.id.rv_users)).perform(RecyclerViewActions.actionOnItemAtPosition(INDEX_LIST, click())); 54 | onView(withId(R.id.tv_name)).check(matches(withText(ID_USER + ":" + USERNAME))); 55 | 56 | takeScreenShot(USERNAME); 57 | } 58 | 59 | @Test public void _3_Search_User() { 60 | mediumWait(); 61 | onView(withId(R.id.rv_users)).perform(RecyclerViewActions.scrollToPosition(INDEX_LIST)); 62 | 63 | mediumWait(); 64 | onView(withId(R.id.rv_users)).perform(RecyclerViewActions.actionOnItemAtPosition(INDEX_LIST, click())); 65 | 66 | onView(withId(R.id.bt_go_to_search_user)).perform(click()); 67 | 68 | onView(withId(R.id.et_name)).perform(click(), replaceText(USERNAME_REFINERIA), closeSoftKeyboard()); 69 | onView(withId(R.id.bt_find_user)).perform(click()); 70 | mediumWait(); 71 | 72 | onView(withId(R.id.tv_name)).check(matches(withText(ID_USER_REFINERIA + ":" + USERNAME_REFINERIA))); 73 | takeScreenShot(USERNAME_REFINERIA); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /presentation/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 13 | 14 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/foundation/AppCare.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.foundation; 18 | 19 | import android.app.Activity; 20 | import android.app.Application; 21 | import android.os.Bundle; 22 | import android.support.annotation.Nullable; 23 | 24 | /** 25 | * Track the current activity using the LifecycleCallback application 26 | */ 27 | public enum AppCare { 28 | YesSir; 29 | 30 | private Activity liveActivityOrNull; 31 | 32 | public void takeCareOn(Application application) { 33 | registerActivityLifeCycle(application); 34 | setDefaultUncaughtExceptionHandler(); 35 | } 36 | 37 | private void registerActivityLifeCycle(Application application) { 38 | application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() { 39 | @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { 40 | liveActivityOrNull = activity; 41 | } 42 | 43 | @Override public void onActivityStarted(Activity activity) {} 44 | 45 | @Override public void onActivityResumed(Activity activity) { 46 | liveActivityOrNull = activity; 47 | } 48 | 49 | @Override public void onActivityPaused(Activity activity) { 50 | liveActivityOrNull = null; 51 | } 52 | 53 | @Override public void onActivityStopped(Activity activity) {} 54 | 55 | @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {} 56 | 57 | @Override public void onActivityDestroyed(Activity activity) {} 58 | }); 59 | } 60 | 61 | /** 62 | * In case you want to ensure exceptions are informed without user submission 63 | */ 64 | private void setDefaultUncaughtExceptionHandler() { 65 | Thread.UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler(); 66 | Thread.setDefaultUncaughtExceptionHandler((thread, ex) -> { 67 | defaultHandler.uncaughtException(thread, ex); 68 | }); 69 | } 70 | 71 | @Nullable public Activity getLiveActivityOrNull() { 72 | return liveActivityOrNull; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/foundation/BaseApp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.foundation; 18 | 19 | import android.app.Application; 20 | import android.support.annotation.Nullable; 21 | 22 | import presentation.internal.di.ApplicationComponent; 23 | import presentation.internal.di.ApplicationModule; 24 | import presentation.internal.di.DaggerApplicationComponent; 25 | 26 | /** 27 | * Custom Application 28 | */ 29 | public class BaseApp extends Application { 30 | private ApplicationComponent applicationComponent; 31 | 32 | @Override public void onCreate() { 33 | super.onCreate(); 34 | initInject(); 35 | AppCare.YesSir.takeCareOn(this); 36 | } 37 | 38 | private void initInject() { 39 | applicationComponent = DaggerApplicationComponent.builder() 40 | .applicationModule(new ApplicationModule(this)) 41 | .build(); 42 | } 43 | 44 | public ApplicationComponent getApplicationComponent() { 45 | return applicationComponent; 46 | } 47 | 48 | @Nullable public BaseFragmentActivity getLiveActivity(){ 49 | return (BaseFragmentActivity) AppCare.YesSir.getLiveActivityOrNull(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/foundation/BaseFragmentActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.foundation; 18 | 19 | import android.os.Build; 20 | import android.os.Bundle; 21 | import android.support.annotation.Nullable; 22 | import android.support.design.widget.AppBarLayout; 23 | import android.support.v4.content.ContextCompat; 24 | import android.support.v7.app.ActionBar; 25 | import android.support.v7.app.AppCompatActivity; 26 | import android.support.v7.widget.Toolbar; 27 | import android.util.Log; 28 | import android.view.MenuItem; 29 | import android.view.View; 30 | 31 | import com.afollestad.materialdialogs.MaterialDialog; 32 | 33 | import java.io.Serializable; 34 | 35 | import base.app.android.R; 36 | import butterknife.Bind; 37 | import butterknife.ButterKnife; 38 | import presentation.internal.di.ApplicationComponent; 39 | 40 | public abstract class BaseFragmentActivity extends AppCompatActivity { 41 | @Nullable @Bind(R.id.app_bar) protected AppBarLayout app_bar; 42 | @Nullable @Bind(R.id.toolbar) protected Toolbar toolbar; 43 | protected String app_name; 44 | private MaterialDialog materialDialog; 45 | 46 | @Override protected void onCreate(Bundle savedInstanceState) { 47 | super.onCreate(savedInstanceState); 48 | app_name = getString(R.string.app_name); 49 | 50 | if (layoutRes() != null) setContentView(layoutRes()); 51 | 52 | ButterKnife.bind(this); 53 | injectDagger(); 54 | 55 | configureToolbar(toolbar, app_bar); 56 | initViews(); 57 | configureFragment(); 58 | } 59 | 60 | protected void initViews() {} 61 | 62 | private Integer layoutRes() { 63 | LayoutResActivity layoutRes = this.getClass().getAnnotation(LayoutResActivity.class); 64 | return layoutRes != null ? layoutRes.value() : null; 65 | } 66 | 67 | protected abstract void injectDagger(); 68 | 69 | public BaseApp getBaseApp() { 70 | return ((BaseApp)getApplication()); 71 | } 72 | 73 | public ApplicationComponent getApplicationComponent() { 74 | return getBaseApp().getApplicationComponent(); 75 | } 76 | 77 | protected BasePresenterFragment replaceFragmentIfItIsNotCurrentDisplayed(Class clazz) { 78 | BasePresenterFragment current = getCurrentPresenterFragment(); 79 | if (current != null && current.getClass() == clazz) return current; 80 | return replaceFragment(clazz); 81 | } 82 | 83 | protected BasePresenterFragment replaceFragment(Class clazz) { 84 | try { 85 | BasePresenterFragment fragment = clazz.newInstance(); 86 | getSupportFragmentManager().beginTransaction().replace(R.id.fl_fragment, fragment).commit(); 87 | return fragment; 88 | } catch (InstantiationException e) { 89 | throw new IllegalStateException(e.getMessage()); 90 | } catch (IllegalAccessException e) { 91 | throw new IllegalStateException(e.getMessage()); 92 | } 93 | } 94 | 95 | public interface Behaviour { 96 | String FRAGMENT_CLASS_KEY = "fragment_class_key"; 97 | String BUNDLE_FOR_FRAGMENT = "bundle_for_fragment"; 98 | boolean SHOW_BACK_AS_DEFAULT = true; 99 | String SHOW_BACK_KEY = "show_back_key"; 100 | String TITLE_KEY = "title_key"; 101 | boolean SHOW_TOOLBAR_AS_DEFAULT = true; 102 | String SHOW_TOOLBAR = "show_toolbar"; 103 | } 104 | 105 | public BasePresenterFragment getCurrentPresenterFragment() { 106 | return (BasePresenterFragment) getSupportFragmentManager().findFragmentById(R.id.fl_fragment); 107 | } 108 | 109 | private void configureFragment() { 110 | Bundle bundle = getIntent().getExtras(); 111 | if (bundle == null || bundle.getSerializable(Behaviour.FRAGMENT_CLASS_KEY) == null) { 112 | Log.w(BaseFragmentActivity.class.getSimpleName(), "When using " + BaseFragmentActivity.class.getSimpleName() + " you could supply" + 113 | " a fragment which extends from " + BasePresenterFragment.class.getSimpleName() + " by extra argument in the intent" + 114 | " as value and " + Behaviour.FRAGMENT_CLASS_KEY + " as key, but a " + 115 | " will be mandatory in your activity layout."); 116 | return; 117 | } 118 | 119 | Serializable serializable = bundle.getSerializable(Behaviour.FRAGMENT_CLASS_KEY); 120 | Class clazz = (Class) serializable; 121 | 122 | BasePresenterFragment basePresenterFragment = replaceFragment(clazz); 123 | Bundle bundleFragment = bundle.getBundle(Behaviour.BUNDLE_FOR_FRAGMENT); 124 | basePresenterFragment.setArguments(bundleFragment); 125 | } 126 | 127 | private void configureToolbar(Toolbar toolbar, @Nullable AppBarLayout appBarLayout) { 128 | setSupportActionBar(toolbar); 129 | ActionBar actionBar = getSupportActionBar(); 130 | boolean showToolbar = Behaviour.SHOW_TOOLBAR_AS_DEFAULT; 131 | 132 | if (actionBar != null) { 133 | Bundle bundle = getIntent().getExtras(); 134 | 135 | if (bundle != null) { 136 | boolean showBackKey = bundle.getBoolean(Behaviour.SHOW_BACK_KEY, Behaviour.SHOW_BACK_AS_DEFAULT); 137 | showToolbar = bundle.getBoolean(Behaviour.SHOW_TOOLBAR, showToolbar); 138 | actionBar.setDisplayHomeAsUpEnabled(showBackKey); 139 | String title = bundle.getString(Behaviour.TITLE_KEY); 140 | actionBar.setTitle(title); 141 | } else { 142 | actionBar.setDisplayHomeAsUpEnabled(Behaviour.SHOW_BACK_AS_DEFAULT); 143 | actionBar.setTitle(app_name); 144 | } 145 | } 146 | 147 | setStatusBarColor(); 148 | 149 | if (appBarLayout != null) 150 | appBarLayout.setVisibility(showToolbar ? View.VISIBLE : View.GONE); 151 | } 152 | 153 | private void setStatusBarColor() { 154 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 155 | getWindow().setStatusBarColor(ContextCompat.getColor(this, R.color.colorPrimaryDark)); 156 | } 157 | } 158 | 159 | @Override public boolean onOptionsItemSelected(MenuItem item) { 160 | if (item.getItemId() == android.R.id.home) onBackPressed(); 161 | return super.onOptionsItemSelected(item); 162 | } 163 | 164 | @Override public void setTitle(CharSequence title) { 165 | getSupportActionBar().setTitle(title); 166 | } 167 | 168 | public void showLoading() { 169 | materialDialog = new MaterialDialog.Builder(this) 170 | .titleColorRes(R.color.colorPrimaryDark) 171 | .cancelable(false) 172 | .contentColor(ContextCompat.getColor(this, R.color.colorPrimaryDark)) 173 | .widgetColorRes(R.color.colorPrimaryDark) 174 | .title(app_name) 175 | .content(getString(R.string.loading)) 176 | .progress(true, 0) 177 | .show(); 178 | } 179 | 180 | public void hideLoading() { 181 | if (materialDialog != null) materialDialog.dismiss(); 182 | } 183 | 184 | @Override public void onBackPressed() { 185 | BasePresenterFragment fragment = getCurrentPresenterFragment(); 186 | BackButtonListener listener = fragment != null && fragment instanceof BackButtonListener ? (BackButtonListener) fragment : null; 187 | 188 | if (listener == null) { 189 | super.onBackPressed(); 190 | return; 191 | } 192 | 193 | if (listener.onBackPressed()) super.onBackPressed(); 194 | } 195 | 196 | /*** 197 | * BasePresenterFragment can implement this interface to be notified when user performs a back action. 198 | */ 199 | public interface BackButtonListener { 200 | /*** 201 | * @return true if activity must handle back action, as removing itself from the stack 202 | */ 203 | boolean onBackPressed(); 204 | } 205 | } -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/foundation/BasePresenterFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.foundation; 18 | 19 | import android.os.Bundle; 20 | import android.support.annotation.Nullable; 21 | import android.support.design.widget.Snackbar; 22 | import android.support.v4.app.Fragment; 23 | import android.support.v4.app.FragmentManager; 24 | import android.view.LayoutInflater; 25 | import android.view.View; 26 | import android.view.ViewGroup; 27 | import android.widget.Toast; 28 | 29 | import javax.inject.Inject; 30 | 31 | import butterknife.ButterKnife; 32 | import domain.foundation.BaseView; 33 | import domain.foundation.Presenter; 34 | import presentation.internal.di.ApplicationComponent; 35 | 36 | public abstract class BasePresenterFragment

extends Fragment implements BaseView { 37 | @Inject protected P presenter; 38 | 39 | @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 40 | View view = inflater.inflate(layoutRes(), container, false); 41 | ButterKnife.bind(this, view); 42 | 43 | injectDagger(); 44 | return view; 45 | } 46 | 47 | private Integer layoutRes() { 48 | LayoutResFragment layoutRes = this.getClass().getAnnotation(LayoutResFragment.class); 49 | return layoutRes != null ? layoutRes.value() : null; 50 | } 51 | 52 | @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { 53 | super.onActivityCreated(savedInstanceState); 54 | initViews(); 55 | presenter.attachView(this); 56 | } 57 | 58 | protected abstract void injectDagger(); 59 | protected void initViews() {} 60 | 61 | @Override public void onDestroyView() { 62 | super.onDestroyView(); 63 | presenter.dispose(); 64 | ButterKnife.unbind(this); 65 | } 66 | 67 | @Override public void onResume() { 68 | super.onResume(); 69 | presenter.resumeView(); 70 | } 71 | 72 | protected ApplicationComponent getApplicationComponent() { 73 | return ((BaseFragmentActivity)getActivity()).getApplicationComponent(); 74 | } 75 | 76 | public void showToast(String title) { 77 | Toast.makeText(getActivity(), title, Toast.LENGTH_LONG) 78 | .show(); 79 | } 80 | 81 | public void showSnackBar(String title) { 82 | Snackbar.make(getView(), title, Snackbar.LENGTH_LONG) 83 | .show(); 84 | } 85 | 86 | protected void replaceFragment(int id, Fragment fragment) { 87 | FragmentManager fragmentManager = getChildFragmentManager(); 88 | fragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); 89 | fragmentManager.beginTransaction() 90 | .replace(id, fragment, fragment.getClass().getSimpleName()) 91 | .commit(); 92 | } 93 | 94 | protected void showLoading() { 95 | if (getActivity() instanceof BaseFragmentActivity) 96 | ((BaseFragmentActivity)getActivity()).showLoading(); 97 | } 98 | 99 | protected void hideLoading() { 100 | if (getActivity() instanceof BaseFragmentActivity) 101 | ((BaseFragmentActivity)getActivity()).hideLoading(); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/foundation/LayoutResActivity.java: -------------------------------------------------------------------------------- 1 | package presentation.foundation; 2 | 3 | import android.support.annotation.LayoutRes; 4 | 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | /** 11 | * Sets the layout resource for every Activity which extends from BaseFragmentActivity 12 | * @see BaseFragmentActivity 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target(ElementType.TYPE) 16 | public @interface LayoutResActivity { 17 | @LayoutRes int value(); 18 | } 19 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/foundation/LayoutResFragment.java: -------------------------------------------------------------------------------- 1 | package presentation.foundation; 2 | 3 | import android.support.annotation.LayoutRes; 4 | 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | /** 11 | * Sets the layout resource for every Fragment which extends from BasePresenterFragment 12 | * @see BasePresenterFragment 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target(ElementType.TYPE) 16 | public @interface LayoutResFragment { 17 | @LayoutRes int value(); 18 | } 19 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/foundation/SingleFragmentActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.foundation; 18 | 19 | import base.app.android.R; 20 | 21 | @LayoutResActivity(R.layout.single_fragment_activity) 22 | public class SingleFragmentActivity extends BaseFragmentActivity { 23 | 24 | @Override protected void injectDagger() {} 25 | 26 | } -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/internal/di/ApplicationComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.internal.di; 18 | 19 | import javax.inject.Singleton; 20 | 21 | import dagger.Component; 22 | import presentation.sections.dashboard.DashBoardActivity; 23 | import presentation.sections.launch.LaunchActivity; 24 | import presentation.sections.user_demo.detail.UserFragment; 25 | import presentation.sections.user_demo.list.UsersFragment; 26 | import presentation.sections.user_demo.search.SearchUserFragment; 27 | 28 | /** 29 | * Every fragment or activity which needs to be part of the dependency system provided by Dagger needs 30 | * to be declared in this component in order to be injected later 31 | */ 32 | @Singleton @Component(modules = {DomainPresentationModule.class, DataPresentationModule.class, ApplicationModule.class}) 33 | public interface ApplicationComponent { 34 | void inject(LaunchActivity launchActivity); 35 | 36 | void inject(DashBoardActivity dashBoardActivity); 37 | void inject(UserFragment userFragment); 38 | void inject(UsersFragment usersFragment); 39 | void inject(SearchUserFragment searchUserFragment); 40 | } 41 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/internal/di/ApplicationModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.internal.di; 18 | 19 | import javax.inject.Singleton; 20 | 21 | import dagger.Module; 22 | import dagger.Provides; 23 | import data.internal.di.DataModule; 24 | import presentation.foundation.BaseApp; 25 | 26 | @Module(includes = DataModule.class) public class ApplicationModule { 27 | private final BaseApp baseApp; 28 | 29 | public ApplicationModule(BaseApp baseApp) { 30 | this.baseApp = baseApp; 31 | } 32 | 33 | @Provides @Singleton BaseApp provideApplication() { 34 | return baseApp; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/internal/di/DataPresentationModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.internal.di; 18 | 19 | import javax.inject.Singleton; 20 | 21 | import dagger.Module; 22 | import dagger.Provides; 23 | import data.internal.di.DataModule; 24 | import data.sections.UI; 25 | import data.storage.RepositoryAdapter; 26 | import presentation.foundation.BaseApp; 27 | import presentation.sections.UIData; 28 | 29 | 30 | /** 31 | * Dependencies required by the data layer need to be provided in this dagger module 32 | */ 33 | @Module(includes = {DataModule.class, ApplicationModule.class}) 34 | public class DataPresentationModule { 35 | 36 | /** 37 | * Provides the file system for the data layer 38 | * @see RepositoryAdapter 39 | */ 40 | @Singleton @Provides RepositoryAdapter provideRepositoryAdapter(BaseApp baseApp) { 41 | return () -> baseApp.getFilesDir(); 42 | } 43 | 44 | /** 45 | * Provides the locale for the data layer 46 | * @see UI 47 | */ 48 | @Singleton @Provides 49 | UI provideLocale(BaseApp baseApp) { 50 | return new UIData(baseApp); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/internal/di/DomainPresentationModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.internal.di; 18 | 19 | 20 | import javax.inject.Singleton; 21 | 22 | import dagger.Module; 23 | import dagger.Provides; 24 | import domain.internal.di.DomainModule; 25 | import domain.foundation.schedulers.ObserveOn; 26 | import domain.sections.UI; 27 | import domain.sections.Wireframe; 28 | import domain.sections.dashboard.DashboardItemsMenu; 29 | import presentation.foundation.BaseApp; 30 | import presentation.sections.UIDomain; 31 | import presentation.sections.WireframeDomain; 32 | import presentation.sections.dashboard.DashboardItemsMenuDomain; 33 | import rx.android.schedulers.AndroidSchedulers; 34 | 35 | /** 36 | * Dependencies required by the domain layer need to be provided in this dagger module 37 | */ 38 | @Module(includes = {DomainModule.class, ApplicationModule.class}) 39 | public class DomainPresentationModule { 40 | 41 | /** 42 | * Provides the Scheduler which will be use for any Observable at the domain layer 43 | * to observeOn 44 | */ 45 | @Singleton @Provides ObserveOn provideObserveOn() { 46 | return (() -> AndroidSchedulers.mainThread()); 47 | } 48 | 49 | /** 50 | * Provides the locale for the domain layer 51 | * @see UI 52 | */ 53 | @Singleton @Provides 54 | UI provideLocale(BaseApp baseApp) { 55 | return new UIDomain(baseApp); 56 | } 57 | 58 | /** 59 | * Implements the navigation system required by the domain layer 60 | * using intents in order to load the following screens 61 | */ 62 | @Singleton @Provides Wireframe provideAndroidWireframe(BaseApp baseApp) { 63 | return new WireframeDomain(baseApp); 64 | } 65 | 66 | /** 67 | * Implements the DashboardItemsMenu 68 | */ 69 | @Singleton @Provides DashboardItemsMenu provideDashboardItemsMenuDomain(BaseApp baseApp) { 70 | return new DashboardItemsMenuDomain(baseApp); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/sections/UIData.java: -------------------------------------------------------------------------------- 1 | package presentation.sections; 2 | 3 | import base.app.android.R; 4 | import data.sections.UI; 5 | import presentation.foundation.BaseApp; 6 | import rx.Observable; 7 | 8 | public class UIData implements UI { 9 | private final BaseApp baseApp; 10 | 11 | public UIData(BaseApp baseApp) { 12 | this.baseApp = baseApp; 13 | } 14 | 15 | @Override public Observable genericError() { 16 | return Observable.just(baseApp.getString(R.string.generic_error)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/sections/UIDomain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.sections; 18 | 19 | import android.widget.Toast; 20 | 21 | import base.app.android.R; 22 | import domain.sections.UI; 23 | import presentation.foundation.BaseApp; 24 | import rx.Observable; 25 | import rx.Subscription; 26 | 27 | public class UIDomain implements UI { 28 | private final BaseApp baseApp; 29 | 30 | public UIDomain(BaseApp baseApp) { 31 | this.baseApp = baseApp; 32 | } 33 | 34 | @Override public Observable errorNonEmptyFields() { 35 | return Observable.just(baseApp.getString(R.string.fill_missing_fields)); 36 | } 37 | 38 | @Override public Subscription showFeedback(Observable oFeedback) { 39 | return oFeedback.subscribe(feedback -> { 40 | Toast.makeText(baseApp, feedback, Toast.LENGTH_LONG) 41 | .show(); 42 | }); 43 | } 44 | 45 | @Override public Subscription showAnchoredScreenFeedback(Observable oFeedback) { 46 | return oFeedback.subscribe(feedback -> { 47 | baseApp.getLiveActivity() 48 | .getCurrentPresenterFragment().showSnackBar(feedback); 49 | }); 50 | } 51 | 52 | @Override public void showLoading() { 53 | baseApp.getLiveActivity().showLoading(); 54 | } 55 | 56 | @Override public void hideLoading() { 57 | baseApp.getLiveActivity().hideLoading(); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/sections/WireframeDomain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.sections; 18 | 19 | import android.content.Intent; 20 | import android.os.Bundle; 21 | 22 | import base.app.android.R; 23 | import domain.sections.Wireframe; 24 | import presentation.foundation.BaseApp; 25 | import presentation.foundation.BaseFragmentActivity; 26 | import presentation.foundation.SingleFragmentActivity; 27 | import presentation.sections.dashboard.DashBoardActivity; 28 | import presentation.sections.user_demo.detail.UserFragment; 29 | import presentation.sections.user_demo.list.UsersFragment; 30 | import presentation.sections.user_demo.search.SearchUserFragment; 31 | 32 | public class WireframeDomain implements Wireframe { 33 | private final BaseApp baseApp; 34 | 35 | public WireframeDomain(BaseApp baseApp) { 36 | this.baseApp = baseApp; 37 | } 38 | 39 | @Override public void dashboard() { 40 | baseApp.getLiveActivity().startActivity(new Intent(baseApp, DashBoardActivity.class)); 41 | } 42 | 43 | @Override public void usersScreen() { 44 | Bundle bundle = new Bundle(); 45 | bundle.putString(BaseFragmentActivity.Behaviour.TITLE_KEY, baseApp.getString(R.string.users)); 46 | bundle.putBoolean(BaseFragmentActivity.Behaviour.SHOW_BACK_KEY, false); 47 | bundle.putSerializable(BaseFragmentActivity.Behaviour.FRAGMENT_CLASS_KEY, UsersFragment.class); 48 | Intent intent = new Intent(baseApp, SingleFragmentActivity.class); 49 | intent.putExtras(bundle); 50 | baseApp.getLiveActivity().startActivity(intent); 51 | } 52 | 53 | @Override public void userScreen() { 54 | Bundle bundle = new Bundle(); 55 | bundle.putString(BaseFragmentActivity.Behaviour.TITLE_KEY, baseApp.getString(R.string.user)); 56 | bundle.putSerializable(BaseFragmentActivity.Behaviour.FRAGMENT_CLASS_KEY, UserFragment.class); 57 | Intent intent = new Intent(baseApp, SingleFragmentActivity.class); 58 | intent.putExtras(bundle); 59 | baseApp.getLiveActivity().startActivity(intent); 60 | } 61 | 62 | @Override public void searchUserScreen() { 63 | Bundle bundleFragment = new Bundle(); 64 | bundleFragment.putString(SearchUserFragment.HELLO_FROM_BUNDLE_WIREFRAME_KEY, "Hi from wireframe bundle"); 65 | Bundle bundle = new Bundle(); 66 | bundle.putString(BaseFragmentActivity.Behaviour.TITLE_KEY, baseApp.getString(R.string.find_user)); 67 | bundle.putSerializable(BaseFragmentActivity.Behaviour.FRAGMENT_CLASS_KEY, SearchUserFragment.class); 68 | bundle.putBundle(BaseFragmentActivity.Behaviour.BUNDLE_FOR_FRAGMENT, bundleFragment); 69 | Intent intent = new Intent(baseApp, SingleFragmentActivity.class); 70 | intent.putExtras(bundle); 71 | baseApp.getLiveActivity().startActivity(intent); 72 | } 73 | 74 | @Override public void popCurrentScreen() { 75 | baseApp.getLiveActivity().finish(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/sections/dashboard/DashBoardActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.sections.dashboard; 18 | 19 | import android.content.Context; 20 | import android.content.res.Configuration; 21 | import android.os.Bundle; 22 | import android.support.v4.widget.DrawerLayout; 23 | import android.support.v7.app.ActionBarDrawerToggle; 24 | import android.support.v7.widget.LinearLayoutManager; 25 | import android.support.v7.widget.RecyclerView; 26 | import android.view.MenuItem; 27 | import android.view.View; 28 | import android.view.ViewGroup; 29 | 30 | import java.util.List; 31 | 32 | import javax.inject.Inject; 33 | 34 | import base.app.android.R; 35 | import butterknife.Bind; 36 | import butterknife.BindString; 37 | import domain.sections.dashboard.DashboardPresenter; 38 | import domain.sections.dashboard.DashboardView; 39 | import domain.sections.dashboard.ItemMenu; 40 | import presentation.foundation.BaseFragmentActivity; 41 | import presentation.foundation.LayoutResActivity; 42 | import presentation.sections.user_demo.detail.UserFragment; 43 | import presentation.sections.user_demo.list.UsersFragment; 44 | import presentation.sections.user_demo.search.SearchUserFragment; 45 | import presentation.utilities.recyclerview_adapter.RecyclerViewAdapter; 46 | import rx.Observable; 47 | import rx.Subscription; 48 | 49 | @LayoutResActivity(R.layout.dashboard_activity) 50 | public class DashBoardActivity extends BaseFragmentActivity implements DashboardView { 51 | @Inject protected DashboardPresenter presenter; 52 | @Bind(R.id.rv_menu_items) protected RecyclerView rv_menu_items; 53 | @Bind(R.id.drawer_layout) protected DrawerLayout drawer_layout; 54 | private ItemMenuDashboardAdapter adapter; 55 | private ActionBarDrawerToggle drawerToggle; 56 | 57 | @Override protected void injectDagger() { 58 | getApplicationComponent().inject(this); 59 | } 60 | 61 | @Override protected void initViews() { 62 | super.initViews(); 63 | adapter = new ItemMenuDashboardAdapter(this); 64 | setUpDrawerToggle(); 65 | setUpRecyclerView(); 66 | presenter.attachView(this); 67 | } 68 | 69 | @Override protected void onDestroy() { 70 | super.onDestroy(); 71 | drawer_layout.removeDrawerListener(drawerToggle); 72 | } 73 | 74 | private void setUpDrawerToggle() { 75 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 76 | getSupportActionBar().setHomeButtonEnabled(true); 77 | 78 | drawerToggle = new ActionBarDrawerToggle(this, drawer_layout, R.string.app_name, R.string.app_name) { 79 | @Override public void onDrawerClosed(View view) { 80 | super.onDrawerClosed(view); 81 | } 82 | 83 | @Override public void onDrawerOpened(View drawerView) { 84 | super.onDrawerOpened(drawerView); 85 | } 86 | }; 87 | 88 | drawer_layout.addDrawerListener(drawerToggle); 89 | } 90 | 91 | private void setUpRecyclerView() { 92 | rv_menu_items.setHasFixedSize(true); 93 | rv_menu_items.setLayoutManager(new LinearLayoutManager(this)); 94 | 95 | adapter.addListener((itemMenu, itemMenuViewGroup) -> { 96 | drawer_layout.closeDrawer(rv_menu_items); 97 | presenter.setSelectedItemMenu(itemMenu); 98 | }); 99 | rv_menu_items.setAdapter(adapter); 100 | } 101 | 102 | @Override public Subscription loadItemsMenu(Observable> oItems) { 103 | return oItems.subscribe(items -> adapter.addAll(items)); 104 | } 105 | 106 | @BindString(R.string.users) protected String users; 107 | @Override public void showUsers() { 108 | replaceFragmentIfItIsNotCurrentDisplayed(UsersFragment.class); 109 | setTitle(users); 110 | } 111 | 112 | @BindString(R.string.user) protected String user; 113 | @Override public void showUser() { 114 | replaceFragmentIfItIsNotCurrentDisplayed(UserFragment.class); 115 | setTitle(user); 116 | } 117 | 118 | @BindString(R.string.find_user) protected String find_user; 119 | @Override public void showUserSearch() { 120 | replaceFragmentIfItIsNotCurrentDisplayed(SearchUserFragment.class); 121 | setTitle(find_user); 122 | } 123 | 124 | @Override protected void onPostCreate(Bundle savedInstanceState) { 125 | super.onPostCreate(savedInstanceState); 126 | drawerToggle.syncState(); 127 | } 128 | 129 | @Override public void onConfigurationChanged(Configuration newConfig) { 130 | super.onConfigurationChanged(newConfig); 131 | drawerToggle.onConfigurationChanged(newConfig); 132 | } 133 | 134 | @Override public boolean onOptionsItemSelected(MenuItem item) { 135 | if (drawerToggle.onOptionsItemSelected(item)) return true; 136 | else if (item.getItemId() == android.R.id.home) onBackPressed(); 137 | return super.onOptionsItemSelected(item); 138 | } 139 | 140 | static private class ItemMenuDashboardAdapter extends RecyclerViewAdapter { 141 | private Context context; 142 | 143 | public ItemMenuDashboardAdapter(Context context) { 144 | this.context = context; 145 | } 146 | 147 | @Override protected ItemMenuViewGroup onCreateItemView(ViewGroup parent, int viewType) { 148 | return new ItemMenuViewGroup(context); 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/sections/dashboard/DashboardItemsMenuDomain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.sections.dashboard; 18 | 19 | import base.app.android.R; 20 | import domain.sections.dashboard.DashboardItemsMenu; 21 | import domain.sections.dashboard.ItemMenu; 22 | import presentation.foundation.BaseApp; 23 | 24 | public class DashboardItemsMenuDomain implements DashboardItemsMenu { 25 | private final BaseApp baseApp; 26 | 27 | public DashboardItemsMenuDomain(BaseApp baseApp) { 28 | this.baseApp = baseApp; 29 | } 30 | 31 | @Override public void configureUsers(ItemMenu itemMenu) { 32 | itemMenu.setTitle(baseApp.getString(R.string.users)); 33 | itemMenu.setImageResource(R.drawable.ic_users); 34 | } 35 | 36 | @Override public void configureUser(ItemMenu itemMenu) { 37 | itemMenu.setTitle(baseApp.getString(R.string.user)); 38 | itemMenu.setImageResource(R.drawable.ic_user); 39 | } 40 | 41 | @Override public void configureSearchUser(ItemMenu itemMenu) { 42 | itemMenu.setTitle(baseApp.getString(R.string.find_user)); 43 | itemMenu.setImageResource(R.drawable.ic_search); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/sections/dashboard/ItemMenuViewGroup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.sections.dashboard; 18 | 19 | import android.content.Context; 20 | import android.util.AttributeSet; 21 | import android.view.LayoutInflater; 22 | import android.view.View; 23 | import android.widget.FrameLayout; 24 | import android.widget.ImageView; 25 | import android.widget.TextView; 26 | 27 | import base.app.android.R; 28 | import butterknife.Bind; 29 | import butterknife.ButterKnife; 30 | import domain.sections.dashboard.ItemMenu; 31 | import presentation.utilities.recyclerview_adapter.ViewWrapper; 32 | 33 | public class ItemMenuViewGroup extends FrameLayout implements ViewWrapper.Binder { 34 | @Bind(R.id.iv_icon) protected ImageView iv_icon; 35 | @Bind(R.id.tv_title) protected TextView tv_title; 36 | 37 | public ItemMenuViewGroup(Context context) { 38 | super(context); 39 | init(); 40 | } 41 | 42 | public ItemMenuViewGroup(Context context, AttributeSet attrs) { 43 | super(context, attrs); 44 | init(); 45 | } 46 | 47 | private void init() { 48 | View view = LayoutInflater.from(getContext()).inflate(R.layout.item_menu_view_group, this, true); 49 | ButterKnife.bind(this, view); 50 | } 51 | 52 | @Override public void bind(ItemMenu itemMenu, int position) { 53 | iv_icon.setImageResource((Integer)itemMenu.getImageResource()); 54 | tv_title.setText(itemMenu.getTitle()); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/sections/launch/LaunchActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.sections.launch; 18 | 19 | import javax.inject.Inject; 20 | 21 | import domain.sections.launch.LaunchPresenter; 22 | import domain.sections.launch.LaunchView; 23 | import presentation.foundation.BaseFragmentActivity; 24 | 25 | public class LaunchActivity extends BaseFragmentActivity implements LaunchView { 26 | @Inject protected LaunchPresenter launchPresenter; 27 | 28 | @Override protected void injectDagger() { 29 | getApplicationComponent().inject(this); 30 | } 31 | 32 | @Override protected void initViews() { 33 | super.initViews(); 34 | launchPresenter.attachView(this); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/sections/user_demo/UserViewGroup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.sections.user_demo; 18 | 19 | import android.content.Context; 20 | import android.util.AttributeSet; 21 | import android.view.LayoutInflater; 22 | import android.view.View; 23 | import android.widget.FrameLayout; 24 | import android.widget.ImageView; 25 | import android.widget.TextView; 26 | 27 | import com.squareup.picasso.Picasso; 28 | 29 | import base.app.android.R; 30 | import butterknife.Bind; 31 | import butterknife.ButterKnife; 32 | import domain.sections.user_demo.entities.UserDemoEntity; 33 | import presentation.utilities.recyclerview_adapter.ViewWrapper; 34 | 35 | public class UserViewGroup extends FrameLayout implements ViewWrapper.Binder { 36 | @Bind(R.id.iv_avatar) protected ImageView iv_avatar; 37 | @Bind(R.id.tv_name) protected TextView tv_name; 38 | 39 | public UserViewGroup(Context context) { 40 | super(context); 41 | init(); 42 | } 43 | 44 | public UserViewGroup(Context context, AttributeSet attrs) { 45 | super(context, attrs); 46 | init(); 47 | } 48 | 49 | private void init() { 50 | View view = LayoutInflater.from(getContext()).inflate(R.layout.user_view_group, this, true); 51 | ButterKnife.bind(this, view); 52 | } 53 | 54 | public void bind(UserDemoEntity user) { 55 | bind(user, 0); 56 | } 57 | 58 | @Override public void bind(UserDemoEntity user, int position) { 59 | Picasso.with(getContext()).load(user.getAvatarUrl()) 60 | .centerCrop() 61 | .fit() 62 | .into(iv_avatar); 63 | tv_name.setText(user.getId() + ":" + user.getLogin()); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/sections/user_demo/detail/UserFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.sections.user_demo.detail; 18 | 19 | import android.view.View; 20 | 21 | import base.app.android.R; 22 | import butterknife.Bind; 23 | import butterknife.OnClick; 24 | import domain.sections.user_demo.common.UserView; 25 | import domain.sections.user_demo.detail.UserDemoPresenter; 26 | import domain.sections.user_demo.entities.UserDemoEntity; 27 | import presentation.foundation.BasePresenterFragment; 28 | import presentation.foundation.LayoutResFragment; 29 | import presentation.sections.user_demo.UserViewGroup; 30 | import rx.Observable; 31 | import rx.Subscription; 32 | 33 | @LayoutResFragment(R.layout.user_fragment) 34 | public class UserFragment extends BasePresenterFragment implements UserView { 35 | @Bind(R.id.pb_loading) protected View pb_loading; 36 | @Bind(R.id.user_view_group) protected UserViewGroup user_view_group; 37 | 38 | @Override protected void injectDagger() { 39 | getApplicationComponent().inject(this); 40 | } 41 | 42 | @Override public Subscription showUser(Observable oUser) { 43 | showProgress(); 44 | 45 | return oUser.doOnCompleted(() -> hideProgress()) 46 | .subscribe(user -> user_view_group.bind(user)); 47 | } 48 | 49 | public void showProgress() { 50 | pb_loading.setVisibility(View.VISIBLE); 51 | } 52 | 53 | public void hideProgress() { 54 | pb_loading.setVisibility(View.GONE); 55 | } 56 | 57 | @OnClick(R.id.bt_go_to_search_user) 58 | protected void bt_go_to_search_user() { 59 | presenter.goToSearchScreen(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/sections/user_demo/list/UsersFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.sections.user_demo.list; 18 | 19 | import android.support.v7.widget.GridLayoutManager; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.View; 22 | import android.view.ViewGroup; 23 | 24 | import java.util.List; 25 | 26 | import base.app.android.R; 27 | import butterknife.Bind; 28 | import domain.sections.user_demo.entities.UserDemoEntity; 29 | import domain.sections.user_demo.list.UsersDemoPresenter; 30 | import domain.sections.user_demo.list.UsersView; 31 | import presentation.foundation.BasePresenterFragment; 32 | import presentation.foundation.LayoutResFragment; 33 | import presentation.sections.user_demo.UserViewGroup; 34 | import presentation.utilities.recyclerview_adapter.RecyclerViewAdapter; 35 | import rx.Observable; 36 | import rx.Subscription; 37 | 38 | 39 | @LayoutResFragment(R.layout.users_fragment) 40 | public class UsersFragment extends BasePresenterFragment implements UsersView { 41 | @Bind(R.id.pb_loading) protected View pb_loading; 42 | @Bind(R.id.rv_users) protected RecyclerView rv_users; 43 | private RecyclerViewAdapter adapter; 44 | 45 | @Override protected void injectDagger() { 46 | getApplicationComponent().inject(this); 47 | } 48 | 49 | @Override protected void initViews() { 50 | setUpRecyclerView(); 51 | } 52 | 53 | private void setUpRecyclerView() { 54 | rv_users.setHasFixedSize(true); 55 | rv_users.setLayoutManager(new GridLayoutManager(getActivity(), 2)); 56 | 57 | adapter = new RecyclerViewAdapter() { 58 | @Override protected UserViewGroup onCreateItemView(ViewGroup parent, int viewType) { 59 | return new UserViewGroup(getActivity()); 60 | } 61 | }; 62 | 63 | adapter.addListener((user, userViewGroup) -> presenter.goToDetail(user)); 64 | adapter.swipeToRemoveItemOn(rv_users) 65 | .withUndoAction() 66 | .notify(item -> showToast(item.getLogin())); 67 | 68 | rv_users.setAdapter(adapter); 69 | } 70 | 71 | @Override public Subscription showUsers(Observable> oUsers) { 72 | showProgress(); 73 | 74 | return oUsers 75 | .doOnCompleted(() -> { 76 | rv_users.setVisibility(View.VISIBLE); 77 | hideProgress(); 78 | }) 79 | .subscribe(users -> adapter.addAll(users)); 80 | } 81 | 82 | public void showProgress() { 83 | pb_loading.setVisibility(View.VISIBLE); 84 | rv_users.setVisibility(View.INVISIBLE); 85 | } 86 | 87 | public void hideProgress() { 88 | pb_loading.setVisibility(View.INVISIBLE); 89 | rv_users.setVisibility(View.VISIBLE); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/sections/user_demo/search/SearchUserFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.sections.user_demo.search; 18 | 19 | import android.os.Bundle; 20 | import android.view.View; 21 | import android.widget.EditText; 22 | 23 | import base.app.android.R; 24 | import butterknife.Bind; 25 | import butterknife.OnClick; 26 | import domain.sections.user_demo.common.UserView; 27 | import domain.sections.user_demo.entities.UserDemoEntity; 28 | import domain.sections.user_demo.search.SearchUserDemoPresenter; 29 | import presentation.foundation.BaseFragmentActivity; 30 | import presentation.foundation.BasePresenterFragment; 31 | import presentation.foundation.LayoutResFragment; 32 | import presentation.sections.user_demo.UserViewGroup; 33 | import rx.Observable; 34 | import rx.Subscription; 35 | 36 | @LayoutResFragment(R.layout.user_search_fragment) 37 | public class SearchUserFragment extends BasePresenterFragment implements UserView, BaseFragmentActivity.BackButtonListener { 38 | public static final String HELLO_FROM_BUNDLE_WIREFRAME_KEY = "hello_from_bundle_key"; 39 | @Bind(R.id.user_view_group) protected UserViewGroup user_view_group; 40 | @Bind(R.id.et_name) protected EditText et_name; 41 | 42 | @Override protected void injectDagger() { 43 | getApplicationComponent().inject(this); 44 | } 45 | 46 | @Override protected void initViews() { 47 | Bundle bundle = getArguments(); 48 | String helloFromBundle = bundle != null ? bundle.getString(HELLO_FROM_BUNDLE_WIREFRAME_KEY, "") : ""; 49 | if (!helloFromBundle.isEmpty()) showSnackBar(helloFromBundle); 50 | } 51 | 52 | @Override public Subscription showUser(Observable oUser) { 53 | showLoading(); 54 | 55 | return oUser.doOnCompleted(() -> hideLoading()) 56 | .subscribe(user -> user_view_group.bind(user)); 57 | } 58 | 59 | @Override protected void showLoading() { 60 | super.showLoading(); 61 | user_view_group.setVisibility(View.GONE); 62 | } 63 | 64 | @Override protected void hideLoading() { 65 | super.hideLoading(); 66 | user_view_group.setVisibility(View.VISIBLE); 67 | } 68 | 69 | @OnClick(R.id.bt_find_user) 70 | protected void bt_find_user() { 71 | presenter.getUserByUserName(et_name.getText().toString()); 72 | } 73 | 74 | @Override public boolean onBackPressed() { 75 | showToast("Closed on back press from fragment"); 76 | getActivity().finish(); 77 | return false; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/utilities/recyclerview_adapter/RecyclerViewAdapter.java: -------------------------------------------------------------------------------- 1 | package presentation.utilities.recyclerview_adapter; 2 | 3 | import android.support.design.widget.Snackbar; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.support.v7.widget.helper.ItemTouchHelper; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | public abstract class RecyclerViewAdapter> extends RecyclerView.Adapter> { 13 | protected List items = new ArrayList<>(); 14 | protected Listener listener; 15 | 16 | @Override public final ViewWrapper onCreateViewHolder(ViewGroup parent, int viewType) { 17 | return new ViewWrapper<>(onCreateItemView(parent, viewType)); 18 | } 19 | 20 | protected abstract V onCreateItemView(ViewGroup parent, int viewType); 21 | 22 | @Override public final void onBindViewHolder(ViewWrapper viewHolder, int position) { 23 | T data = items.get(position); 24 | 25 | V view = viewHolder.getView(); 26 | view.bind(data, position); 27 | if (listener != null) view.setOnClickListener(v -> listener.onClickItem(data, view)); 28 | } 29 | 30 | @Override public int getItemCount() { 31 | return items.size(); 32 | } 33 | 34 | public void addListener(Listener lister) { 35 | this.listener = lister; 36 | } 37 | 38 | public void add(T item) { 39 | items.add(item); 40 | notifyDataSetChanged(); 41 | } 42 | 43 | public void addAll(List data) { 44 | items.addAll(data); 45 | notifyDataSetChanged(); 46 | } 47 | 48 | public void setAll(List data) { 49 | clear(); 50 | addAll(data); 51 | } 52 | 53 | public List getAll() { 54 | return items; 55 | } 56 | 57 | public void clear() { 58 | items.clear(); 59 | } 60 | 61 | public interface Listener { 62 | void onClickItem(T t, V v); 63 | } 64 | 65 | public SwipeRemoveAction swipeToRemoveItemOn(final RecyclerView recyclerView) { 66 | return new SwipeRemoveAction(recyclerView); 67 | } 68 | 69 | public class SwipeRemoveAction { 70 | private final RecyclerView recyclerView; 71 | private OnItemRemoved onItemRemoved; 72 | private String titleAction = "Undo", descriptionAction = "Item removed"; 73 | private boolean redrawOnRemovedItem, undoAction; 74 | 75 | public SwipeRemoveAction(RecyclerView recyclerView) { 76 | this.recyclerView = recyclerView; 77 | 78 | ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { 79 | @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { 80 | return false; 81 | } 82 | 83 | @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { 84 | final int position = viewHolder.getAdapterPosition(); 85 | T itemRemoved = items.get(position); 86 | items.remove(position); 87 | notifyItemRemoved(position); 88 | 89 | if (undoAction) showSnackbarUndo(itemRemoved, position); 90 | else if (onItemRemoved != null) onItemRemoved.onRemoved(itemRemoved); 91 | } 92 | }); 93 | itemTouchHelper.attachToRecyclerView(recyclerView); 94 | } 95 | 96 | public SwipeRemoveAction notify(OnItemRemoved onItemRemoved) { 97 | this.onItemRemoved = onItemRemoved; 98 | return this; 99 | } 100 | 101 | public SwipeRemoveAction withUndoAction() { 102 | this.undoAction = true; 103 | return this; 104 | } 105 | 106 | public SwipeRemoveAction withTitleAction(String titleAction) { 107 | this.titleAction = titleAction; 108 | return this; 109 | } 110 | 111 | public SwipeRemoveAction withDescriptionAction(String descriptionAction) { 112 | this.descriptionAction = descriptionAction; 113 | return this; 114 | } 115 | 116 | public SwipeRemoveAction redrawAfterRemoved(boolean redrawOnRemovedItem) { 117 | this.redrawOnRemovedItem = redrawOnRemovedItem; 118 | return this; 119 | } 120 | 121 | private void showSnackbarUndo(final T itemRemoved, final int position) { 122 | Snackbar.make(recyclerView, descriptionAction, Snackbar.LENGTH_LONG) 123 | .setCallback(new Snackbar.Callback() { 124 | @Override public void onDismissed(Snackbar snackbar, int event) { 125 | if (redrawOnRemovedItem) notifyDataSetChanged(); 126 | if (onItemRemoved != null && event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT) onItemRemoved.onRemoved(itemRemoved); 127 | } 128 | }) 129 | .setAction(titleAction, v -> { 130 | v.setEnabled(false); //prevent multiple clicks 131 | items.add(position, itemRemoved); 132 | notifyItemInserted(position); 133 | }).show(); 134 | } 135 | } 136 | 137 | 138 | public interface OnItemRemoved { 139 | void onRemoved(T item); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /presentation/src/main/java/presentation/utilities/recyclerview_adapter/ViewWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 RefineriaWeb 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package presentation.utilities.recyclerview_adapter; 18 | 19 | import android.support.v7.widget.RecyclerView; 20 | import android.view.View; 21 | 22 | public class ViewWrapper> extends RecyclerView.ViewHolder { 23 | private final V view; 24 | 25 | public ViewWrapper(V itemView) { 26 | super(itemView); 27 | view = itemView; 28 | } 29 | 30 | public V getView() { 31 | return view; 32 | } 33 | 34 | public interface Binder { 35 | void bind(T data, int position); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable-xxxhdpi/geek.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RefineriaWeb/base_app_android/47e586e66fedf572ee97956ab3885ba9f0a2755c/presentation/src/main/res/drawable-xxxhdpi/geek.jpg -------------------------------------------------------------------------------- /presentation/src/main/res/drawable-xxxhdpi/ic_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RefineriaWeb/base_app_android/47e586e66fedf572ee97956ab3885ba9f0a2755c/presentation/src/main/res/drawable-xxxhdpi/ic_search.png -------------------------------------------------------------------------------- /presentation/src/main/res/drawable-xxxhdpi/ic_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RefineriaWeb/base_app_android/47e586e66fedf572ee97956ab3885ba9f0a2755c/presentation/src/main/res/drawable-xxxhdpi/ic_user.png -------------------------------------------------------------------------------- /presentation/src/main/res/drawable-xxxhdpi/ic_users.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RefineriaWeb/base_app_android/47e586e66fedf572ee97956ab3885ba9f0a2755c/presentation/src/main/res/drawable-xxxhdpi/ic_users.png -------------------------------------------------------------------------------- /presentation/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RefineriaWeb/base_app_android/47e586e66fedf572ee97956ab3885ba9f0a2755c/presentation/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /presentation/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RefineriaWeb/base_app_android/47e586e66fedf572ee97956ab3885ba9f0a2755c/presentation/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /presentation/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RefineriaWeb/base_app_android/47e586e66fedf572ee97956ab3885ba9f0a2755c/presentation/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /presentation/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RefineriaWeb/base_app_android/47e586e66fedf572ee97956ab3885ba9f0a2755c/presentation/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /presentation/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RefineriaWeb/base_app_android/47e586e66fedf572ee97956ab3885ba9f0a2755c/presentation/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /presentation/src/main/res/sections/common/layout/action_bar.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /presentation/src/main/res/sections/common/layout/single_fragment_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /presentation/src/main/res/sections/common/layout/toolbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | -------------------------------------------------------------------------------- /presentation/src/main/res/sections/dashboard/layout/dashboard_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 15 | 16 | 20 | 21 | 25 | 26 | 27 | 28 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /presentation/src/main/res/sections/dashboard/layout/item_menu_view_group.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | 13 | 18 | 19 | 26 | -------------------------------------------------------------------------------- /presentation/src/main/res/sections/user_demo/layout/user_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 18 | 19 | 23 | 24 |