├── .gitignore
├── .idea
├── compiler.xml
├── gradle.xml
├── kotlinScripting.xml
├── misc.xml
└── vcs.xml
├── README.md
├── android-common-build.gradle
├── android-core-build.gradle
├── android-feature-build.gradle
├── app
├── .gitignore
├── build.gradle.kts
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── emamagic
│ │ └── android_multi_module
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── emamagic
│ │ │ └── android_multi_module
│ │ │ ├── App.kt
│ │ │ ├── MainActivity.kt
│ │ │ ├── NoInternetAvailableDialog.kt
│ │ │ ├── OnAppVisibilityListener.kt
│ │ │ └── di
│ │ │ ├── AppComponent.kt
│ │ │ ├── AppComponentProvider.kt
│ │ │ ├── SubComponents.kt
│ │ │ └── SubComponentsModule.kt
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ ├── ic_launcher_background.xml
│ │ ├── ic_splash.xml
│ │ ├── rounded_btn_blue.xml
│ │ └── splash_screen.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ └── fragment_no_internet_available.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── raw
│ │ └── no_internet_available.json
│ │ ├── values-night
│ │ └── themes.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── themes.xml
│ └── test
│ └── java
│ └── com
│ └── emamagic
│ └── android_multi_module
│ └── ExampleUnitTest.kt
├── application
├── .gitignore
├── build.gradle.kts
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── emamagic
│ │ └── core
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── emamagic
│ │ │ └── core
│ │ │ ├── base
│ │ │ ├── Action.kt
│ │ │ ├── BaseEffect.kt
│ │ │ ├── BaseFragment.kt
│ │ │ ├── BaseFragmentRedux.kt
│ │ │ ├── BaseStore.kt
│ │ │ ├── BaseViewModel.kt
│ │ │ ├── BaseViewModelRedux.kt
│ │ │ ├── Event.kt
│ │ │ ├── Middleware.kt
│ │ │ ├── Reducer.kt
│ │ │ ├── State.kt
│ │ │ ├── Store.kt
│ │ │ ├── ViewModelDelegation.kt
│ │ │ ├── ViewModelFactory.kt
│ │ │ └── ViewModelFactoryBinderModule.kt
│ │ │ ├── extension
│ │ │ ├── BindingAdapter.kt
│ │ │ ├── ComponentExt.kt
│ │ │ └── ViewExt.kt
│ │ │ ├── interactor
│ │ │ ├── HomeUseCase.kt
│ │ │ ├── MovieUseCase.kt
│ │ │ └── MoviesUseCase.kt
│ │ │ ├── interfaces
│ │ │ ├── InitialVisibleFragmentFun.kt
│ │ │ └── OnAppVisibility.kt
│ │ │ └── utils
│ │ │ ├── AlertType.java
│ │ │ ├── Logger.kt
│ │ │ ├── ToastyMode.java
│ │ │ ├── ViewExt.kt
│ │ │ ├── ViewModelKey.kt
│ │ │ ├── ViewModelScope.java
│ │ │ └── keyboard
│ │ │ ├── KeyboardEventListener.kt
│ │ │ └── keyboardExt.kt
│ └── res
│ │ ├── drawable
│ │ ├── bg_corroct_toast.xml
│ │ ├── bg_error_toast.xml
│ │ ├── bg_rank.xml
│ │ ├── bg_warning_toast.xml
│ │ ├── hover_oval.xml
│ │ ├── hover_oval_drawable.xml
│ │ ├── ic_access_time.xml
│ │ ├── ic_corroct_toast.xml
│ │ ├── ic_cross.xml
│ │ ├── ic_error_blue_24dp.xml
│ │ ├── ic_error_red_24dp.xml
│ │ ├── ic_error_toast.xml
│ │ ├── ic_error_yellow_24dp.xml
│ │ ├── ic_favorite_empty.xml
│ │ ├── ic_favorite_fill.xml
│ │ ├── ic_folder_special.xml
│ │ ├── ic_warning_toast.xml
│ │ ├── rounded_btn_grey.xml
│ │ ├── rounded_btn_red.xml
│ │ ├── rounded_iw.xml
│ │ └── simple_round_transparent.xml
│ │ ├── layout
│ │ ├── dialog_alert.xml
│ │ └── layout_toast.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── themes.xml
│ │ └── values-night
│ │ └── themes.xml
│ └── test
│ └── java
│ └── com
│ └── emamagic
│ └── core
│ └── ExampleUnitTest.kt
├── build.gradle.kts
├── buildSrc
├── build.gradle.kts
├── build
│ ├── classes
│ │ └── kotlin
│ │ │ └── main
│ │ │ ├── Android.class
│ │ │ ├── Build.class
│ │ │ ├── Libs.class
│ │ │ ├── META-INF
│ │ │ └── buildSrc.kotlin_module
│ │ │ ├── Modules.class
│ │ │ ├── Releases.class
│ │ │ ├── Tests.class
│ │ │ └── Versions.class
│ ├── kotlin
│ │ ├── buildSrcjar-classes.txt
│ │ └── compileKotlin
│ │ │ ├── build-history.bin
│ │ │ ├── caches-jvm
│ │ │ ├── inputs
│ │ │ │ ├── source-to-output.tab
│ │ │ │ ├── source-to-output.tab.keystream
│ │ │ │ ├── source-to-output.tab.keystream.len
│ │ │ │ ├── source-to-output.tab.len
│ │ │ │ ├── source-to-output.tab.values.at
│ │ │ │ ├── source-to-output.tab_i
│ │ │ │ └── source-to-output.tab_i.len
│ │ │ ├── jvm
│ │ │ │ └── kotlin
│ │ │ │ │ ├── class-attributes.tab
│ │ │ │ │ ├── class-attributes.tab.keystream
│ │ │ │ │ ├── class-attributes.tab.keystream.len
│ │ │ │ │ ├── class-attributes.tab.len
│ │ │ │ │ ├── class-attributes.tab.values.at
│ │ │ │ │ ├── class-attributes.tab_i
│ │ │ │ │ ├── class-attributes.tab_i.len
│ │ │ │ │ ├── class-fq-name-to-source.tab
│ │ │ │ │ ├── class-fq-name-to-source.tab.keystream
│ │ │ │ │ ├── class-fq-name-to-source.tab.keystream.len
│ │ │ │ │ ├── class-fq-name-to-source.tab.len
│ │ │ │ │ ├── class-fq-name-to-source.tab.values.at
│ │ │ │ │ ├── class-fq-name-to-source.tab_i
│ │ │ │ │ ├── class-fq-name-to-source.tab_i.len
│ │ │ │ │ ├── constants.tab
│ │ │ │ │ ├── constants.tab.keystream
│ │ │ │ │ ├── constants.tab.keystream.len
│ │ │ │ │ ├── constants.tab.len
│ │ │ │ │ ├── constants.tab.values.at
│ │ │ │ │ ├── constants.tab_i
│ │ │ │ │ ├── constants.tab_i.len
│ │ │ │ │ ├── internal-name-to-source.tab
│ │ │ │ │ ├── internal-name-to-source.tab.keystream
│ │ │ │ │ ├── internal-name-to-source.tab.keystream.len
│ │ │ │ │ ├── internal-name-to-source.tab.len
│ │ │ │ │ ├── internal-name-to-source.tab.values.at
│ │ │ │ │ ├── internal-name-to-source.tab_i
│ │ │ │ │ ├── internal-name-to-source.tab_i.len
│ │ │ │ │ ├── proto.tab
│ │ │ │ │ ├── proto.tab.keystream
│ │ │ │ │ ├── proto.tab.keystream.len
│ │ │ │ │ ├── proto.tab.len
│ │ │ │ │ ├── proto.tab.values.at
│ │ │ │ │ ├── proto.tab_i
│ │ │ │ │ ├── proto.tab_i.len
│ │ │ │ │ ├── source-to-classes.tab
│ │ │ │ │ ├── source-to-classes.tab.keystream
│ │ │ │ │ ├── source-to-classes.tab.keystream.len
│ │ │ │ │ ├── source-to-classes.tab.len
│ │ │ │ │ ├── source-to-classes.tab.values.at
│ │ │ │ │ ├── source-to-classes.tab_i
│ │ │ │ │ └── source-to-classes.tab_i.len
│ │ │ └── lookups
│ │ │ │ ├── counters.tab
│ │ │ │ ├── file-to-id.tab
│ │ │ │ ├── file-to-id.tab.keystream
│ │ │ │ ├── file-to-id.tab.keystream.len
│ │ │ │ ├── file-to-id.tab.len
│ │ │ │ ├── file-to-id.tab.values.at
│ │ │ │ ├── file-to-id.tab_i
│ │ │ │ ├── file-to-id.tab_i.len
│ │ │ │ ├── id-to-file.tab
│ │ │ │ ├── id-to-file.tab.keystream
│ │ │ │ ├── id-to-file.tab.keystream.len
│ │ │ │ ├── id-to-file.tab.len
│ │ │ │ ├── id-to-file.tab.values.at
│ │ │ │ ├── id-to-file.tab_i
│ │ │ │ ├── id-to-file.tab_i.len
│ │ │ │ ├── lookups.tab
│ │ │ │ ├── lookups.tab.keystream
│ │ │ │ ├── lookups.tab.keystream.len
│ │ │ │ ├── lookups.tab.len
│ │ │ │ ├── lookups.tab.values.at
│ │ │ │ ├── lookups.tab_i
│ │ │ │ └── lookups.tab_i.len
│ │ │ └── last-build.bin
│ ├── libs
│ │ └── buildSrc.jar
│ ├── pluginUnderTestMetadata
│ │ └── plugin-under-test-metadata.properties
│ ├── reports
│ │ └── plugin-development
│ │ │ └── validation-report.txt
│ ├── source-roots
│ │ └── buildSrc
│ │ │ └── source-roots.txt
│ └── tmp
│ │ └── jar
│ │ └── MANIFEST.MF
└── src
│ └── main
│ └── kotlin
│ ├── Android.kt
│ ├── Build.kt
│ ├── Libs.kt
│ ├── Modules.kt
│ ├── Releases.kt
│ ├── Tests.kt
│ └── Versions.kt
├── data
├── cache
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── emamagic
│ │ │ └── cache
│ │ │ └── ExampleInstrumentedTest.kt
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── com
│ │ │ └── emamagic
│ │ │ └── cache
│ │ │ ├── BaseDao.kt
│ │ │ ├── MoviesDB.kt
│ │ │ ├── PreferenceManager.kt
│ │ │ ├── dao
│ │ │ ├── GenreDao.kt
│ │ │ ├── MovieDao.kt
│ │ │ └── SliderDao.kt
│ │ │ └── entity
│ │ │ ├── GenreEntity.kt
│ │ │ ├── MovieEntity.kt
│ │ │ └── SliderEntity.kt
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── emamagic
│ │ └── cache
│ │ └── ExampleUnitTest.kt
├── network
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── emamagic
│ │ │ └── network
│ │ │ └── ExampleInstrumentedTest.kt
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── com
│ │ │ └── emamagic
│ │ │ └── network
│ │ │ ├── di
│ │ │ └── RetrofitModule.kt
│ │ │ ├── dto
│ │ │ ├── CastDto.kt
│ │ │ ├── EpisodeDto.kt
│ │ │ ├── GenreDto.kt
│ │ │ ├── MovieDetailDto.kt
│ │ │ ├── MovieDto.kt
│ │ │ ├── SeasonDto.kt
│ │ │ └── SliderDto.kt
│ │ │ ├── interceptor
│ │ │ ├── ClientInterceptor.kt
│ │ │ ├── NetworkInterceptor.kt
│ │ │ └── ServerConnection.kt
│ │ │ ├── response
│ │ │ ├── CastResponse.kt
│ │ │ ├── EpisodeResponse.kt
│ │ │ ├── GenreListResponse.kt
│ │ │ ├── MovieDetailResponse.kt
│ │ │ ├── MovieListResponse.kt
│ │ │ ├── SeasonResponse.kt
│ │ │ └── SliderListResponse.kt
│ │ │ ├── service
│ │ │ ├── GenreService.kt
│ │ │ ├── MovieDetailsService.kt
│ │ │ └── MovieService.kt
│ │ │ └── util
│ │ │ └── Const.kt
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── emamagic
│ │ └── network
│ │ └── ExampleUnitTest.kt
└── repository-impl
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── emamagic
│ │ └── repository
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ └── java
│ │ └── com
│ │ └── emamagic
│ │ └── repository
│ │ ├── di
│ │ └── RepositoryBinderModule.kt
│ │ ├── mapper
│ │ ├── DataClassMapper.kt
│ │ └── EntityMapper.kt
│ │ └── repository
│ │ ├── GenreRepositoryImpl.kt
│ │ ├── MovieDetailRepositoryImpl.kt
│ │ └── MovieRepositoryImpl.kt
│ └── test
│ └── java
│ └── com
│ └── emamagic
│ └── repository
│ └── ExampleUnitTest.kt
├── domain
├── common-entity
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ └── java
│ │ └── com
│ │ └── emamagic
│ │ └── common_entity
│ │ ├── Cast.kt
│ │ ├── Episode.kt
│ │ ├── Genre.kt
│ │ ├── Movie.kt
│ │ ├── MovieDetail.kt
│ │ ├── Season.kt
│ │ └── Slider.kt
├── common-jvm
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ └── java
│ │ └── com
│ │ └── emamagic
│ │ └── common_jvm
│ │ ├── ErrorEntity.kt
│ │ ├── Exceptions.kt
│ │ ├── GenreCategory.java
│ │ ├── MovieCategory.java
│ │ └── ResultWrapper.kt
└── repository
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ └── main
│ └── java
│ └── com
│ └── emamagic
│ └── domain
│ ├── GenreRepository.kt
│ ├── MovieDetailRepository.kt
│ └── MovieRepository.kt
├── features
├── home
│ ├── .gitignore
│ ├── build.gradle
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── emamagic
│ │ │ └── home
│ │ │ └── ExampleInstrumentedTest.kt
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── emamagic
│ │ │ │ └── home
│ │ │ │ ├── HomeFragment.kt
│ │ │ │ ├── HomeViewModel.kt
│ │ │ │ ├── contract
│ │ │ │ ├── HomeAction.kt
│ │ │ │ ├── HomeState.kt
│ │ │ │ └── redux
│ │ │ │ │ ├── HomeMiddleware.kt
│ │ │ │ │ ├── HomeReducer.kt
│ │ │ │ │ └── HomeStore.kt
│ │ │ │ ├── di
│ │ │ │ ├── HomeComponent.kt
│ │ │ │ ├── HomeComponentProvider.kt
│ │ │ │ └── ViewModelModule.kt
│ │ │ │ └── util
│ │ │ │ └── EpoxyDataBindingConfig.java
│ │ └── res
│ │ │ ├── drawable
│ │ │ ├── ic_apps.xml
│ │ │ ├── ic_home.xml
│ │ │ ├── ic_menu.xml
│ │ │ ├── ic_payment.xml
│ │ │ └── ic_search.xml
│ │ │ ├── layout
│ │ │ ├── fragment_home.xml
│ │ │ ├── shimmer_genre_layout.xml
│ │ │ ├── shimmer_movie_h_layout.xml
│ │ │ ├── shimmer_movie_v_layout.xml
│ │ │ ├── view_holder_genre.xml
│ │ │ ├── view_holder_movie_h.xml
│ │ │ └── view_holder_movie_v.xml
│ │ │ ├── menu
│ │ │ └── home_menu.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── themes.xml
│ │ │ └── values-night
│ │ │ └── themes.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── emamagic
│ │ └── home
│ │ └── ExampleUnitTest.kt
├── movie
│ ├── .gitignore
│ ├── build.gradle
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── emamagic
│ │ │ └── movie
│ │ │ └── ExampleInstrumentedTest.kt
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── emamagic
│ │ │ │ └── movie
│ │ │ │ ├── MovieFragment.kt
│ │ │ │ ├── MovieViewModel.kt
│ │ │ │ ├── contract
│ │ │ │ ├── MovieAction.kt
│ │ │ │ ├── MovieState.kt
│ │ │ │ └── redux
│ │ │ │ │ ├── MovieMiddleware.kt
│ │ │ │ │ ├── MovieReducer.kt
│ │ │ │ │ └── MovieStore.kt
│ │ │ │ ├── di
│ │ │ │ ├── MovieComponent.kt
│ │ │ │ ├── MovieComponentProvider.kt
│ │ │ │ └── ViewModelModule.kt
│ │ │ │ └── util
│ │ │ │ └── EpoxyDataBindingConfig.java
│ │ └── res
│ │ │ ├── drawable
│ │ │ ├── bg_detail.xml
│ │ │ ├── bg_genre.xml
│ │ │ ├── bg_rate_imdb.xml
│ │ │ ├── ic_comment.xml
│ │ │ ├── ic_get_app.xml
│ │ │ └── play_arrow.xml
│ │ │ └── layout
│ │ │ ├── fragment_movie.xml
│ │ │ └── view_holder_cast.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── emamagic
│ │ └── movie
│ │ └── ExampleUnitTest.kt
└── movies
│ ├── .gitignore
│ ├── build.gradle
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── emamagic
│ │ └── movies
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── emamagic
│ │ │ └── movies
│ │ │ ├── MoviesFragment.kt
│ │ │ ├── MoviesViewModel.kt
│ │ │ ├── contract
│ │ │ ├── MoviesEvent.kt
│ │ │ └── MoviesState.kt
│ │ │ ├── di
│ │ │ ├── MoviesComponent.kt
│ │ │ ├── MoviesComponentProvider.kt
│ │ │ └── ViewModelModule.kt
│ │ │ └── util
│ │ │ └── EpoxyDataBindingConfig.java
│ └── res
│ │ ├── drawable
│ │ ├── bg_rate_imdb.xml
│ │ ├── ic_arrow_back.xml
│ │ └── ic_favorite_border.xml
│ │ └── layout
│ │ ├── fragment_movies.xml
│ │ ├── view_holder_movie.xml
│ │ └── view_holder_season.xml
│ └── test
│ └── java
│ └── com
│ └── emamagic
│ └── movies
│ └── ExampleUnitTest.kt
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── navigator
├── .gitignore
├── build.gradle.kts
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── emamagic
│ │ └── navigator
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ └── res
│ │ └── navigation
│ │ └── nav_graph.xml
│ └── test
│ └── java
│ └── com
│ └── emamagic
│ └── navigator
│ └── ExampleUnitTest.kt
├── photo
├── multi_module_diagram.png
├── screen_1.jpg
└── screen_2.jpg
├── safe
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── emamagic
│ │ └── safe
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ └── java
│ │ └── com
│ │ └── emamagic
│ │ └── safe
│ │ ├── General.kt
│ │ ├── SafeApi.kt
│ │ ├── connectivity
│ │ ├── ConnectionLiveData.kt
│ │ ├── Connectivity.kt
│ │ ├── ConnectivityPublisher.kt
│ │ ├── ConnectivityPublisherDelegate.kt
│ │ ├── ConnectivityReceiver.kt
│ │ ├── ConnectivityStatus.kt
│ │ └── DoesNetworkHaveInternet.kt
│ │ ├── error
│ │ ├── ErrorHandler.kt
│ │ └── GeneralErrorHandlerImpl.kt
│ │ ├── policy
│ │ ├── CachePolicy.kt
│ │ └── RetryPolicy.kt
│ │ └── store
│ │ ├── ITimeLimitedResource.kt
│ │ ├── RefreshControl.kt
│ │ ├── Resource.kt
│ │ └── ResourceGroup.kt
│ └── test
│ └── java
│ └── com
│ └── emamagic
│ └── safe
│ └── ExampleUnitTest.kt
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | local.properties
16 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
35 |
36 |
--------------------------------------------------------------------------------
/.idea/kotlinScripting.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 2147483647
6 | true
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [Android-Multi-Module-App](https://github.com/emamagic/Android-Multi-Module)
2 |
3 | **NOTE**
4 | this is a sample template for android multi module application, I do my best for extending this app,
5 | if you have any idea to improve the project, It is open for contribution
6 |
7 | **TODO**
8 | complete modules functionality and writing test
9 |
10 | **Dependencies**
11 | 1. MVI (UDF)
12 | 2. SSOT
13 | 3. coroutines
14 | 4. clean architecture
15 | 5. navigation components
16 | 6. dagger 2
17 | 7. kotlin dsl
18 | 8. epoxy
19 | 9. room
20 | 10. retrofit
21 | 11. data binding
22 | 12. ....
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/android-common-build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'kotlin-android'
2 | apply plugin: 'kotlin-kapt'
3 | apply from: "$rootDir/android-core-build.gradle"
4 |
5 | android {
6 | compileSdk Android.compileSdk
7 |
8 | defaultConfig {
9 | minSdk Android.minSdk
10 | targetSdk Android.targetSdk
11 | versionCode Releases.versionCode
12 | versionName Releases.versionName
13 |
14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
15 | consumerProguardFiles "consumer-rules.pro"
16 | }
17 |
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 | lint {
25 | abortOnError false
26 | }
27 | compileOptions {
28 | sourceCompatibility JavaVersion.VERSION_1_8
29 | targetCompatibility JavaVersion.VERSION_1_8
30 | }
31 | kotlinOptions {
32 | jvmTarget = "1.8"
33 | }
34 | }
--------------------------------------------------------------------------------
/android-core-build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 |
3 | implementation Libs.androidx_core
4 | implementation Libs.androidx_compat
5 | implementation Libs.material
6 | implementation Libs.constraint_layout
7 | testImplementation Tests.junit_4
8 | androidTestImplementation Tests.androidx_junit
9 | androidTestImplementation Tests.androidx_espresso
10 |
11 | }
--------------------------------------------------------------------------------
/android-feature-build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply from: "$rootDir/android-common-build.gradle"
3 | apply plugin: "androidx.navigation.safeargs.kotlin"
4 |
5 | android {
6 | buildFeatures {
7 | dataBinding true
8 | }
9 | }
10 |
11 | kapt {
12 | correctErrorTypes = true
13 | }
14 |
15 | dependencies {
16 |
17 | implementation project(Modules.application)
18 | implementation project(Modules.navigator)
19 | implementation project(Modules.commonEntity)
20 | implementation project(Modules.commonJvm)
21 | implementation Libs.kotlin_coroutines
22 | implementation Libs.dagger
23 | kapt Libs.dagger_kapt
24 | implementation (Libs.navigation_component_fragment)
25 | implementation (Libs.navigation_component_ui)
26 |
27 | implementation Libs.view_model_scope
28 |
29 | implementation Libs.epoxy
30 | implementation Libs.epoxy_data_binding
31 | kapt Libs.epoxy_kapt
32 | }
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.kts.kts.kts.kts.kts.kts.kts.kts.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/emamagic/android_multi_module/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.android_multi_module
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.ext.junit.runners.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22 | assertEquals("com.emamagic.limonad_android", appContext.packageName)
23 | }
24 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
15 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/emamagic/android_multi_module/App.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.android_multi_module
2 |
3 | import androidx.lifecycle.Lifecycle
4 | import androidx.lifecycle.LifecycleEventObserver
5 | import androidx.lifecycle.LifecycleOwner
6 | import androidx.lifecycle.ProcessLifecycleOwner
7 | import androidx.multidex.MultiDexApplication
8 | import com.emamagic.android_multi_module.di.AppComponentProvider
9 | import com.emamagic.android_multi_module.di.SubComponents
10 | import com.emamagic.core.interfaces.OnAppVisibility
11 |
12 | class App: MultiDexApplication(), SubComponents, LifecycleEventObserver, OnAppVisibility {
13 |
14 | private var isInBackground = false
15 | var appVisibilityListener: OnAppVisibilityListener? = null
16 |
17 | override fun onCreate() {
18 | super.onCreate()
19 | AppComponentProvider.provideAppComponent(this)
20 | ProcessLifecycleOwner.get().lifecycle.addObserver(this)
21 | }
22 |
23 | override fun appIsInBackground(): Boolean = isInBackground
24 |
25 | override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
26 | isInBackground =
27 | !(event == Lifecycle.Event.ON_CREATE || event == Lifecycle.Event.ON_RESUME || event == Lifecycle.Event.ON_START)
28 | appVisibilityListener?.appVisibility(isInBackground)
29 | }
30 |
31 |
32 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/emamagic/android_multi_module/NoInternetAvailableDialog.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.android_multi_module
2 |
3 | import android.os.Bundle
4 | import android.util.Log
5 | import android.view.*
6 | import androidx.databinding.DataBindingUtil
7 | import androidx.fragment.app.DialogFragment
8 | import androidx.navigation.fragment.findNavController
9 | import com.emamagic.android_multi_module.R
10 | import com.emamagic.android_multi_module.databinding.FragmentNoInternetAvailableBinding
11 |
12 | class NoInternetAvailableDialog: DialogFragment() {
13 |
14 | private var _binding: FragmentNoInternetAvailableBinding? = null
15 | private val binding: FragmentNoInternetAvailableBinding get() = _binding!!
16 |
17 | override fun onCreate(savedInstanceState: Bundle?) {
18 | setStyle(STYLE_NORMAL, R.style.AppTheme_FullScreenDialog)
19 | super.onCreate(savedInstanceState)
20 | }
21 |
22 | override fun onCreateView(
23 | inflater: LayoutInflater,
24 | container: ViewGroup?,
25 | savedInstanceState: Bundle?
26 | ): View {
27 | _binding = DataBindingUtil.inflate(inflater,
28 | R.layout.fragment_no_internet_available, container, false)
29 | binding.lifecycleOwner = viewLifecycleOwner
30 | return binding.root
31 | }
32 |
33 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
34 | super.onViewCreated(view, savedInstanceState)
35 | binding.btnOk.setOnClickListener { findNavController().navigateUp() }
36 | }
37 |
38 |
39 | override fun onDestroyView() {
40 | _binding = null
41 | super.onDestroyView()
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/emamagic/android_multi_module/OnAppVisibilityListener.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.android_multi_module
2 |
3 | interface OnAppVisibilityListener {
4 | fun appVisibility(isInBackground: Boolean)
5 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/emamagic/android_multi_module/di/AppComponent.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.android_multi_module.di
2 |
3 | import android.app.Application
4 | import com.emamagic.core.base.ViewModelFactoryBinderModule
5 | import com.emamagic.home.di.HomeComponent
6 | import com.emamagic.movie.di.MovieComponent
7 | import com.emamagic.movies.di.MoviesComponent
8 | import com.emamagic.network.di.RetrofitModule
9 | import com.emamagic.repository.di.RepositoryBinderModule
10 | import dagger.BindsInstance
11 | import dagger.Component
12 | import javax.inject.Singleton
13 |
14 | @Singleton
15 | @Component(
16 | modules = [
17 | RetrofitModule::class,
18 | RepositoryBinderModule::class,
19 | SubComponentsModule::class,
20 | ViewModelFactoryBinderModule::class
21 | ]
22 | )
23 | interface AppComponent {
24 |
25 | // Save the reference of factories in the app component for creating sub components
26 | fun homeComponent(): HomeComponent.Factory
27 | fun moviesComponent(): MoviesComponent.Factory
28 | fun movieComponent(): MovieComponent.Factory
29 |
30 | @Component.Factory
31 | interface Factory {
32 | fun create(@BindsInstance application: Application): AppComponent
33 | }
34 |
35 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/emamagic/android_multi_module/di/AppComponentProvider.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.android_multi_module.di
2 |
3 | import android.app.Application
4 |
5 | object AppComponentProvider {
6 | private lateinit var appComponent: AppComponent
7 |
8 | @JvmStatic
9 | fun appComponent() = appComponent
10 |
11 | fun provideAppComponent(application: Application) {
12 | appComponent = DaggerAppComponent.factory().create(application)
13 | }
14 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/emamagic/android_multi_module/di/SubComponents.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.android_multi_module.di
2 |
3 | import com.emamagic.home.di.HomeComponent
4 | import com.emamagic.home.di.HomeComponentProvider
5 | import com.emamagic.movie.di.MovieComponent
6 | import com.emamagic.movie.di.MovieComponentProvider
7 | import com.emamagic.movies.di.MoviesComponent
8 | import com.emamagic.movies.di.MoviesComponentProvider
9 |
10 | interface SubComponents: HomeComponentProvider, MoviesComponentProvider, MovieComponentProvider {
11 |
12 | override fun provideHomeComponent(): HomeComponent =
13 | AppComponentProvider.appComponent().homeComponent().create()
14 |
15 | override fun provideMoviesComponent(): MoviesComponent =
16 | AppComponentProvider.appComponent().moviesComponent().create()
17 |
18 | override fun provideMovieComponent(): MovieComponent =
19 | AppComponentProvider.appComponent().movieComponent().create()
20 |
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/emamagic/android_multi_module/di/SubComponentsModule.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.android_multi_module.di
2 |
3 | import com.emamagic.home.di.HomeComponent
4 | import com.emamagic.movie.di.MovieComponent
5 | import com.emamagic.movies.di.MoviesComponent
6 | import dagger.Module
7 |
8 | @Module(
9 | subcomponents = [
10 | HomeComponent::class,
11 | MoviesComponent::class,
12 | MovieComponent::class
13 | ]
14 | )
15 | class SubComponentsModule
--------------------------------------------------------------------------------
/app/src/main/res/drawable/rounded_btn_blue.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/splash_screen.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_no_internet_available.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
14 |
27 |
28 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #110414
5 | #0A030E
6 | #F8CB06
7 |
8 | #06172b
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | MovieStreaming
3 |
--------------------------------------------------------------------------------
/app/src/test/java/com/emamagic/android_multi_module/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.android_multi_module
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
--------------------------------------------------------------------------------
/application/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/application/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.library")
3 | kotlin("android")
4 | kotlin("kapt")
5 | }
6 |
7 | apply {
8 | from("$rootDir/android-common-build.gradle")
9 | }
10 |
11 | android {
12 | buildFeatures {
13 | dataBinding = true
14 | }
15 | }
16 |
17 | dependencies {
18 |
19 | implementation(project(Modules.navigator))
20 | implementation(project(Modules.repository))
21 | implementation(project(Modules.commonEntity))
22 | implementation(project(Modules.commonJvm))
23 | implementation(Libs.navigation_component_fragment)
24 | implementation(Libs.navigation_component_ui)
25 | implementation(Libs.dagger)
26 | implementation(Libs.kotlin_coroutines)
27 | kapt(Libs.dagger_kapt)
28 |
29 | implementation(Libs.glide)
30 | kapt(Libs.glide_kapt)
31 | }
32 |
33 | kapt {
34 | correctErrorTypes = true
35 | }
36 |
--------------------------------------------------------------------------------
/application/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/application/consumer-rules.pro
--------------------------------------------------------------------------------
/application/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.kts.kts.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/application/src/androidTest/java/com/emamagic/core/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.ext.junit.runners.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22 | assertEquals("com.emamagic.common_android.test", appContext.packageName)
23 | }
24 | }
--------------------------------------------------------------------------------
/application/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/base/Action.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.base
2 |
3 | interface Action
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/base/BaseStore.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.base
2 |
3 | import kotlinx.coroutines.channels.Channel
4 | import kotlinx.coroutines.flow.MutableStateFlow
5 | import kotlinx.coroutines.flow.StateFlow
6 | import kotlinx.coroutines.flow.receiveAsFlow
7 |
8 | open class BaseStore(
9 | initialState: STATE,
10 | private val reducer: Reducer,
11 | private val middlewares: List> = emptyList(),
12 | ) : Store {
13 |
14 | private val _state = MutableStateFlow(initialState)
15 | override val state: StateFlow = _state
16 |
17 | private val _effect : Channel = Channel()
18 | override val effect = _effect
19 |
20 | private val currentState: STATE
21 | get() = _state.value
22 |
23 | override suspend fun dispatch(action: ACTION) {
24 | middlewares.forEach { middleware ->
25 | middleware.process(action, currentState, this)
26 | }
27 |
28 | val newState = reducer.reduce(currentState, action)
29 | _state.value = newState
30 | }
31 |
32 | override suspend fun setEffect(effect: BaseEffect) {
33 | _effect.send(effect)
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/base/Event.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.base
2 |
3 | /** marker interface */
4 | interface Event
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/base/Middleware.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.base
2 |
3 | import com.emamagic.common_jvm.ErrorEntity
4 | import com.emamagic.common_jvm.NoInternetException
5 | import com.emamagic.common_jvm.ResultWrapper
6 | import com.emamagic.common_jvm.succeeded
7 | import com.emamagic.core.utils.Logger
8 |
9 | abstract class Middleware {
10 |
11 | abstract suspend fun process(
12 | action: ACTION,
13 | currentState: STATE,
14 | store: Store,
15 | )
16 |
17 |
18 | suspend fun ResultWrapper.manageResult(store: Store): T? {
19 | if (!succeeded) {
20 | store.setEffect(BaseEffect.ShowToast(error?.message ?: "unKnown error"))
21 | Logger.e("Error Happened", error?.message)
22 | return null
23 | }
24 | return data
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/base/Reducer.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.base
2 |
3 | interface Reducer {
4 |
5 | fun reduce(currentState: STATE, action: ACTION): STATE
6 | }
7 |
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/base/State.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.base
2 |
3 | /** marker interface */
4 | interface State
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/base/Store.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.base
2 |
3 | import kotlinx.coroutines.channels.Channel
4 | import kotlinx.coroutines.flow.Flow
5 | import kotlinx.coroutines.flow.StateFlow
6 |
7 | interface Store {
8 |
9 | val state: StateFlow
10 |
11 | val effect: Channel
12 |
13 | suspend fun dispatch(action: ACTION)
14 |
15 | suspend fun setEffect(effect: BaseEffect)
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/base/ViewModelDelegation.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.base
2 |
3 | import androidx.fragment.app.Fragment
4 | import androidx.lifecycle.ViewModel
5 | import androidx.lifecycle.ViewModelProvider
6 | import androidx.lifecycle.ViewModelProviders
7 |
8 | inline fun viewModelFactory(
9 | crossinline f: () -> VM
10 | ) =
11 | object : ViewModelProvider.Factory {
12 | override fun create(aClass: Class) =
13 | f() as T
14 | }
15 |
16 | //inline fun Fragment.viewModelProvider(
17 | // crossinline provider: () -> VM) = lazy {
18 | // ViewModelProvider(this, object : ViewModelProvider.Factory {
19 | // override fun create(aClass: Class) =
20 | // provider() as T1
21 | // }).get(VM::class.java)
22 | //}
23 |
24 | inline fun Fragment.viewModelProvider(
25 | mode: LazyThreadSafetyMode = LazyThreadSafetyMode.NONE,
26 | crossinline provider: () -> VM) = lazy(mode) {
27 | ViewModelProvider(this, object : ViewModelProvider.Factory {
28 | override fun create(aClass: Class) =
29 | provider() as T1
30 | }).get(VM::class.java)
31 | }
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/base/ViewModelFactory.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.base
2 |
3 | import androidx.lifecycle.ViewModel
4 | import androidx.lifecycle.ViewModelProvider
5 | import javax.inject.Inject
6 | import javax.inject.Provider
7 |
8 | class ViewModelFactory @Inject constructor(
9 | private val viewModels: MutableMap,
10 | @JvmSuppressWildcards Provider>
11 | ) : ViewModelProvider.Factory {
12 |
13 | @Suppress("UNCHECKED_CAST")
14 | override fun create(modelClass: Class): T {
15 | var creator: Provider? = viewModels[modelClass]
16 | if (creator == null) {
17 | for ((key, value) in viewModels) {
18 | if (modelClass.isAssignableFrom(key)) {
19 | creator = value
20 | break
21 | }
22 | }
23 | }
24 | if (creator == null) {
25 | throw IllegalArgumentException("unknown model class $modelClass")
26 | }
27 | try {
28 | return creator.get() as T
29 | } catch (e: Exception) {
30 | throw RuntimeException(e)
31 | }
32 | }
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/base/ViewModelFactoryBinderModule.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.base
2 |
3 | import androidx.lifecycle.ViewModelProvider
4 | import dagger.Binds
5 | import dagger.Module
6 | import dagger.Reusable
7 |
8 | @Module
9 | abstract class ViewModelFactoryBinderModule {
10 |
11 | @Reusable
12 | @Binds
13 | abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
14 |
15 | }
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/extension/BindingAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.extension
2 |
3 | import android.view.View
4 | import android.widget.ImageView
5 | import android.widget.TextView
6 | import androidx.databinding.BindingAdapter
7 | import com.bumptech.glide.Glide
8 | import com.emamagic.common_jvm.MovieCategory
9 | import com.emamagic.core.R
10 |
11 | @BindingAdapter("loadImage")
12 | fun loadImage(imageView: ImageView, imageUrl: String) {
13 | Glide.with(imageView.context)
14 | .load(imageUrl).into(imageView)
15 | }
16 |
17 | @BindingAdapter("rank")
18 | fun setRank(textView: TextView, rank: String?) {
19 | if (rank.isNullOrEmpty()) {
20 | textView.visibility = View.INVISIBLE
21 | } else {
22 | textView.visibility = View.VISIBLE
23 | textView.text = "Rank:$rank"
24 | }
25 | }
26 |
27 | @BindingAdapter("imageTime")
28 | fun setTimeImage(imageView: ImageView, @MovieCategory category: String) {
29 | if (category == MovieCategory.SERIES) {
30 | imageView.setImageResource(R.drawable.ic_folder_special)
31 | } else {
32 | imageView.setImageResource(R.drawable.ic_access_time)
33 | }
34 | }
35 |
36 | @BindingAdapter("isFavorite")
37 | fun setIsFavorite(imageView: ImageView, isFavorite: Boolean) {
38 | if (isFavorite) {
39 | imageView.setImageResource(R.drawable.ic_favorite_fill)
40 | } else {
41 | imageView.setImageResource(R.drawable.ic_favorite_empty)
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/extension/ComponentExt.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.extension
2 |
3 | import android.content.Context
4 | import android.view.View
5 | import androidx.fragment.app.Fragment
6 | import com.emamagic.core.interfaces.InitialVisibleFragmentFun
7 | import kotlinx.coroutines.flow.Flow
8 | import kotlinx.coroutines.flow.flow
9 |
10 | inline fun Context.findComponent(): SubComponentProvider {
11 | return if (applicationContext is SubComponentProvider) {
12 | (applicationContext as SubComponentProvider)
13 | } else {
14 | throw IllegalStateException("Provide the application context which implement SubComponent")
15 | }
16 | }
17 |
18 | inline fun View.findComponent(): SubComponentProvider = context.findComponent()
19 |
20 | inline fun Fragment.findComponent(): SubComponentProvider = requireContext().findComponent()
21 |
22 | fun Fragment.setInitialFunctionsForRefreshing(pair: Pair Unit>, Long>) {
23 | (requireActivity() as InitialVisibleFragmentFun).onInitialFunctions(pair)
24 | }
25 |
26 |
27 | fun Flow.throttleFirst(periodMillis: Long): Flow {
28 | require(periodMillis > 0) { "period should be positive" }
29 | return flow {
30 | var lastTime = 0L
31 | collect { value ->
32 | val currentTime = System.currentTimeMillis()
33 | if (currentTime - lastTime >= periodMillis) {
34 | lastTime = currentTime
35 | emit(value)
36 | }
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/extension/ViewExt.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.extension
2 |
3 | import android.content.Context
4 | import android.view.View
5 | import android.view.ViewTreeObserver
6 | import androidx.core.view.isVisible
7 | import androidx.fragment.app.Fragment
8 | import com.emamagic.core.interfaces.OnAppVisibility
9 | import java.lang.ref.WeakReference
10 |
11 | fun View.gone() {
12 | if (isVisible)
13 | visibility = View.GONE
14 | }
15 |
16 | fun View.inVisible() {
17 | if (isVisible)
18 | visibility = View.INVISIBLE
19 | }
20 |
21 | fun View.visible() {
22 | if (!isVisible)
23 | visibility = View.VISIBLE
24 | }
25 |
26 | inline fun T.afterMeasured(crossinline f: T.() -> Unit) {
27 | viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
28 | override fun onGlobalLayout() {
29 | if (measuredWidth > 0 && measuredHeight > 0) {
30 | viewTreeObserver.removeOnGlobalLayoutListener(this)
31 | f()
32 | }
33 | }
34 | })
35 | }
36 |
37 | fun isFragmentVisible(fragment: WeakReference): Boolean =
38 | (fragment.get() != null && fragment.get()!!.activity != null &&
39 | fragment.get()!!.isVisible && !fragment.get()!!.isRemoving)
40 |
41 |
42 | fun Context.appIsInBackground(): Boolean {
43 | return if (applicationContext is OnAppVisibility) {
44 | (applicationContext as OnAppVisibility).appIsInBackground()
45 | } else {
46 | throw IllegalStateException("Provide the application context which implement App Visibility")
47 | }
48 | }
49 |
50 | fun View.appIsInBackground(): Boolean = context.appIsInBackground()
51 |
52 | fun Fragment.appIsInBackground(): Boolean = requireContext().appIsInBackground()
53 |
54 |
55 |
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/interactor/HomeUseCase.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.interactor
2 |
3 | import com.emamagic.common_jvm.MovieCategory
4 | import com.emamagic.domain.GenreRepository
5 | import com.emamagic.domain.MovieRepository
6 | import javax.inject.Inject
7 |
8 | class HomeUseCase @Inject constructor(
9 | private val movieRepository: MovieRepository,
10 | private val genreRepository: GenreRepository
11 | ) {
12 |
13 | suspend fun getSliders() =
14 | movieRepository.getSliders()
15 |
16 | suspend fun getMoviesByMovieCategory(@MovieCategory category: String) =
17 | movieRepository.getMoviesByMovieCategory(category)
18 |
19 | suspend fun getGenre() =
20 | genreRepository.getAllGenre()
21 | }
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/interactor/MovieUseCase.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.interactor
2 |
3 | import com.emamagic.domain.MovieDetailRepository
4 | import javax.inject.Inject
5 |
6 | class MovieUseCase @Inject constructor(
7 | private val movieDetailRepository: MovieDetailRepository
8 | ) {
9 |
10 | suspend fun getMovieDetail(movieId: String) = movieDetailRepository.getMovieDetails(movieId)
11 |
12 | suspend fun getCasts(movieId: String) = movieDetailRepository.getMovieCasts(movieId)
13 |
14 | suspend fun getSeasons(movieId: String) = movieDetailRepository.getMovieSeasons(movieId)
15 |
16 | }
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/interactor/MoviesUseCase.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.interactor
2 |
3 | import com.emamagic.common_jvm.MovieCategory
4 | import com.emamagic.domain.MovieRepository
5 | import javax.inject.Inject
6 |
7 | class MoviesUseCase @Inject constructor(
8 | private val movieRepository: MovieRepository
9 | ) {
10 |
11 | suspend fun getMoviesByMovieCategory(@MovieCategory category: String) =
12 | movieRepository.getMoviesByMovieCategory(category)
13 |
14 | }
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/interfaces/InitialVisibleFragmentFun.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.interfaces
2 |
3 | // for safe modules that call initial functions of visible fragment when user comes to online
4 | interface InitialVisibleFragmentFun {
5 | fun onInitialFunctions(pair: Pair Unit>, Long>)
6 | }
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/interfaces/OnAppVisibility.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.interfaces
2 |
3 | interface OnAppVisibility {
4 | fun appIsInBackground(): Boolean
5 | }
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/utils/AlertType.java:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.utils;
2 |
3 | import androidx.annotation.IntDef;
4 |
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 |
8 | @IntDef({
9 | AlertType.INFO,
10 | AlertType.WARNING,
11 | AlertType.ERROR
12 | })
13 | @Retention(RetentionPolicy.SOURCE)
14 | public @interface AlertType {
15 | int INFO = 0;
16 | int WARNING = 1;
17 | int ERROR = 2;
18 | }
19 |
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/utils/ToastyMode.java:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.utils;
2 |
3 | import androidx.annotation.IntDef;
4 |
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 |
8 | @IntDef({
9 | ToastyMode.MODE_TOAST_SUCCESS,
10 | ToastyMode.MODE_TOAST_WARNING,
11 | ToastyMode.MODE_TOAST_ERROR,
12 | ToastyMode.MODE_TOAST_DEFAULT
13 | })
14 |
15 | @Retention(RetentionPolicy.SOURCE)
16 | public @interface ToastyMode {
17 | int MODE_TOAST_DEFAULT = 0;
18 | int MODE_TOAST_SUCCESS = 1;
19 | int MODE_TOAST_WARNING = 2;
20 | int MODE_TOAST_ERROR = 3;
21 | }
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/utils/ViewExt.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.utils
2 |
3 | import android.text.Editable
4 | import android.text.TextWatcher
5 | import android.view.View
6 | import android.widget.EditText
7 | import androidx.drawerlayout.widget.DrawerLayout
8 | import androidx.fragment.app.FragmentManager
9 |
10 | inline fun EditText.onTextChange(crossinline listener: (String) -> Unit) {
11 | this.addTextChangedListener(object : TextWatcher {
12 | override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
13 | override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
14 | override fun afterTextChanged(s: Editable?) {
15 | listener(s.toString())
16 | }
17 | })
18 | }
19 |
20 | inline fun DrawerLayout.onDrawerListener(crossinline listener: (Float, View) -> Unit) {
21 | this.addDrawerListener(object: DrawerLayout.DrawerListener{
22 | override fun onDrawerSlide(drawerView: View, slideOffset: Float) { listener(slideOffset ,drawerView) }
23 | override fun onDrawerOpened(drawerView: View) {}
24 | override fun onDrawerClosed(drawerView: View) {}
25 | override fun onDrawerStateChanged(newState: Int) {}
26 | })
27 | }
28 |
29 | val T.exhaustive: T
30 | get() = this
31 |
32 |
33 | private fun FragmentManager.isOnBackStack(backStackName: String): Boolean {
34 | val backStackCount = backStackEntryCount
35 | for (index in 0 until backStackCount) {
36 | if (getBackStackEntryAt(index).name == backStackName) {
37 | return true
38 | }
39 | }
40 | return false
41 | }
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/utils/ViewModelKey.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.utils
2 |
3 | import androidx.lifecycle.ViewModel
4 | import dagger.MapKey
5 | import kotlin.reflect.KClass
6 |
7 | @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
8 | @kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
9 | @MapKey
10 | annotation class ViewModelKey(val value: KClass)
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/utils/ViewModelScope.java:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.utils;
2 |
3 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
4 | import java.lang.annotation.Documented;
5 | import java.lang.annotation.Retention;
6 | import javax.inject.Scope;
7 |
8 | @Scope
9 | @Documented
10 | @Retention(RUNTIME)
11 | public @interface ViewModelScope {}
12 |
--------------------------------------------------------------------------------
/application/src/main/java/com/emamagic/core/utils/keyboard/keyboardExt.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core.utils.keyboard
2 |
3 | import android.app.Activity
4 | import android.content.Context
5 | import android.graphics.Rect
6 | import android.util.TypedValue
7 | import android.view.View
8 | import kotlin.math.roundToInt
9 |
10 | fun Activity.getRootView(): View {
11 | return findViewById(android.R.id.content)
12 | }
13 | fun Context.convertDpToPx(dp: Float): Float {
14 | return TypedValue.applyDimension(
15 | TypedValue.COMPLEX_UNIT_DIP,
16 | dp,
17 | this.resources.displayMetrics
18 | )
19 | }
20 | fun Activity.isKeyboardOpen(): Boolean {
21 | val visibleBounds = Rect()
22 | this.getRootView().getWindowVisibleDisplayFrame(visibleBounds)
23 | val heightDiff = getRootView().height - visibleBounds.height()
24 | val marginOfError = this.convertDpToPx(50F).roundToInt()
25 | return heightDiff > marginOfError
26 | }
27 |
28 | fun Activity.isKeyboardClosed(): Boolean {
29 | return !this.isKeyboardOpen()
30 | }
--------------------------------------------------------------------------------
/application/src/main/res/drawable/bg_corroct_toast.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/bg_error_toast.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/bg_rank.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/bg_warning_toast.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/hover_oval.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/hover_oval_drawable.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/ic_access_time.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/ic_corroct_toast.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/ic_cross.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/ic_error_blue_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/ic_error_red_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/ic_error_toast.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/ic_error_yellow_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/ic_favorite_empty.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/ic_favorite_fill.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/ic_folder_special.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/ic_warning_toast.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/rounded_btn_grey.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/rounded_btn_red.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/rounded_iw.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/application/src/main/res/drawable/simple_round_transparent.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/application/src/main/res/layout/layout_toast.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
33 |
34 |
--------------------------------------------------------------------------------
/application/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 8dp
5 | 10dp
6 | 16dp
7 | 24dp
8 | 16dp
9 | 8dp
10 | 56dp
11 |
12 | 8sp
13 | 11sp
14 | 12sp
15 | 14sp
16 | 16sp
17 | 18sp
18 |
19 | 48dp
20 | 52dp
21 |
22 |
23 |
--------------------------------------------------------------------------------
/application/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/application/src/main/res/values/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
17 |
--------------------------------------------------------------------------------
/application/src/test/java/com/emamagic/core/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.emamagic.core
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | repositories {
4 | google()
5 | mavenCentral()
6 | jcenter()
7 | }
8 | dependencies {
9 | classpath(Build.tools)
10 | classpath(Build.gradle)
11 | classpath(Build.safe_args)
12 | // NOTE: Do not place your application dependencies here; they belong
13 | // in the individual module build.gradle files
14 | }
15 | }
16 |
17 | tasks.register("clean", Delete::class) {
18 | delete(rootProject.buildDir)
19 | }
--------------------------------------------------------------------------------
/buildSrc/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | `kotlin-dsl`
3 | }
4 | repositories {
5 | google()
6 | mavenCentral()
7 | }
8 |
--------------------------------------------------------------------------------
/buildSrc/build/classes/kotlin/main/Android.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/classes/kotlin/main/Android.class
--------------------------------------------------------------------------------
/buildSrc/build/classes/kotlin/main/Build.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/classes/kotlin/main/Build.class
--------------------------------------------------------------------------------
/buildSrc/build/classes/kotlin/main/Libs.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/classes/kotlin/main/Libs.class
--------------------------------------------------------------------------------
/buildSrc/build/classes/kotlin/main/META-INF/buildSrc.kotlin_module:
--------------------------------------------------------------------------------
1 | " *
--------------------------------------------------------------------------------
/buildSrc/build/classes/kotlin/main/Modules.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/classes/kotlin/main/Modules.class
--------------------------------------------------------------------------------
/buildSrc/build/classes/kotlin/main/Releases.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/classes/kotlin/main/Releases.class
--------------------------------------------------------------------------------
/buildSrc/build/classes/kotlin/main/Tests.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/classes/kotlin/main/Tests.class
--------------------------------------------------------------------------------
/buildSrc/build/classes/kotlin/main/Versions.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/classes/kotlin/main/Versions.class
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/buildSrcjar-classes.txt:
--------------------------------------------------------------------------------
1 | /home/emamagic/Android/Project/Android-Multi-Module/buildSrc/build/classes/kotlin/main/Android.class:/home/emamagic/Android/Project/Android-Multi-Module/buildSrc/build/classes/kotlin/main/Build.class:/home/emamagic/Android/Project/Android-Multi-Module/buildSrc/build/classes/kotlin/main/Libs.class:/home/emamagic/Android/Project/Android-Multi-Module/buildSrc/build/classes/kotlin/main/Modules.class:/home/emamagic/Android/Project/Android-Multi-Module/buildSrc/build/classes/kotlin/main/Releases.class:/home/emamagic/Android/Project/Android-Multi-Module/buildSrc/build/classes/kotlin/main/Tests.class:/home/emamagic/Android/Project/Android-Multi-Module/buildSrc/build/classes/kotlin/main/Versions.class
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/compileKotlin/build-history.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/kotlin/compileKotlin/build-history.bin
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab.keystream.len:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab.len:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab.len
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab.values.at:
--------------------------------------------------------------------------------
1 | / Header Record For PersistentHashMapValueStorage 6$PROJECT_DIR$/build/classes/kotlin/main/Versions.classG$PROJECT_DIR$/build/classes/kotlin/main/META-INF/buildSrc.kotlin_module| 3$PROJECT_DIR$/build/classes/kotlin/main/Tests.classG$PROJECT_DIR$/build/classes/kotlin/main/META-INF/buildSrc.kotlin_module{ 2$PROJECT_DIR$/build/classes/kotlin/main/Libs.classG$PROJECT_DIR$/build/classes/kotlin/main/META-INF/buildSrc.kotlin_module 6$PROJECT_DIR$/build/classes/kotlin/main/Releases.classG$PROJECT_DIR$/build/classes/kotlin/main/META-INF/buildSrc.kotlin_module| 3$PROJECT_DIR$/build/classes/kotlin/main/Build.classG$PROJECT_DIR$/build/classes/kotlin/main/META-INF/buildSrc.kotlin_module~ 5$PROJECT_DIR$/build/classes/kotlin/main/Modules.classG$PROJECT_DIR$/build/classes/kotlin/main/META-INF/buildSrc.kotlin_module~ 5$PROJECT_DIR$/build/classes/kotlin/main/Android.classG$PROJECT_DIR$/build/classes/kotlin/main/META-INF/buildSrc.kotlin_module~ 5$PROJECT_DIR$/build/classes/kotlin/main/Modules.classG$PROJECT_DIR$/build/classes/kotlin/main/META-INF/buildSrc.kotlin_module~ 5$PROJECT_DIR$/build/classes/kotlin/main/Modules.classG$PROJECT_DIR$/build/classes/kotlin/main/META-INF/buildSrc.kotlin_module
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab_i:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab_i
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab_i.len:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab_i.len
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len:
--------------------------------------------------------------------------------
1 | 3
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab.len:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab.len
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab.values.at:
--------------------------------------------------------------------------------
1 | / Header Record For PersistentHashMapValueStorage
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab_i:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab_i
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab_i.len:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab_i.len
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len:
--------------------------------------------------------------------------------
1 | 3
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emamagic/Android-Multi-Module/3c8e8a06525f178843741e616b729b6a3040d701/buildSrc/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len
--------------------------------------------------------------------------------
/buildSrc/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at:
--------------------------------------------------------------------------------
1 | / Header Record For PersistentHashMapValueStorage) ($PROJECT_DIR$/src/main/kotlin/Android.kt' &$PROJECT_DIR$/src/main/kotlin/Build.kt&