diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 78e1ae5..cecd3cd 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -4,6 +4,7 @@ plugins { id("kotlin-android") id("kotlin-parcelize") id("kotlin-kapt") + id("com.google.dagger.hilt.android") } android { @@ -40,6 +41,7 @@ android { } buildFeatures { + buildConfig = true viewBinding = true } @@ -56,13 +58,45 @@ dependencies { implementation("androidx.fragment:fragment-ktx:1.6.2") implementation("androidx.lifecycle:lifecycle-livedata-core-ktx:2.7.0") - implementation("androidx.lifecycle:lifecycle-extensions:2.2.0") implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0") implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.7.0") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0") implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:2.7.0") + implementation("androidx.recyclerview:recyclerview:1.3.2") + implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") + + implementation("androidx.room:room-runtime:${DepGradleVersion.room}") + + // To use Kotlin annotation processing tool (kapt) + kapt("androidx.room:room-compiler:${DepGradleVersion.room}") + + // optional - Kotlin Extensions and Coroutines support for Room + implementation("androidx.room:room-ktx:${DepGradleVersion.room}") + + implementation("androidx.datastore:datastore-preferences:${DepGradleVersion.preferences_version}") + + // Glide + implementation("com.github.bumptech.glide:glide:${DepGradleVersion.glide}") + + implementation("com.google.code.gson:gson:2.10.1") + implementation("com.squareup.retrofit2:retrofit:${DepGradleVersion.retrofit}") + implementation("com.squareup.retrofit2:converter-gson:${DepGradleVersion.retrofit}") + implementation("com.squareup.okhttp3:logging-interceptor:${DepGradleVersion.logging_interceptor}") + + implementation("com.google.dagger:hilt-android:${DepGradleVersion.dagger_hilt}") + + kapt("com.google.dagger:hilt-android-compiler:${DepGradleVersion.dagger_hilt}") + + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:${DepGradleVersion.coroutine}") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:${DepGradleVersion.coroutine}") + + + debugImplementation("com.github.chuckerteam.chucker:library:${DepGradleVersion.chucker}") + releaseImplementation("com.github.chuckerteam.chucker:library-no-op:${DepGradleVersion.chucker}") + + kapt("androidx.lifecycle:lifecycle-compiler:2.7.0") implementation("androidx.lifecycle:lifecycle-common-java8:2.7.0") implementation("androidx.lifecycle:lifecycle-service:2.7.0") diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/QomunalApp.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/QomunalApp.kt index 1ee274f..0c69907 100644 --- a/app/src/main/java/com/qomunal/opensource/androidresearch/QomunalApp.kt +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/QomunalApp.kt @@ -1,6 +1,8 @@ package com.qomunal.opensource.androidresearch import android.app.Application +import android.content.Context +import dagger.hilt.android.HiltAndroidApp /** * Created by faisalamircs on 13/01/2024 @@ -12,6 +14,25 @@ import android.app.Application */ +@HiltAndroidApp class QomunalApp : Application() { + init { + instance = this + } + + companion object { + private var instance: QomunalApp? = null + + fun applicationContext(): Context { + return instance!!.applicationContext + } + + + } + + override fun onCreate() { + super.onCreate() + } + } \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/di/NetworkModule.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/di/NetworkModule.kt new file mode 100644 index 0000000..5e0bc22 --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/di/NetworkModule.kt @@ -0,0 +1,69 @@ +package com.qomunal.opensource.androidresearch.di + +import android.content.Context +import com.chuckerteam.chucker.api.ChuckerInterceptor +import com.qomunal.opensource.androidresearch.BuildConfig +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent + +import okhttp3.Cache +import okhttp3.OkHttpClient +import okhttp3.ResponseBody +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Converter +import retrofit2.Retrofit +import java.lang.reflect.Type +import java.util.concurrent.TimeUnit + +@Module +@InstallIn(SingletonComponent::class) +class NetworkModule { + + @Provides + fun provideRetrofitLogging(): HttpLoggingInterceptor = if (BuildConfig.DEBUG) { + HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY) + } else { + HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.NONE) + } + + @Provides + fun provideOkHTTPClient( + loggingInterceptor: HttpLoggingInterceptor, + cache: Cache, + @ApplicationContext context: Context + ): OkHttpClient.Builder { + + // Create the Interceptor + val chuckerInterceptor = ChuckerInterceptor.Builder(context) + .build() + + return OkHttpClient.Builder() + .cache(cache) + .connectTimeout(60, TimeUnit.SECONDS) + .writeTimeout(60, TimeUnit.SECONDS) + .readTimeout(60, TimeUnit.SECONDS) + .addInterceptor(loggingInterceptor) + .addInterceptor(chuckerInterceptor) + } + + @Provides + fun provideRetrofitFactory() : Converter.Factory { + return object : Converter.Factory() { + fun converterFactory() = this + override fun responseBodyConverter( + type: Type, + annotations: Array, + retrofit: Retrofit + ) = object : Converter { + val nextResponseBodyConverter = + retrofit.nextResponseBodyConverter(converterFactory(), type, annotations) + override fun convert(value: ResponseBody) = + if (value.contentLength() != 0L) nextResponseBodyConverter.convert(value) else null + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/di/ServiceModule.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/di/ServiceModule.kt new file mode 100644 index 0000000..f5ab365 --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/di/ServiceModule.kt @@ -0,0 +1,42 @@ +package com.qomunal.opensource.androidresearch.di + +import com.qomunal.opensource.androidresearch.domain.meal.MealApiService +import com.qomunal.opensource.androidresearch.domain.news.NewsApiService +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import okhttp3.OkHttpClient +import retrofit2.Converter + +/** + * Created by faisalamircs on 14/01/2024 + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * ----------------------------------------- + */ + +@Module(includes = [NetworkModule::class]) +@InstallIn(SingletonComponent::class) +class ServiceModule { + + @Provides + fun provideNewsApiService( + httpClient: OkHttpClient.Builder, + converterFactory: Converter.Factory + ): NewsApiService { + return NewsApiService.Creator().createApi(httpClient, converterFactory) + } + + @Provides + fun provideMealApiService( + httpClient: OkHttpClient.Builder, + converterFactory: Converter.Factory + ): MealApiService { + return MealApiService.Creator().createApi(httpClient, converterFactory) + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/MealApiService.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/MealApiService.kt new file mode 100644 index 0000000..17b6a88 --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/MealApiService.kt @@ -0,0 +1,121 @@ +package com.qomunal.opensource.androidresearch.domain.meal + + +import com.google.gson.GsonBuilder +import com.qomunal.opensource.androidresearch.domain.meal.response.* +import okhttp3.OkHttpClient +import retrofit2.Converter +import retrofit2.Response +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.http.GET +import retrofit2.http.Path +import retrofit2.http.Query +import javax.inject.Inject + +/** + * Created by Faisal Amir + * FrogoBox Inc License + * ========================================= + * consumable-code-the-meal-db-api + * Copyright (C) 15/03/2020. + * All rights reserved + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * LinkedIn : linkedin.com/in/faisalamircs + * ----------------------------------------- + * FrogoBox Software Industries + * com.frogobox.frogomealsapi.data.source + * + */ +interface MealApiService { + + // Search meal by name + @GET(MealUrl.URL_SEARCH_MEAL) + suspend fun searchMeal( + @Path(MealConstant.PATH_API_KEY) apiKey: String, + @Query(MealConstant.QUERY_NAME) nameMeal: String + ): Response> + + // List all meals by first letter + @GET(MealUrl.URL_SEARCH_MEAL) + suspend fun listAllMeal( + @Path(MealConstant.PATH_API_KEY) apiKey: String, + @Query(MealConstant.QUERY_FIRST_LETTER) firstLetter: String + ): Response> + + // Lookup full meal details by id + @GET(MealUrl.URL_LOOKUP_MEAL) + suspend fun lookupFullMeal( + @Path(MealConstant.PATH_API_KEY) apiKey: String, + @Query(MealConstant.QUERY_ID) idMeal: String + ): Response> + + // Lookup a single random meal + @GET(MealUrl.URL_RANDOM_MEAL) + suspend fun lookupRandomMeal( + @Path(MealConstant.PATH_API_KEY) apiKey: String + ): Response> + + // List all meal categories + @GET(MealUrl.URL_CATEGORIES) + suspend fun listMealCategories( + @Path(MealConstant.PATH_API_KEY) apiKey: String + ): Response + + // List all Categories + @GET(MealUrl.URL_LIST) + suspend fun listAllCateories( + @Path(MealConstant.PATH_API_KEY) apiKey: String, + @Query(MealConstant.QUERY_CATEGORY) query: String + ): Response> + + // List all Area + @GET(MealUrl.URL_LIST) + suspend fun listAllArea( + @Path(MealConstant.PATH_API_KEY) apiKey: String, + @Query(MealConstant.QUERY_AREA) query: String + ): Response> + + // List all Ingredients + @GET(MealUrl.URL_LIST) + suspend fun listAllIngredients( + @Path(MealConstant.PATH_API_KEY) apiKey: String, + @Query(MealConstant.QUERY_INGREDIENT) query: String + ): Response> + + // Filter by main ingredient + @GET(MealUrl.URL_FILTER) + suspend fun filterByIngredient( + @Path(MealConstant.PATH_API_KEY) apiKey: String, + @Query(MealConstant.QUERY_INGREDIENT) ingredient: String + ): Response> + + // Filter by Category + suspend fun filterByCategory( + @Path(MealConstant.PATH_API_KEY) apiKey: String, + @Query(MealConstant.QUERY_CATEGORY) category: String + ): Response> + + // Filter by Area + suspend fun filterByArea( + @Path(MealConstant.PATH_API_KEY) apiKey: String, + @Query(MealConstant.QUERY_AREA) area: String + ): Response> + + class Creator { + @Inject + fun createApi(httpClient: OkHttpClient.Builder, converterFactory: Converter.Factory): MealApiService { + val retrofit = Retrofit.Builder().baseUrl(MealUrl.BASE_URL) + .addConverterFactory(converterFactory) + .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create())) + .client(httpClient.build()) + .build() + + return retrofit.create(MealApiService::class.java) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/MealConstant.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/MealConstant.kt new file mode 100644 index 0000000..8786b9a --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/MealConstant.kt @@ -0,0 +1,30 @@ +package com.qomunal.opensource.androidresearch.domain.meal + +/** + * Created by Faisal Amir + * ========================================= + * Copyright (C) 15/03/2020. + * All rights reserved + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * LinkedIn : linkedin.com/in/faisalamircs + * ----------------------------------------- + * + */ + +object MealConstant { + + const val QUERY_NAME = "s" + const val QUERY_FIRST_LETTER = "f" + const val QUERY_ID = "i" + const val QUERY_CATEGORY = "c" + const val QUERY_AREA = "a" + const val QUERY_INGREDIENT = "i" + + const val PATH_API_KEY = "api_key" + + const val VALUE_LIST = "list" + +} \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/MealUrl.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/MealUrl.kt new file mode 100644 index 0000000..9cc5941 --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/MealUrl.kt @@ -0,0 +1,29 @@ +package com.qomunal.opensource.androidresearch.domain.meal + +/* + * Created by faisalamir on 27/07/21 + * Consumable + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * ----------------------------------------- + * Copyright (C) 2021 FrogoBox Inc. + * All rights reserved + * + */ +object MealUrl { + + const val BASE_URL = "https://www.themealdb.com/" + const val BASE_PATH = "api/json/v1/" + const val PATH_API = "{api_key}/" + const val API_KEY = "1" + + const val URL_SEARCH_MEAL = "$BASE_PATH$PATH_API" + "search.php" + const val URL_LOOKUP_MEAL = "$BASE_PATH$PATH_API" + "lookup.php" + const val URL_RANDOM_MEAL = "$BASE_PATH$PATH_API" + "random.php" + const val URL_CATEGORIES = "$BASE_PATH$PATH_API" + "categories.php" + const val URL_LIST = "$BASE_PATH$PATH_API" + "list.php" + const val URL_FILTER = "$BASE_PATH$PATH_API" + "filter.php" + +} \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/AreaResponse.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/AreaResponse.kt new file mode 100644 index 0000000..27c74ac --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/AreaResponse.kt @@ -0,0 +1,27 @@ +package com.qomunal.opensource.androidresearch.domain.meal.response + +import com.google.gson.annotations.SerializedName + +/** + * Created by Faisal Amir + * FrogoBox Inc License + * ========================================= + * TheMealsAPI + * Copyright (C) 15/03/2020. + * All rights reserved + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * LinkedIn : linkedin.com/in/faisalamircs + * ----------------------------------------- + * FrogoBox Software Industries + * com.frogobox.frogoconsumeapi.meal.data.model + * + */ +data class AreaResponse( + + @SerializedName("strArea") + var strArea: String? = null + +) \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/CategoriesResponse.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/CategoriesResponse.kt new file mode 100644 index 0000000..cc42ff9 --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/CategoriesResponse.kt @@ -0,0 +1,27 @@ +package com.qomunal.opensource.androidresearch.domain.meal.response + +import com.google.gson.annotations.SerializedName + +/** + * Created by Faisal Amir + * FrogoBox Inc License + * ========================================= + * TheMealsAPI + * Copyright (C) 15/03/2020. + * All rights reserved + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * LinkedIn : linkedin.com/in/faisalamircs + * ----------------------------------------- + * FrogoBox Software Industries + * com.frogobox.frogoconsumeapi.meal.data.response + * + */ +data class CategoriesResponse( + + @SerializedName("categories") + var categories: List? = null + +) \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/CategoryResponse.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/CategoryResponse.kt new file mode 100644 index 0000000..c257be2 --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/CategoryResponse.kt @@ -0,0 +1,36 @@ +package com.qomunal.opensource.androidresearch.domain.meal.response + +import com.google.gson.annotations.SerializedName + +/** + * Created by Faisal Amir + * FrogoBox Inc License + * ========================================= + * TheMealsAPI + * Copyright (C) 15/03/2020. + * All rights reserved + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * LinkedIn : linkedin.com/in/faisalamircs + * ----------------------------------------- + * FrogoBox Software Industries + * com.frogobox.frogoconsumeapi.meal.data.model + * + */ +data class CategoryResponse( + + @SerializedName("idCategory") + var idCategory: String? = null, + + @SerializedName("strCategory") + var strCategory: String? = null, + + @SerializedName("strCategoryThumb") + var strCategoryThumb: String? = null, + + @SerializedName("strCategoryDescription") + var strCategoryDescription: String? = null + +) \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/IngredientResponse.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/IngredientResponse.kt new file mode 100644 index 0000000..e10dc54 --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/IngredientResponse.kt @@ -0,0 +1,36 @@ +package com.qomunal.opensource.androidresearch.domain.meal.response + +import com.google.gson.annotations.SerializedName + +/** + * Created by Faisal Amir + * FrogoBox Inc License + * ========================================= + * TheMealsAPI + * Copyright (C) 15/03/2020. + * All rights reserved + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * LinkedIn : linkedin.com/in/faisalamircs + * ----------------------------------------- + * FrogoBox Software Industries + * com.frogobox.frogoconsumeapi.meal.data.model + * + */ +data class IngredientResponse( + + @SerializedName("idIngredient") + var idIngredient: String? = null, + + @SerializedName("strIngredient") + var strIngredient: String? = null, + + @SerializedName("strDescription") + var strDescription: String? = null, + + @SerializedName("strType") + var strType: String? = null + +) \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/MealFilterResponse.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/MealFilterResponse.kt new file mode 100644 index 0000000..687a986 --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/MealFilterResponse.kt @@ -0,0 +1,33 @@ +package com.qomunal.opensource.androidresearch.domain.meal.response + +import com.google.gson.annotations.SerializedName + +/** + * Created by Faisal Amir + * FrogoBox Inc License + * ========================================= + * TheMealsAPI + * Copyright (C) 15/03/2020. + * All rights reserved + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * LinkedIn : linkedin.com/in/faisalamircs + * ----------------------------------------- + * FrogoBox Software Industries + * com.frogobox.frogoconsumeapi.meal.data.model + * + */ +data class MealFilterResponse( + + @SerializedName("strMeal") + var strMeal: String? = null, + + @SerializedName("strMealThumb") + var strMealThumb: String? = null, + + @SerializedName("idMeal") + var idMeal: String? = null + +) \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/MealResponse.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/MealResponse.kt new file mode 100644 index 0000000..6c0ba97 --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/MealResponse.kt @@ -0,0 +1,177 @@ +package com.qomunal.opensource.androidresearch.domain.meal.response + +import com.google.gson.annotations.SerializedName + +/** + * Created by Faisal Amir + * FrogoBox Inc License + * ========================================= + * consumable-code-the-meal-db-api + * Copyright (C) 15/03/2020. + * All rights reserved + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * LinkedIn : linkedin.com/in/faisalamircs + * ----------------------------------------- + * FrogoBox Software Industries + * com.frogobox.frogomealsapi.data.model + * + */ +data class MealResponse( + + @SerializedName("idMeal") + var idMeal: String? = null, + + @SerializedName("strMeal") + var strMeal: String? = null, + + @SerializedName("strDrinkAlternate") + var strDrinkAlternate: String? = null, + + @SerializedName("strCategory") + var strCategory: String? = null, + + @SerializedName("strArea") + var strArea: String? = null, + + @SerializedName("strInstructions") + var strInstructions: String? = null, + + @SerializedName("strMealThumb") + var strMealThumb: String? = null, + + @SerializedName("strTags") + var strTags: String? = null, + + @SerializedName("strYoutube") + var strYoutube: String? = null, + + @SerializedName("strIngredient1") + var strIngredient1: String? = null, + + @SerializedName("strIngredient2") + var strIngredient2: String? = null, + + @SerializedName("strIngredient3") + var strIngredient3: String? = null, + + @SerializedName("strIngredient4") + var strIngredient4: String? = null, + + @SerializedName("strIngredient5") + var strIngredient5: String? = null, + + @SerializedName("strIngredient6") + var strIngredient6: String? = null, + + @SerializedName("strIngredient7") + var strIngredient7: String? = null, + + @SerializedName("strIngredient8") + var strIngredient8: String? = null, + + @SerializedName("strIngredient9") + var strIngredient9: String? = null, + + @SerializedName("strIngredient10") + var strIngredient10: String? = null, + + @SerializedName("strIngredient11") + var strIngredient11: String? = null, + + @SerializedName("strIngredient12") + var strIngredient12: String? = null, + + @SerializedName("strIngredient13") + var strIngredient13: String? = null, + + @SerializedName("strIngredient14") + var strIngredient14: String? = null, + + @SerializedName("strIngredient15") + var strIngredient15: String? = null, + + @SerializedName("strIngredient16") + var strIngredient16: String? = null, + + @SerializedName("strIngredient17") + var strIngredient17: String? = null, + + @SerializedName("strIngredient18") + var strIngredient18: String? = null, + + @SerializedName("strIngredient19") + var strIngredient19: String? = null, + + @SerializedName("strIngredient20") + var strIngredient20: String? = null, + + @SerializedName("strMeasure1") + var strMeasure1: String? = null, + + @SerializedName("strMeasure2") + var strMeasure2: String? = null, + + @SerializedName("strMeasure3") + var strMeasure3: String? = null, + + @SerializedName("strMeasure4") + var strMeasure4: String? = null, + + @SerializedName("strMeasure5") + var strMeasure5: String? = null, + + @SerializedName("strMeasure6") + var strMeasure6: String? = null, + + @SerializedName("strMeasure7") + var strMeasure7: String? = null, + + @SerializedName("strMeasure8") + var strMeasure8: String? = null, + + @SerializedName("strMeasure9") + var strMeasure9: String? = null, + + @SerializedName("strMeasure10") + var strMeasure10: String? = null, + + @SerializedName("strMeasure11") + var strMeasure11: String? = null, + + @SerializedName("strMeasure12") + var strMeasure12: String? = null, + + @SerializedName("strMeasure13") + var strMeasure13: String? = null, + + @SerializedName("strMeasure14") + var strMeasure14: String? = null, + + @SerializedName("strMeasure15") + var strMeasure15: String? = null, + + @SerializedName("strMeasure16") + var strMeasure16: String? = null, + + @SerializedName("strMeasure17") + var strMeasure17: String? = null, + + @SerializedName("strMeasure18") + var strMeasure18: String? = null, + + @SerializedName("strMeasure19") + var strMeasure19: String? = null, + + @SerializedName("strMeasure20") + var strMeasure20: String? = null, + + @SerializedName("strSource") + var strSource: String? = null, + + @SerializedName("dateModified") + var dateModified: String? = null + +) \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/MealsResponse.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/MealsResponse.kt new file mode 100644 index 0000000..5361618 --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/meal/response/MealsResponse.kt @@ -0,0 +1,27 @@ +package com.qomunal.opensource.androidresearch.domain.meal.response + +import com.google.gson.annotations.SerializedName + +/** + * Created by Faisal Amir + * FrogoBox Inc License + * ========================================= + * TheMealsAPI + * Copyright (C) 15/03/2020. + * All rights reserved + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * LinkedIn : linkedin.com/in/faisalamircs + * ----------------------------------------- + * FrogoBox Software Industries + * com.frogobox.frogoconsumeapi.meal.data.response + * + */ +data class MealsResponse( + + @SerializedName("meals") + var meals: List? = null + +) \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/NewsApiService.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/NewsApiService.kt new file mode 100644 index 0000000..073dd28 --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/NewsApiService.kt @@ -0,0 +1,99 @@ +package com.qomunal.opensource.androidresearch.domain.news + +import com.google.gson.GsonBuilder +import com.qomunal.opensource.androidresearch.domain.news.NewsConstant.QUERY_API_KEY +import com.qomunal.opensource.androidresearch.domain.news.NewsConstant.QUERY_CATEGORY +import com.qomunal.opensource.androidresearch.domain.news.NewsConstant.QUERY_COUNTRY +import com.qomunal.opensource.androidresearch.domain.news.NewsConstant.QUERY_DOMAINS +import com.qomunal.opensource.androidresearch.domain.news.NewsConstant.QUERY_EXCLUDE_DOMAINS +import com.qomunal.opensource.androidresearch.domain.news.NewsConstant.QUERY_FROM +import com.qomunal.opensource.androidresearch.domain.news.NewsConstant.QUERY_LANGUAGE +import com.qomunal.opensource.androidresearch.domain.news.NewsConstant.QUERY_PAGE +import com.qomunal.opensource.androidresearch.domain.news.NewsConstant.QUERY_PAGE_SIZE +import com.qomunal.opensource.androidresearch.domain.news.NewsConstant.QUERY_Q +import com.qomunal.opensource.androidresearch.domain.news.NewsConstant.QUERY_Q_IN_TITLE +import com.qomunal.opensource.androidresearch.domain.news.NewsConstant.QUERY_SORT_BY +import com.qomunal.opensource.androidresearch.domain.news.NewsConstant.QUERY_SOURCES +import com.qomunal.opensource.androidresearch.domain.news.NewsConstant.QUERY_TO +import com.qomunal.opensource.androidresearch.domain.news.NewsUrl.URL_EVERYTHING +import com.qomunal.opensource.androidresearch.domain.news.NewsUrl.URL_SOURCES +import com.qomunal.opensource.androidresearch.domain.news.NewsUrl.URL_TOP_HEADLINE +import com.qomunal.opensource.androidresearch.domain.news.response.* +import okhttp3.OkHttpClient +import retrofit2.Converter +import retrofit2.Response +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.http.GET +import retrofit2.http.Query +import javax.inject.Inject + +/** + * Created by Faisal Amir + * FrogoBox Inc License + * ========================================= + * Copyright (C) 15/03/2020. + * All rights reserved + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * LinkedIn : linkedin.com/in/faisalamircs + * ----------------------------------------- + * FrogoBox Software Industries + * + */ +interface NewsApiService { + + // Get Top Headline + @GET(URL_TOP_HEADLINE) + suspend fun getTopHeadline( + @Query(QUERY_API_KEY) apiKey: String, + @Query(QUERY_Q) q: String?, + @Query(QUERY_SOURCES) sources: String?, + @Query(QUERY_CATEGORY) category: String?, + @Query(QUERY_COUNTRY) country: String?, + @Query(QUERY_PAGE_SIZE) pageSize: Int?, + @Query(QUERY_PAGE) page: Int? + ): Response + + // Get Everythings + @GET(URL_EVERYTHING) + suspend fun getEverythings( + @Query(QUERY_API_KEY) apiKey: String, + @Query(QUERY_Q) q: String?, + @Query(QUERY_FROM) from: String?, + @Query(QUERY_TO) to: String?, + @Query(QUERY_Q_IN_TITLE) qInTitle: String?, + @Query(QUERY_SOURCES) sources: String?, + @Query(QUERY_DOMAINS) domains: String?, + @Query(QUERY_EXCLUDE_DOMAINS) excludeDomains: String?, + @Query(QUERY_LANGUAGE) language: String?, + @Query(QUERY_SORT_BY) sortBy: String?, + @Query(QUERY_PAGE_SIZE) pageSize: Int?, + @Query(QUERY_PAGE) page: Int? + ): Response + + // Get Sources + @GET(URL_SOURCES) + suspend fun getSources( + @Query(QUERY_API_KEY) apiKey: String, + @Query(QUERY_LANGUAGE) language: String, + @Query(QUERY_COUNTRY) country: String, + @Query(QUERY_CATEGORY) category: String + ): Response + + class Creator { + @Inject + fun createApi(httpClient: OkHttpClient.Builder, converterFactory: Converter.Factory): NewsApiService { + val retrofit = Retrofit.Builder().baseUrl(NewsUrl.BASE_URL) + .addConverterFactory(converterFactory) + .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create())) + .client(httpClient.build()) + .build() + + return retrofit.create(NewsApiService::class.java) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/NewsConstant.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/NewsConstant.kt new file mode 100644 index 0000000..96834dc --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/NewsConstant.kt @@ -0,0 +1,100 @@ +package com.qomunal.opensource.androidresearch.domain.news + +/** + * Created by Faisal Amir + * FrogoBox Inc License + * ========================================= + * consumable-code-news-api + * Copyright (C) 15/03/2020. + * All rights reserved + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * LinkedIn : linkedin.com/in/faisalamircs + * ----------------------------------------- + * FrogoBox Software Industries + * com.frogobox.frogoconsumeapi.news.util + * + */ +object NewsConstant { + + const val QUERY_API_KEY = "apiKey" + const val QUERY_SOURCES = "sources" + const val QUERY_CATEGORY = "category" + const val QUERY_Q = "q" + const val QUERY_Q_IN_TITLE = "qInTitle" + const val QUERY_LANGUAGE = "language" + const val QUERY_COUNTRY = "country" + const val QUERY_PAGE_SIZE = "pageSize" + const val QUERY_PAGE = "page" + const val QUERY_DOMAINS = "domains" + const val QUERY_EXCLUDE_DOMAINS = "excludeDomains" + const val QUERY_FROM = "from" + const val QUERY_TO = "to" + const val QUERY_SORT_BY = "sortBy" + + const val CATEGORY_BUSINESS = "business" + const val CATEGORY_ENTERTAIMENT = "entertainment" + const val CATEGORY_GENERAL = "general" + const val CATEGORY_HEALTH = "health" + const val CATEGORY_SCIENCE = "science" + const val CATEGORY_SPORTS = "sports" + const val CATEGORY_TECHNOLOGY = "technology" + + const val COUNTRY_AE = "ae" + const val COUNTRY_AR = "ar" + const val COUNTRY_AT = "at" + const val COUNTRY_AU = "au" + const val COUNTRY_BE = "be" + const val COUNTRY_BG = "bg" + const val COUNTRY_BR = "br" + const val COUNTRY_CA = "ca" + const val COUNTRY_CH = "ch" + const val COUNTRY_CN = "cn" + const val COUNTRY_CO = "co" + const val COUNTRY_CU = "cu" + const val COUNTRY_CZ = "cz" + const val COUNTRY_DE = "de" + const val COUNTRY_EG = "eg" + const val COUNTRY_FR = "fr" + const val COUNTRY_GB = "gb" + const val COUNTRY_GR = "gr" + const val COUNTRY_HK = "hk" + const val COUNTRY_HU = "hu" + const val COUNTRY_ID = "id" + const val COUNTRY_IE = "ie" + const val COUNTRY_IL = "il" + const val COUNTRY_IN = "in" + const val COUNTRY_IT = "it" + const val COUNTRY_JP = "jp" + const val COUNTRY_KR = "kr" + const val COUNTRY_LT = "lt" + const val COUNTRY_LV = "lv" + const val COUNTRY_MA = "ma" + const val COUNTRY_MX = "mx" + const val COUNTRY_MY = "my" + const val COUNTRY_NG = "ng" + const val COUNTRY_NL = "nl" + const val COUNTRY_NO = "no" + const val COUNTRY_NZ = "nz" + const val COUNTRY_PH = "ph" + const val COUNTRY_PL = "pl" + const val COUNTRY_PT = "pt" + const val COUNTRY_RO = "ro" + const val COUNTRY_RS = "rs" + const val COUNTRY_RU = "ru" + const val COUNTRY_SA = "sa" + const val COUNTRY_SE = "se" + const val COUNTRY_SG = "sg" + const val COUNTRY_SI = "si" + const val COUNTRY_SK = "sk" + const val COUNTRY_TH = "th" + const val COUNTRY_TR = "tr" + const val COUNTRY_TW = "tw" + const val COUNTRY_UA = "ua" + const val COUNTRY_US = "us" + const val COUNTRY_VE = "ve" + const val COUNTRY_ZA = "za" + +} \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/NewsUrl.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/NewsUrl.kt new file mode 100644 index 0000000..54d0036 --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/NewsUrl.kt @@ -0,0 +1,29 @@ +package com.qomunal.opensource.androidresearch.domain.news + +/* + * Created by faisalamir on 27/07/21 + * Consumable + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * ----------------------------------------- + * All rights reserved + * + */ +object NewsUrl { + + const val BASE_URL = "https://newsapi.org/" + const val API_KEY = "84d090d0537548ee8ac77620217b1b52" + + const val BASE_PATH = "v2/" + + const val PATH_TOP_HEADLINE = "top-headlines" + const val PATH_EVERYTHING = "everything" + const val PATH_SOURCES = "sources" + + const val URL_TOP_HEADLINE = "$BASE_PATH$PATH_TOP_HEADLINE" + const val URL_EVERYTHING = "$BASE_PATH$PATH_EVERYTHING" + const val URL_SOURCES = "$BASE_PATH$PATH_SOURCES" + +} \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/response/ArticleResponse.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/response/ArticleResponse.kt new file mode 100644 index 0000000..dfe0d1e --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/response/ArticleResponse.kt @@ -0,0 +1,47 @@ +package com.qomunal.opensource.androidresearch.domain.news.response + +import com.google.gson.annotations.SerializedName + +/** + * Created by Faisal Amir + * FrogoBox Inc License + * ========================================= + * NewsApi + * Copyright (C) 15/03/2020. + * All rights reserved + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * LinkedIn : linkedin.com/in/faisalamircs + * ----------------------------------------- + * FrogoBox Software Industries + * com.frogobox.frogoconsumeapi.news.data.model + * + */ +data class ArticleResponse( + + @SerializedName("source") + var source: SourceResponse? = null, + + @SerializedName("author") + var author: String? = null, + + @SerializedName("title") + var title: String? = null, + + @SerializedName("description") + var description: String? = null, + + @SerializedName("url") + var url: String? = null, + + @SerializedName("urlToImage") + var urlToImage: String? = null, + + @SerializedName("publishedAt") + var publishedAt: String? = null, + + @SerializedName("content") + var content: String? = null +) \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/response/ArticlesResponse.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/response/ArticlesResponse.kt new file mode 100644 index 0000000..d234e78 --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/response/ArticlesResponse.kt @@ -0,0 +1,39 @@ +package com.qomunal.opensource.androidresearch.domain.news.response + +import com.google.gson.annotations.SerializedName + +/** + * Created by Faisal Amir + * FrogoBox Inc License + * ========================================= + * NewsApi + * Copyright (C) 15/03/2020. + * All rights reserved + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * LinkedIn : linkedin.com/in/faisalamircs + * ----------------------------------------- + * FrogoBox Software Industries + * com.frogobox.frogoconsumeapi.news.data.response + * + */ +data class ArticlesResponse( + + @SerializedName("status") + var status: String? = null, + + @SerializedName("totalResults") + var totalResults: Int? = null, + + @SerializedName("code") + var code: String? = null, + + @SerializedName("message") + var message: String? = null, + + @SerializedName("articles") + var articles: List? = null + +) \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/response/SourceResponse.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/response/SourceResponse.kt new file mode 100644 index 0000000..40f3101 --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/response/SourceResponse.kt @@ -0,0 +1,39 @@ +package com.qomunal.opensource.androidresearch.domain.news.response + +import com.google.gson.annotations.SerializedName + +/** + * Created by Faisal Amir + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * LinkedIn : linkedin.com/in/faisalamircs + * ----------------------------------------- + * FrogoBox Software Industries + * + */ +data class SourceResponse( + + @SerializedName("id") + var id: String? = null, + + @SerializedName("name") + var name: String? = null, + + @SerializedName("description") + var description: String? = null, + + @SerializedName("url") + var url: String? = null, + + @SerializedName("category") + var category: String? = null, + + @SerializedName("language") + var language: String? = null, + + @SerializedName("country") + var country: String? = null + +) \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/response/SourcesResponse.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/response/SourcesResponse.kt new file mode 100644 index 0000000..08439c5 --- /dev/null +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/domain/news/response/SourcesResponse.kt @@ -0,0 +1,30 @@ +package com.qomunal.opensource.androidresearch.domain.news.response + +import com.google.gson.annotations.SerializedName + +/** + * Created by Faisal Amir + * FrogoBox Inc License + * ========================================= + * NewsApi + * Copyright (C) 15/03/2020. + * All rights reserved + * ----------------------------------------- + * Name : Muhammad Faisal Amir + * E-mail : faisalamircs@gmail.com + * Github : github.com/amirisback + * LinkedIn : linkedin.com/in/faisalamircs + * ----------------------------------------- + * FrogoBox Software Industries + * com.frogobox.frogoconsumeapi.news.data.response + * + */ +data class SourcesResponse( + + @SerializedName("status") + var status: String? = null, + + @SerializedName("sources") + var sources: List? = null + +) \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/model/MainModel.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/model/MainModel.kt index b3403ae..288678b 100644 --- a/app/src/main/java/com/qomunal/opensource/androidresearch/model/MainModel.kt +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/model/MainModel.kt @@ -1,5 +1,7 @@ package com.qomunal.opensource.androidresearch.model +import androidx.annotation.Keep + /** * Created by faisalamircs on 13/01/2024 * ----------------------------------------- @@ -10,6 +12,7 @@ package com.qomunal.opensource.androidresearch.model */ +@Keep data class MainModel( val tag: String ) \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/ui/detail/DetailActivity.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/ui/detail/DetailActivity.kt index 44a8b6c..784a366 100644 --- a/app/src/main/java/com/qomunal/opensource/androidresearch/ui/detail/DetailActivity.kt +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/ui/detail/DetailActivity.kt @@ -4,6 +4,7 @@ import android.os.Bundle import androidx.activity.viewModels import com.qomunal.opensource.androidresearch.common.base.BaseActivity import com.qomunal.opensource.androidresearch.databinding.ActivityDetailBinding +import dagger.hilt.android.AndroidEntryPoint /** * Created by faisalamircs on 13/01/2024 @@ -15,6 +16,7 @@ import com.qomunal.opensource.androidresearch.databinding.ActivityDetailBinding */ +@AndroidEntryPoint class DetailActivity : BaseActivity() { private val viewModel: DetailViewModel by viewModels() diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/ui/detail/DetailViewModel.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/ui/detail/DetailViewModel.kt index aeb437b..66efc1e 100644 --- a/app/src/main/java/com/qomunal/opensource/androidresearch/ui/detail/DetailViewModel.kt +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/ui/detail/DetailViewModel.kt @@ -1,6 +1,8 @@ package com.qomunal.opensource.androidresearch.ui.detail import com.qomunal.opensource.androidresearch.common.base.BaseViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject /** * Created by faisalamircs on 13/01/2024 @@ -11,7 +13,7 @@ import com.qomunal.opensource.androidresearch.common.base.BaseViewModel * ----------------------------------------- */ - -class DetailViewModel : BaseViewModel() { +@HiltViewModel +class DetailViewModel @Inject constructor() : BaseViewModel() { } \ No newline at end of file diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/ui/main/MainActivity.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/ui/main/MainActivity.kt index 0f1cb33..12c5353 100644 --- a/app/src/main/java/com/qomunal/opensource/androidresearch/ui/main/MainActivity.kt +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/ui/main/MainActivity.kt @@ -4,7 +4,9 @@ import android.os.Bundle import androidx.activity.viewModels import com.qomunal.opensource.androidresearch.common.base.BaseActivity import com.qomunal.opensource.androidresearch.databinding.ActivityMainBinding +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class MainActivity : BaseActivity() { private val viewModel: MainViewModel by viewModels() diff --git a/app/src/main/java/com/qomunal/opensource/androidresearch/ui/main/MainViewModel.kt b/app/src/main/java/com/qomunal/opensource/androidresearch/ui/main/MainViewModel.kt index b54f970..b616135 100644 --- a/app/src/main/java/com/qomunal/opensource/androidresearch/ui/main/MainViewModel.kt +++ b/app/src/main/java/com/qomunal/opensource/androidresearch/ui/main/MainViewModel.kt @@ -1,6 +1,8 @@ package com.qomunal.opensource.androidresearch.ui.main import com.qomunal.opensource.androidresearch.common.base.BaseViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject /** * Created by faisalamircs on 13/01/2024 @@ -11,6 +13,7 @@ import com.qomunal.opensource.androidresearch.common.base.BaseViewModel * ----------------------------------------- */ -class MainViewModel : BaseViewModel() { +@HiltViewModel +class MainViewModel @Inject constructor() : BaseViewModel() { } \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 174c2c7..4207c1f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,4 +2,5 @@ plugins { id("com.android.application") version "8.2.0" apply false id("org.jetbrains.kotlin.android") version "1.9.10" apply false + id("com.google.dagger.hilt.android") version DepGradleVersion.dagger_hilt apply false } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/DepGradleVersion.kt b/buildSrc/src/main/kotlin/DepGradleVersion.kt index 2369aed..1a0598f 100644 --- a/buildSrc/src/main/kotlin/DepGradleVersion.kt +++ b/buildSrc/src/main/kotlin/DepGradleVersion.kt @@ -10,4 +10,55 @@ object DepGradleVersion { + // Android + const val core_ktx = "1.12.0" + const val app_compat = "1.6.1" + const val material = "1.10.0" + const val ktx = "2.6.2" + const val constraint_layout = "2.1.4" + const val fragment_ktx_version = "1.6.2" + const val room = "2.6.1" + const val dagger_hilt = "2.49" + const val junit = "4.13.2" + const val ext_junit = "1.1.5" + const val espresso_core = "3.5.1" + const val navigation_fragment = "2.7.5" + const val preferences_version = "1.0.0" + const val permissionx_version = "1.7.1" + const val google_gms_location = "21.0.1" + const val google_gms_auth = "20.7.0" + const val coroutine = "1.7.3" + + const val retrofit = "2.9.0" + const val logging_interceptor = "4.11.0" + + const val locus = "5.0.0" + const val pretty_time = "5.0.4.Final" + const val apache = "1.9" + + const val firebase_bom = "31.1.1" + const val firebase_messaging = "23.3.1" + const val image_picker = "2.1" + + const val pusher = "2.4.4" + const val light_compressor = "1.2.3" + const val compressor = "3.0.1" + + const val exo_player = "2.19.1" + const val pager_indicator = "1.2.4" + const val currency_et = "1.0.0" + + const val flexbox = "3.0.0" + const val camerax = "1.1.0-alpha25" + + // Github + const val timber = "5.0.1" + const val social_view = "0.1" + const val qrgen = "3.0.1" // https://github.com/kenglxn/QRGen + const val chucker = "4.0.0" + const val glide = "4.15.1" + const val piximage = "1.6.3" + const val pinview = "1.4.4" + const val mp_chart = "v3.1.0" + } \ No newline at end of file