├── .gitignore
├── Application
├── .gitignore
├── .idea
│ ├── .gitignore
│ ├── .name
│ ├── compiler.xml
│ ├── gradle.xml
│ ├── inspectionProfiles
│ │ └── Project_Default.xml
│ ├── jarRepositories.xml
│ └── misc.xml
├── app
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── dev
│ │ └── debug
│ │ │ └── output-metadata.json
│ ├── proguard-rules.pro
│ ├── release
│ │ └── output-metadata.json
│ └── src
│ │ ├── debug
│ │ └── ic_launcher-playstore.png
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── istudio
│ │ │ │ └── distancetracker
│ │ │ │ ├── Constants.kt
│ │ │ │ ├── TrackerApplication.kt
│ │ │ │ ├── compose
│ │ │ │ └── theme
│ │ │ │ │ ├── Color.kt
│ │ │ │ │ ├── Shape.kt
│ │ │ │ │ ├── Theme.kt
│ │ │ │ │ └── Type.kt
│ │ │ │ ├── di
│ │ │ │ └── NotificationModule.kt
│ │ │ │ ├── features
│ │ │ │ ├── KeysFeatureNames.kt
│ │ │ │ ├── distancelog
│ │ │ │ │ └── DistanceLogFragment.kt
│ │ │ │ ├── map
│ │ │ │ │ ├── domain
│ │ │ │ │ │ ├── MapFragmentUseCases.kt
│ │ │ │ │ │ ├── di
│ │ │ │ │ │ │ └── MapDomainModule.kt
│ │ │ │ │ │ ├── entities
│ │ │ │ │ │ │ ├── inputs
│ │ │ │ │ │ │ │ └── CalculateResultInput.kt
│ │ │ │ │ │ │ └── outputs
│ │ │ │ │ │ │ │ └── CalculateResultOutput.kt
│ │ │ │ │ │ └── usecases
│ │ │ │ │ │ │ └── CalculateResultUseCase.kt
│ │ │ │ │ ├── events
│ │ │ │ │ │ └── EventMapStyleSelected.kt
│ │ │ │ │ ├── presentation
│ │ │ │ │ │ ├── custom
│ │ │ │ │ │ │ ├── MapDisplayView.kt
│ │ │ │ │ │ │ ├── MapErrorView.kt
│ │ │ │ │ │ │ └── MapMasterView.kt
│ │ │ │ │ │ ├── state
│ │ │ │ │ │ │ └── MapStates.kt
│ │ │ │ │ │ ├── view
│ │ │ │ │ │ │ ├── MapFragment.kt
│ │ │ │ │ │ │ └── MapTypeSelectionFragment.kt
│ │ │ │ │ │ └── vm
│ │ │ │ │ │ │ └── MapsVm.kt
│ │ │ │ │ └── util
│ │ │ │ │ │ ├── AnimateCamera.kt
│ │ │ │ │ │ ├── FileOperations.kt
│ │ │ │ │ │ └── MapUtil.kt
│ │ │ │ ├── permission
│ │ │ │ │ └── presentation
│ │ │ │ │ │ ├── state
│ │ │ │ │ │ └── PermissionStates.kt
│ │ │ │ │ │ ├── view
│ │ │ │ │ │ └── PermissionFragment.kt
│ │ │ │ │ │ └── vm
│ │ │ │ │ │ └── PermissionVm.kt
│ │ │ │ └── result
│ │ │ │ │ └── ResultFragment.kt
│ │ │ │ ├── main
│ │ │ │ ├── MainActivity.kt
│ │ │ │ └── presentation
│ │ │ │ │ ├── state
│ │ │ │ │ └── MainEvent.kt
│ │ │ │ │ └── vm
│ │ │ │ │ └── MainVm.kt
│ │ │ │ ├── model
│ │ │ │ └── Result.kt
│ │ │ │ └── service
│ │ │ │ ├── InAppUpdate.kt
│ │ │ │ └── TrackerService.kt
│ │ └── res
│ │ │ ├── drawable
│ │ │ ├── custom_marker.png
│ │ │ ├── ic_app_launcher.png
│ │ │ ├── ic_app_launcher_round.png
│ │ │ ├── ic_baseline_arrow_forward.xml
│ │ │ ├── ic_close.xml
│ │ │ ├── ic_launcher_foreground.xml
│ │ │ ├── ic_reset.xml
│ │ │ ├── ic_run.xml
│ │ │ ├── ic_share.xml
│ │ │ ├── ic_splash.xml
│ │ │ └── ic_welcome_image.xml
│ │ │ ├── layout
│ │ │ ├── activity_main.xml
│ │ │ ├── bottom_sheet_map_type.xml
│ │ │ ├── fragment_distance_log.xml
│ │ │ ├── fragment_map.xml
│ │ │ ├── fragment_map_type.xml
│ │ │ ├── fragment_permission.xml
│ │ │ ├── fragment_result.xml
│ │ │ ├── include_cust_error_view.xml
│ │ │ ├── include_cust_map_view.xml
│ │ │ └── include_cust_master_view.xml
│ │ │ ├── navigation
│ │ │ └── nav_graph.xml
│ │ │ ├── raw
│ │ │ ├── map_dark_mode.json
│ │ │ └── map_light_mode.json
│ │ │ └── values
│ │ │ └── strings.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── istudio
│ │ └── distancetracker
│ │ └── ExampleUnitNetworkUtils.kt
├── base-module.gradle
├── build.gradle.kts
├── buildSrc
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── scripts
│ │ └── spotless.gradle
│ └── src
│ │ └── main
│ │ └── java
│ │ ├── Accompanist.kt
│ │ ├── AndroidX.kt
│ │ ├── Build.kt
│ │ ├── Coil.kt
│ │ ├── Compose.kt
│ │ ├── Coroutines.kt
│ │ ├── CustomLogging.kt
│ │ ├── DaggerHilt.kt
│ │ ├── DataStorePreferences.kt
│ │ ├── Firebase.kt
│ │ ├── FlavourUtils.kt
│ │ ├── Glide.kt
│ │ ├── Google.kt
│ │ ├── Gson.kt
│ │ ├── Kotlin.kt
│ │ ├── KotlinSerialization.kt
│ │ ├── LifeCycle.kt
│ │ ├── Lotte.kt
│ │ ├── Maps.kt
│ │ ├── Modules.kt
│ │ ├── Moshi.kt
│ │ ├── Navigation.kt
│ │ ├── Permission.kt
│ │ ├── ProjectConfig.kt
│ │ ├── Retrofit.kt
│ │ ├── Room.kt
│ │ ├── ScriptPlugins.kt
│ │ ├── SplashScreen.kt
│ │ ├── SqlDelight.kt
│ │ └── Testing.kt
├── core
│ ├── core-common
│ │ ├── .gitignore
│ │ ├── build.gradle.kts
│ │ ├── consumer-rules.pro
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── androidTest
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── istudio
│ │ │ │ └── core_common
│ │ │ │ └── ExampleInstrumentedTest.kt
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── istudio
│ │ │ │ │ └── core_common
│ │ │ │ │ ├── base
│ │ │ │ │ └── BaseViewModel.kt
│ │ │ │ │ ├── constants
│ │ │ │ │ └── DbConstants.kt
│ │ │ │ │ ├── di
│ │ │ │ │ ├── modules
│ │ │ │ │ │ └── CoroutineModule.kt
│ │ │ │ │ └── qualifiers
│ │ │ │ │ │ └── Dispatchers.kt
│ │ │ │ │ ├── extensions
│ │ │ │ │ ├── Activity.kt
│ │ │ │ │ ├── Channels.kt
│ │ │ │ │ ├── Context.kt
│ │ │ │ │ ├── SnackBarDisplay.kt
│ │ │ │ │ ├── Snackbar.kt
│ │ │ │ │ ├── Tag.kt
│ │ │ │ │ └── ViewVisibilityExtensions.kt
│ │ │ │ │ ├── functional
│ │ │ │ │ ├── NetworkBoundResource.kt
│ │ │ │ │ ├── PublisherEventBus.kt
│ │ │ │ │ ├── Resource.kt
│ │ │ │ │ ├── State.kt
│ │ │ │ │ ├── SuspendUseCase.kt
│ │ │ │ │ └── UseCaseResult.kt
│ │ │ │ │ ├── navigation
│ │ │ │ │ └── NavigationUtils.kt
│ │ │ │ │ ├── network
│ │ │ │ │ └── NetworkHandler.kt
│ │ │ │ │ └── ui
│ │ │ │ │ └── uiEvent
│ │ │ │ │ ├── UiEvent.kt
│ │ │ │ │ └── UiText.kt
│ │ │ └── res
│ │ │ │ ├── layout
│ │ │ │ └── layout.xml
│ │ │ │ └── values
│ │ │ │ ├── colors.xml
│ │ │ │ └── strings.xml
│ │ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── istudio
│ │ │ └── core_common
│ │ │ └── ExampleUnitTest.kt
│ ├── core-connectivity
│ │ ├── .gitignore
│ │ ├── build.gradle.kts
│ │ ├── consumer-rules.pro
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── androidTest
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── istudio
│ │ │ │ └── core_connectivity
│ │ │ │ └── ExampleInstrumentedTest.kt
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── istudio
│ │ │ │ └── core_connectivity
│ │ │ │ ├── data
│ │ │ │ └── implementation
│ │ │ │ │ └── ConnectivityFeatureImpl.kt
│ │ │ │ ├── di
│ │ │ │ └── ConnectivityModule.kt
│ │ │ │ ├── domain
│ │ │ │ └── ConnectivityFeature.kt
│ │ │ │ └── service
│ │ │ │ └── NetworkObserver.kt
│ │ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── istudio
│ │ │ └── core_connectivity
│ │ │ └── ExampleUnitTest.kt
│ ├── core-database
│ │ ├── .gitignore
│ │ ├── build.gradle.kts
│ │ ├── consumer-rules.pro
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── androidTest
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── istudio
│ │ │ │ └── core_database
│ │ │ │ └── ExampleInstrumentedTest.kt
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── istudio
│ │ │ │ └── core_database
│ │ │ │ ├── Constants.kt
│ │ │ │ ├── data
│ │ │ │ └── implementation
│ │ │ │ │ └── DistanceTrackerConstantsDaoImpl.kt
│ │ │ │ ├── database
│ │ │ │ └── DistanceTrackerDatabase.kt
│ │ │ │ ├── di
│ │ │ │ └── DatabaseModule.kt
│ │ │ │ └── domain
│ │ │ │ └── dao
│ │ │ │ └── DistanceTrackerConstantsDao.kt
│ │ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── istudio
│ │ │ └── core_database
│ │ │ └── ExampleUnitTest.kt
│ ├── core-location
│ │ ├── .gitignore
│ │ ├── build.gradle.kts
│ │ ├── consumer-rules.pro
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── androidTest
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── istudio
│ │ │ │ └── core_location
│ │ │ │ └── ExampleInstrumentedTest.kt
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── istudio
│ │ │ │ └── core_location
│ │ │ │ ├── data
│ │ │ │ ├── LastLocationFeatureImpl.kt
│ │ │ │ └── LocationFeatureImpl.kt
│ │ │ │ ├── di
│ │ │ │ └── LocationModule.kt
│ │ │ │ └── domain
│ │ │ │ ├── LastLocationFeature.kt
│ │ │ │ └── LocationFeature.kt
│ │ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── istudio
│ │ │ └── core_location
│ │ │ └── ExampleUnitTest.kt
│ ├── core-logger
│ │ ├── .gitignore
│ │ ├── build.gradle.kts
│ │ ├── consumer-rules.pro
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── androidTest
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── istudio
│ │ │ │ └── core_logger
│ │ │ │ └── ExampleInstrumentedTest.kt
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── istudio
│ │ │ │ └── core_logger
│ │ │ │ ├── ApplicationLoggerConfig.kt
│ │ │ │ ├── data
│ │ │ │ ├── implementaion
│ │ │ │ │ └── LoggerFeatureImpl.kt
│ │ │ │ └── repository
│ │ │ │ │ └── LoggerRepository.kt
│ │ │ │ ├── di
│ │ │ │ └── LoggerModule.kt
│ │ │ │ └── domain
│ │ │ │ └── LoggerFeature.kt
│ │ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── istudio
│ │ │ └── core_logger
│ │ │ └── ExampleUnitTest.kt
│ ├── core-models
│ │ ├── .gitignore
│ │ ├── build.gradle.kts
│ │ ├── consumer-rules.pro
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── androidTest
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── demo
│ │ │ │ └── core_models
│ │ │ │ └── ExampleInstrumentedTest.kt
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── demo
│ │ │ │ └── core_models
│ │ │ │ └── DistanceTrackerConstants.kt
│ │ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── demo
│ │ │ └── core_models
│ │ │ └── ExampleUnitTest.kt
│ ├── core-network
│ │ ├── .gitignore
│ │ ├── build.gradle.kts
│ │ ├── consumer-rules.pro
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── androidTest
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── demo
│ │ │ │ └── core_network
│ │ │ │ └── ExampleInstrumentedTest.kt
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── demo
│ │ │ │ └── core_network
│ │ │ │ ├── api
│ │ │ │ └── DistanceTrackerApi.kt
│ │ │ │ ├── di
│ │ │ │ └── AppModule.kt
│ │ │ │ ├── interceptors
│ │ │ │ ├── AnalyticsInterceptor.kt
│ │ │ │ └── ApiKeyInterceptor.kt
│ │ │ │ └── utils
│ │ │ │ └── NetworkUtils.kt
│ │ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── demo
│ │ │ └── core_network
│ │ │ └── ExampleUnitNetworkUtils.kt
│ ├── core-permission
│ │ ├── .gitignore
│ │ ├── build.gradle.kts
│ │ ├── consumer-rules.pro
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── androidTest
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── demo
│ │ │ │ └── core_permission
│ │ │ │ └── ExampleInstrumentedTest.kt
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── demo
│ │ │ │ └── core_permission
│ │ │ │ ├── Permissions.kt
│ │ │ │ ├── data
│ │ │ │ └── implementation
│ │ │ │ │ └── PermissionFeatureImpl.kt
│ │ │ │ ├── di
│ │ │ │ └── PermissionModule.kt
│ │ │ │ └── domain
│ │ │ │ └── PermissionFeature.kt
│ │ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── demo
│ │ │ └── core_permission
│ │ │ └── ExampleUnitTest.kt
│ ├── core-preferences
│ │ ├── .gitignore
│ │ ├── build.gradle.kts
│ │ ├── consumer-rules.pro
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── androidTest
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── istudio
│ │ │ │ └── core_preferences
│ │ │ │ └── ExampleInstrumentedTest.kt
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── istudio
│ │ │ │ └── core_preferences
│ │ │ │ ├── data
│ │ │ │ ├── implementation
│ │ │ │ │ ├── PreferenceDatastoreImpl.kt
│ │ │ │ │ └── utilities
│ │ │ │ │ │ └── KeysPreferences.kt
│ │ │ │ └── repository
│ │ │ │ │ └── PreferenceRepository.kt
│ │ │ │ ├── di
│ │ │ │ └── PreferenceModule.kt
│ │ │ │ └── domain
│ │ │ │ └── InAppReviewPreferences.kt
│ │ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── istudio
│ │ │ └── core_preferences
│ │ │ └── ExampleUnitTest.kt
│ └── core-ui
│ │ ├── .gitignore
│ │ ├── build.gradle.kts
│ │ ├── consumer-rules.pro
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── istudio
│ │ │ └── core_ui
│ │ │ └── ExampleInstrumentedTest.kt
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── istudio
│ │ │ │ └── core_ui
│ │ │ │ ├── composeUi
│ │ │ │ └── theme
│ │ │ │ │ ├── Color.kt
│ │ │ │ │ ├── Shape.kt
│ │ │ │ │ ├── Theme.kt
│ │ │ │ │ └── Type.kt
│ │ │ │ ├── customviews
│ │ │ │ ├── button
│ │ │ │ │ ├── ButtonViewBold.kt
│ │ │ │ │ ├── ButtonViewMedium.kt
│ │ │ │ │ └── ButtonViewRegular.kt
│ │ │ │ └── text
│ │ │ │ │ ├── TextViewBold.kt
│ │ │ │ │ ├── TextViewMedium.kt
│ │ │ │ │ └── TextViewRegular.kt
│ │ │ │ ├── data
│ │ │ │ ├── implementation
│ │ │ │ │ └── SwitchUiModeFeatureImpl.kt
│ │ │ │ └── models
│ │ │ │ │ └── Mode.kt
│ │ │ │ ├── di
│ │ │ │ └── SwitchUiModule.kt
│ │ │ │ └── domain
│ │ │ │ └── SwitchUiModeFeature.kt
│ │ └── res
│ │ │ ├── anim
│ │ │ ├── fade_in.xml
│ │ │ └── fade_out.xml
│ │ │ ├── drawable-hdpi
│ │ │ ├── ic_current_location.png
│ │ │ ├── ic_current_location_dark_mode.png
│ │ │ └── ic_list.png
│ │ │ ├── drawable-mdpi
│ │ │ ├── ic_current_location.png
│ │ │ ├── ic_current_location_dark_mode.png
│ │ │ └── ic_list.png
│ │ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── drawable-xhdpi
│ │ │ ├── ic_current_location.png
│ │ │ ├── ic_current_location_dark_mode.png
│ │ │ └── ic_list.png
│ │ │ ├── drawable-xxhdpi
│ │ │ ├── ic_current_location.png
│ │ │ ├── ic_current_location_dark_mode.png
│ │ │ └── ic_list.png
│ │ │ ├── drawable-xxxhdpi
│ │ │ ├── ic_current_location.png
│ │ │ ├── ic_current_location_dark_mode.png
│ │ │ └── ic_list.png
│ │ │ ├── drawable
│ │ │ ├── ic_add_action.xml
│ │ │ ├── ic_dark_mode.xml
│ │ │ ├── ic_dialog_bg.xml
│ │ │ ├── ic_light_mode.xml
│ │ │ ├── ic_lock_black_24dp.xml
│ │ │ ├── ic_map_journey.xml
│ │ │ ├── ic_map_styles.xml
│ │ │ ├── ic_photo_album_black_24dp.xml
│ │ │ ├── ic_splash.xml
│ │ │ └── ic_splash_dark_mode.xml
│ │ │ ├── font
│ │ │ ├── roboto.xml
│ │ │ ├── roboto_bold.xml
│ │ │ ├── roboto_bold_italic.xml
│ │ │ ├── roboto_italic.xml
│ │ │ ├── roboto_light_italic.xml
│ │ │ └── roboto_medium.xml
│ │ │ ├── layout
│ │ │ └── test_layout.xml
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── raw
│ │ │ ├── gps_lotte.json
│ │ │ ├── map.geojson
│ │ │ ├── map_navigation_lotte.json
│ │ │ ├── permission_lotte.json
│ │ │ ├── rate_app_lotte.json
│ │ │ ├── result_lotte.json
│ │ │ ├── style.json
│ │ │ └── wifi_lotte.json
│ │ │ ├── values-night
│ │ │ ├── colors.xml
│ │ │ └── themes.xml
│ │ │ ├── values
│ │ │ ├── colors.xml
│ │ │ ├── common_styles.xml
│ │ │ ├── dimens.xml
│ │ │ ├── font_certs.xml
│ │ │ ├── preloaded_fonts.xml
│ │ │ ├── strings.xml
│ │ │ └── themes.xml
│ │ │ └── xml
│ │ │ ├── backup_rules.xml
│ │ │ └── data_extraction_rules.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── istudio
│ │ └── core_ui
│ │ └── ExampleUnitTest.kt
├── data.json
├── features
│ ├── feat-gallery
│ │ ├── .gitignore
│ │ ├── build.gradle.kts
│ │ ├── consumer-rules.pro
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── androidTest
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── feat_gallery
│ │ │ │ └── ExampleInstrumentedTest.kt
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── feat_gallery
│ │ │ │ │ ├── presentation
│ │ │ │ │ ├── adapter
│ │ │ │ │ │ └── GalleryAdapter.kt
│ │ │ │ │ ├── models
│ │ │ │ │ │ └── InternalStoragePhoto.kt
│ │ │ │ │ ├── vh
│ │ │ │ │ │ └── ImageViewHolder.kt
│ │ │ │ │ ├── view
│ │ │ │ │ │ └── GalleryActivity.kt
│ │ │ │ │ └── vm
│ │ │ │ │ │ └── GalleryVm.kt
│ │ │ │ │ └── utils
│ │ │ │ │ └── PermissionUtils.kt
│ │ │ └── res
│ │ │ │ └── layout
│ │ │ │ ├── activity_demo_one.xml
│ │ │ │ └── image_layout.xml
│ │ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── feat_gallery
│ │ │ └── ExampleUnitTest.kt
│ ├── feat-inappreview
│ │ ├── .gitignore
│ │ ├── build.gradle.kts
│ │ ├── consumer-rules.pro
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── androidTest
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── istudio
│ │ │ │ └── feat_inappreview
│ │ │ │ └── ExampleInstrumentedTest.kt
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── istudio
│ │ │ │ │ └── feat_inappreview
│ │ │ │ │ ├── InAppReviewView.kt
│ │ │ │ │ ├── ReviewFeatureConstants.kt
│ │ │ │ │ ├── di
│ │ │ │ │ ├── InAppReviewBinds.kt
│ │ │ │ │ └── ReviewManagerModule.kt
│ │ │ │ │ ├── dialog
│ │ │ │ │ ├── ReviewDialog.kt
│ │ │ │ │ ├── ReviewDialogVm.kt
│ │ │ │ │ └── ReviewStates.kt
│ │ │ │ │ └── manager
│ │ │ │ │ ├── InAppReviewManager.kt
│ │ │ │ │ └── InAppReviewManagerImpl.kt
│ │ │ └── res
│ │ │ │ ├── drawable
│ │ │ │ ├── happy_face.png
│ │ │ │ ├── ic_rate_review.xml
│ │ │ │ ├── not_now_action_border.xml
│ │ │ │ ├── progress_black.png
│ │ │ │ ├── progress_white.png
│ │ │ │ ├── review_action_border.xml
│ │ │ │ └── sad_face.png
│ │ │ │ └── layout
│ │ │ │ └── fragment_in_app_review_prompt.xml
│ │ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── istudio
│ │ │ └── feat_inappreview
│ │ │ └── ExampleUnitTest.kt
│ └── feat-repository
│ │ ├── .gitignore
│ │ ├── build.gradle.kts
│ │ ├── consumer-rules.pro
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── demo
│ │ │ └── feat_repository
│ │ │ └── ExampleInstrumentedTest.kt
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── com
│ │ │ └── demo
│ │ │ └── feat_repository
│ │ │ └── DistanceTrackerRepository.kt
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── demo
│ │ └── feat_repository
│ │ └── ExampleUnitNetworkUtils.kt
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
├── Assets
├── Architecture
│ ├── MVVM.png
│ └── projectstructure.drawio.png
├── Banner
│ └── banner.jpeg
├── Images
│ ├── google-play-store.png
│ ├── google-play.png
│ └── playstore.png
└── ScreenGif
│ ├── BackgroundPermission.gif
│ ├── Demo.gif
│ ├── RuntimePermission.gif
│ ├── dark_light_mode.gif
│ ├── locating_user.gif
│ ├── network_observer.gif
│ ├── splash.gif
│ ├── switch_map_types.gif
│ └── updates.gif
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.aar
4 | *.ap_
5 | *.aab
6 |
7 | # Files for the ART/Dalvik VM
8 | *.dex
9 |
10 | # Java class files
11 | *.class
12 |
13 | # Generated files
14 | bin/
15 | gen/
16 | out/
17 | # Uncomment the following line in case you need and you don't have the release build type files in your app
18 | # release/
19 |
20 | # Gradle files
21 | .gradle/
22 | build/
23 |
24 | # Local configuration file (sdk path, etc)
25 | local.properties
26 |
27 | # Proguard folder generated by Eclipse
28 | proguard/
29 |
30 | # Log Files
31 | *.log
32 |
33 | # Android Studio Navigation editor temp files
34 | .navigation/
35 |
36 | # Android Studio captures folder
37 | captures/
38 |
39 | # IntelliJ
40 | *.iml
41 | .idea/workspace.xml
42 | .idea/tasks.xml
43 | .idea/gradle.xml
44 | .idea/assetWizardSettings.xml
45 | .idea/dictionaries
46 | .idea/libraries
47 | # Android Studio 3 in .gitignore file.
48 | .idea/caches
49 | .idea/modules.xml
50 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you
51 | .idea/navEditor.xml
52 |
53 | # Keystore files
54 | # Uncomment the following lines if you do not want to check your keystore files in.
55 | #*.jks
56 | #*.keystore
57 |
58 | # External native build folder generated in Android Studio 2.2 and later
59 | .externalNativeBuild
60 | .cxx/
61 |
62 | # Google Services (e.g. APIs or Firebase)
63 | # google-services.json
64 |
65 | # Freeline
66 | freeline.py
67 | freeline/
68 | freeline_project_description.json
69 |
70 | # fastlane
71 | fastlane/report.xml
72 | fastlane/Preview.html
73 | fastlane/screenshots
74 | fastlane/test_output
75 | fastlane/readme.md
76 |
77 | # Version control
78 | vcs.xml
79 |
80 | # lint
81 | lint/intermediates/
82 | lint/generated/
83 | lint/outputs/
84 | lint/tmp/
85 | # lint/reports/
86 |
--------------------------------------------------------------------------------
/Application/.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 |
17 | **/*/res/values/secrets.xml
18 | google-services.json
19 |
--------------------------------------------------------------------------------
/Application/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/Application/.idea/.name:
--------------------------------------------------------------------------------
1 | Distance Tracker
--------------------------------------------------------------------------------
/Application/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Application/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
36 |
37 |
--------------------------------------------------------------------------------
/Application/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Application/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Application/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/Application/app/dev/debug/output-metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "artifactType": {
4 | "type": "APK",
5 | "kind": "Directory"
6 | },
7 | "applicationId": "com.istudio.distancetracker",
8 | "variantName": "devDebug",
9 | "elements": [
10 | {
11 | "type": "SINGLE",
12 | "filters": [],
13 | "attributes": [],
14 | "versionCode": 8,
15 | "versionName": "1.1",
16 | "outputFile": "app-dev-debug.apk"
17 | }
18 | ],
19 | "elementType": "File"
20 | }
--------------------------------------------------------------------------------
/Application/app/release/output-metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "artifactType": {
4 | "type": "APK",
5 | "kind": "Directory"
6 | },
7 | "applicationId": "com.istudio.distancetracker",
8 | "variantName": "release",
9 | "elements": [
10 | {
11 | "type": "SINGLE",
12 | "filters": [],
13 | "attributes": [],
14 | "versionCode": 1,
15 | "versionName": "1.0",
16 | "outputFile": "app-release.apk"
17 | }
18 | ],
19 | "elementType": "File"
20 | }
--------------------------------------------------------------------------------
/Application/app/src/debug/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/app/src/debug/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/compose/theme/Color.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.compose.theme
2 |
3 | import androidx.compose.ui.graphics.Color
4 |
5 | val Purple200 = Color(0xFFBB86FC)
6 | val Purple500 = Color(0xFF6200EE)
7 | val Purple700 = Color(0xFF3700B3)
8 | val Teal200 = Color(0xFF03DAC5)
9 |
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/compose/theme/Shape.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.compose.theme
2 |
3 | import androidx.compose.foundation.shape.RoundedCornerShape
4 | import androidx.compose.material.Shapes
5 | import androidx.compose.ui.unit.dp
6 |
7 | val Shapes = Shapes(
8 | small = RoundedCornerShape(4.dp),
9 | medium = RoundedCornerShape(4.dp),
10 | large = RoundedCornerShape(0.dp)
11 | )
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/compose/theme/Theme.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.compose.theme
2 |
3 | import androidx.compose.foundation.isSystemInDarkTheme
4 | import androidx.compose.material.MaterialTheme
5 | import androidx.compose.material.darkColors
6 | import androidx.compose.material.lightColors
7 | import androidx.compose.runtime.Composable
8 |
9 | private val DarkColorPalette = darkColors(
10 | primary = Purple200,
11 | primaryVariant = Purple700,
12 | secondary = Teal200
13 | )
14 |
15 | private val LightColorPalette = lightColors(
16 | primary = Purple500,
17 | primaryVariant = Purple700,
18 | secondary = Teal200
19 |
20 | /* Other default colors to override
21 | background = Color.White,
22 | surface = Color.White,
23 | onPrimary = Color.White,
24 | onSecondary = Color.Black,
25 | onBackground = Color.Black,
26 | onSurface = Color.Black,
27 | */
28 | )
29 |
30 | @Composable
31 | fun MyApplicationTheme(
32 | darkTheme: Boolean = isSystemInDarkTheme(),
33 | content: @Composable () -> Unit
34 | ) {
35 | val colors = if (darkTheme) {
36 | DarkColorPalette
37 | } else {
38 | LightColorPalette
39 | }
40 |
41 | MaterialTheme(
42 | colors = colors,
43 | typography = Typography,
44 | shapes = Shapes,
45 | content = content
46 | )
47 | }
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/compose/theme/Type.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.compose.theme
2 |
3 | import androidx.compose.material.Typography
4 | import androidx.compose.ui.text.TextStyle
5 | import androidx.compose.ui.text.font.FontFamily
6 | import androidx.compose.ui.text.font.FontWeight
7 | import androidx.compose.ui.unit.sp
8 |
9 | // Set of Material typography styles to start with
10 | val Typography = Typography(
11 | body1 = TextStyle(
12 | fontFamily = FontFamily.Default,
13 | fontWeight = FontWeight.Normal,
14 | fontSize = 16.sp
15 | )
16 | /* Other default text styles to override
17 | button = TextStyle(
18 | fontFamily = FontFamily.Default,
19 | fontWeight = FontWeight.W500,
20 | fontSize = 14.sp
21 | ),
22 | caption = TextStyle(
23 | fontFamily = FontFamily.Default,
24 | fontWeight = FontWeight.Normal,
25 | fontSize = 12.sp
26 | )
27 | */
28 | )
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/features/KeysFeatureNames.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.features
2 |
3 | object KeysFeatureNames {
4 | const val FEATURE_MAP = "Screen-Map"
5 | const val FEATURE_RESULT = "Screen-Result"
6 | const val FEATURE_PERMISSION = "Screen-Permission"
7 | }
8 |
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/features/map/domain/MapFragmentUseCases.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.features.map.domain
2 |
3 | import com.istudio.distancetracker.features.map.domain.usecases.CalculateResultUseCase
4 |
5 | data class MapFragmentUseCases (
6 | val calculateResult : CalculateResultUseCase
7 | )
8 |
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/features/map/domain/di/MapDomainModule.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.features.map.domain.di
2 |
3 | import com.istudio.core_logger.domain.LoggerFeature
4 | import com.istudio.distancetracker.features.map.domain.MapFragmentUseCases
5 | import com.istudio.distancetracker.features.map.domain.usecases.CalculateResultUseCase
6 | import dagger.Module
7 | import dagger.Provides
8 | import dagger.hilt.InstallIn
9 | import dagger.hilt.android.components.ViewModelComponent
10 | import dagger.hilt.android.scopes.ViewModelScoped
11 |
12 | @Module
13 | @InstallIn(ViewModelComponent::class)
14 | object MapDomainModule {
15 |
16 | @ViewModelScoped
17 | @Provides
18 | fun provideTrackerUseCases(logger: LoggerFeature ): MapFragmentUseCases {
19 | return MapFragmentUseCases(calculateResult = CalculateResultUseCase(log = logger))
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/features/map/domain/entities/inputs/CalculateResultInput.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.features.map.domain.entities.inputs
2 |
3 | import com.google.android.gms.maps.model.LatLng
4 |
5 | data class CalculateResultInput(
6 | val locationData: MutableList,
7 | val startTime: Long,
8 | val stopTime: Long
9 | )
10 |
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/features/map/domain/entities/outputs/CalculateResultOutput.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.features.map.domain.entities.outputs
2 |
3 | data class CalculateResultOutput( val distanceTravelled: String, val elapsedTime: String, )
4 |
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/features/map/events/EventMapStyleSelected.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.features.map.events
2 |
3 | data class EventMapStyleSelected(val selection : Int)
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/features/map/presentation/state/MapStates.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.features.map.presentation.state
2 |
3 | import com.google.android.gms.maps.model.LatLng
4 | import com.google.android.gms.maps.model.LatLngBounds
5 | import com.google.android.gms.maps.model.PolylineOptions
6 | import com.istudio.core_common.ui.uiEvent.UiText
7 | import com.istudio.distancetracker.features.map.domain.entities.outputs.CalculateResultOutput
8 |
9 | sealed class MapStates {
10 | //object OnSubmitClick : MapStates()
11 | data class ShowErrorMessage(val message: UiText) : MapStates()
12 | data class JourneyResult(val result: CalculateResultOutput) : MapStates()
13 | data class AnimateCamera(val location: LatLng) : MapStates()
14 | data class AnimateCameraForBiggerPitchure(val bounds: LatLngBounds, val padding:Int, val duration:Int) : MapStates()
15 |
16 | data class AddPolyline(val polyLine: PolylineOptions) : MapStates()
17 | data class FollowCurrentLocation(val location: LatLng, val duration:Int) : MapStates()
18 | data class AddMarker(val location: LatLng) : MapStates()
19 |
20 | object DisplayStartButton : MapStates()
21 | object DisableStopButton : MapStates()
22 |
23 | object LaunchInAppReview : MapStates()
24 | object CounterGoState : MapStates()
25 | object CounterFinishedState : MapStates()
26 | data class CounterCountDownState(val currentSecond: String) : MapStates()
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/features/map/util/AnimateCamera.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.features.map.util
2 |
3 | object AnimateCamera {
4 |
5 |
6 |
7 |
8 | }
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/features/map/util/FileOperations.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.features.map.util
2 |
3 | import android.app.RecoverableSecurityException
4 | import android.content.*
5 | import android.content.Context.MODE_PRIVATE
6 | import android.graphics.Bitmap
7 | import android.graphics.Bitmap.CompressFormat
8 | import android.graphics.BitmapFactory
9 | import android.net.Uri
10 | import android.os.Build
11 | import android.os.Environment
12 | import android.provider.MediaStore
13 | import android.util.Log
14 | import androidx.annotation.RequiresApi
15 | import com.example.feat_gallery.presentation.models.InternalStoragePhoto
16 | import com.istudio.distancetracker.R
17 | import kotlinx.coroutines.Dispatchers
18 | import kotlinx.coroutines.withContext
19 | import java.io.File
20 | import java.io.FileOutputStream
21 | import java.io.IOException
22 | import java.util.UUID
23 |
24 |
25 | private const val TAG = "FileOperations"
26 | private const val QUALITY = 100
27 |
28 | object FileOperations {
29 |
30 | fun savePhotoToInternalStorage(context: Context,bitmap:Bitmap) : Boolean{
31 | return try {
32 | val fileName =UUID.randomUUID().toString()
33 | context.openFileOutput("$fileName.jpg", MODE_PRIVATE).use { stream ->
34 | if(!bitmap.compress(Bitmap.CompressFormat.JPEG, 95, stream)) {
35 | throw IOException("Couldn't save bitmap.")
36 | }
37 | }
38 | true
39 | }catch (ex:Exception){
40 | ex.printStackTrace()
41 | false
42 | }
43 | }
44 |
45 | }
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/features/map/util/MapUtil.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.features.map.util
2 |
3 | import com.google.android.gms.maps.model.CameraPosition
4 | import com.google.android.gms.maps.model.LatLng
5 | import com.google.maps.android.SphericalUtil
6 | import java.text.DecimalFormat
7 |
8 | object MapUtil {
9 |
10 | fun setCameraPosition(location: LatLng): CameraPosition {
11 | return CameraPosition.Builder()
12 | .target(location)
13 | .zoom(18f)
14 | .build()
15 | }
16 |
17 | fun calculateTheDistance(locationList: MutableList): String {
18 | val firstPoint = locationList.first()
19 | val lastPoint = locationList.last()
20 |
21 | if(locationList.size > 1){
22 | // Meters
23 | val meters = SphericalUtil.computeDistanceBetween(firstPoint,lastPoint)
24 | // Kilometers
25 | val kilometers = meters / 1000
26 | return DecimalFormat("#.##").format(kilometers)
27 | }
28 | return "0.00"
29 | }
30 |
31 | }
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/features/permission/presentation/state/PermissionStates.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.features.permission.presentation.state
2 |
3 | sealed class PermissionStates {
4 | //object OnSubmitClick : MapStates()
5 | //data class ShowErrorMessage(val message: UiText) : PermissionStates()
6 | object NavigateToMapsScreen : PermissionStates()
7 | object RuntimeLocationPermission : PermissionStates()
8 | }
9 |
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/features/permission/presentation/vm/PermissionVm.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.features.permission.presentation.vm
2 |
3 | import androidx.lifecycle.viewModelScope
4 | import com.demo.core_permission.domain.PermissionFeature
5 | import com.istudio.core_common.base.BaseViewModel
6 | import com.istudio.core_logger.domain.LoggerFeature
7 | import com.istudio.distancetracker.features.permission.presentation.state.PermissionStates
8 | import dagger.hilt.android.lifecycle.HiltViewModel
9 | import kotlinx.coroutines.channels.Channel
10 | import kotlinx.coroutines.flow.receiveAsFlow
11 | import kotlinx.coroutines.launch
12 | import javax.inject.Inject
13 |
14 | @HiltViewModel
15 | class PermissionVm @Inject constructor(
16 | private var log: LoggerFeature,
17 | var permissionRepository: PermissionFeature
18 | ) : BaseViewModel() {
19 |
20 | /**
21 | * Using channel: We can notify the fragment to make fragment do something
22 | * Fragment should not be able to add values into the channel instead it should only be able to take value from the channel
23 | * Turning into the flow, the fragment can't put anything into it
24 | */
25 | private val _eventChannel = Channel()
26 | val events = _eventChannel.receiveAsFlow()
27 |
28 |
29 | fun initiateLocationFlow() {
30 | if (permissionRepository.hasLocationPermission()) {
31 | viewModelScope.launch {
32 | _eventChannel.send(PermissionStates.NavigateToMapsScreen)
33 | }
34 | } else {
35 | viewModelScope.launch {
36 | _eventChannel.send(PermissionStates.RuntimeLocationPermission)
37 | }
38 | }
39 | }
40 |
41 |
42 | override fun onCleared() {
43 | super.onCleared()
44 | _eventChannel.cancel()
45 | }
46 |
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/main/presentation/state/MainEvent.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.main.presentation.state
2 |
3 |
4 | sealed class MainEvent {
5 | data class ShowErrorMessage(val error: Throwable) : MainEvent()
6 | data class GetTrackerConstantsApiCall(val isSuccess: Boolean) : MainEvent()
7 | object SplashSuccessful : MainEvent()
8 | }
9 |
--------------------------------------------------------------------------------
/Application/app/src/main/java/com/istudio/distancetracker/model/Result.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker.model
2 |
3 | import android.os.Parcelable
4 | import androidx.annotation.Keep
5 | import kotlinx.parcelize.Parcelize
6 |
7 | @Parcelize
8 | @Keep
9 | data class Result(
10 | var distance: String,
11 | var time: String
12 | ): Parcelable
--------------------------------------------------------------------------------
/Application/app/src/main/res/drawable/custom_marker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/app/src/main/res/drawable/custom_marker.png
--------------------------------------------------------------------------------
/Application/app/src/main/res/drawable/ic_app_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/app/src/main/res/drawable/ic_app_launcher.png
--------------------------------------------------------------------------------
/Application/app/src/main/res/drawable/ic_app_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/app/src/main/res/drawable/ic_app_launcher_round.png
--------------------------------------------------------------------------------
/Application/app/src/main/res/drawable/ic_baseline_arrow_forward.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Application/app/src/main/res/drawable/ic_close.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Application/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Application/app/src/main/res/drawable/ic_reset.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/Application/app/src/main/res/drawable/ic_run.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/Application/app/src/main/res/drawable/ic_share.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/Application/app/src/main/res/drawable/ic_splash.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Application/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
22 |
--------------------------------------------------------------------------------
/Application/app/src/main/res/layout/fragment_distance_log.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
13 |
14 |
--------------------------------------------------------------------------------
/Application/app/src/main/res/layout/fragment_map.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Application/app/src/main/res/layout/include_cust_error_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
18 |
19 |
26 |
27 |
35 |
36 |
41 |
42 |
47 |
48 |
--------------------------------------------------------------------------------
/Application/app/src/main/res/layout/include_cust_master_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
20 |
21 |
31 |
32 |
--------------------------------------------------------------------------------
/Application/app/src/main/res/raw/map_light_mode.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/Application/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Distance Tracker
3 |
4 | App successfully updated
5 | It was not possible to update your app
6 | App update cancelled
7 |
8 |
--------------------------------------------------------------------------------
/Application/app/src/test/java/com/istudio/distancetracker/ExampleUnitNetworkUtils.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.distancetracker
2 |
3 | import org.junit.Assert.assertEquals
4 | import org.junit.Test
5 |
6 | /**
7 | * Example local unit test, which will execute on the development machine (host).
8 | *
9 | * See [testing documentation](http://d.android.com/tools/testing).
10 | */
11 | class ExampleUnitNetworkUtils {
12 | @Test
13 | fun addition_isCorrect() {
14 | assertEquals(4, 2 + 2)
15 | }
16 | }
--------------------------------------------------------------------------------
/Application/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 | maven("https://plugins.gradle.org/m2/")
7 | }
8 | dependencies {
9 | classpath(Build.androidBuildTools)
10 | classpath(Build.hiltAndroidGradlePlugin)
11 | classpath(Build.kotlinGradlePlugin)
12 | classpath(Build.googleServicesGradlePlugin)
13 | classpath(Build.crashlyticsPlugin)
14 | classpath(Build.ktLintPlugin)
15 | classpath(Build.navSafeArgs)
16 | classpath(Build.secretsGradle)
17 | classpath(Build.spotlessPlugin)
18 | classpath(kotlin(Build.gradlePlugin, version = Kotlin.version))
19 | classpath(kotlin(Build.kotlinSerialization, version = Kotlin.version))
20 | // NOTE: Do not place your application dependencies here; they belong
21 | // in the individual module build.gradle files
22 | }
23 | }
24 |
25 | subprojects {
26 | apply(plugin = Build.BuildPlugins.ktLint) // Version should be inherited from parent
27 | apply(plugin = Build.BuildPlugins.spotless) // Version should be inherited from parent
28 |
29 | repositories {
30 | google()
31 | mavenCentral()
32 | // Required to download KtLint
33 | maven("https://plugins.gradle.org/m2/")
34 | }
35 |
36 | // Optionally configure plugin
37 | configure { debug.set(true) }
38 | }
39 |
40 | tasks.register("clean", Delete::class) {
41 | delete(rootProject.buildDir)
42 | }
--------------------------------------------------------------------------------
/Application/buildSrc/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | build
--------------------------------------------------------------------------------
/Application/buildSrc/build.gradle.kts:
--------------------------------------------------------------------------------
1 | repositories {
2 | mavenCentral()
3 | }
4 |
5 | plugins {
6 | `kotlin-dsl`
7 | }
--------------------------------------------------------------------------------
/Application/buildSrc/scripts/spotless.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.diffplug.spotless"
2 |
3 | spotless {
4 | java {
5 | target '**/*.java'
6 | googleJavaFormat().aosp()
7 | removeUnusedImports()
8 | trimTrailingWhitespace()
9 | indentWithSpaces()
10 | endWithNewline()
11 | }
12 | kotlin {
13 | target '**/*.kt'
14 | ktlint()
15 | trimTrailingWhitespace()
16 | indentWithSpaces()
17 | endWithNewline()
18 | }
19 | format 'misc', {
20 | target '**/*.gradle', '**/*.md', '**/.gitignore'
21 | indentWithSpaces()
22 | trimTrailingWhitespace()
23 | endWithNewline()
24 | }
25 |
26 | format 'xml', {
27 | target '**/*.xml'
28 | indentWithSpaces()
29 | trimTrailingWhitespace()
30 | endWithNewline()
31 | }
32 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/Accompanist.kt:
--------------------------------------------------------------------------------
1 | object Accompanist {
2 | private const val accompanistPagerVersion = "0.24.2-alpha"
3 | const val accompanistPager = "com.google.accompanist:accompanist-pager:$accompanistPagerVersion"
4 | const val accompanistPagerIndicators = "com.google.accompanist:accompanist-pager-indicators:$accompanistPagerVersion"
5 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/AndroidX.kt:
--------------------------------------------------------------------------------
1 | object AndroidX {
2 | private const val coreKtxVersion = "1.7.0"
3 | const val coreKtx = "androidx.core:core-ktx:$coreKtxVersion"
4 |
5 | private const val appCompatVersion = "1.4.0"
6 | const val appCompat = "androidx.appcompat:appcompat:$appCompatVersion"
7 |
8 | private const val constraintVersion = "2.0.4"
9 | const val constraint = "com.android.support.constraint:constraint-layout:$constraintVersion"
10 |
11 | private const val cardViewVersion = "1.0.0"
12 | const val cardView = "androidx.cardview:cardview:$cardViewVersion"
13 |
14 | private const val fragmentVersion = "1.4.1"
15 | const val fragment = "androidx.fragment:fragment:$fragmentVersion"
16 |
17 | private const val fragmentKtxVersion = "1.4.1"
18 | const val fragmentKtx = "androidx.fragment:fragment-ktx:$fragmentKtxVersion"
19 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/Coil.kt:
--------------------------------------------------------------------------------
1 | object Coil {
2 | private const val version = "1.3.2"
3 | const val coilCompose = "io.coil-kt:coil-compose:$version"
4 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/Compose.kt:
--------------------------------------------------------------------------------
1 | object Compose {
2 | const val composeVersion = "1.3.0"
3 | const val composeCompilerVersion = "1.3.2"
4 | const val material = "androidx.compose.material:material:$composeVersion"
5 | const val ui = "androidx.compose.ui:ui:$composeVersion"
6 | const val uiTooling = "androidx.compose.ui:ui-tooling:$composeVersion"
7 | const val uiToolingPreview = "androidx.compose.ui:ui-tooling-preview:$composeVersion"
8 | const val runtime = "androidx.compose.runtime:runtime:$composeVersion"
9 | const val compiler = "androidx.compose.compiler:compiler:$composeCompilerVersion"
10 |
11 | private const val navigationVersion = "2.5.0"
12 | const val navigation = "androidx.navigation:navigation-compose:$navigationVersion"
13 |
14 | private const val hiltNavigationComposeVersion = "1.0.0"
15 | const val hiltNavigationCompose = "androidx.hilt:hilt-navigation-compose:$hiltNavigationComposeVersion"
16 |
17 | private const val activityComposeVersion = "1.5.0"
18 | const val activityCompose = "androidx.activity:activity-compose:$activityComposeVersion"
19 |
20 | private const val lifecycleVersion = "2.5.0"
21 | const val viewModelCompose = "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycleVersion"
22 | }
23 |
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/Coroutines.kt:
--------------------------------------------------------------------------------
1 | object Coroutines {
2 | const val version = "1.6.0"
3 | const val versionCoroutinesCoreKtx = "1.3.2"
4 | const val coroutineLib = "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version"
5 | const val coroutinesKtx = "androidx.core:core-ktx:$versionCoroutinesCoreKtx"
6 | const val coroutineAndroidLib = "org.jetbrains.kotlinx:kotlinx-coroutines-android:$version"
7 | const val coroutinePlayServicesLib = "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$version"
8 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/CustomLogging.kt:
--------------------------------------------------------------------------------
1 | object CustomLogging {
2 | private const val timberVersion = "5.0.1"
3 | private const val orhanobutVersion = "2.2.0"
4 | const val timber = "com.jakewharton.timber:timber:$timberVersion"
5 | const val orhanobut = "com.orhanobut:logger:$orhanobutVersion"
6 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/DaggerHilt.kt:
--------------------------------------------------------------------------------
1 | object DaggerHilt {
2 | const val version = "2.44"
3 | const val hiltAndroid = "com.google.dagger:hilt-android:$version"
4 | const val hiltCompiler = "com.google.dagger:hilt-android-compiler:$version"
5 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/DataStorePreferences.kt:
--------------------------------------------------------------------------------
1 | object DataStorePreferences {
2 | private const val datastorePreferencesVersion = "1.0.0"
3 | const val datastorePreferences = "androidx.datastore:datastore-preferences:$datastorePreferencesVersion"
4 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/Firebase.kt:
--------------------------------------------------------------------------------
1 | object Firebase {
2 | private const val firebaseBomVersion = "30.2.0"
3 | const val googleFirebase = "com.google.firebase:firebase-bom:$firebaseBomVersion"
4 | const val firebaseAnalyticsKtx = "com.google.firebase:firebase-analytics-ktx"
5 |
6 | const val firebaseKtx = "com.google.firebase:firebase-common-ktx"
7 | const val firebaseDatabaseKtx = "com.google.firebase:firebase-database-ktx"
8 | const val firebaseAnalytics = "com.google.firebase:firebase-analytics"
9 | const val firebaseCrashlyticsKtx = "com.google.firebase:firebase-crashlytics-ktx"
10 | const val firebaseAuthKtx = "com.google.firebase:firebase-auth-ktx"
11 |
12 | const val firebaseFirestoreKtx = "com.google.firebase:firebase-firestore-ktx"
13 | const val firebaseStorageKtx = "com.google.firebase:firebase-storage-ktx"
14 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/FlavourUtils.kt:
--------------------------------------------------------------------------------
1 | object FlavourUtils {
2 | object BuildTypes {
3 | const val DEBUG = "debug"
4 | const val RELEASE = "release"
5 | }
6 |
7 | object ProductFlavors {
8 | const val DEV = "dev"
9 | const val PUBLIC = "prod"
10 | }
11 |
12 | object FlavorDimensions {
13 | const val DEFAULT = "default"
14 | }
15 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/Glide.kt:
--------------------------------------------------------------------------------
1 | object Glide {
2 | private const val glideVersion = "4.13.2"
3 | const val glideLibrary = "com.github.bumptech.glide:glide:$glideVersion"
4 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/Google.kt:
--------------------------------------------------------------------------------
1 | object Google {
2 | private const val materialVersion = "1.4.0"
3 | private const val playCoreVersion = "1.10.3"
4 | const val material = "com.google.android.material:material:$materialVersion"
5 | const val playCore = "com.google.android.play:core:$playCoreVersion"
6 | const val playCoreKtx = "com.google.android.play:core-ktx:$playCoreVersion"
7 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/Gson.kt:
--------------------------------------------------------------------------------
1 | object Gson {
2 | private const val gsonVersion = "2.10"
3 | const val gson = "com.google.code.gson:gson:$gsonVersion"
4 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/Kotlin.kt:
--------------------------------------------------------------------------------
1 | object Kotlin {
2 | const val version = "1.7.10"
3 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/KotlinSerialization.kt:
--------------------------------------------------------------------------------
1 | object KotlinSerialization {
2 | private const val kotlinSerializationJsonVersion = "1.4.1"
3 | const val kotlinSerializationJson = "org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinSerializationJsonVersion"
4 | private const val kotlinSerializationConverterVersion = "0.8.0"
5 | const val kotlinSerializationConverter = "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:$kotlinSerializationConverterVersion"
6 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/LifeCycle.kt:
--------------------------------------------------------------------------------
1 | object LifeCycle {
2 | private const val lifecycleExtensionsVersion = "2.2.0"
3 | const val lifecycleExtensions = "androidx.lifecycle:lifecycle-extensions:$lifecycleExtensionsVersion"
4 |
5 | private const val lifecycleLiveDataVersion = "2.5.1"
6 | const val lifecycleLiveData = "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycleLiveDataVersion"
7 |
8 | private const val lifecycleRuntimeKtxVersion = ":2.4.0"
9 | const val lifecycleRuntimeKtx = "androidx.lifecycle:lifecycle-runtime-ktx$lifecycleRuntimeKtxVersion"
10 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/Lotte.kt:
--------------------------------------------------------------------------------
1 | object Lotte {
2 | private const val lotteVersion = "5.2.0"
3 | const val lotteAnimation = "com.airbnb.android:lottie:$lotteVersion"
4 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/Maps.kt:
--------------------------------------------------------------------------------
1 | object Maps {
2 |
3 | private const val playServicesLocationVersion = "21.0.1"
4 | const val playServicesLocation = "com.google.android.gms:play-services-location:$playServicesLocationVersion"
5 |
6 | private const val androidMapsUtilsVersion = "2.2.0"
7 | const val androidMapsUtils = "com.google.maps.android:android-maps-utils:$androidMapsUtilsVersion"
8 |
9 | private const val playServicesMapsVersion = "18.1.0"
10 | const val playServicesMaps = "com.google.android.gms:play-services-maps:$playServicesMapsVersion"
11 |
12 |
13 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/Modules.kt:
--------------------------------------------------------------------------------
1 | object Modules {
2 | const val app = ":app"
3 | const val core = ":core"
4 | const val features = ":features"
5 | const val corePreferences = ":core:core-preferences"
6 | const val coreUi = ":core:core-ui"
7 | const val coreCommon = ":core:core-common"
8 | const val coreLogger = ":core:core-logger"
9 | const val coreLocation = ":core:core-location"
10 | const val coreConnectivity = ":core:core-connectivity"
11 | const val coreDatabase = ":core:core-database"
12 | const val corePermission = ":core:core-permission"
13 | const val coreNetwork = ":core:core-network"
14 | const val coreModels = ":core:core-models"
15 | const val featInAppReview = ":features:feat-inappreview"
16 | const val featRepository = ":features:feat-repository"
17 | const val featGallery = ":features:feat-gallery"
18 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/Moshi.kt:
--------------------------------------------------------------------------------
1 | object Moshi {
2 | private const val version = "1.13.0"
3 | const val moshiRepo = "com.squareup.moshi:moshi:$version"
4 | const val moshiCodegen = "com.squareup.moshi:moshi-kotlin-codegen:$version"
5 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/Navigation.kt:
--------------------------------------------------------------------------------
1 | object Navigation {
2 | private const val navigationVersion = "2.5.3"
3 | const val navigationFragmentKtx = "androidx.navigation:navigation-fragment-ktx:$navigationVersion"
4 | const val navigationUiKtx = "androidx.navigation:navigation-ui-ktx:$navigationVersion"
5 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/Permission.kt:
--------------------------------------------------------------------------------
1 | object Permission {
2 | private const val permissionVersion = "1.7.1"
3 | const val customPermission = "com.guolindev.permissionx:permissionx:$permissionVersion"
4 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/ProjectConfig.kt:
--------------------------------------------------------------------------------
1 | object ProjectConfig {
2 | const val appId = "com.istudio.distancetracker"
3 | const val compileSdk = 33
4 | const val minSdk = 21
5 | const val targetSdk = 33
6 | const val majorVersion = 1
7 | const val minorVersion = 1
8 | const val patchVersion = 0
9 | const val versionName = "$majorVersion.$minorVersion.$patchVersion"
10 | const val versionCode = 20
11 | const val jvmTarget = "1.8"
12 | const val testRunner = "com.istudio.distancetracker.TestRunner"
13 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/Retrofit.kt:
--------------------------------------------------------------------------------
1 | object Retrofit {
2 | private const val version = "2.9.0"
3 | const val retrofit = "com.squareup.retrofit2:retrofit:$version"
4 | const val moshiConverter = "com.squareup.retrofit2:converter-moshi:$version"
5 | const val gsonConverter = "com.squareup.retrofit2:converter-gson:$version"
6 |
7 | private const val okHttpVersion = "4.10.0"
8 | const val okHttp = "com.squareup.okhttp3:okhttp:$okHttpVersion"
9 | const val okHttpLoggingInterceptor = "com.squareup.okhttp3:logging-interceptor:$okHttpVersion"
10 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/Room.kt:
--------------------------------------------------------------------------------
1 | object Room {
2 | private const val version = "2.5.0-rc01"
3 | const val roomRuntime = "androidx.room:room-runtime:$version"
4 | const val roomCompiler = "androidx.room:room-compiler:$version"
5 | const val roomKtx = "androidx.room:room-ktx:$version"
6 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/ScriptPlugins.kt:
--------------------------------------------------------------------------------
1 | object ScriptPlugins {
2 | const val infrastructure = "scripts.infrastructure"
3 | const val variants = "scripts.variants"
4 | const val quality = "scripts.quality"
5 | const val compilation = "scripts.compilation"
6 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/SplashScreen.kt:
--------------------------------------------------------------------------------
1 | object SplashScreen {
2 | // In Android-11 and above, its automatically provided but for backward compatibility, we include this
3 | private const val version = "1.0.0-rc01"
4 | const val splashAndroidApi = "androidx.core:core-splashscreen:$version"
5 | }
--------------------------------------------------------------------------------
/Application/buildSrc/src/main/java/SqlDelight.kt:
--------------------------------------------------------------------------------
1 | object SqlDelight {
2 | private const val version = "1.5.2"
3 | const val repo = "com.squareup.sqldelight:gradle-plugin:$version"
4 | }
--------------------------------------------------------------------------------
/Application/core/core-common/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/Application/core/core-common/build.gradle.kts:
--------------------------------------------------------------------------------
1 | apply {
2 | from("$rootDir/base-module.gradle")
3 | }
4 |
5 | dependencies {
6 | // "implementation"(project(Modules.core))
7 | "implementation"(Coroutines.coroutineLib)
8 | }
9 |
--------------------------------------------------------------------------------
/Application/core/core-common/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-common/consumer-rules.pro
--------------------------------------------------------------------------------
/Application/core/core-common/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.
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/core/core-common/src/androidTest/java/com/istudio/core_common/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4
4 | import androidx.test.platform.app.InstrumentationRegistry
5 | import org.junit.Assert.*
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | /**
10 | * Instrumented test, which will execute on an Android device.
11 | *
12 | * See [testing documentation](http://d.android.com/tools/testing).
13 | */
14 | @RunWith(AndroidJUnit4::class)
15 | class ExampleInstrumentedTest {
16 | @Test
17 | fun useAppContext() {
18 | // Context of the app under test.
19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
20 | assertEquals("com.istudio.core_common.test", appContext.packageName)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/base/BaseViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.base
2 |
3 | import androidx.lifecycle.ViewModel
4 |
5 | open class BaseViewModel : ViewModel()
6 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/constants/DbConstants.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.constants
2 |
3 | object DbConstants {
4 |
5 | const val TABLE_NAME_DISTANCE_TRACKER_CONSTANTS = "distance_tracker_constants"
6 |
7 | }
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/di/modules/CoroutineModule.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.di.modules
2 |
3 | import com.istudio.core_common.di.qualifiers.DefaultDispatcher
4 | import com.istudio.core_common.di.qualifiers.IoDispatcher
5 | import com.istudio.core_common.di.qualifiers.MainDispatcher
6 | import dagger.Module
7 | import dagger.Provides
8 | import dagger.hilt.InstallIn
9 | import dagger.hilt.components.SingletonComponent
10 | import kotlinx.coroutines.CoroutineDispatcher
11 | import kotlinx.coroutines.Dispatchers
12 |
13 | @Module
14 | @InstallIn(SingletonComponent::class)
15 | object CoroutineModule {
16 |
17 | @DefaultDispatcher
18 | @Provides
19 | fun providesDefaultDispatcher(): CoroutineDispatcher = Dispatchers.Default
20 |
21 | @IoDispatcher
22 | @Provides
23 | fun providesIoDispatcher(): CoroutineDispatcher = Dispatchers.IO
24 |
25 | @MainDispatcher
26 | @Provides
27 | fun providesMainDispatcher(): CoroutineDispatcher = Dispatchers.Main
28 | }
29 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/di/qualifiers/Dispatchers.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.di.qualifiers
2 |
3 | import javax.inject.Qualifier
4 |
5 | @Retention(AnnotationRetention.BINARY)
6 | @Qualifier
7 | annotation class DefaultDispatcher
8 |
9 | @Retention(AnnotationRetention.BINARY)
10 | @Qualifier
11 | annotation class IoDispatcher
12 |
13 | @Retention(AnnotationRetention.BINARY)
14 | @Qualifier
15 | annotation class MainDispatcher
16 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/extensions/Activity.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.extensions
2 |
3 | import android.app.Activity
4 | import android.content.Context
5 | import android.content.Intent
6 |
7 | /**
8 | * What it does: Starts a activity
9 | * Source: https://stackoverflow.com/a/57925521/1083093
10 | */
11 | inline fun Context.startActivity(block: Intent.() -> Unit = {}) {
12 | startActivity(Intent(this, T::class.java).apply(block))
13 | }
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/extensions/Channels.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.extensions
2 |
3 | // Forcing compiler to treat as expression
4 | val T.exhaustive: T
5 | get() = this
6 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/extensions/Context.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.extensions
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.net.ConnectivityManager
6 | import android.net.Uri
7 | import android.os.Build
8 | import android.provider.Settings
9 | import android.widget.Toast
10 | import androidx.annotation.StringRes
11 |
12 | val Context.connectivityManager: ConnectivityManager
13 | get() =
14 | this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
15 |
16 | fun Context.openAppNotificationSettings() {
17 | val intent = Intent().apply {
18 | when {
19 | Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
20 | action = Settings.ACTION_LOCATION_SOURCE_SETTINGS
21 | putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
22 | }
23 | else -> {
24 | action = Settings.ACTION_LOCATION_SOURCE_SETTINGS
25 | addCategory(Intent.CATEGORY_DEFAULT)
26 | data = Uri.parse("package:$packageName")
27 | }
28 | }
29 | }
30 | startActivity(intent)
31 | }
32 |
33 | fun Context.toast(message: String, duration: Int = Toast.LENGTH_SHORT) {
34 | Toast.makeText(this, message, duration).show()
35 | }
36 |
37 | fun Context.toast(@StringRes resId: Int, duration: Int = Toast.LENGTH_SHORT) {
38 | Toast.makeText(this, this.resources.getText(resId), duration).show()
39 | }
40 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/extensions/SnackBarDisplay.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.extensions
2 |
3 | import android.view.View
4 | import android.widget.TextView
5 | import androidx.core.content.ContextCompat
6 | import com.google.android.material.snackbar.Snackbar
7 | import com.istudio.core_common.R
8 | import kotlin.concurrent.timer
9 |
10 | object SnackBarDisplay {
11 |
12 | private var snackbar: Snackbar? = null
13 |
14 | fun showNetworkUnavailableAlert(view: View) {
15 | snackbar = Snackbar.make(view, R.string.network_is_unavailable, Snackbar.LENGTH_INDEFINITE)
16 | .setActionTextColor(ContextCompat.getColor(view.context, R.color.white))
17 | snackbar?.let {
18 | val snackBarView: View = it.view
19 | snackBarView.setBackgroundColor(ContextCompat.getColor(view.context, R.color.colorRed))
20 | }
21 | snackbar?.show()
22 | }
23 |
24 | fun removeNetworkUnavailableAlert() {
25 | snackbar?.let {
26 | val view: View = it.view
27 | val snackBarText = view.findViewById(com.google.android.material.R.id.snackbar_text) as TextView
28 | snackBarText.text = view.context.resources.getText(R.string.network_is_available)
29 | view.setBackgroundColor(ContextCompat.getColor(view.context, R.color.colorGreen))
30 | timer(initialDelay = 1000L, period = 1000L) { it.dismiss() }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/extensions/Snackbar.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.extensions
2 |
3 | import android.view.View
4 | import androidx.annotation.StringRes
5 | import androidx.core.content.ContextCompat
6 | import androidx.fragment.app.Fragment
7 | import com.google.android.material.snackbar.Snackbar
8 |
9 | fun Fragment.showSnackbar(
10 | message: String,
11 | duration: Int = Snackbar.LENGTH_LONG,
12 | view: View = requireView()
13 | ) {
14 | Snackbar.make(view, message, duration).show()
15 | }
16 |
17 | inline fun View.snack(@StringRes messageRes: Int, length: Int = Snackbar.LENGTH_LONG, f: Snackbar.() -> Unit) {
18 | snack(resources.getString(messageRes), length, f)
19 | }
20 |
21 | inline fun View.snack(message: String, length: Int = Snackbar.LENGTH_LONG, f: Snackbar.() -> Unit) {
22 | val snack = Snackbar.make(this, message, length)
23 | snack.f()
24 | snack.show()
25 | }
26 |
27 | fun Snackbar.action(@StringRes actionRes: Int, color: Int? = null, listener: (View) -> Unit) {
28 | action(view.resources.getString(actionRes), color, listener)
29 | }
30 |
31 | fun Snackbar.action(action: String, color: Int? = null, listener: (View) -> Unit) {
32 | setAction(action, listener)
33 | color?.let { setActionTextColor(ContextCompat.getColor(context, color)) }
34 | }
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/extensions/Tag.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.extensions
2 |
3 | import android.os.Build
4 |
5 | val Any.TAG: String
6 | get() {
7 | return if (!javaClass.isAnonymousClass) {
8 | val name = javaClass.simpleName
9 | if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) name else
10 | name.substring(0, 23)// first 23 chars
11 | } else {
12 | val name = javaClass.name
13 | if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
14 | name else name.substring(name.length - 23, name.length)// last 23 chars
15 | }
16 | }
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/functional/PublisherEventBus.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.functional
2 |
3 | import kotlinx.coroutines.GlobalScope.coroutineContext
4 | import kotlinx.coroutines.ensureActive
5 | import kotlinx.coroutines.flow.MutableSharedFlow
6 | import kotlinx.coroutines.flow.asSharedFlow
7 | import kotlinx.coroutines.flow.collectLatest
8 | import kotlinx.coroutines.flow.filterIsInstance
9 |
10 | object PublisherEventBus {
11 | private val _events = MutableSharedFlow()
12 | val events = _events.asSharedFlow()
13 |
14 | suspend fun publish(event: Any) {
15 | _events.emit(event)
16 | }
17 |
18 | suspend inline fun subscribe(crossinline onEvent: (T) -> Unit) {
19 | events.filterIsInstance()
20 | .collectLatest { event ->
21 | coroutineContext.ensureActive()
22 | onEvent(event)
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/functional/Resource.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.functional
2 |
3 | /**
4 | * By making a class a sealed class, We will be telling the compiler that only the sub-classes possible are the ones that we can put in here
5 | * ***
6 | * On comparing when with sealed class: -> When condition will have a else case but a sealed class already knows the number of conditions it has so there is no scenario of else condition
7 | */
8 | sealed class Resource(
9 | val data: T? = null,
10 | val error: Throwable? = null
11 | ) {
12 | class Success(data: T) : Resource(data)
13 | class Loading(data: T? = null) : Resource(data)
14 | class Error(throwable: Throwable, data: T? = null) : Resource(data, throwable)
15 | }
16 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/functional/State.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.functional
2 |
3 | sealed class State {
4 | class Loading : State()
5 | data class Success(val data: T) : State()
6 | data class Failed(val message: String) : State()
7 |
8 | companion object {
9 | fun loading() = Loading()
10 | fun success(data: T) = Success(data)
11 | fun failed(message: String) = Failed(message)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/functional/SuspendUseCase.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.functional
2 |
3 | import kotlinx.coroutines.CoroutineDispatcher
4 | import kotlinx.coroutines.withContext
5 |
6 | /**
7 | * Executes business logic synchronously or asynchronously using Coroutines.
8 | *
9 | * The [execute] method of [SuspendUseCase] is a suspend function as opposed to the
10 | * [UseCase.execute] method of [UseCase].
11 | */
12 |
13 | // fixme: export it into share module
14 | abstract class SuspendUseCase(private val coroutineDispatcher: CoroutineDispatcher) {
15 |
16 | /** Executes the use case asynchronously and returns a [UseCaseResult].
17 | *
18 | * @return a [UseCaseResult].
19 | *
20 | * @param parameters the input parameters to run the use case with
21 | */
22 | val tag: String = this.javaClass.simpleName
23 |
24 | suspend operator fun invoke(parameters: P): UseCaseResult {
25 | return try {
26 | // Moving all use case's executions to the injected dispatcher
27 | // In production code, this is usually the Default dispatcher (background thread)
28 | // In tests, this becomes a TestCoroutineDispatcher
29 | withContext(coroutineDispatcher) {
30 | execute(parameters).let {
31 | UseCaseResult.Success(it)
32 | }
33 | }
34 | } catch (e: Exception) {
35 | UseCaseResult.Error(e)
36 | }
37 | }
38 |
39 | /**
40 | * Override this to set the code to be executed.
41 | */
42 | @Throws(RuntimeException::class)
43 | protected abstract suspend fun execute(parameters: P): R
44 | }
45 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/functional/UseCaseResult.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.functional
2 |
3 | import androidx.lifecycle.MutableLiveData
4 | import kotlinx.coroutines.flow.MutableStateFlow
5 |
6 | /**
7 | * A generic class that holds a value with its loading status.
8 | * @param
9 | */
10 | sealed class UseCaseResult {
11 |
12 | data class Success(val value: T) : UseCaseResult()
13 | data class Error(val exception: Exception) : UseCaseResult()
14 | object Loading : UseCaseResult()
15 |
16 | override fun toString(): String {
17 | return when (this) {
18 | is Success<*> -> "Success[data=$value]"
19 | is Error -> "Error[exception=$exception]"
20 | Loading -> "Loading"
21 | }
22 | }
23 | }
24 |
25 | /**
26 | * [Success.value] if [UseCaseResult] is of type [Success]
27 | */
28 | fun UseCaseResult.successOr(fallback: T): T {
29 | return (this as? UseCaseResult.Success)?.value ?: fallback
30 | }
31 |
32 | val UseCaseResult.data: T?
33 | get() = (this as? UseCaseResult.Success)?.value
34 |
35 | /**
36 | * Updates value of [liveData] if [UseCaseResult] is of type [Success]
37 | */
38 | inline fun UseCaseResult.updateOnSuccess(liveData: MutableLiveData) {
39 | if (this is UseCaseResult.Success) {
40 | liveData.value = value
41 | }
42 | }
43 |
44 | /**
45 | * Updates value of [stateFlow] if [UseCaseResult] is of type [Success]
46 | */
47 | inline fun UseCaseResult.flowOnSuccess(stateFlow: MutableStateFlow) {
48 | if (this is UseCaseResult.Success) {
49 | stateFlow.value = value
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/network/NetworkHandler.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.network
2 |
3 | import android.content.Context
4 | import android.net.NetworkCapabilities
5 | import android.os.Build
6 | import com.istudio.core_common.extensions.connectivityManager
7 | import dagger.hilt.android.qualifiers.ApplicationContext
8 | import javax.inject.Inject
9 | import javax.inject.Singleton
10 |
11 | /**
12 | * Injectable class which returns information about the network connection state.
13 | */
14 | @Singleton
15 | open class NetworkHandler
16 | @Inject constructor(@ApplicationContext private val context: Context) {
17 | open fun isNetworkAvailable(): Boolean {
18 | val connectivityManager = context.connectivityManager
19 |
20 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
21 | val network = connectivityManager.activeNetwork ?: return false
22 | val activeNetwork =
23 | connectivityManager.getNetworkCapabilities(network) ?: return false
24 |
25 | return when {
26 | activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
27 | activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
28 | activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
29 | activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> true
30 | else -> false
31 | }
32 | } else {
33 | @Suppress("DEPRECATION") val networkInfo =
34 | connectivityManager.activeNetworkInfo ?: return false
35 | @Suppress("DEPRECATION")
36 | return networkInfo.isConnected
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/ui/uiEvent/UiEvent.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.ui.uiEvent
2 |
3 | sealed class UiEvent {
4 | object Success : UiEvent()
5 | object NavigateUp : UiEvent()
6 | data class ShowSnackbar(val message: UiText) : UiEvent()
7 | }
8 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/java/com/istudio/core_common/ui/uiEvent/UiText.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common.ui.uiEvent
2 |
3 | import android.content.Context
4 |
5 | sealed class UiText {
6 | data class DynamicString(val text: String) : UiText()
7 | data class StringResource(val resId: Int) : UiText()
8 |
9 | fun asString(context: Context): String {
10 | return when (this) {
11 | is DynamicString -> text
12 | is StringResource -> context.getString(resId)
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/res/layout/layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFFFF
4 | #FF0000
5 | #008000
6 | #000000
7 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Network connected
3 | Network connection is lost
4 |
--------------------------------------------------------------------------------
/Application/core/core-common/src/test/java/com/istudio/core_common/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_common
2 |
3 | import org.junit.Assert.assertEquals
4 | import org.junit.Test
5 |
6 | /**
7 | * Example local unit test, which will execute on the development machine (host).
8 | *
9 | * See [testing documentation](http://d.android.com/tools/testing).
10 | */
11 | class ExampleUnitTest {
12 | @Test
13 | fun addition_isCorrect() {
14 | assertEquals(4, 2 + 2)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Application/core/core-connectivity/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/Application/core/core-connectivity/build.gradle.kts:
--------------------------------------------------------------------------------
1 | apply {
2 | from("$rootDir/base-module.gradle")
3 | }
4 |
5 | dependencies {
6 | // "implementation"(project(Modules.core))
7 | // "implementation"(Coroutines.coroutineLib)
8 | }
9 |
--------------------------------------------------------------------------------
/Application/core/core-connectivity/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-connectivity/consumer-rules.pro
--------------------------------------------------------------------------------
/Application/core/core-connectivity/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.
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/core/core-connectivity/src/androidTest/java/com/istudio/core_connectivity/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_connectivity
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4
4 | import androidx.test.platform.app.InstrumentationRegistry
5 | import org.junit.Assert.*
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | /**
10 | * Instrumented test, which will execute on an Android device.
11 | *
12 | * See [testing documentation](http://d.android.com/tools/testing).
13 | */
14 | @RunWith(AndroidJUnit4::class)
15 | class ExampleInstrumentedTest {
16 | @Test
17 | fun useAppContext() {
18 | // Context of the app under test.
19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
20 | assertEquals("com.istudio.core_connectivity.test", appContext.packageName)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Application/core/core-connectivity/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Application/core/core-connectivity/src/main/java/com/istudio/core_connectivity/data/implementation/ConnectivityFeatureImpl.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_connectivity.data.implementation
2 |
3 | import android.content.Context
4 | import android.net.ConnectivityManager
5 | import android.net.NetworkCapabilities
6 | import android.os.Build
7 | import com.istudio.core_connectivity.domain.ConnectivityFeature
8 |
9 | class ConnectivityFeatureImpl(
10 | private val context: Context
11 | ) : ConnectivityFeature {
12 |
13 | override fun checkConnectivity(): Boolean {
14 | val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
15 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
16 | val nw = connectivityManager.activeNetwork ?: return false
17 | val actNw = connectivityManager.getNetworkCapabilities(nw) ?: return false
18 | return when {
19 | actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
20 | actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
21 | // for other device how are able to connect with Ethernet
22 | actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
23 | // for check internet over Bluetooth
24 | actNw.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> true
25 | else -> false
26 | }
27 | } else {
28 | return connectivityManager.activeNetworkInfo?.isConnected ?: false
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Application/core/core-connectivity/src/main/java/com/istudio/core_connectivity/di/ConnectivityModule.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_connectivity.di
2 |
3 | import android.content.Context
4 | import com.istudio.core_connectivity.data.implementation.ConnectivityFeatureImpl
5 | import com.istudio.core_connectivity.domain.ConnectivityFeature
6 | import dagger.Module
7 | import dagger.Provides
8 | import dagger.hilt.InstallIn
9 | import dagger.hilt.android.qualifiers.ApplicationContext
10 | import dagger.hilt.components.SingletonComponent
11 | import javax.inject.Singleton
12 |
13 | @Module
14 | @InstallIn(SingletonComponent::class)
15 | object ConnectivityModule {
16 |
17 | @Provides
18 | @Singleton
19 | fun provideConnectivityFeature(connectivityFeature: ConnectivityFeature) = connectivityFeature.checkConnectivity()
20 |
21 | @Provides
22 | @Singleton
23 | fun provideConnectivityImplementation(@ApplicationContext appContext: Context): ConnectivityFeature {
24 | return ConnectivityFeatureImpl(appContext)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Application/core/core-connectivity/src/main/java/com/istudio/core_connectivity/domain/ConnectivityFeature.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_connectivity.domain
2 |
3 | interface ConnectivityFeature {
4 | fun checkConnectivity(): Boolean
5 | }
6 |
--------------------------------------------------------------------------------
/Application/core/core-connectivity/src/test/java/com/istudio/core_connectivity/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_connectivity
2 |
3 | import org.junit.Assert.assertEquals
4 | import org.junit.Test
5 |
6 | /**
7 | * Example local unit test, which will execute on the development machine (host).
8 | *
9 | * See [testing documentation](http://d.android.com/tools/testing).
10 | */
11 | class ExampleUnitTest {
12 | @Test
13 | fun addition_isCorrect() {
14 | assertEquals(4, 2 + 2)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Application/core/core-database/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/Application/core/core-database/build.gradle.kts:
--------------------------------------------------------------------------------
1 | apply {
2 | from("$rootDir/base-module.gradle")
3 | }
4 |
5 | dependencies {
6 | // "implementation"(project(Modules.core))
7 | "implementation"(Room.roomKtx)
8 | "api"(Room.roomRuntime)
9 | "kapt"(Room.roomCompiler)
10 | "implementation"(Coroutines.coroutineLib)
11 | "implementation"(project(Modules.coreUi))
12 | "implementation"(project(Modules.coreModels))
13 | "implementation"(project(Modules.coreCommon))
14 | }
15 |
--------------------------------------------------------------------------------
/Application/core/core-database/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-database/consumer-rules.pro
--------------------------------------------------------------------------------
/Application/core/core-database/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.
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/core/core-database/src/androidTest/java/com/istudio/core_database/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_database
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4
4 | import androidx.test.platform.app.InstrumentationRegistry
5 | import org.junit.Assert.*
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | /**
10 | * Instrumented test, which will execute on an Android device.
11 | *
12 | * See [testing documentation](http://d.android.com/tools/testing).
13 | */
14 | @RunWith(AndroidJUnit4::class)
15 | class ExampleInstrumentedTest {
16 | @Test
17 | fun useAppContext() {
18 | // Context of the app under test.
19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
20 | assertEquals("com.istudio.core_database.test", appContext.packageName)
21 | }
22 | }
--------------------------------------------------------------------------------
/Application/core/core-database/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Application/core/core-database/src/main/java/com/istudio/core_database/Constants.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_database
2 |
3 | object Constants {
4 |
5 | const val DATABASE_TABLE = "todo_table"
6 | const val DATABASE_NAME = "distance_tracker_database"
7 |
8 |
9 |
10 | }
--------------------------------------------------------------------------------
/Application/core/core-database/src/main/java/com/istudio/core_database/data/implementation/DistanceTrackerConstantsDaoImpl.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_database.data.implementation
2 |
3 | import com.demo.core_models.DistanceTrackerConstants
4 | import com.istudio.core_database.domain.dao.DistanceTrackerConstantsDao
5 | import kotlinx.coroutines.flow.Flow
6 | import javax.inject.Inject
7 |
8 | class DistanceTrackerConstantsDaoImpl @Inject constructor(
9 | private val dao: DistanceTrackerConstantsDao
10 | ) : DistanceTrackerConstantsDao {
11 |
12 | override suspend fun insertTrackerConstants(distTrackerConst: DistanceTrackerConstants) {
13 | dao.insertTrackerConstants(distTrackerConst)
14 | }
15 |
16 | override suspend fun insertTrackerConstantsWithTransaction(distTrackerConst: DistanceTrackerConstants) {
17 | super.insertTrackerConstantsWithTransaction(distTrackerConst)
18 | }
19 |
20 | override suspend fun deleteTrackerConstants() {
21 | dao.deleteTrackerConstants()
22 | }
23 |
24 | override fun getAllConstants(): Flow {
25 | return dao.getAllConstants()
26 | }
27 | }
--------------------------------------------------------------------------------
/Application/core/core-database/src/main/java/com/istudio/core_database/database/DistanceTrackerDatabase.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_database.database
2 |
3 | import androidx.room.Database
4 | import androidx.room.RoomDatabase
5 | import com.demo.core_models.DistanceTrackerConstants
6 | import com.istudio.core_database.domain.dao.DistanceTrackerConstantsDao
7 |
8 |
9 | /**
10 | * Abstract class:: ---> Because room later generates the code for this class
11 | * Why not make it Interface:: ---> This class need to extend the room-database and interface cannot extend the class so we make class abstract
12 | */
13 | @Database(
14 | entities = [DistanceTrackerConstants::class],
15 | version = 1
16 | )
17 | abstract class DistanceTrackerDatabase : RoomDatabase() {
18 | abstract fun distanceTrackerConstantsDao() : DistanceTrackerConstantsDao
19 | }
--------------------------------------------------------------------------------
/Application/core/core-database/src/main/java/com/istudio/core_database/di/DatabaseModule.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_database.di
2 |
3 | import android.content.Context
4 | import androidx.room.Room
5 | import com.istudio.core_database.Constants.DATABASE_NAME
6 | import com.istudio.core_database.database.DistanceTrackerDatabase
7 | import dagger.Module
8 | import dagger.Provides
9 | import dagger.hilt.InstallIn
10 | import dagger.hilt.android.qualifiers.ApplicationContext
11 | import dagger.hilt.components.SingletonComponent
12 | import javax.inject.Singleton
13 |
14 | @Module
15 | @InstallIn(SingletonComponent::class)
16 | object DatabaseModule {
17 |
18 | /**
19 | * Provides a instance of RoomDatabase
20 | */
21 | @Provides
22 | @Singleton
23 | fun provideDatabase(
24 | @ApplicationContext context: Context
25 | ): DistanceTrackerDatabase =
26 | Room.databaseBuilder(context, DistanceTrackerDatabase::class.java, DATABASE_NAME)
27 | .fallbackToDestructiveMigration()
28 | .build()
29 |
30 |
31 | @Singleton
32 | @Provides
33 | fun provideDao(database: DistanceTrackerDatabase) = database.distanceTrackerConstantsDao()
34 |
35 | }
--------------------------------------------------------------------------------
/Application/core/core-database/src/main/java/com/istudio/core_database/domain/dao/DistanceTrackerConstantsDao.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_database.domain.dao
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Insert
5 | import androidx.room.OnConflictStrategy
6 | import androidx.room.Query
7 | import androidx.room.Transaction
8 | import com.demo.core_models.DistanceTrackerConstants
9 | import kotlinx.coroutines.flow.Flow
10 |
11 | /**
12 | * DESCRIPTION: We mention all the queries related to a table in the DAO interface class
13 | * The class has abstract methods, each representing a query each
14 | */
15 | @Dao
16 | interface DistanceTrackerConstantsDao {
17 |
18 | /**
19 | * DESCRIPTION: Using the insert command we add a entry to the table
20 | * STRATEGY: If there is a value that already exists, then just ignore it
21 | */
22 | @Insert(onConflict = OnConflictStrategy.REPLACE)
23 | suspend fun insertTrackerConstants(distTrackerConst : DistanceTrackerConstants)
24 |
25 |
26 | @Transaction
27 | suspend fun insertTrackerConstantsWithTransaction(distTrackerConst :DistanceTrackerConstants){
28 | deleteTrackerConstants()
29 | insertTrackerConstants(distTrackerConst)
30 | }
31 |
32 | /**
33 | * DESCRIPTION: Deleting the table
34 | */
35 | @Query("DELETE FROM distance_tracker_constants")
36 | suspend fun deleteTrackerConstants()
37 |
38 | /**
39 | * DESCRIPTION: Getting all the constants from the table
40 | */
41 | @Query("SELECT * FROM distance_tracker_constants")
42 | fun getAllConstants(): Flow
43 |
44 | }
--------------------------------------------------------------------------------
/Application/core/core-database/src/test/java/com/istudio/core_database/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_database
2 |
3 | import org.junit.Assert.assertEquals
4 | import org.junit.Test
5 |
6 | /**
7 | * Example local unit test, which will execute on the development machine (host).
8 | *
9 | * See [testing documentation](http://d.android.com/tools/testing).
10 | */
11 | class ExampleUnitTest {
12 | @Test
13 | fun addition_isCorrect() {
14 | assertEquals(4, 2 + 2)
15 | }
16 | }
--------------------------------------------------------------------------------
/Application/core/core-location/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/Application/core/core-location/build.gradle.kts:
--------------------------------------------------------------------------------
1 | apply {
2 | from("$rootDir/base-module.gradle")
3 | }
4 |
5 | dependencies {
6 | // "implementation"(project(Modules.core))
7 | // "implementation"(Coroutines.coroutineLib)
8 |
9 | // ********************************** Map *****************************************
10 | "implementation"(Maps.playServicesLocation)
11 | "implementation"(Maps.androidMapsUtils)
12 | "implementation"(Maps.playServicesMaps)
13 | // ********************************** Map *****************************************
14 | }
15 |
--------------------------------------------------------------------------------
/Application/core/core-location/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-location/consumer-rules.pro
--------------------------------------------------------------------------------
/Application/core/core-location/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.
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/core/core-location/src/androidTest/java/com/istudio/core_location/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_location
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4
4 | import androidx.test.platform.app.InstrumentationRegistry
5 | import org.junit.Assert.*
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | /**
10 | * Instrumented test, which will execute on an Android device.
11 | *
12 | * See [testing documentation](http://d.android.com/tools/testing).
13 | */
14 | @RunWith(AndroidJUnit4::class)
15 | class ExampleInstrumentedTest {
16 | @Test
17 | fun useAppContext() {
18 | // Context of the app under test.
19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
20 | assertEquals("com.istudio.core_location.test", appContext.packageName)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Application/core/core-location/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Application/core/core-location/src/main/java/com/istudio/core_location/data/LastLocationFeatureImpl.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_location.data
2 |
3 | import android.annotation.SuppressLint
4 | import android.location.Location
5 | import com.google.android.gms.location.FusedLocationProviderClient
6 | import com.istudio.core_location.domain.LastLocationFeature
7 | import kotlinx.coroutines.flow.Flow
8 | import kotlinx.coroutines.flow.flow
9 | import kotlinx.coroutines.tasks.asDeferred
10 |
11 | @SuppressLint("MissingPermission")
12 | class LastLocationFeatureImpl(
13 | private var fusedLocationProviderClient: FusedLocationProviderClient,
14 | ) : LastLocationFeature {
15 |
16 | override suspend fun currentLocation(): Flow {
17 | return lastLocationFlow
18 | }
19 |
20 | private val lastLocationFlow: Flow = flow {
21 | emit(fusedLocationProviderClient.lastLocation.asDeferred().await())
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/Application/core/core-location/src/main/java/com/istudio/core_location/data/LocationFeatureImpl.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_location.data
2 |
3 | import android.location.LocationManager
4 | import com.istudio.core_location.domain.LocationFeature
5 |
6 | class LocationFeatureImpl(
7 | private var loacationManager: LocationManager
8 | ) : LocationFeature {
9 |
10 | override fun isLocationEnabled(): Boolean {
11 | val isGpsProviderEnabled = loacationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
12 | val isNetworkProviderEnabled = loacationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
13 | return isGpsProviderEnabled && isNetworkProviderEnabled
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/Application/core/core-location/src/main/java/com/istudio/core_location/domain/LastLocationFeature.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_location.domain
2 |
3 | import android.location.Location
4 | import kotlinx.coroutines.flow.Flow
5 |
6 | interface LastLocationFeature {
7 | suspend fun currentLocation() : Flow
8 | }
9 |
--------------------------------------------------------------------------------
/Application/core/core-location/src/main/java/com/istudio/core_location/domain/LocationFeature.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_location.domain
2 |
3 | interface LocationFeature {
4 | fun isLocationEnabled(): Boolean
5 | }
6 |
--------------------------------------------------------------------------------
/Application/core/core-location/src/test/java/com/istudio/core_location/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_location
2 |
3 | import org.junit.Assert.assertEquals
4 | import org.junit.Test
5 |
6 | /**
7 | * Example local unit test, which will execute on the development machine (host).
8 | *
9 | * See [testing documentation](http://d.android.com/tools/testing).
10 | */
11 | class ExampleUnitTest {
12 | @Test
13 | fun addition_isCorrect() {
14 | assertEquals(4, 2 + 2)
15 | }
16 | }
--------------------------------------------------------------------------------
/Application/core/core-logger/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/Application/core/core-logger/build.gradle.kts:
--------------------------------------------------------------------------------
1 | apply {
2 | from("$rootDir/base-module.gradle")
3 | }
4 |
5 | dependencies {
6 | // "implementation"(project(Modules.core))
7 | // "implementation"(Coroutines.coroutineLib)
8 | "implementation"(CustomLogging.timber)
9 | }
10 |
--------------------------------------------------------------------------------
/Application/core/core-logger/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-logger/consumer-rules.pro
--------------------------------------------------------------------------------
/Application/core/core-logger/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.
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/core/core-logger/src/androidTest/java/com/istudio/core_logger/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_logger
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4
4 | import androidx.test.platform.app.InstrumentationRegistry
5 | import org.junit.Assert.*
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | /**
10 | * Instrumented test, which will execute on an Android device.
11 | *
12 | * See [testing documentation](http://d.android.com/tools/testing).
13 | */
14 | @RunWith(AndroidJUnit4::class)
15 | class ExampleInstrumentedTest {
16 | @Test
17 | fun useAppContext() {
18 | // Context of the app under test.
19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
20 | assertEquals("com.istudio.core_logger.test", appContext.packageName)
21 | }
22 | }
--------------------------------------------------------------------------------
/Application/core/core-logger/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Application/core/core-logger/src/main/java/com/istudio/core_logger/ApplicationLoggerConfig.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_logger
2 |
3 | import android.content.Context
4 | import timber.log.Timber
5 |
6 |
7 | class ApplicationLoggerConfig(private val context: Context?) {
8 |
9 | companion object {
10 | var isLoggerEnabled = false
11 | }
12 |
13 | fun initializeLogging(isEnabled : Boolean) {
14 | context?.let {
15 | isLoggerEnabled = isEnabled
16 | if(isLoggerEnabled){
17 | Timber.plant(Timber.DebugTree())
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Application/core/core-logger/src/main/java/com/istudio/core_logger/data/implementaion/LoggerFeatureImpl.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_logger.data.implementaion
2 |
3 | import com.istudio.core_logger.ApplicationLoggerConfig.Companion.isLoggerEnabled
4 | import com.istudio.core_logger.domain.LoggerFeature
5 | import timber.log.Timber
6 |
7 | class LoggerFeatureImpl() : LoggerFeature {
8 | override fun d(featureName: String?, msg: String?) {
9 | if (isLoggerEnabled && featureName != null && msg != null) {
10 | Timber.tag(featureName).d(msg)
11 | }
12 | }
13 |
14 | override fun e(featureName: String?, msg: String?) {
15 | if (isLoggerEnabled && featureName != null && msg != null) {
16 | Timber.tag(featureName).e(msg)
17 | }
18 | }
19 |
20 | override fun w(featureName: String?, msg: String?) {
21 | if (isLoggerEnabled && featureName != null && msg != null) {
22 | Timber.tag(featureName).w(msg)
23 | }
24 | }
25 |
26 | override fun v(featureName: String?, msg: String?) {
27 | if (isLoggerEnabled && featureName != null && msg != null) {
28 | Timber.tag(featureName).v(msg)
29 | }
30 | }
31 |
32 | override fun i(featureName: String?, msg: String?) {
33 | if (isLoggerEnabled && featureName != null && msg != null) {
34 | Timber.tag(featureName).i(msg)
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Application/core/core-logger/src/main/java/com/istudio/core_logger/data/repository/LoggerRepository.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_logger.data.repository
2 |
3 | import com.istudio.core_logger.domain.LoggerFeature
4 |
5 |
6 | open class LoggerRepository(
7 | private val loggerFeature: LoggerFeature
8 | ) {
9 | open fun d(featureName: String?, msg: String?) { loggerFeature.d(featureName, msg) }
10 | open fun e(featureName: String?, msg: String?) { loggerFeature.e(featureName, msg) }
11 | open fun w(featureName: String?, msg: String?) { loggerFeature.w(featureName, msg) }
12 | open fun v(featureName: String?, msg: String?) { loggerFeature.v(featureName, msg) }
13 | open fun i(featureName: String?, msg: String?) { loggerFeature.i(featureName, msg) }
14 | }
15 |
--------------------------------------------------------------------------------
/Application/core/core-logger/src/main/java/com/istudio/core_logger/di/LoggerModule.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_logger.di
2 |
3 | import com.istudio.core_logger.data.implementaion.LoggerFeatureImpl
4 | import com.istudio.core_logger.data.repository.LoggerRepository
5 | import com.istudio.core_logger.domain.LoggerFeature
6 | import dagger.Module
7 | import dagger.Provides
8 | import dagger.hilt.InstallIn
9 | import dagger.hilt.components.SingletonComponent
10 | import javax.inject.Singleton
11 |
12 | /**
13 | * How module works: Instance creation happens from the bottom to the top
14 | * This Module provides the instance of repository to be used
15 | * Only exception being that Timber and Logger instance is created in the Application class which is a singleton
16 | */
17 | @Module
18 | @InstallIn(SingletonComponent::class)
19 | object LoggerModule {
20 |
21 | /**
22 | * STEP-3: --->
23 | * Provides a instance of LOGGER-REPOSITORY
24 | * *********************************************
25 | * We always inject a repository
26 | */
27 | @Provides
28 | @Singleton
29 | fun provideRepositoryLogger(store: LoggerFeature) = LoggerRepository(store)
30 |
31 | /**
32 | * STEP-2: --->
33 | * Provides a instance of Logger data store implementation
34 | * *********************************************
35 | * We don't inject the instance of implementation directly - instead we provide it to the repository above
36 | */
37 | @Provides
38 | @Singleton
39 | fun provideLoggerFeature(): LoggerFeature {
40 | return LoggerFeatureImpl()
41 | }
42 |
43 | /**
44 | * STEP-1: --->
45 | * We don't do this here since we perform this from the application class of the app
46 | */
47 | }
48 |
--------------------------------------------------------------------------------
/Application/core/core-logger/src/main/java/com/istudio/core_logger/domain/LoggerFeature.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_logger.domain
2 |
3 | interface LoggerFeature {
4 | fun d(featureName: String?, msg: String?)
5 | fun e(featureName: String?, msg: String?)
6 | fun w(featureName: String?, msg: String?)
7 | fun v(featureName: String?, msg: String?)
8 | fun i(featureName: String?, msg: String?)
9 | }
10 |
--------------------------------------------------------------------------------
/Application/core/core-logger/src/test/java/com/istudio/core_logger/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_logger
2 |
3 | import org.junit.Assert.assertEquals
4 | import org.junit.Test
5 |
6 | /**
7 | * Example local unit test, which will execute on the development machine (host).
8 | *
9 | * See [testing documentation](http://d.android.com/tools/testing).
10 | */
11 | class ExampleUnitTest {
12 | @Test
13 | fun addition_isCorrect() {
14 | assertEquals(4, 2 + 2)
15 | }
16 | }
--------------------------------------------------------------------------------
/Application/core/core-models/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/Application/core/core-models/build.gradle.kts:
--------------------------------------------------------------------------------
1 | apply {
2 | from("$rootDir/base-module.gradle")
3 | }
4 |
5 | dependencies {
6 | // "implementation"(project(Modules.core))
7 | "implementation"(Retrofit.gsonConverter)
8 | "implementation"(Room.roomKtx)
9 | "implementation"(Room.roomRuntime)
10 | "implementation"(Coroutines.coroutineLib)
11 | "implementation"(KotlinSerialization.kotlinSerializationJson)
12 | "implementation"(project(Modules.coreCommon))
13 | //"implementation"(Retrofit.okHttp)
14 | //"implementation"(Retrofit.okHttpLoggingInterceptor)
15 | }
16 |
--------------------------------------------------------------------------------
/Application/core/core-models/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-models/consumer-rules.pro
--------------------------------------------------------------------------------
/Application/core/core-models/src/androidTest/java/com/demo/core_models/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.demo.core_models
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4
4 | import androidx.test.platform.app.InstrumentationRegistry
5 | import org.junit.Assert.*
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | /**
10 | * Instrumented test, which will execute on an Android device.
11 | *
12 | * See [testing documentation](http://d.android.com/tools/testing).
13 | */
14 | @RunWith(AndroidJUnit4::class)
15 | class ExampleInstrumentedTest {
16 | @Test
17 | fun useAppContext() {
18 | // Context of the app under test.
19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
20 | assertEquals("com.demo.core_models.test", appContext.packageName)
21 | }
22 | }
--------------------------------------------------------------------------------
/Application/core/core-models/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Application/core/core-models/src/main/java/com/demo/core_models/DistanceTrackerConstants.kt:
--------------------------------------------------------------------------------
1 | package com.demo.core_models
2 |
3 | import androidx.room.Entity
4 | import androidx.room.PrimaryKey
5 | import com.istudio.core_common.constants.DbConstants.TABLE_NAME_DISTANCE_TRACKER_CONSTANTS
6 | import kotlinx.serialization.SerialName
7 | import kotlinx.serialization.Serializable
8 |
9 | @Serializable
10 | @Entity(tableName = TABLE_NAME_DISTANCE_TRACKER_CONSTANTS)
11 | data class DistanceTrackerConstants (
12 | @PrimaryKey(autoGenerate = true) val id : Int = 0,
13 | val isUpdatedAt : Long = System.currentTimeMillis(),
14 | @SerialName("appUpdateConstantType") val appUpdateConstantType : Int,
15 | @SerialName("timerDuration") val timerDuration : Int,
16 | @SerialName("timerInterval") val timerInterval : Int,
17 | @SerialName("locationUpdateInterval") val locationUpdateInterval : Int,
18 | @SerialName("locationFastestUpdateInterval") val locationFastestUpdateInterval : Int,
19 | @SerialName("locationMyselfTimerDuration") val locationMyselfTimerDuration : Int,
20 | @SerialName("resultPageDisplayDuration") val resultPageDisplayDuration : Int,
21 | @SerialName("mapsFollowPolylineUpdateDuration") val mapsFollowPolylineUpdateDuration : Int
22 | )
--------------------------------------------------------------------------------
/Application/core/core-models/src/test/java/com/demo/core_models/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.demo.core_models
2 |
3 | import org.junit.Assert.assertEquals
4 | import org.junit.Test
5 |
6 | /**
7 | * Example local unit test, which will execute on the development machine (host).
8 | *
9 | * See [testing documentation](http://d.android.com/tools/testing).
10 | */
11 | class ExampleUnitTest {
12 | @Test
13 | fun addition_isCorrect() {
14 | assertEquals(4, 2 + 2)
15 | }
16 | }
--------------------------------------------------------------------------------
/Application/core/core-network/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/Application/core/core-network/build.gradle.kts:
--------------------------------------------------------------------------------
1 | apply {
2 | from("$rootDir/base-module.gradle")
3 | }
4 |
5 | dependencies {
6 | // "implementation"(project(Modules.core))
7 | "implementation"(project(Modules.coreModels))
8 | "implementation"(project(Modules.coreCommon))
9 | "implementation"(project(Modules.coreLogger))
10 | "implementation"(Retrofit.retrofit)
11 | "implementation"(Retrofit.gsonConverter)
12 | "implementation"(Retrofit.okHttp)
13 | "implementation"(Retrofit.okHttpLoggingInterceptor)
14 | "implementation"(KotlinSerialization.kotlinSerializationJson)
15 | "implementation"(KotlinSerialization.kotlinSerializationConverter)
16 | }
17 |
--------------------------------------------------------------------------------
/Application/core/core-network/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-network/consumer-rules.pro
--------------------------------------------------------------------------------
/Application/core/core-network/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.
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/core/core-network/src/androidTest/java/com/demo/core_network/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.demo.core_network
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4
4 | import androidx.test.platform.app.InstrumentationRegistry
5 | import org.junit.Assert.*
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | /**
10 | * Instrumented test, which will execute on an Android device.
11 | *
12 | * See [testing documentation](http://d.android.com/tools/testing).
13 | */
14 | @RunWith(AndroidJUnit4::class)
15 | class ExampleInstrumentedTest {
16 | @Test
17 | fun useAppContext() {
18 | // Context of the app under test.
19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
20 | assertEquals("com.demo.core_network.test", appContext.packageName)
21 | }
22 | }
--------------------------------------------------------------------------------
/Application/core/core-network/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Application/core/core-network/src/main/java/com/demo/core_network/api/DistanceTrackerApi.kt:
--------------------------------------------------------------------------------
1 | package com.demo.core_network.api
2 |
3 | import com.demo.core_models.DistanceTrackerConstants
4 | import retrofit2.http.GET
5 |
6 | interface DistanceTrackerApi {
7 | // https://raw.githubusercontent.com/devrath/Distance-Tracker/master/Application/data.json
8 | companion object {
9 | const val BASE_URL = "https://raw.githubusercontent.com/devrath/Distance-Tracker/master/Application/"
10 | }
11 |
12 | @GET("data.json")
13 | suspend fun getConstants(): DistanceTrackerConstants
14 |
15 |
16 | }
--------------------------------------------------------------------------------
/Application/core/core-network/src/main/java/com/demo/core_network/interceptors/AnalyticsInterceptor.kt:
--------------------------------------------------------------------------------
1 | package com.demo.core_network.interceptors
2 |
3 | import android.content.Context
4 | import android.os.Build
5 | import okhttp3.Interceptor
6 | import okhttp3.Request
7 | import okhttp3.Response
8 |
9 | class AnalyticsInterceptor(private val context: Context): Interceptor {
10 |
11 | private val APP_VERSION = "X-App-Version"
12 | private val DEVICE_MODEL = "X-Device-Model"
13 | private val DEVICE_PLATFORM = "X-Device-Platform"
14 | private val OS_VERSION = "X-Device-OS-Version"
15 |
16 | override fun intercept(chain: Interceptor.Chain): Response {
17 | val request: Request = chain.request()
18 |
19 | val requestBuilder: Request.Builder = request.newBuilder()
20 |
21 | val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
22 | val version = packageInfo.versionName
23 |
24 | requestBuilder.addHeader(APP_VERSION, version)
25 | requestBuilder.addHeader(OS_VERSION, Build.VERSION.SDK_INT.toString())
26 | requestBuilder.addHeader(DEVICE_MODEL, Build.MODEL)
27 | requestBuilder.addHeader(DEVICE_PLATFORM, "android")
28 |
29 | return chain.proceed(requestBuilder.build())
30 | }
31 | }
--------------------------------------------------------------------------------
/Application/core/core-network/src/main/java/com/demo/core_network/interceptors/ApiKeyInterceptor.kt:
--------------------------------------------------------------------------------
1 | package com.demo.core_network.interceptors
2 |
3 | import okhttp3.Interceptor
4 | import okhttp3.Response
5 |
6 | class ApiKeyInterceptor: Interceptor {
7 |
8 | private val apiKeyQueryParameterKey = "api_key"
9 |
10 | override fun intercept(chain: Interceptor.Chain): Response {
11 | val originalRequest = chain.request()
12 | val originalUrl = originalRequest.url
13 |
14 | val url = originalUrl.newBuilder()
15 | .addQueryParameter(apiKeyQueryParameterKey, "SomeToken")
16 | .build()
17 |
18 | val newRequest = originalRequest.newBuilder()
19 | .url(url)
20 | .build()
21 |
22 | return chain.proceed(newRequest)
23 | }
24 | }
--------------------------------------------------------------------------------
/Application/core/core-network/src/main/java/com/demo/core_network/utils/NetworkUtils.kt:
--------------------------------------------------------------------------------
1 | package com.demo.core_network.utils
2 |
3 | import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
4 | import kotlinx.serialization.ExperimentalSerializationApi
5 | import kotlinx.serialization.json.Json
6 | import okhttp3.MediaType.Companion.toMediaType
7 | import retrofit2.Converter
8 |
9 | object NetworkUtils {
10 |
11 | @OptIn(ExperimentalSerializationApi::class)
12 | fun buildFactoryForKotlinSerialiser(): Converter.Factory {
13 | val contentType = "application/json".toMediaType()
14 | return Json.asConverterFactory(contentType)
15 | }
16 |
17 | }
--------------------------------------------------------------------------------
/Application/core/core-network/src/test/java/com/demo/core_network/ExampleUnitNetworkUtils.kt:
--------------------------------------------------------------------------------
1 | package com.demo.core_network
2 |
3 | import org.junit.Assert.assertEquals
4 | import org.junit.Test
5 |
6 | /**
7 | * Example local unit test, which will execute on the development machine (host).
8 | *
9 | * See [testing documentation](http://d.android.com/tools/testing).
10 | */
11 | class ExampleUnitNetworkUtils {
12 | @Test
13 | fun addition_isCorrect() {
14 | assertEquals(4, 2 + 2)
15 | }
16 | }
--------------------------------------------------------------------------------
/Application/core/core-permission/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/Application/core/core-permission/build.gradle.kts:
--------------------------------------------------------------------------------
1 | apply {
2 | from("$rootDir/base-module.gradle")
3 | }
4 |
5 | dependencies {
6 | "implementation"(project(Modules.coreCommon))
7 | "implementation"(project(Modules.coreUi))
8 | "implementation"(Permission.customPermission)
9 | }
10 |
--------------------------------------------------------------------------------
/Application/core/core-permission/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-permission/consumer-rules.pro
--------------------------------------------------------------------------------
/Application/core/core-permission/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.
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/core/core-permission/src/androidTest/java/com/demo/core_permission/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.demo.core_permission
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4
4 | import androidx.test.platform.app.InstrumentationRegistry
5 | import org.junit.Assert.*
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | /**
10 | * Instrumented test, which will execute on an Android device.
11 | *
12 | * See [testing documentation](http://d.android.com/tools/testing).
13 | */
14 | @RunWith(AndroidJUnit4::class)
15 | class ExampleInstrumentedTest {
16 | @Test
17 | fun useAppContext() {
18 | // Context of the app under test.
19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
20 | assertEquals("com.demo.core_permission.test", appContext.packageName)
21 | }
22 | }
--------------------------------------------------------------------------------
/Application/core/core-permission/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Application/core/core-permission/src/main/java/com/demo/core_permission/di/PermissionModule.kt:
--------------------------------------------------------------------------------
1 | package com.demo.core_permission.di
2 |
3 | import android.content.Context
4 | import com.demo.core_permission.data.implementation.PermissionFeatureImpl
5 | import com.demo.core_permission.domain.PermissionFeature
6 | import dagger.Module
7 | import dagger.Provides
8 | import dagger.hilt.InstallIn
9 | import dagger.hilt.android.qualifiers.ApplicationContext
10 | import dagger.hilt.components.SingletonComponent
11 | import javax.inject.Singleton
12 |
13 | @Module
14 | @InstallIn(SingletonComponent::class)
15 | object PermissionModule {
16 |
17 | @Provides
18 | @Singleton
19 | fun providePermissionFeature(
20 | @ApplicationContext context: Context
21 | ): PermissionFeature {
22 | return PermissionFeatureImpl(context)
23 | }
24 |
25 | }
--------------------------------------------------------------------------------
/Application/core/core-permission/src/main/java/com/demo/core_permission/domain/PermissionFeature.kt:
--------------------------------------------------------------------------------
1 | package com.demo.core_permission.domain
2 |
3 | import android.view.View
4 | import androidx.fragment.app.Fragment
5 |
6 | interface PermissionFeature {
7 | fun hasLocationPermission(): Boolean
8 | fun runtimeLocationPermission(fragment: Fragment, view: View)
9 | fun isBackgroundPermissionRequired(): Boolean
10 | fun hasBackgroundLocationPermission(): Boolean
11 | fun runtimeBackgroundPermission(fragment: Fragment, view: View)
12 | }
13 |
--------------------------------------------------------------------------------
/Application/core/core-permission/src/test/java/com/demo/core_permission/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.demo.core_permission
2 |
3 | import org.junit.Assert.assertEquals
4 | import org.junit.Test
5 |
6 | /**
7 | * Example local unit test, which will execute on the development machine (host).
8 | *
9 | * See [testing documentation](http://d.android.com/tools/testing).
10 | */
11 | class ExampleUnitTest {
12 | @Test
13 | fun addition_isCorrect() {
14 | assertEquals(4, 2 + 2)
15 | }
16 | }
--------------------------------------------------------------------------------
/Application/core/core-preferences/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/Application/core/core-preferences/build.gradle.kts:
--------------------------------------------------------------------------------
1 | apply {
2 | from("$rootDir/base-module.gradle")
3 | }
4 |
5 | dependencies {
6 | // "implementation"(project(Modules.core))
7 | "implementation"(Coroutines.coroutineLib)
8 | "implementation"(DataStorePreferences.datastorePreferences)
9 | }
10 |
--------------------------------------------------------------------------------
/Application/core/core-preferences/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-preferences/consumer-rules.pro
--------------------------------------------------------------------------------
/Application/core/core-preferences/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.
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/core/core-preferences/src/androidTest/java/com/istudio/core_preferences/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_preferences
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4
4 | import androidx.test.platform.app.InstrumentationRegistry
5 | import org.junit.Assert.*
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | /**
10 | * Instrumented test, which will execute on an Android device.
11 | *
12 | * See [testing documentation](http://d.android.com/tools/testing).
13 | */
14 | @RunWith(AndroidJUnit4::class)
15 | class ExampleInstrumentedTest {
16 | @Test
17 | fun useAppContext() {
18 | // Context of the app under test.
19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
20 | assertEquals("com.istudio.core_preferences.test", appContext.packageName)
21 | }
22 | }
--------------------------------------------------------------------------------
/Application/core/core-preferences/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Application/core/core-preferences/src/main/java/com/istudio/core_preferences/data/implementation/utilities/KeysPreferences.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_preferences.data.implementation.utilities
2 |
3 | object KeysPreferences {
4 | const val SHARED_PREFERENCES_NAME = "preferences_file"
5 | const val KEY_TEXT = "key_text"
6 |
7 |
8 | const val keyHasUserRatedApp = "hasUserRatedApp"
9 | const val keyHasUserChosenRateLater = "hasUserChosenRateLater"
10 | const val keyGetRateLaterTime = "getRateLaterTime"
11 | const val keyNoOfDistanceTracked = "noOfDistanceTracked"
12 | const val keyUiModeOfApp = "uiModeOfApp"
13 |
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/Application/core/core-preferences/src/main/java/com/istudio/core_preferences/data/repository/PreferenceRepository.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_preferences.data.repository
2 |
3 | import com.istudio.core_preferences.domain.InAppReviewPreferences
4 | import kotlinx.coroutines.flow.Flow
5 |
6 | class PreferenceRepository(
7 | private val preference: InAppReviewPreferences,
8 | ) {
9 |
10 | suspend fun saveUiModeState(mode: Int) {
11 | preference.setUiModeForApp(mode)
12 | }
13 |
14 | suspend fun getUiModeState(): Flow {
15 | return preference.getUiModeForApp()
16 | }
17 |
18 | suspend fun saveOnBoardingState(hasRated: Boolean) {
19 | preference.setUserRatedApp(hasRated)
20 | }
21 |
22 | suspend fun hasUserRatedApp(): Flow {
23 | return preference.hasUserRatedApp()
24 | }
25 |
26 | suspend fun setUserChosenRateLater(hasChosenRateLater: Boolean) {
27 | preference.setUserChosenRateLater(hasChosenRateLater)
28 | }
29 |
30 | suspend fun hasUserChosenRateLater(): Flow {
31 | return preference.hasUserChosenRateLater()
32 | }
33 |
34 | suspend fun setRateLater(time: Long) {
35 | preference.setRateLater(time)
36 | }
37 |
38 | suspend fun getRateLaterTime(): Flow {
39 | return preference.getRateLaterTime()
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Application/core/core-preferences/src/test/java/com/istudio/core_preferences/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_preferences
2 |
3 | import org.junit.Assert.assertEquals
4 | import org.junit.Test
5 |
6 | /**
7 | * Example local unit test, which will execute on the development machine (host).
8 | *
9 | * See [testing documentation](http://d.android.com/tools/testing).
10 | */
11 | class ExampleUnitTest {
12 | @Test
13 | fun addition_isCorrect() {
14 | assertEquals(4, 2 + 2)
15 | }
16 | }
--------------------------------------------------------------------------------
/Application/core/core-ui/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/Application/core/core-ui/build.gradle.kts:
--------------------------------------------------------------------------------
1 | apply {
2 | from("$rootDir/base-module.gradle")
3 | }
4 |
5 | dependencies {
6 | // "implementation"(project(Modules.core))
7 | "implementation"(SplashScreen.splashAndroidApi)
8 | "implementation"(project(Modules.corePreferences))
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/Application/core/core-ui/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/consumer-rules.pro
--------------------------------------------------------------------------------
/Application/core/core-ui/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.
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/core/core-ui/src/androidTest/java/com/istudio/core_ui/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_ui
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4
4 | import androidx.test.platform.app.InstrumentationRegistry
5 | import org.junit.Assert.*
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | /**
10 | * Instrumented test, which will execute on an Android device.
11 | *
12 | * See [testing documentation](http://d.android.com/tools/testing).
13 | */
14 | @RunWith(AndroidJUnit4::class)
15 | class ExampleInstrumentedTest {
16 | @Test
17 | fun useAppContext() {
18 | // Context of the app under test.
19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
20 | assertEquals("com.istudio.core_ui.test", appContext.packageName)
21 | }
22 | }
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/java/com/istudio/core_ui/composeUi/theme/Color.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_ui.composeUi.theme
2 |
3 | import androidx.compose.ui.graphics.Color
4 |
5 | val Purple200 = Color(0xFFBB86FC)
6 | val Purple500 = Color(0xFF6200EE)
7 | val Purple700 = Color(0xFF3700B3)
8 | val Teal200 = Color(0xFF03DAC5)
9 |
10 | val LightGray = Color(0xFFFCFCFC)
11 | val MediumGray = Color(0xFF9C9C9C)
12 | val DarkGray = Color(0xFF141414)
13 |
14 | val LowPriorityColor = Color(0xFF00C980)
15 | val MediumPriorityColor = Color(0xFFFFC114)
16 | val HighPriorityColor = Color(0XFFFF4646)
17 | val NonePriorityColor = MediumGray
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/java/com/istudio/core_ui/composeUi/theme/Shape.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_ui.composeUi.theme
2 |
3 | import androidx.compose.foundation.shape.RoundedCornerShape
4 | import androidx.compose.material.Shapes
5 | import androidx.compose.ui.unit.dp
6 |
7 | val Shapes = Shapes(
8 | small = RoundedCornerShape(4.dp),
9 | medium = RoundedCornerShape(4.dp),
10 | large = RoundedCornerShape(0.dp)
11 | )
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/java/com/istudio/core_ui/composeUi/theme/Theme.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_ui.composeUi.theme
2 |
3 | import androidx.compose.foundation.isSystemInDarkTheme
4 | import androidx.compose.material.MaterialTheme
5 | import androidx.compose.material.darkColors
6 | import androidx.compose.material.lightColors
7 | import androidx.compose.runtime.Composable
8 |
9 | private val DarkColorPalette = darkColors(
10 | primary = Purple200,
11 | primaryVariant = Purple700,
12 | secondary = Teal200
13 | )
14 |
15 | private val LightColorPalette = lightColors(
16 | primary = Purple500,
17 | primaryVariant = Purple700,
18 | secondary = Teal200
19 |
20 | /* Other default colors to override
21 | background = Color.White,
22 | surface = Color.White,
23 | onPrimary = Color.White,
24 | onSecondary = Color.Black,
25 | onBackground = Color.Black,
26 | onSurface = Color.Black,
27 | */
28 | )
29 |
30 | @Composable
31 | fun DistanceTrackerTheme(
32 | darkTheme: Boolean = isSystemInDarkTheme(),
33 | content: @Composable () -> Unit
34 | ) {
35 | val colors = if (darkTheme) {
36 | DarkColorPalette
37 | } else {
38 | LightColorPalette
39 | }
40 |
41 | MaterialTheme(
42 | colors = colors,
43 | typography = Typography,
44 | shapes = Shapes,
45 | content = content
46 | )
47 | }
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/java/com/istudio/core_ui/composeUi/theme/Type.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_ui.composeUi.theme
2 |
3 | import androidx.compose.material.Typography
4 | import androidx.compose.ui.text.TextStyle
5 | import androidx.compose.ui.text.font.FontFamily
6 | import androidx.compose.ui.text.font.FontWeight
7 | import androidx.compose.ui.unit.sp
8 |
9 | // Set of Material typography styles to start with
10 | val Typography = Typography(
11 | body1 = TextStyle(
12 | fontFamily = FontFamily.Default,
13 | fontWeight = FontWeight.Normal,
14 | fontSize = 16.sp
15 | )
16 | /* Other default text styles to override
17 | button = TextStyle(
18 | fontFamily = FontFamily.Default,
19 | fontWeight = FontWeight.W500,
20 | fontSize = 14.sp
21 | ),
22 | caption = TextStyle(
23 | fontFamily = FontFamily.Default,
24 | fontWeight = FontWeight.Normal,
25 | fontSize = 12.sp
26 | )
27 | */
28 | )
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/java/com/istudio/core_ui/customviews/button/ButtonViewBold.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_ui.customviews.button
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import androidx.appcompat.widget.AppCompatButton
6 | import androidx.core.content.res.ResourcesCompat
7 | import com.istudio.core_ui.R
8 |
9 | class ButtonViewBold : AppCompatButton {
10 |
11 | constructor(context: Context) : super(context) {
12 | init(context, null)
13 | }
14 |
15 | constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
16 | init(context, attrs)
17 | }
18 |
19 | constructor(context: Context, attrs: AttributeSet?, style: Int) : super(context, attrs, style) {
20 | init(context, attrs)
21 | }
22 |
23 | private fun init(context: Context, attrs: AttributeSet?) {
24 | if (attrs != null) {
25 | val myTypeface = ResourcesCompat.getFont(context, R.font.roboto_bold)
26 | this.typeface = myTypeface
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/java/com/istudio/core_ui/customviews/button/ButtonViewMedium.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_ui.customviews.button
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import androidx.appcompat.widget.AppCompatButton
6 | import androidx.core.content.res.ResourcesCompat
7 | import com.istudio.core_ui.R
8 |
9 | class ButtonViewMedium : AppCompatButton {
10 |
11 | constructor(context: Context) : super(context) {
12 | init(context, null)
13 | }
14 |
15 | constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
16 | init(context, attrs)
17 | }
18 |
19 | constructor(context: Context, attrs: AttributeSet?, style: Int) : super(context, attrs, style) {
20 | init(context, attrs)
21 | }
22 |
23 | private fun init(context: Context, attrs: AttributeSet?) {
24 | if (attrs != null) {
25 | val myTypeface = ResourcesCompat.getFont(context, R.font.roboto_medium)
26 | this.typeface = myTypeface
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/java/com/istudio/core_ui/customviews/button/ButtonViewRegular.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_ui.customviews.button
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import androidx.appcompat.widget.AppCompatButton
6 | import androidx.core.content.res.ResourcesCompat
7 | import com.istudio.core_ui.R
8 |
9 | class ButtonViewRegular : AppCompatButton {
10 |
11 | constructor(context: Context) : super(context) {
12 | init(context, null)
13 | }
14 |
15 | constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
16 | init(context, attrs)
17 | }
18 |
19 | constructor(context: Context, attrs: AttributeSet?, style: Int) : super(context, attrs, style) {
20 | init(context, attrs)
21 | }
22 |
23 | private fun init(context: Context, attrs: AttributeSet?) {
24 | if (attrs != null) {
25 | val myTypeface = ResourcesCompat.getFont(context, R.font.roboto)
26 | this.typeface = myTypeface
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/java/com/istudio/core_ui/customviews/text/TextViewBold.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_ui.customviews.text
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import androidx.appcompat.widget.AppCompatTextView
6 | import androidx.core.content.res.ResourcesCompat
7 | import com.istudio.core_ui.R
8 |
9 | class TextViewBold : AppCompatTextView {
10 |
11 | constructor(context: Context) : super(context) {
12 | init(context, null)
13 | }
14 |
15 | constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
16 | init(context, attrs)
17 | }
18 |
19 | constructor(context: Context, attrs: AttributeSet?, style: Int) : super(context, attrs, style) {
20 | init(context, attrs)
21 | }
22 |
23 | private fun init(context: Context, attrs: AttributeSet?) {
24 | if (attrs != null) {
25 | val myTypeface = ResourcesCompat.getFont(context, R.font.roboto_bold)
26 | this.typeface = myTypeface
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/java/com/istudio/core_ui/customviews/text/TextViewMedium.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_ui.customviews.text
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import androidx.appcompat.widget.AppCompatTextView
6 | import androidx.core.content.res.ResourcesCompat
7 | import com.istudio.core_ui.R
8 |
9 | class TextViewMedium : AppCompatTextView {
10 |
11 | constructor(context: Context) : super(context) {
12 | init(context, null)
13 | }
14 |
15 | constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
16 | init(context, attrs)
17 | }
18 |
19 | constructor(context: Context, attrs: AttributeSet?, style: Int) : super(context, attrs, style) {
20 | init(context, attrs)
21 | }
22 |
23 | private fun init(context: Context, attrs: AttributeSet?) {
24 | if (attrs != null) {
25 | val myTypeface = ResourcesCompat.getFont(context, R.font.roboto_medium)
26 | this.typeface = myTypeface
27 | }
28 | }
29 |
30 | }
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/java/com/istudio/core_ui/customviews/text/TextViewRegular.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_ui.customviews.text
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import androidx.appcompat.widget.AppCompatTextView
6 | import androidx.core.content.res.ResourcesCompat
7 | import com.istudio.core_ui.R
8 |
9 | class TextViewRegular : AppCompatTextView {
10 |
11 | constructor(context: Context) : super(context) {
12 | init(context, null)
13 | }
14 |
15 | constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
16 | init(context, attrs)
17 | }
18 |
19 | constructor(context: Context, attrs: AttributeSet?, style: Int) : super(context, attrs, style) {
20 | init(context, attrs)
21 | }
22 |
23 | private fun init(context: Context, attrs: AttributeSet?) {
24 | if (attrs != null) {
25 | val myTypeface = ResourcesCompat.getFont(context, R.font.roboto)
26 | this.typeface = myTypeface
27 | }
28 | }
29 |
30 | }
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/java/com/istudio/core_ui/data/models/Mode.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_ui.data.models
2 |
3 | enum class Mode {
4 | LIGHT, DARK, SYSTEM, BATTERY
5 | }
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/java/com/istudio/core_ui/di/SwitchUiModule.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_ui.di
2 |
3 | import com.istudio.core_preferences.domain.InAppReviewPreferences
4 | import com.istudio.core_ui.data.implementation.SwitchUiModeFeatureImpl
5 | import com.istudio.core_ui.domain.SwitchUiModeFeature
6 | import dagger.Module
7 | import dagger.Provides
8 | import dagger.hilt.InstallIn
9 | import dagger.hilt.components.SingletonComponent
10 | import javax.inject.Singleton
11 |
12 | @Module
13 | @InstallIn(SingletonComponent::class)
14 | object SwitchUiModule {
15 |
16 | @Provides
17 | @Singleton
18 | fun provideSwitchUiFeature(preferences: InAppReviewPreferences): SwitchUiModeFeature {
19 | return SwitchUiModeFeatureImpl(preferences)
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/java/com/istudio/core_ui/domain/SwitchUiModeFeature.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_ui.domain
2 |
3 | import android.app.Activity
4 |
5 |
6 | interface SwitchUiModeFeature {
7 | suspend fun toggleUiMode() : Int
8 | suspend fun isDarkMode() : Boolean
9 | suspend fun isUiModeKeyStored() : Boolean
10 | suspend fun saveToggledUiMode()
11 | fun animateAndRestartApplication(activity : Activity)
12 | }
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/anim/fade_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/anim/fade_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable-hdpi/ic_current_location.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/drawable-hdpi/ic_current_location.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable-hdpi/ic_current_location_dark_mode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/drawable-hdpi/ic_current_location_dark_mode.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable-hdpi/ic_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/drawable-hdpi/ic_list.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable-mdpi/ic_current_location.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/drawable-mdpi/ic_current_location.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable-mdpi/ic_current_location_dark_mode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/drawable-mdpi/ic_current_location_dark_mode.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable-mdpi/ic_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/drawable-mdpi/ic_list.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable-xhdpi/ic_current_location.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/drawable-xhdpi/ic_current_location.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable-xhdpi/ic_current_location_dark_mode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/drawable-xhdpi/ic_current_location_dark_mode.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable-xhdpi/ic_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/drawable-xhdpi/ic_list.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable-xxhdpi/ic_current_location.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/drawable-xxhdpi/ic_current_location.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable-xxhdpi/ic_current_location_dark_mode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/drawable-xxhdpi/ic_current_location_dark_mode.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable-xxhdpi/ic_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/drawable-xxhdpi/ic_list.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable-xxxhdpi/ic_current_location.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/drawable-xxxhdpi/ic_current_location.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable-xxxhdpi/ic_current_location_dark_mode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/drawable-xxxhdpi/ic_current_location_dark_mode.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable-xxxhdpi/ic_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/drawable-xxxhdpi/ic_list.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable/ic_add_action.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable/ic_dark_mode.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable/ic_dialog_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
14 |
15 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable/ic_light_mode.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable/ic_lock_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable/ic_map_journey.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable/ic_map_styles.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable/ic_photo_album_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable/ic_splash.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/drawable/ic_splash_dark_mode.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/font/roboto.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/font/roboto_bold.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/font/roboto_bold_italic.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/font/roboto_italic.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/font/roboto_light_italic.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/font/roboto_medium.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/layout/test_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
20 |
21 |
27 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/core/core-ui/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/values-night/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #5ed0ff
4 | #009FCF
5 | #00719e
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
11 | #FF5353
12 | #FB7813
13 | #FF0000
14 | #008000
15 | #6495ED
16 |
17 | #FFFFFFFF
18 | #00FFFF
19 | #FFFFFFFF
20 | #FFFFFFFF
21 |
22 |
23 |
24 | #FFFFFF
25 | #FF018786
26 | #FFFFFF
27 | #000000
28 | #FF018786
29 | #000000
30 | #FFFFFF
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #5ed0ff
4 | #009FCF
5 | #00719e
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
11 | #FF5353
12 | #FB7813
13 | #FF0000
14 | #008000
15 | #6495ED
16 |
17 | #FF000000
18 | #FF000000
19 | #FF000000
20 | #FF000000
21 |
22 | #FFFFFF
23 |
24 |
25 |
26 | #000000
27 | #FFFFFF
28 | #D4A017
29 | #FFFFFF
30 | #D4A017
31 | #FFFFFF
32 | #000000
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/values/common_styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 200dp
4 | 400dp
5 | 40dp
6 | 80sp
7 | 10dp
8 | 20sp
9 | 10dp
10 | 10dp
11 | 30sp
12 | 30sp
13 | 20dp
14 |
15 | 16dp
16 | 32dp
17 | 6dp
18 | 40dp
19 | 40dp
20 | 150dp
21 | 16sp
22 | 20sp
23 | 50dp
24 | 12dp
25 | 12sp
26 | 300dp
27 | 350dp
28 | 12dp
29 | 16dp
30 |
31 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/values/preloaded_fonts.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - @font/roboto
5 | - @font/roboto_bold
6 | - @font/roboto_bold_italic
7 | - @font/roboto_italic
8 | - @font/roboto_light_italic
9 | - @font/roboto_medium
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
13 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/Application/core/core-ui/src/test/java/com/istudio/core_ui/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.core_ui
2 |
3 | import org.junit.Assert.assertEquals
4 | import org.junit.Test
5 |
6 | /**
7 | * Example local unit test, which will execute on the development machine (host).
8 | *
9 | * See [testing documentation](http://d.android.com/tools/testing).
10 | */
11 | class ExampleUnitTest {
12 | @Test
13 | fun addition_isCorrect() {
14 | assertEquals(4, 2 + 2)
15 | }
16 | }
--------------------------------------------------------------------------------
/Application/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "appUpdateConstantType": 1,
3 | "timerDuration": 5000,
4 | "timerInterval": 1000,
5 | "locationUpdateInterval": 4000,
6 | "locationFastestUpdateInterval": 2000,
7 | "locationMyselfTimerDuration": 5000,
8 | "resultPageDisplayDuration": 2500,
9 | "mapsFollowPolylineUpdateDuration": 1000
10 | }
11 |
--------------------------------------------------------------------------------
/Application/features/feat-gallery/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/Application/features/feat-gallery/build.gradle.kts:
--------------------------------------------------------------------------------
1 | apply {
2 | from("$rootDir/base-module.gradle")
3 | }
4 |
5 | dependencies {
6 | "implementation"(Coroutines.coroutineLib)
7 | "implementation"(Glide.glideLibrary)
8 |
9 | // ********************************** Modules ************************************
10 | "implementation"(project(Modules.coreCommon))
11 | "implementation"(project(Modules.coreModels))
12 | "implementation"(project(Modules.coreNetwork))
13 | "implementation"(project(Modules.corePermission))
14 | "implementation"(project(Modules.coreUi))
15 | // ********************************** Modules ************************************
16 | }
17 |
--------------------------------------------------------------------------------
/Application/features/feat-gallery/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/features/feat-gallery/consumer-rules.pro
--------------------------------------------------------------------------------
/Application/features/feat-gallery/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.
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/features/feat-gallery/src/androidTest/java/com/example/feat_gallery/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.example.feat_gallery
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.example.feat_gallery.test", appContext.packageName)
23 | }
24 | }
--------------------------------------------------------------------------------
/Application/features/feat-gallery/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
11 |
12 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Application/features/feat-gallery/src/main/java/com/example/feat_gallery/presentation/adapter/GalleryAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.example.feat_gallery.presentation.adapter
2 |
3 | import android.view.LayoutInflater
4 | import android.view.ViewGroup
5 | import androidx.recyclerview.widget.ListAdapter
6 | import com.bumptech.glide.Glide
7 | import com.example.feat_gallery.presentation.models.InternalStoragePhoto
8 | import com.example.feat_gallery.presentation.vh.ImageViewHolder
9 | import com.example.feat_gallery.R
10 |
11 | class GalleryAdapter(val onClick: (InternalStoragePhoto) -> Unit) :
12 | ListAdapter(InternalStoragePhoto.DiffCallback) {
13 |
14 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageViewHolder {
15 | val layoutInflater = LayoutInflater.from(parent.context)
16 | val view = layoutInflater.inflate(R.layout.image_layout, parent, false)
17 | return ImageViewHolder(view, onClick)
18 | }
19 |
20 | override fun onBindViewHolder(holder: ImageViewHolder, position: Int) {
21 | val image = getItem(position)
22 | holder.rootView.tag = image
23 |
24 | Glide.with(holder.imageView)
25 | .load(image.bmp)
26 | .thumbnail(0.33f)
27 | .centerCrop()
28 | .into(holder.imageView)
29 | }
30 | }
--------------------------------------------------------------------------------
/Application/features/feat-gallery/src/main/java/com/example/feat_gallery/presentation/models/InternalStoragePhoto.kt:
--------------------------------------------------------------------------------
1 | package com.example.feat_gallery.presentation.models
2 |
3 | import android.graphics.Bitmap
4 | import android.net.Uri
5 | import androidx.recyclerview.widget.DiffUtil
6 | import java.util.Date
7 |
8 | data class InternalStoragePhoto(
9 | val id: Int, val name: String, val bmp: Bitmap
10 | ) {
11 | companion object {
12 | val DiffCallback = object : DiffUtil.ItemCallback() {
13 | override fun areItemsTheSame(oldItem: InternalStoragePhoto, newItem: InternalStoragePhoto) =
14 | oldItem.id == newItem.id
15 |
16 | override fun areContentsTheSame(oldItem: InternalStoragePhoto, newItem: InternalStoragePhoto) =
17 | oldItem == newItem
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/Application/features/feat-gallery/src/main/java/com/example/feat_gallery/presentation/vh/ImageViewHolder.kt:
--------------------------------------------------------------------------------
1 | package com.example.feat_gallery.presentation.vh
2 |
3 | import android.view.View
4 | import android.widget.ImageView
5 | import androidx.recyclerview.widget.RecyclerView
6 | import com.example.feat_gallery.presentation.models.InternalStoragePhoto
7 | import com.example.feat_gallery.R
8 |
9 | class ImageViewHolder(view: View, onClick: (InternalStoragePhoto) -> Unit) :
10 | RecyclerView.ViewHolder(view) {
11 | val rootView = view
12 | val imageView: ImageView = view.findViewById(R.id.image)
13 |
14 | init {
15 | imageView.setOnClickListener {
16 | val internalStoragePhoto = rootView.tag as? InternalStoragePhoto ?: return@setOnClickListener
17 | onClick(internalStoragePhoto)
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Application/features/feat-gallery/src/main/java/com/example/feat_gallery/presentation/view/GalleryActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.feat_gallery.presentation.view
2 |
3 | import android.os.Bundle
4 | import android.view.View
5 | import androidx.activity.viewModels
6 | import androidx.appcompat.app.AppCompatActivity
7 | import androidx.lifecycle.Observer
8 | import androidx.recyclerview.widget.GridLayoutManager
9 | import com.example.feat_gallery.databinding.ActivityDemoOneBinding
10 | import com.example.feat_gallery.presentation.adapter.GalleryAdapter
11 | import com.example.feat_gallery.presentation.vm.GalleryVm
12 | import dagger.hilt.android.AndroidEntryPoint
13 |
14 | @AndroidEntryPoint
15 | class GalleryActivity : AppCompatActivity() {
16 |
17 | private lateinit var binding: ActivityDemoOneBinding
18 | private val viewModel: GalleryVm by viewModels()
19 |
20 | override fun onCreate(savedInstanceState: Bundle?) {
21 | super.onCreate(savedInstanceState)
22 | binding = ActivityDemoOneBinding.inflate(layoutInflater)
23 | setContentView(binding.root)
24 | initImageGridAdapter()
25 | showImages()
26 | }
27 |
28 | private fun initImageGridAdapter() {
29 | // Create a instance of adapter
30 | val galleryAdapter = GalleryAdapter { image ->
31 | // Pass the onclick action as lambda for deleting the image to the instance
32 | //vdeleteImage(image)
33 | }
34 | // Set the properties for the grid layout
35 | binding.imageGallery.also { view ->
36 | view.layoutManager = GridLayoutManager(this, 3)
37 | view.adapter = galleryAdapter
38 | }
39 | // Observe the changes for the image collection loaded in grid view for changes
40 | viewModel.images.observe(this, Observer { images ->
41 | galleryAdapter.submitList(images)
42 | })
43 | }
44 |
45 | private fun showImages() {
46 | viewModel.loadImages(this)
47 | }
48 | }
--------------------------------------------------------------------------------
/Application/features/feat-gallery/src/main/java/com/example/feat_gallery/utils/PermissionUtils.kt:
--------------------------------------------------------------------------------
1 | package com.example.feat_gallery.utils
2 |
3 | import android.Manifest
4 | import android.content.Context
5 | import android.content.pm.PackageManager
6 | import androidx.core.content.ContextCompat
7 |
8 | object PermissionUtils {
9 | fun haveStoragePermission(context: Context) = ContextCompat.checkSelfPermission(
10 | context, Manifest.permission.READ_EXTERNAL_STORAGE
11 | ) == PackageManager.PERMISSION_GRANTED
12 | }
--------------------------------------------------------------------------------
/Application/features/feat-gallery/src/main/res/layout/activity_demo_one.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
--------------------------------------------------------------------------------
/Application/features/feat-gallery/src/main/res/layout/image_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
15 |
16 |
--------------------------------------------------------------------------------
/Application/features/feat-gallery/src/test/java/com/example/feat_gallery/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.example.feat_gallery
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/features/feat-inappreview/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/build.gradle.kts:
--------------------------------------------------------------------------------
1 | apply {
2 | from("$rootDir/base-module.gradle")
3 | }
4 |
5 | dependencies {
6 | "implementation"(Coroutines.coroutineLib)
7 | "implementation"(Google.playCore)
8 | "implementation"(AndroidX.constraint)
9 | "implementation"(AndroidX.cardView)
10 | "implementation"(Lotte.lotteAnimation)
11 | "implementation"(AndroidX.fragment)
12 | "implementation"(AndroidX.fragmentKtx)
13 |
14 | // ********************************** Modules ************************************
15 | "implementation"(project(Modules.coreUi))
16 | "implementation"(project(Modules.corePreferences))
17 | "implementation"(project(Modules.coreCommon))
18 | // ********************************** Modules ************************************
19 | }
20 |
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/features/feat-inappreview/consumer-rules.pro
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/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.
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/features/feat-inappreview/src/androidTest/java/com/istudio/feat_inappreview/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.feat_inappreview
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4
4 | import androidx.test.platform.app.InstrumentationRegistry
5 | import org.junit.Assert.*
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | /**
10 | * Instrumented test, which will execute on an Android device.
11 | *
12 | * See [testing documentation](http://d.android.com/tools/testing).
13 | */
14 | @RunWith(AndroidJUnit4::class)
15 | class ExampleInstrumentedTest {
16 | @Test
17 | fun useAppContext() {
18 | // Context of the app under test.
19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
20 | assertEquals("com.istudio.feat_inappreview.test", appContext.packageName)
21 | }
22 | }
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/src/main/java/com/istudio/feat_inappreview/InAppReviewView.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.feat_inappreview
2 |
3 | /**
4 | * Represents an interface all features that can prompt the In App Review Flow should implement.
5 | * Via this interface your app can call this and invoke the review feature
6 | * */
7 | interface InAppReviewView {
8 |
9 | /**
10 | * Tells the UI to attempt to trigger the In App Review flow.
11 | * This doesn't guarantee the Flow will be triggered, as Google imposes hidden, mutable, quotas
12 | * for review flow requests.
13 | * */
14 | fun showReviewFlow()
15 | }
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/src/main/java/com/istudio/feat_inappreview/ReviewFeatureConstants.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.feat_inappreview
2 |
3 | object ReviewFeatureConstants {
4 | const val DAYS_FOR_REVIEW_REMINDER : Long = 14
5 | }
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/src/main/java/com/istudio/feat_inappreview/di/InAppReviewBinds.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.feat_inappreview.di
2 |
3 | import com.istudio.feat_inappreview.manager.InAppReviewManager
4 | import com.istudio.feat_inappreview.manager.InAppReviewManagerImpl
5 | import dagger.Binds
6 | import dagger.Module
7 | import dagger.hilt.InstallIn
8 | import dagger.hilt.components.SingletonComponent
9 | import javax.inject.Singleton
10 |
11 | /**
12 | * Provides dependencies required for In App Review flow.
13 | * */
14 | @Module
15 | @InstallIn(SingletonComponent::class)
16 | abstract class InAppReviewBinds {
17 | /**
18 | * Provides In App Review flow wrapper.
19 | * */
20 | @Binds
21 | @Singleton
22 | abstract fun bindInAppReviewManager(
23 | inAppReviewManagerImpl: InAppReviewManagerImpl
24 | ): InAppReviewManager
25 | }
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/src/main/java/com/istudio/feat_inappreview/di/ReviewManagerModule.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.feat_inappreview.di
2 |
3 | import android.content.Context
4 | import com.google.android.play.core.review.ReviewManager
5 | import com.google.android.play.core.review.ReviewManagerFactory
6 | import dagger.Module
7 | import dagger.Provides
8 | import dagger.hilt.InstallIn
9 | import dagger.hilt.android.qualifiers.ApplicationContext
10 | import dagger.hilt.components.SingletonComponent
11 | import javax.inject.Singleton
12 |
13 | @Module
14 | @InstallIn(SingletonComponent::class)
15 | object ReviewManagerModule {
16 |
17 | @Provides
18 | @Singleton
19 | fun provideReviewManager(
20 | @ApplicationContext context: Context
21 | ) : ReviewManager {
22 | return ReviewManagerFactory.create(context);
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/src/main/java/com/istudio/feat_inappreview/dialog/ReviewStates.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.feat_inappreview.dialog
2 |
3 | sealed class ReviewStates {
4 | //data class AddMarker(val location: LatLng) : MapStates()
5 | object RateLaterAction : ReviewStates()
6 | object LeaveReviewAction : ReviewStates()
7 | object SendToPlayStoreScreen : ReviewStates()
8 | }
9 |
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/src/main/java/com/istudio/feat_inappreview/manager/InAppReviewManager.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.feat_inappreview.manager
2 |
3 | import android.app.Activity
4 |
5 | /**
6 | * Abstracts away the implementation behind the In-App Review flow.
7 | * */
8 | interface InAppReviewManager {
9 |
10 | /**
11 | * Attempts to start the In-App Review flow.
12 | * */
13 | suspend fun startReview(activity: Activity) : Boolean
14 |
15 | /**
16 | * Gives the information if the user should see the review flow/prompt.
17 | * */
18 | suspend fun isEligibleForReview(): Boolean
19 |
20 | /**
21 | * Cancels the coroutines if any are under the process
22 | * */
23 | fun cancelCoroutines(message: String)
24 | }
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/src/main/res/drawable/happy_face.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/features/feat-inappreview/src/main/res/drawable/happy_face.png
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/src/main/res/drawable/ic_rate_review.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/src/main/res/drawable/not_now_action_border.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/src/main/res/drawable/progress_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/features/feat-inappreview/src/main/res/drawable/progress_black.png
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/src/main/res/drawable/progress_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/features/feat-inappreview/src/main/res/drawable/progress_white.png
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/src/main/res/drawable/review_action_border.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/src/main/res/drawable/sad_face.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/features/feat-inappreview/src/main/res/drawable/sad_face.png
--------------------------------------------------------------------------------
/Application/features/feat-inappreview/src/test/java/com/istudio/feat_inappreview/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.istudio.feat_inappreview
2 |
3 | import org.junit.Assert.assertEquals
4 | import org.junit.Test
5 |
6 | /**
7 | * Example local unit test, which will execute on the development machine (host).
8 | *
9 | * See [testing documentation](http://d.android.com/tools/testing).
10 | */
11 | class ExampleUnitTest {
12 | @Test
13 | fun addition_isCorrect() {
14 | assertEquals(4, 2 + 2)
15 | }
16 | }
--------------------------------------------------------------------------------
/Application/features/feat-repository/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/Application/features/feat-repository/build.gradle.kts:
--------------------------------------------------------------------------------
1 | apply {
2 | from("$rootDir/base-module.gradle")
3 | }
4 |
5 | dependencies {
6 | "implementation"(Coroutines.coroutineLib)
7 |
8 | // ********************************** Modules ************************************
9 | "implementation"(project(Modules.coreCommon))
10 | "implementation"(project(Modules.coreModels))
11 | "implementation"(project(Modules.coreNetwork))
12 | "implementation"(project(Modules.coreDatabase))
13 | // ********************************** Modules ************************************
14 | }
15 |
--------------------------------------------------------------------------------
/Application/features/feat-repository/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/features/feat-repository/consumer-rules.pro
--------------------------------------------------------------------------------
/Application/features/feat-repository/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.
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/features/feat-repository/src/androidTest/java/com/demo/feat_repository/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.demo.feat_repository
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4
4 | import androidx.test.platform.app.InstrumentationRegistry
5 | import org.junit.Assert.*
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | /**
10 | * Instrumented test, which will execute on an Android device.
11 | *
12 | * See [testing documentation](http://d.android.com/tools/testing).
13 | */
14 | @RunWith(AndroidJUnit4::class)
15 | class ExampleInstrumentedTest {
16 | @Test
17 | fun useAppContext() {
18 | // Context of the app under test.
19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
20 | assertEquals("com.demo.feat_repository.test", appContext.packageName)
21 | }
22 | }
--------------------------------------------------------------------------------
/Application/features/feat-repository/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Application/features/feat-repository/src/main/java/com/demo/feat_repository/DistanceTrackerRepository.kt:
--------------------------------------------------------------------------------
1 | package com.demo.feat_repository
2 |
3 | import com.demo.core_models.DistanceTrackerConstants
4 | import com.demo.core_network.api.DistanceTrackerApi
5 | import com.istudio.core_common.functional.Resource
6 | import com.istudio.core_common.functional.networkBoundResource
7 | import com.istudio.core_database.database.DistanceTrackerDatabase
8 | import kotlinx.coroutines.flow.Flow
9 | import javax.inject.Inject
10 |
11 | class DistanceTrackerRepository @Inject constructor(
12 | private val api: DistanceTrackerApi,
13 | private val database: DistanceTrackerDatabase
14 | ) {
15 |
16 | private val trackerDao = database.distanceTrackerConstantsDao()
17 |
18 | fun getConstants(shouldFetchFromApi : Boolean): Flow> =
19 | networkBoundResource(
20 | shouldFetch = { shouldFetchFromApi },
21 | query = {
22 | // Getting the data from database
23 | trackerDao.getAllConstants()
24 | },
25 | fetch = {
26 | // Getting the data from the API
27 | api.getConstants()
28 | },
29 | saveFetchResult = { trackerConstants ->
30 | // save the data in data base that is fetched from server
31 | trackerDao.insertTrackerConstantsWithTransaction(trackerConstants)
32 | }
33 | )
34 | }
--------------------------------------------------------------------------------
/Application/features/feat-repository/src/test/java/com/demo/feat_repository/ExampleUnitNetworkUtils.kt:
--------------------------------------------------------------------------------
1 | package com.demo.feat_repository
2 |
3 | import org.junit.Assert.assertEquals
4 | import org.junit.Test
5 |
6 | /**
7 | * Example local unit test, which will execute on the development machine (host).
8 | *
9 | * See [testing documentation](http://d.android.com/tools/testing).
10 | */
11 | class ExampleUnitNetworkUtils {
12 | @Test
13 | fun addition_isCorrect() {
14 | assertEquals(4, 2 + 2)
15 | }
16 | }
--------------------------------------------------------------------------------
/Application/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Kotlin code style for this project: "official" or "obsolete":
19 | kotlin.code.style=official
20 | # Enables namespacing of each library's R class so that its R class includes only the
21 | # resources declared in the library itself and none from the library's dependencies,
22 | # thereby reducing the size of the R class for that library
23 | android.nonTransitiveRClass=true
24 | # jettifier
25 | android.enableJetifier=true
--------------------------------------------------------------------------------
/Application/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Application/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/Application/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Nov 25 20:54:15 IST 2022
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/Application/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = "Distance Tracker"
2 | include ':app'
3 | include ':core'
4 | include ':features'
5 | include ':core:core-preferences'
6 | include ':core:core-common'
7 | include ':core:core-ui'
8 | include ':core:core-logger'
9 | include ':core:core-location'
10 | include ':core:core-connectivity'
11 | include ':core:core-database'
12 | include ':core:core-permission'
13 | include ':core:core-network'
14 | include ':core:core-models'
15 | include ':features:feat-inappreview'
16 | include ':features:feat-repository'
17 | include ':features:feat-gallery'
18 |
--------------------------------------------------------------------------------
/Assets/Architecture/MVVM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Assets/Architecture/MVVM.png
--------------------------------------------------------------------------------
/Assets/Architecture/projectstructure.drawio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Assets/Architecture/projectstructure.drawio.png
--------------------------------------------------------------------------------
/Assets/Banner/banner.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Assets/Banner/banner.jpeg
--------------------------------------------------------------------------------
/Assets/Images/google-play-store.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Assets/Images/google-play-store.png
--------------------------------------------------------------------------------
/Assets/Images/google-play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Assets/Images/google-play.png
--------------------------------------------------------------------------------
/Assets/Images/playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Assets/Images/playstore.png
--------------------------------------------------------------------------------
/Assets/ScreenGif/BackgroundPermission.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Assets/ScreenGif/BackgroundPermission.gif
--------------------------------------------------------------------------------
/Assets/ScreenGif/Demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Assets/ScreenGif/Demo.gif
--------------------------------------------------------------------------------
/Assets/ScreenGif/RuntimePermission.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Assets/ScreenGif/RuntimePermission.gif
--------------------------------------------------------------------------------
/Assets/ScreenGif/dark_light_mode.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Assets/ScreenGif/dark_light_mode.gif
--------------------------------------------------------------------------------
/Assets/ScreenGif/locating_user.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Assets/ScreenGif/locating_user.gif
--------------------------------------------------------------------------------
/Assets/ScreenGif/network_observer.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Assets/ScreenGif/network_observer.gif
--------------------------------------------------------------------------------
/Assets/ScreenGif/splash.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Assets/ScreenGif/splash.gif
--------------------------------------------------------------------------------
/Assets/ScreenGif/switch_map_types.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Assets/ScreenGif/switch_map_types.gif
--------------------------------------------------------------------------------
/Assets/ScreenGif/updates.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devrath/Distance-Tracker/17d03b535e2ced992b97cc1e3a6d40c5393afded/Assets/ScreenGif/updates.gif
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Feeling Awesome! Thanks for thinking about this.
2 |
3 | You can contribute us by filing issues, bugs and PRs. You can also take a look at active issues and fix them.
4 |
5 | If you want to discuss on something then feel free to present your opinions, views or any other relevant comment on [discussions](https://github.com/devrath/Distance-Tracker/discussions).
6 |
7 | ### Code contribution
8 |
9 | - Open issue regarding proposed change.
10 | - If your proposed change is approved, Fork this repo and do changes.
11 | - Open PR against latest *development* branch. Add nice description in PR.
12 | - You're done!
13 |
14 | ### How to Contribute
15 | - Fork it
16 | - Create your feature branch (git checkout -b my-new-feature)
17 | - Commit your changes (git commit -am 'Add some feature')
18 | - Push to the branch (git push origin my-new-feature)
19 | - Create new Pull Request
20 |
21 | ### Code contribution checklist
22 |
23 | - New code addition/deletion should not break existing flow of a system.
24 | - All tests should be passed.
25 | - Verify `./gradlew build` is passing before raising a PR.
26 | - Reformat code with Spotless `./gradlew spotlessApply` before raising a PR.
27 |
--------------------------------------------------------------------------------