diff --git a/.editorconfig b/.editorconfig
index d1668e9..612698b 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,5 +1,103 @@
root = true
-[*.{kt,java}]
+[*]
+charset = utf-8
+end_of_line = lf
indent_size = 4
-insert_final_newline = true
\ No newline at end of file
+indent_style = space
+insert_final_newline = true
+max_line_length = 120
+tab_width = 4
+ij_continuation_indent_size = 8
+ij_formatter_off_tag = @formatter:off
+ij_formatter_on_tag = @formatter:on
+ij_formatter_tags_enabled = true
+ij_smart_tabs = false
+ij_visual_guides =
+ij_wrap_on_typing = false
+
+[{*.kt,*.kts}]
+ij_kotlin_align_in_columns_case_branch = false
+ij_kotlin_align_multiline_binary_operation = false
+ij_kotlin_align_multiline_extends_list = false
+ij_kotlin_align_multiline_method_parentheses = false
+ij_kotlin_align_multiline_parameters = true
+ij_kotlin_align_multiline_parameters_in_calls = false
+ij_kotlin_allow_trailing_comma = false
+ij_kotlin_allow_trailing_comma_on_call_site = false
+ij_kotlin_assignment_wrap = normal
+ij_kotlin_blank_lines_after_class_header = 0
+ij_kotlin_blank_lines_around_block_when_branches = 0
+ij_kotlin_blank_lines_before_declaration_with_comment_or_annotation_on_separate_line = 1
+ij_kotlin_block_comment_add_space = false
+ij_kotlin_block_comment_at_first_column = true
+ij_kotlin_call_parameters_new_line_after_left_paren = true
+ij_kotlin_call_parameters_right_paren_on_new_line = true
+ij_kotlin_call_parameters_wrap = on_every_item
+ij_kotlin_catch_on_new_line = false
+ij_kotlin_class_annotation_wrap = split_into_lines
+ij_kotlin_code_style_defaults = KOTLIN_OFFICIAL
+ij_kotlin_continuation_indent_for_chained_calls = false
+ij_kotlin_continuation_indent_for_expression_bodies = false
+ij_kotlin_continuation_indent_in_argument_lists = false
+ij_kotlin_continuation_indent_in_elvis = false
+ij_kotlin_continuation_indent_in_if_conditions = false
+ij_kotlin_continuation_indent_in_parameter_lists = false
+ij_kotlin_continuation_indent_in_supertype_lists = false
+ij_kotlin_else_on_new_line = false
+ij_kotlin_enum_constants_wrap = off
+ij_kotlin_extends_list_wrap = normal
+ij_kotlin_field_annotation_wrap = split_into_lines
+ij_kotlin_finally_on_new_line = false
+ij_kotlin_if_rparen_on_new_line = true
+ij_kotlin_import_nested_classes = false
+ij_kotlin_imports_layout = *,java.**,javax.**,kotlin.**,^
+ij_kotlin_insert_whitespaces_in_simple_one_line_method = true
+ij_kotlin_keep_blank_lines_before_right_brace = 2
+ij_kotlin_keep_blank_lines_in_code = 2
+ij_kotlin_keep_blank_lines_in_declarations = 2
+ij_kotlin_keep_first_column_comment = true
+ij_kotlin_keep_indents_on_empty_lines = false
+ij_kotlin_keep_line_breaks = true
+ij_kotlin_lbrace_on_next_line = false
+ij_kotlin_line_break_after_multiline_when_entry = true
+ij_kotlin_line_comment_add_space = false
+ij_kotlin_line_comment_add_space_on_reformat = false
+ij_kotlin_line_comment_at_first_column = true
+ij_kotlin_method_annotation_wrap = split_into_lines
+ij_kotlin_method_call_chain_wrap = normal
+ij_kotlin_method_parameters_new_line_after_left_paren = true
+ij_kotlin_method_parameters_right_paren_on_new_line = true
+ij_kotlin_method_parameters_wrap = on_every_item
+ij_kotlin_name_count_to_use_star_import = 2147483647
+ij_kotlin_name_count_to_use_star_import_for_members = 2147483647
+ij_kotlin_packages_to_use_import_on_demand =
+ij_kotlin_parameter_annotation_wrap = off
+ij_kotlin_space_after_comma = true
+ij_kotlin_space_after_extend_colon = true
+ij_kotlin_space_after_type_colon = true
+ij_kotlin_space_before_catch_parentheses = true
+ij_kotlin_space_before_comma = false
+ij_kotlin_space_before_extend_colon = true
+ij_kotlin_space_before_for_parentheses = true
+ij_kotlin_space_before_if_parentheses = true
+ij_kotlin_space_before_lambda_arrow = true
+ij_kotlin_space_before_type_colon = false
+ij_kotlin_space_before_when_parentheses = true
+ij_kotlin_space_before_while_parentheses = true
+ij_kotlin_spaces_around_additive_operators = true
+ij_kotlin_spaces_around_assignment_operators = true
+ij_kotlin_spaces_around_equality_operators = true
+ij_kotlin_spaces_around_function_type_arrow = true
+ij_kotlin_spaces_around_logical_operators = true
+ij_kotlin_spaces_around_multiplicative_operators = true
+ij_kotlin_spaces_around_range = false
+ij_kotlin_spaces_around_relational_operators = true
+ij_kotlin_spaces_around_unary_operator = false
+ij_kotlin_spaces_around_when_arrow = true
+ij_kotlin_use_custom_formatting_for_modifiers = true
+ij_kotlin_variable_annotation_wrap = off
+ij_kotlin_while_on_new_line = false
+ij_kotlin_wrap_elvis_expressions = 1
+ij_kotlin_wrap_expression_body_functions = 1
+ij_kotlin_wrap_first_method_in_call_chain = false
diff --git a/.github/workflows/detekt-action.yml b/.github/workflows/detekt-action.yml
new file mode 100644
index 0000000..dc9b0c9
--- /dev/null
+++ b/.github/workflows/detekt-action.yml
@@ -0,0 +1,21 @@
+name: detekt
+on: [ push, pull_request ]
+jobs:
+ detekt:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Setup JDK
+ uses: actions/setup-java@v3
+ with:
+ distribution: oracle
+ java-version: '17'
+
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+
+ - name: Run detekt
+ run: ./gradlew detekt
diff --git a/.gitignore b/.gitignore
index f8fc33b..9f57cd7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,8 @@
.cxx
local.properties
/app/config/release.keystore
+/.idea/appInsightsSettings.xml
+/.idea/deploymentTargetSelector.xml
+/.idea/migrations.xml
+/.idea/other.xml
+/config/release.keystore
diff --git a/.idea/.name b/.idea/.name
deleted file mode 100644
index fdbe9f4..0000000
--- a/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-Inmuslim
\ No newline at end of file
diff --git a/.idea/detekt.xml b/.idea/detekt.xml
new file mode 100644
index 0000000..6166a57
--- /dev/null
+++ b/.idea/detekt.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index ae388c2..0897082 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -4,16 +4,15 @@
-
-
-
+
+
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 103e00c..44ca2d9 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -3,30 +3,39 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index 0fc3113..148fdd2 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
deleted file mode 100644
index a55c547..0000000
--- a/app/build.gradle
+++ /dev/null
@@ -1,145 +0,0 @@
-plugins {
- id 'com.android.application'
- id 'org.jetbrains.kotlin.android'
- id "dagger.hilt.android.plugin"
- id "kotlin-kapt"
- id 'com.google.gms.google-services'
- id 'com.google.firebase.crashlytics'
- id 'io.gitlab.arturbosch.detekt'
-}
-
-android {
- namespace 'tj.rsdevteam.inmuslim'
- compileSdk 33
-
- defaultConfig {
- applicationId "tj.rsdevteam.inmuslim"
- minSdk 24
- targetSdk 33
- versionCode 4
- versionName "1.0.3"
-
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
- vectorDrawables {
- useSupportLibrary true
- }
- }
- signingConfigs {
- debug {
- storeFile file("config/debug.keystore")
- storePassword DEBUG_STORE_PASSWORD
- keyAlias DEBUG_KEY_ALIAS
- keyPassword DEBUG_KEY_PASSWORD
- }
- release {
- Properties properties = new Properties()
- properties.load(project.rootProject.file("local.properties").newDataInputStream())
-
- storeFile file("config/release.keystore")
- storePassword properties.getProperty("RELEASE_STORE_PASSWORD", "")
- keyAlias properties.getProperty("RELEASE_KEY_ALIAS", "")
- keyPassword properties.getProperty("RELEASE_KEY_PASSWORD", "")
- }
- }
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- signingConfig signingConfigs.release
- }
- debug {
- debuggable true
- applicationIdSuffix '.beta'
- signingConfig signingConfigs.debug
- }
- }
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_17
- targetCompatibility JavaVersion.VERSION_17
- }
- kotlinOptions {
- jvmTarget = '17'
- }
- buildFeatures {
- compose true
- }
- composeOptions {
- kotlinCompilerExtensionVersion '1.4.3'
- }
- packaging {
- resources {
- excludes += '/META-INF/{AL2.0,LGPL2.1}'
- }
- }
-}
-
-detekt {
- toolVersion = "1.23.0"
- config = files("config/detekt/detekt.yml")
- buildUponDefaultConfig = true
- baseline = file("$rootDir/detekt-baseline.xml")
-}
-
-dependencies {
-
- implementation 'androidx.core:core-ktx:1.9.0'
-
- // compose
- implementation platform('androidx.compose:compose-bom:2023.06.00')
- implementation 'androidx.compose.ui:ui'
- implementation 'androidx.compose.ui:ui-graphics'
- implementation 'androidx.compose.ui:ui-tooling-preview'
- implementation 'androidx.compose.material3:material3'
- implementation 'androidx.activity:activity-compose:1.7.2'
- debugImplementation 'androidx.compose.ui:ui-tooling'
- debugImplementation 'androidx.compose.ui:ui-test-manifest'
-
- testImplementation 'junit:junit:4.13.2'
- androidTestImplementation 'androidx.test.ext:junit:1.1.5'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
- androidTestImplementation platform('androidx.compose:compose-bom:2023.03.00')
- androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
-
- // navigation
- implementation "androidx.navigation:navigation-compose:2.6.0"
-
- // hilt
- implementation "com.google.dagger:hilt-android:2.44"
- kapt "com.google.dagger:hilt-android-compiler:2.44"
- kapt "androidx.hilt:hilt-compiler:1.0.0"
- implementation "androidx.hilt:hilt-navigation-compose:1.0.0"
-
- // lifecycle
- def lifecycle_version = "2.5.0"
- implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version"
- implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
- implementation "androidx.lifecycle:lifecycle-runtime-compose:$lifecycle_version"
- implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
-
- // coroutines
- def coroutines_version = '1.3.7'
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
-
- // okhttp
- def okhttp_version = '4.10.0'
- implementation "com.squareup.okhttp3:okhttp:$okhttp_version"
- implementation "com.squareup.okhttp3:logging-interceptor:$okhttp_version"
-
- // retrofit
- def retrofit_version = '2.9.0'
- implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
- implementation "com.squareup.retrofit2:converter-moshi:$retrofit_version"
-
- // moshi
- def moshi_version = "1.14.0"
- implementation "com.squareup.moshi:moshi:$moshi_version"
- implementation "com.squareup.moshi:moshi-kotlin:$moshi_version"
- kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
-
- // firebase
- implementation platform('com.google.firebase:firebase-bom:28.3.0')
- implementation 'com.google.firebase:firebase-messaging-ktx'
- implementation 'com.google.firebase:firebase-analytics-ktx'
- implementation 'com.google.firebase:firebase-crashlytics-ktx'
-}
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
new file mode 100644
index 0000000..9490b2f
--- /dev/null
+++ b/app/build.gradle.kts
@@ -0,0 +1,143 @@
+import java.io.FileInputStream
+import java.util.Properties
+
+plugins {
+ alias(libs.plugins.android.application)
+ alias(libs.plugins.jetbrains.kotlin.android)
+ alias(libs.plugins.jetbrains.kotlin.kapt)
+ alias(libs.plugins.ksp)
+ alias(libs.plugins.dagger.hilt.android)
+ alias(libs.plugins.google.services)
+ alias(libs.plugins.firebase.crashlytics)
+}
+
+android {
+ namespace = "tj.rsdevteam.inmuslim"
+ compileSdk = libs.versions.androidSdk.get().toInt()
+
+ defaultConfig {
+ applicationId = "tj.rsdevteam.inmuslim"
+ minSdk = libs.versions.androidMinSdk.get().toInt()
+ targetSdk = libs.versions.androidSdk.get().toInt()
+ versionCode = 4
+ versionName = "1.0.3"
+
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ vectorDrawables {
+ useSupportLibrary = true
+ }
+ }
+ signingConfigs {
+ getByName("debug") {
+ storeFile = file("$rootDir/config/debug.keystore")
+ storePassword = project.properties["DEBUG_STORE_PASSWORD"] as String
+ keyAlias = project.properties["DEBUG_KEY_ALIAS"] as String
+ keyPassword = project.properties["DEBUG_KEY_PASSWORD"] as String
+ }
+ create("release") {
+ val localPropertiesFile = File(rootProject.rootDir, "local.properties")
+ if (localPropertiesFile.exists()) {
+ val properties = Properties().apply {
+ load(FileInputStream(localPropertiesFile))
+ }
+ storeFile = file("$rootDir/config/release.keystore")
+ storePassword = properties.getProperty("RELEASE_STORE_PASSWORD", "")
+ keyAlias = properties.getProperty("RELEASE_KEY_ALIAS", "")
+ keyPassword = properties.getProperty("RELEASE_KEY_PASSWORD", "")
+ }
+ }
+ }
+ buildTypes {
+ release {
+ isMinifyEnabled = true
+ isShrinkResources = true
+ proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
+ signingConfig = signingConfigs.getByName("release")
+ buildConfigField("String", "BASE_URL", "\"https://rsdevteam.ru/inmuslim/api/\"")
+ }
+ debug {
+ isDebuggable = true
+ applicationIdSuffix = ".beta"
+ signingConfig = signingConfigs.getByName("debug")
+ buildConfigField("String", "BASE_URL", "\"https://rsdevteam.ru/inmuslim/api/\"")
+ }
+ }
+ compileOptions {
+ sourceCompatibility = JavaVersion.toVersion(libs.versions.java.get())
+ targetCompatibility = JavaVersion.toVersion(libs.versions.java.get())
+ }
+ kotlinOptions {
+ jvmTarget = libs.versions.java.get()
+ }
+ buildFeatures {
+ compose = true
+ buildConfig = true
+ }
+ composeOptions {
+ kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get()
+ }
+ packaging {
+ resources {
+ excludes += "/META-INF/{AL2.0,LGPL2.1}"
+ excludes += "/okhttp3/internal/publicsuffix/NOTICE"
+ excludes += "/kotlin/**"
+ excludes += "/META-INF/androidx.*.version"
+ excludes += "/META-INF/com.google.*.version"
+ excludes += "/META-INF/kotlinx_*.version"
+ excludes += "kotlin-tooling-metadata.json"
+ excludes += "DebugProbesKt.bin"
+ excludes += "/META-INF/com/android/build/gradle/app-**.properties"
+ }
+ }
+}
+
+dependencies {
+
+ implementation(libs.androidx.core.ktx)
+
+ implementation(platform(libs.compose.bom))
+ implementation(libs.androidx.compose.ui)
+ implementation(libs.androidx.compose.ui.graphics)
+ implementation(libs.androidx.compose.material3)
+ implementation(libs.androidx.activity.compose)
+ implementation(libs.androidx.compose.ui.tooling)
+ implementation(libs.androidx.compose.ui.tooling.preview)
+ implementation(libs.androidx.compose.ui.test.manifest)
+
+ testImplementation(libs.junit)
+ androidTestImplementation(libs.androidx.junit)
+ androidTestImplementation(libs.androidx.espresso)
+ androidTestImplementation(platform(libs.compose.bom))
+ androidTestImplementation(libs.androidx.compose.ui.junit4)
+
+ implementation(libs.androidx.navigation.compose)
+
+ implementation(libs.dagger.hilt.android)
+ kapt(libs.dagger.hilt.android.compiler)
+ kapt(libs.dagger.hilt.compiler)
+ implementation(libs.dagger.hilt.navigation)
+
+ implementation(libs.androidx.lifecycle.viewmodel.compose)
+ implementation(libs.androidx.lifecycle.viewmodel.ktx)
+ implementation(libs.androidx.lifecycle.runtime.compose)
+ implementation(libs.androidx.lifecycle.runtime.ktx)
+
+ implementation(libs.coroutines.core)
+ implementation(libs.coroutines.android)
+
+ implementation(libs.okhttp)
+ implementation(libs.okhttp.logging)
+ implementation(libs.retrofit)
+ implementation(libs.retrofit.moshi)
+ implementation(libs.retrofit.adapters.result)
+ implementation(libs.moshi)
+ implementation(libs.moshi.kotlin)
+ ksp(libs.moshi.kotlin.codegen)
+
+ implementation(platform(libs.firebase.bom))
+ implementation(libs.firebase.messaging.ktx)
+ implementation(libs.firebase.analytics.ktx)
+ implementation(libs.firebase.crashlytics.ktx)
+
+ implementation(libs.google.play.review.ktx)
+}
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index 481bb43..422e4e1 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -18,4 +18,8 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
-#-renamesourcefileattribute SourceFile
\ No newline at end of file
+#-renamesourcefileattribute SourceFile
+
+-optimizationpasses 5
+
+-keep public class kotlin.Result { *; }
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/config/BuildVars.kt b/app/src/main/java/tj/rsdevteam/inmuslim/config/BuildVars.kt
index 075d5e9..6ef1d90 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/config/BuildVars.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/config/BuildVars.kt
@@ -1,5 +1,7 @@
package tj.rsdevteam.inmuslim.config
+import tj.rsdevteam.inmuslim.BuildConfig
+
/**
* Created by Rustam Safarov on 8/13/23.
* github.com/rustamsafarovrs
@@ -7,16 +9,8 @@ package tj.rsdevteam.inmuslim.config
object BuildVars {
- val BUILD_TYPE = BuildType.TEST
-
- val BASE_URL: String = when (BUILD_TYPE) {
- BuildType.TEST -> {
- "http://rsdevteam.ru:8088/inmuslim/staging/api/"
- }
- BuildType.PROD -> {
- "https://rsdevteam.ru/inmuslim/api/"
- }
- }
+ val BUILD_TYPE = if (BuildConfig.DEBUG) BuildType.TEST else BuildType.PROD
+ const val BASE_URL = BuildConfig.BASE_URL
}
enum class BuildType {
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/api/Api.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/api/Api.kt
index bb888f3..d764200 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/data/api/Api.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/api/Api.kt
@@ -1,16 +1,15 @@
package tj.rsdevteam.inmuslim.data.api
-import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
-import tj.rsdevteam.inmuslim.data.models.network.GetRegionsResponse
-import tj.rsdevteam.inmuslim.data.models.network.GetTimingBody
-import tj.rsdevteam.inmuslim.data.models.network.GetTimingResponse
-import tj.rsdevteam.inmuslim.data.models.network.RegisterUserBody
-import tj.rsdevteam.inmuslim.data.models.network.RegisterUserResponse
-import tj.rsdevteam.inmuslim.data.models.network.UpdateMessagingIdBody
-import tj.rsdevteam.inmuslim.data.models.network.UpdateMessagingIdResponse
+import tj.rsdevteam.inmuslim.data.models.api.GetRegionsDTO
+import tj.rsdevteam.inmuslim.data.models.api.GetTimingBodyDTO
+import tj.rsdevteam.inmuslim.data.models.api.GetTimingDTO
+import tj.rsdevteam.inmuslim.data.models.api.RegisterUserBodyDTO
+import tj.rsdevteam.inmuslim.data.models.api.RegisterUserDTO
+import tj.rsdevteam.inmuslim.data.models.api.UpdateMessagingIdBodyDTO
+import tj.rsdevteam.inmuslim.data.models.api.UpdateMessagingIdDTO
/**
* Created by Rustam Safarov on 8/13/23.
@@ -20,14 +19,14 @@ import tj.rsdevteam.inmuslim.data.models.network.UpdateMessagingIdResponse
interface Api {
@GET("GetRegions")
- suspend fun getRegions(): Response
+ suspend fun getRegions(): Result
@POST("GetTiming")
- suspend fun getTiming(@Body body: GetTimingBody): Response
+ suspend fun getTiming(@Body body: GetTimingBodyDTO): Result
@POST("RegisterUser")
- suspend fun registerUser(@Body body: RegisterUserBody): Response
+ suspend fun registerUser(@Body body: RegisterUserBodyDTO): Result
@POST("UpdateMessagingId")
- suspend fun updateMessagingId(@Body body: UpdateMessagingIdBody): Response
+ suspend fun updateMessagingId(@Body body: UpdateMessagingIdBodyDTO): Result
}
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/exceptions/ApiException.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/exceptions/ApiException.kt
new file mode 100644
index 0000000..f3d986a
--- /dev/null
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/exceptions/ApiException.kt
@@ -0,0 +1,3 @@
+package tj.rsdevteam.inmuslim.data.exceptions
+
+class ApiException(msg: String?) : Exception(msg)
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/exceptions/ConnectionTimeoutException.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/exceptions/ConnectionTimeoutException.kt
new file mode 100644
index 0000000..0d32305
--- /dev/null
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/exceptions/ConnectionTimeoutException.kt
@@ -0,0 +1,3 @@
+package tj.rsdevteam.inmuslim.data.exceptions
+
+class ConnectionTimeoutException : Exception("No internet connection")
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/exceptions/UnknownException.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/exceptions/UnknownException.kt
new file mode 100644
index 0000000..cdbaabd
--- /dev/null
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/exceptions/UnknownException.kt
@@ -0,0 +1,3 @@
+package tj.rsdevteam.inmuslim.data.exceptions
+
+class UnknownException(error: String?) : Exception("Something went wrong...\n$error")
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/Message.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/Message.kt
new file mode 100644
index 0000000..7a97084
--- /dev/null
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/Message.kt
@@ -0,0 +1,10 @@
+package tj.rsdevteam.inmuslim.data.models
+
+/**
+ * Created by Rustam Safarov on 6/25/24.
+ * github.com/rustamsafarovrs
+ */
+
+data class Message(
+ val message: String
+)
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/Region.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/Region.kt
index 6fcd994..7af0eef 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/Region.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/Region.kt
@@ -1,14 +1,12 @@
package tj.rsdevteam.inmuslim.data.models
import androidx.compose.runtime.mutableStateOf
-import com.squareup.moshi.JsonClass
/**
- * Created by Rustam Safarov on 14/08/23.
+ * Created by Rustam Safarov on 6/25/24.
* github.com/rustamsafarovrs
*/
-@JsonClass(generateAdapter = true)
data class Region(
val id: Long,
val name: String
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/Resource.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/Resource.kt
new file mode 100644
index 0000000..9dfd40c
--- /dev/null
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/Resource.kt
@@ -0,0 +1,15 @@
+package tj.rsdevteam.inmuslim.data.models
+
+/**
+ * Created by Rustam Safarov on 8/13/23.
+ * github.com/rustamsafarovrs
+ */
+
+sealed class Resource(open val data: T? = null) {
+
+ class InProgress(data: T? = null) : Resource(data)
+
+ class Success(override val data: T) : Resource(data)
+
+ class Error(data: T? = null, val error: Throwable? = null) : Resource(data)
+}
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/Timing.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/Timing.kt
index ff4cc47..c4f5f33 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/Timing.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/Timing.kt
@@ -1,13 +1,10 @@
package tj.rsdevteam.inmuslim.data.models
-import com.squareup.moshi.JsonClass
-
/**
- * Created by Rustam Safarov on 8/13/23.
+ * Created by Rustam Safarov on 6/25/24.
* github.com/rustamsafarovrs
*/
-@JsonClass(generateAdapter = true)
data class Timing(
val fajr: String,
val sunrise: String,
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/User.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/User.kt
new file mode 100644
index 0000000..1ee7541
--- /dev/null
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/User.kt
@@ -0,0 +1,10 @@
+package tj.rsdevteam.inmuslim.data.models
+
+/**
+ * Created by Rustam Safarov on 6/25/24.
+ * github.com/rustamsafarovrs
+ */
+
+data class User(
+ val id: Long
+)
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/GetRegionsResponse.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/GetRegionsDTO.kt
similarity index 55%
rename from app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/GetRegionsResponse.kt
rename to app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/GetRegionsDTO.kt
index 9fa5442..dbae9cc 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/GetRegionsResponse.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/GetRegionsDTO.kt
@@ -1,7 +1,6 @@
-package tj.rsdevteam.inmuslim.data.models.network
+package tj.rsdevteam.inmuslim.data.models.api
import com.squareup.moshi.JsonClass
-import tj.rsdevteam.inmuslim.data.models.Region
/**
* Created by Rustam Safarov on 14/08/23.
@@ -9,8 +8,8 @@ import tj.rsdevteam.inmuslim.data.models.Region
*/
@JsonClass(generateAdapter = true)
-data class GetRegionsResponse(
+data class GetRegionsDTO(
val result: Int,
val msg: String,
- val regions: List
+ val regions: List
)
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/GetTimingBody.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/GetTimingBodyDTO.kt
similarity index 65%
rename from app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/GetTimingBody.kt
rename to app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/GetTimingBodyDTO.kt
index ee6518e..d94d77c 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/GetTimingBody.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/GetTimingBodyDTO.kt
@@ -1,4 +1,4 @@
-package tj.rsdevteam.inmuslim.data.models.network
+package tj.rsdevteam.inmuslim.data.models.api
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@@ -9,7 +9,7 @@ import com.squareup.moshi.JsonClass
*/
@JsonClass(generateAdapter = true)
-data class GetTimingBody(
- @field:Json(name = "region_id")
+data class GetTimingBodyDTO(
+ @Json(name = "region_id")
val regionId: Long
)
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/GetTimingResponse.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/GetTimingDTO.kt
similarity index 59%
rename from app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/GetTimingResponse.kt
rename to app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/GetTimingDTO.kt
index 0a55bc7..83d3e4c 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/GetTimingResponse.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/GetTimingDTO.kt
@@ -1,8 +1,7 @@
-package tj.rsdevteam.inmuslim.data.models.network
+package tj.rsdevteam.inmuslim.data.models.api
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
-import tj.rsdevteam.inmuslim.data.models.Timing
/**
* Created by Rustam Safarov on 8/13/23.
@@ -10,11 +9,11 @@ import tj.rsdevteam.inmuslim.data.models.Timing
*/
@JsonClass(generateAdapter = true)
-data class GetTimingResponse(
+data class GetTimingDTO(
val result: Int,
val msg: String,
val region: String,
- @field:Json(name = "begin_date")
+ @Json(name = "begin_date")
val beginDate: String,
- val timing: Timing
+ val timing: TimingDTO
)
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/MessageDTO.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/MessageDTO.kt
new file mode 100644
index 0000000..0854e64
--- /dev/null
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/MessageDTO.kt
@@ -0,0 +1,14 @@
+package tj.rsdevteam.inmuslim.data.models.api
+
+import com.squareup.moshi.JsonClass
+
+/**
+ * Created by Rustam Safarov on 6/25/24.
+ * github.com/rustamsafarovrs
+ */
+
+@JsonClass(generateAdapter = true)
+data class MessageDTO(
+ val result: Int,
+ val msg: String
+)
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/RegionDTO.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/RegionDTO.kt
new file mode 100644
index 0000000..6af9075
--- /dev/null
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/RegionDTO.kt
@@ -0,0 +1,14 @@
+package tj.rsdevteam.inmuslim.data.models.api
+
+import com.squareup.moshi.JsonClass
+
+/**
+ * Created by Rustam Safarov on 14/08/23.
+ * github.com/rustamsafarovrs
+ */
+
+@JsonClass(generateAdapter = true)
+data class RegionDTO(
+ val id: Long,
+ val name: String
+)
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/RegisterUserBody.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/RegisterUserBodyDTO.kt
similarity index 69%
rename from app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/RegisterUserBody.kt
rename to app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/RegisterUserBodyDTO.kt
index aff5cc4..dcebed5 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/RegisterUserBody.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/RegisterUserBodyDTO.kt
@@ -1,4 +1,4 @@
-package tj.rsdevteam.inmuslim.data.models.network
+package tj.rsdevteam.inmuslim.data.models.api
import com.squareup.moshi.JsonClass
@@ -8,6 +8,6 @@ import com.squareup.moshi.JsonClass
*/
@JsonClass(generateAdapter = true)
-data class RegisterUserBody(
+data class RegisterUserBodyDTO(
val name: String
)
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/RegisterUserResponse.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/RegisterUserDTO.kt
similarity index 72%
rename from app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/RegisterUserResponse.kt
rename to app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/RegisterUserDTO.kt
index 5216aa3..fdd1b69 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/RegisterUserResponse.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/RegisterUserDTO.kt
@@ -1,4 +1,4 @@
-package tj.rsdevteam.inmuslim.data.models.network
+package tj.rsdevteam.inmuslim.data.models.api
import com.squareup.moshi.JsonClass
@@ -8,7 +8,7 @@ import com.squareup.moshi.JsonClass
*/
@JsonClass(generateAdapter = true)
-data class RegisterUserResponse(
+data class RegisterUserDTO(
val result: Int,
val msg: String,
val id: Long
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/TimingDTO.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/TimingDTO.kt
new file mode 100644
index 0000000..717e9dc
--- /dev/null
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/TimingDTO.kt
@@ -0,0 +1,19 @@
+package tj.rsdevteam.inmuslim.data.models.api
+
+import com.squareup.moshi.JsonClass
+
+/**
+ * Created by Rustam Safarov on 8/13/23.
+ * github.com/rustamsafarovrs
+ */
+
+@JsonClass(generateAdapter = true)
+data class TimingDTO(
+ val fajr: String,
+ val sunrise: String,
+ val zuhr: String,
+ val asr: String,
+ val sunset: String,
+ val maghrib: String,
+ val isha: String
+)
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/UpdateMessagingIdBody.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/UpdateMessagingIdBodyDTO.kt
similarity index 70%
rename from app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/UpdateMessagingIdBody.kt
rename to app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/UpdateMessagingIdBodyDTO.kt
index 7996eff..74710e4 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/UpdateMessagingIdBody.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/UpdateMessagingIdBodyDTO.kt
@@ -1,4 +1,4 @@
-package tj.rsdevteam.inmuslim.data.models.network
+package tj.rsdevteam.inmuslim.data.models.api
import com.squareup.moshi.JsonClass
@@ -8,7 +8,7 @@ import com.squareup.moshi.JsonClass
*/
@JsonClass(generateAdapter = true)
-data class UpdateMessagingIdBody(
+data class UpdateMessagingIdBodyDTO(
val id: Long,
val msgid: String
)
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/UpdateMessagingIdResponse.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/UpdateMessagingIdDTO.kt
similarity index 69%
rename from app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/UpdateMessagingIdResponse.kt
rename to app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/UpdateMessagingIdDTO.kt
index 00a5d3d..9e5da54 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/UpdateMessagingIdResponse.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/api/UpdateMessagingIdDTO.kt
@@ -1,4 +1,4 @@
-package tj.rsdevteam.inmuslim.data.models.network
+package tj.rsdevteam.inmuslim.data.models.api
import com.squareup.moshi.JsonClass
@@ -8,7 +8,7 @@ import com.squareup.moshi.JsonClass
*/
@JsonClass(generateAdapter = true)
-data class UpdateMessagingIdResponse(
+data class UpdateMessagingIdDTO(
val result: Int,
val msg: String
)
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/ApiError.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/ApiError.kt
deleted file mode 100644
index c7c3e8d..0000000
--- a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/ApiError.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package tj.rsdevteam.inmuslim.data.models.network
-
-/**
- * Created by Rustam Safarov on 8/13/23.
- * github.com/rustamsafarovrs
- */
-
-data class ApiError(
- val result: Int,
- val msg: String
-)
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/Resource.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/Resource.kt
deleted file mode 100644
index 4cd2874..0000000
--- a/app/src/main/java/tj/rsdevteam/inmuslim/data/models/network/Resource.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package tj.rsdevteam.inmuslim.data.models.network
-
-/**
- * Created by Rustam Safarov on 8/13/23.
- * github.com/rustamsafarovrs
- */
-
-data class Resource(
- val status: Status,
- val data: T?,
- val message: String?,
- val exception: Exception? = null
-) {
-
- companion object {
- fun success(data: T?): Resource {
- return Resource(Status.SUCCESS, data, null)
- }
-
- fun error(msg: String?, data: T?, exception: Exception?): Resource {
- return Resource(Status.ERROR, data, msg, exception)
- }
-
- fun loading(data: T? = null): Resource {
- return Resource(Status.LOADING, data, null)
- }
- }
-
-}
-
-enum class Status {
- LOADING,
- SUCCESS,
- ERROR
-}
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/preferences/Preferences.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/preferences/Preferences.kt
index e6e818b..9efe56b 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/data/preferences/Preferences.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/preferences/Preferences.kt
@@ -10,19 +10,17 @@ import android.content.SharedPreferences
class Preferences(context: Context) {
- private val prefs: SharedPreferences
- private val editor: SharedPreferences.Editor
-
- init {
- prefs = context.getSharedPreferences("prefs", Context.MODE_PRIVATE)
- editor = prefs.edit()
- }
+ private val prefs: SharedPreferences = context.getSharedPreferences(PREFS_FILE_NAME, Context.MODE_PRIVATE)
+ private val editor: SharedPreferences.Editor = prefs.edit()
companion object {
+ const val PREFS_FILE_NAME = "prefs"
+
const val PREFS_REGION_ID = "region_id"
const val PREFS_USER_ID = "user_id"
const val PREFS_FIREBASE_TOKEN = "firebase_token"
+ const val PREFS_REVIEW_SHOWN = "review_shown"
}
fun saveRegionId(id: Long) {
@@ -37,7 +35,6 @@ class Preferences(context: Context) {
fun getUserId() = prefs.getLong(PREFS_USER_ID, -1)
-
fun saveFirebaseToken(token: String) {
editor.putString(PREFS_FIREBASE_TOKEN, token).apply()
}
@@ -45,4 +42,12 @@ class Preferences(context: Context) {
fun getFirebaseToken(): String {
return prefs.getString(PREFS_FIREBASE_TOKEN, null) ?: ""
}
+
+ fun saveReviewShown() {
+ editor.putBoolean(PREFS_REVIEW_SHOWN, true).commit()
+ }
+
+ fun isReviewShown(): Boolean {
+ return prefs.getBoolean(PREFS_REVIEW_SHOWN, false)
+ }
}
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/ErrorHandler.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/ErrorHandler.kt
index 1e9eb23..3c8fb60 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/ErrorHandler.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/ErrorHandler.kt
@@ -1,98 +1,32 @@
package tj.rsdevteam.inmuslim.data.repositories
-import com.squareup.moshi.Moshi
-import okhttp3.ResponseBody
import retrofit2.HttpException
-import tj.rsdevteam.inmuslim.data.constants.Constants
-import tj.rsdevteam.inmuslim.data.models.network.ApiError
-import tj.rsdevteam.inmuslim.data.models.network.Resource
+import tj.rsdevteam.inmuslim.data.exceptions.ApiException
+import tj.rsdevteam.inmuslim.data.exceptions.ConnectionTimeoutException
+import tj.rsdevteam.inmuslim.data.exceptions.UnknownException
+import tj.rsdevteam.inmuslim.data.models.Resource
+import tj.rsdevteam.inmuslim.data.models.api.MessageDTO
import java.io.IOException
+import java.net.UnknownHostException
/**
* Created by Rustam Safarov on 8/13/23.
* github.com/rustamsafarovrs
*/
-@Suppress("TooGenericExceptionCaught")
-class ErrorHandler constructor(private val moshi: Moshi) {
-
- fun getError(e: Throwable): Resource {
- val exception = handleException(e)
- return getErrorResource(exception)
- }
-
- fun getError(httpStatusCode: Int, responseBody: ResponseBody?): Resource {
- val exception = handleHttpException(httpStatusCode, responseBody?.string())
- return getErrorResource(exception)
- }
-
- fun getError(httpStatusCode: Int, errorBody: ResponseBody?, body: Any?): Resource {
- if (errorBody != null) {
- val exception = handleHttpException(httpStatusCode, errorBody.string())
- return getErrorResource(exception)
+class ErrorHandler {
+
+ fun getError(result: Result<*>): Resource {
+ return if (result.getOrNull() is MessageDTO) {
+ Resource.Error(error = ApiException((result.getOrThrow() as MessageDTO).msg))
+ } else if (result.exceptionOrNull() is UnknownHostException) {
+ Resource.Error(error = ConnectionTimeoutException())
+ } else if (result.exceptionOrNull() is HttpException) {
+ Resource.Error(error = ApiException(result.exceptionOrNull()?.localizedMessage))
+ } else if (result.exceptionOrNull() is IOException) {
+ Resource.Error(error = ConnectionTimeoutException())
} else {
- val tmp = moshi.adapter(Any::class.java)
- val str: String = tmp.toJson(body)
- val exception = handleHttpException(httpStatusCode, str)
- return getErrorResource(exception)
- }
- }
-
- private fun handleException(e: Throwable): Exception =
- when (e) {
- is HttpException -> {
- handleHttpException(e.code(), e.response()?.errorBody()?.string())
- }
-
- is IOException -> {
- ConnectionTimeoutException()
- }
-
- else -> {
- e.printStackTrace()
- UnknownException(e.message.toString())
- }
+ Resource.Error(error = UnknownException(result.exceptionOrNull()?.localizedMessage))
}
-
- private fun handleHttpException(code: Int, errorBody: String?): Exception =
- try {
- val error: ApiError = moshi.adapter(ApiError::class.java).fromJson(errorBody!!)!!
- if (code == Constants.UNAUTHORIZED) {
- SessionException()
- } else {
- ApiException(error)
- }
- } catch (e: Exception) {
- // Logger.exception(e)
- UnknownException(e.message.toString())
- }
-
- private fun getErrorResource(e: Exception): Resource {
- var message: String? = null
-
- when (e) {
- is ApiException -> {
- message = e.apiError.msg
- }
-
- is ConnectionTimeoutException -> {
- message = "No internet connection"
- }
-
- is UnknownException -> {
- message = "Something went wrong..."
- }
-
- is SessionException -> {
- message = e.message.toString()
- }
- }
- return Resource.error(msg = message, data = null, exception = e)
-
}
}
-
-class SessionException : Exception("Unauthorized")
-class UnknownException(error: String) : Exception("Something went wrong...\n$error")
-class ConnectionTimeoutException : Exception("No internet connection")
-class ApiException(val apiError: ApiError) : Exception(apiError.msg)
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/Mappers.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/Mappers.kt
new file mode 100644
index 0000000..d58b70b
--- /dev/null
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/Mappers.kt
@@ -0,0 +1,53 @@
+package tj.rsdevteam.inmuslim.data.repositories
+
+import tj.rsdevteam.inmuslim.data.models.Message
+import tj.rsdevteam.inmuslim.data.models.Region
+import tj.rsdevteam.inmuslim.data.models.Timing
+import tj.rsdevteam.inmuslim.data.models.User
+import tj.rsdevteam.inmuslim.data.models.api.MessageDTO
+import tj.rsdevteam.inmuslim.data.models.api.RegionDTO
+import tj.rsdevteam.inmuslim.data.models.api.RegisterUserDTO
+import tj.rsdevteam.inmuslim.data.models.api.TimingDTO
+import tj.rsdevteam.inmuslim.data.models.api.UpdateMessagingIdDTO
+
+/**
+ * Created by Rustam Safarov on 6/25/24.
+ * github.com/rustamsafarovrs
+ */
+
+fun RegionDTO.toRegion(): Region {
+ return Region(
+ id = this.id,
+ name = this.name
+ )
+}
+
+fun TimingDTO.toTiming(): Timing {
+ return Timing(
+ fajr = this.fajr,
+ sunrise = this.sunrise,
+ zuhr = this.zuhr,
+ asr = this.asr,
+ sunset = this.sunset,
+ maghrib = this.maghrib,
+ isha = this.isha
+ )
+}
+
+fun MessageDTO.toMessage(): Message {
+ return Message(
+ message = this.msg
+ )
+}
+
+fun RegisterUserDTO.toUser(): User {
+ return User(
+ id = this.id
+ )
+}
+
+fun UpdateMessagingIdDTO.toMessage(): Message {
+ return Message(
+ message = this.msg
+ )
+}
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/RegionRepository.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/RegionRepository.kt
index 4e479d2..b614e13 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/RegionRepository.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/RegionRepository.kt
@@ -1,12 +1,10 @@
package tj.rsdevteam.inmuslim.data.repositories
-import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import tj.rsdevteam.inmuslim.data.api.Api
-import tj.rsdevteam.inmuslim.data.constants.Constants
import tj.rsdevteam.inmuslim.data.models.Region
-import tj.rsdevteam.inmuslim.data.models.network.Resource
+import tj.rsdevteam.inmuslim.data.models.Resource
import tj.rsdevteam.inmuslim.data.preferences.Preferences
import javax.inject.Inject
import javax.inject.Singleton
@@ -17,7 +15,6 @@ import javax.inject.Singleton
*/
@Singleton
-@Suppress("TooGenericExceptionCaught")
class RegionRepository
@Inject constructor(
private val api: Api,
@@ -30,23 +27,12 @@ class RegionRepository
fun saveRegionId(id: Long) = preferences.saveRegionId(id)
fun getRegions(): Flow>> = flow {
- try {
- emit(Resource.loading())
- val response = api.getRegions()
- delay(Constants.MIDDLE_DELAY)
- if (response.isSuccessful && response.body()?.result == 0) {
- emit(Resource.success(response.body()!!.regions))
- } else {
- emit(
- errorHandler.getError(
- response.code(),
- response.errorBody(),
- response.body()
- )
- )
- }
- } catch (e: Exception) {
- emit(errorHandler.getError(e))
+ emit(Resource.InProgress())
+ val result = api.getRegions()
+ if (result.isSuccess && result.getOrNull()?.result == 0) {
+ emit(Resource.Success(result.getOrThrow().regions.map { it.toRegion() }))
+ } else {
+ emit(errorHandler.getError(result))
}
}
}
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/TimingRepository.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/TimingRepository.kt
index f056e5a..e124b34 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/TimingRepository.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/TimingRepository.kt
@@ -1,13 +1,11 @@
package tj.rsdevteam.inmuslim.data.repositories
-import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import tj.rsdevteam.inmuslim.data.api.Api
-import tj.rsdevteam.inmuslim.data.constants.Constants
-import tj.rsdevteam.inmuslim.data.models.network.GetTimingBody
-import tj.rsdevteam.inmuslim.data.models.network.GetTimingResponse
-import tj.rsdevteam.inmuslim.data.models.network.Resource
+import tj.rsdevteam.inmuslim.data.models.Resource
+import tj.rsdevteam.inmuslim.data.models.Timing
+import tj.rsdevteam.inmuslim.data.models.api.GetTimingBodyDTO
import tj.rsdevteam.inmuslim.data.preferences.Preferences
import javax.inject.Inject
import javax.inject.Singleton
@@ -18,7 +16,6 @@ import javax.inject.Singleton
*/
@Singleton
-@Suppress("TooGenericExceptionCaught")
class TimingRepository
@Inject constructor(
private val api: Api,
@@ -26,24 +23,13 @@ class TimingRepository
private val errorHandler: ErrorHandler
) {
- fun getTiming(): Flow> = flow {
- try {
- emit(Resource.loading())
- val response = api.getTiming(GetTimingBody(regionId = preferences.getRegionId()))
- delay(Constants.MIDDLE_DELAY)
- if (response.isSuccessful && response.body()?.result == 0) {
- emit(Resource.success(response.body()!!))
- } else {
- emit(
- errorHandler.getError(
- response.code(),
- response.errorBody(),
- response.body()
- )
- )
- }
- } catch (e: Exception) {
- emit(errorHandler.getError(e))
+ fun getTiming(): Flow> = flow {
+ emit(Resource.InProgress())
+ val result = api.getTiming(GetTimingBodyDTO(regionId = preferences.getRegionId()))
+ if (result.isSuccess && result.getOrNull()?.result == 0) {
+ emit(Resource.Success(result.getOrThrow().timing.toTiming()))
+ } else {
+ emit(errorHandler.getError(result))
}
}
}
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/UserRepository.kt b/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/UserRepository.kt
index ae4fccd..aadf5bd 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/UserRepository.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/data/repositories/UserRepository.kt
@@ -1,19 +1,19 @@
package tj.rsdevteam.inmuslim.data.repositories
import com.google.firebase.messaging.FirebaseMessaging
-import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
-import kotlinx.coroutines.withContext
import tj.rsdevteam.inmuslim.data.api.Api
-import tj.rsdevteam.inmuslim.data.models.network.RegisterUserBody
-import tj.rsdevteam.inmuslim.data.models.network.RegisterUserResponse
-import tj.rsdevteam.inmuslim.data.models.network.Resource
-import tj.rsdevteam.inmuslim.data.models.network.UpdateMessagingIdBody
-import tj.rsdevteam.inmuslim.data.models.network.UpdateMessagingIdResponse
+import tj.rsdevteam.inmuslim.data.models.Message
+import tj.rsdevteam.inmuslim.data.models.Resource
+import tj.rsdevteam.inmuslim.data.models.User
+import tj.rsdevteam.inmuslim.data.models.api.RegisterUserBodyDTO
+import tj.rsdevteam.inmuslim.data.models.api.UpdateMessagingIdBodyDTO
import tj.rsdevteam.inmuslim.data.preferences.Preferences
import javax.inject.Inject
import javax.inject.Singleton
+import kotlin.coroutines.resume
+import kotlin.coroutines.suspendCoroutine
/**
* Created by Rustam Safarov on 15/08/23.
@@ -21,7 +21,6 @@ import javax.inject.Singleton
*/
@Singleton
-@Suppress("TooGenericExceptionCaught")
class UserRepository
@Inject constructor(
private val api: Api,
@@ -29,56 +28,38 @@ class UserRepository
private val errorHandler: ErrorHandler
) {
- fun registerUser(body: RegisterUserBody): Flow> = flow {
- try {
- emit(Resource.loading())
- val response = api.registerUser(body)
- if (response.isSuccessful && response.body()?.result == 0) {
- preferences.saveUserId(response.body()!!.id)
- emit(Resource.success(response.body()!!))
- } else {
- emit(
- errorHandler.getError(
- response.code(),
- response.errorBody(),
- response.body()
- )
- )
- }
- } catch (e: Exception) {
- emit(errorHandler.getError(e))
+ fun registerUser(name: String): Flow> = flow {
+ emit(Resource.InProgress())
+ val result = api.registerUser(RegisterUserBodyDTO(name = name))
+ if (result.isSuccess && result.getOrNull()?.result == 0) {
+ preferences.saveUserId(result.getOrThrow().id)
+ emit(Resource.Success(result.getOrThrow().toUser()))
+ } else {
+ emit(errorHandler.getError(result))
}
}
- fun updateMessagingId(): Flow> = flow {
- try {
- emit(Resource.loading())
- var msgid = ""
- withContext(Dispatchers.IO) {
- FirebaseMessaging.getInstance().token.addOnSuccessListener { token ->
- msgid = token
+ fun updateMessagingId(): Flow> = flow {
+ emit(Resource.InProgress())
+ val token = suspendCoroutine { continuation ->
+ FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
+ if (task.isSuccessful) {
+ continuation.resume(task.result)
+ } else {
+ continuation.resume(null)
}
}
- val response = api.updateMessagingId(
- UpdateMessagingIdBody(
- id = preferences.getUserId(),
- msgid = msgid
- )
- )
- if (response.isSuccessful && response.body()?.result == 0) {
- preferences.saveFirebaseToken(msgid)
- emit(Resource.success(response.body()!!))
- } else {
- emit(
- errorHandler.getError(
- response.code(),
- response.errorBody(),
- response.body()
- )
- )
- }
- } catch (e: Exception) {
- emit(errorHandler.getError(e))
+ }
+ if (token == null) {
+ emit(Resource.Error(Message("Cannot get Firebase Messaging token")))
+ return@flow
+ }
+ val result = api.updateMessagingId(UpdateMessagingIdBodyDTO(id = preferences.getUserId(), msgid = token))
+ if (result.isSuccess && result.getOrNull()?.result == 0) {
+ preferences.saveFirebaseToken(token)
+ emit(Resource.Success(result.getOrThrow().toMessage()))
+ } else {
+ emit(errorHandler.getError(result))
}
}
@@ -86,7 +67,19 @@ class UserRepository
return preferences.getUserId() == -1L
}
- fun getUserId() = preferences.getUserId()
+ fun getUserId(): Long {
+ return preferences.getUserId()
+ }
+
+ fun getFirebaseToken(): String {
+ return preferences.getFirebaseToken()
+ }
- fun getFirebaseToken() = preferences.getFirebaseToken()
+ fun isReviewShown(): Boolean {
+ return preferences.isReviewShown()
+ }
+
+ fun saveReviewShown() {
+ preferences.saveReviewShown()
+ }
}
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/di/modules/AppModule.kt b/app/src/main/java/tj/rsdevteam/inmuslim/di/modules/AppModule.kt
new file mode 100644
index 0000000..577791a
--- /dev/null
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/di/modules/AppModule.kt
@@ -0,0 +1,86 @@
+package tj.rsdevteam.inmuslim.di.modules
+
+import android.content.Context
+import com.skydoves.retrofit.adapters.result.ResultCallAdapterFactory
+import com.squareup.moshi.Moshi
+import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import okhttp3.OkHttpClient
+import okhttp3.logging.HttpLoggingInterceptor
+import retrofit2.Retrofit
+import retrofit2.converter.moshi.MoshiConverterFactory
+import tj.rsdevteam.inmuslim.config.BuildType
+import tj.rsdevteam.inmuslim.config.BuildVars
+import tj.rsdevteam.inmuslim.data.api.Api
+import tj.rsdevteam.inmuslim.data.constants.Constants
+import tj.rsdevteam.inmuslim.data.preferences.Preferences
+import tj.rsdevteam.inmuslim.data.repositories.ErrorHandler
+import java.util.concurrent.TimeUnit
+
+/**
+ * Created by Rustam Safarov on 8/13/23.
+ * github.com/rustamsafarovrs
+ */
+
+@Module
+@InstallIn(SingletonComponent::class)
+class AppModule {
+
+ @Provides
+ fun provideMoshi(): Moshi {
+ return Moshi.Builder()
+ .add(KotlinJsonAdapterFactory())
+ .build()
+ }
+
+ @Provides
+ fun provideLoggingInterceptor(): HttpLoggingInterceptor {
+ return HttpLoggingInterceptor().apply {
+ level = if (BuildVars.BUILD_TYPE == BuildType.TEST) {
+ HttpLoggingInterceptor.Level.BODY
+ } else {
+ HttpLoggingInterceptor.Level.NONE
+ }
+ }
+ }
+
+ @Provides
+ fun provideOkhttp(
+ loggingInterceptor: HttpLoggingInterceptor
+ ): OkHttpClient {
+ return OkHttpClient.Builder()
+ .addInterceptor(loggingInterceptor)
+ .readTimeout(Constants.DEFAULT_TIMEOUT, TimeUnit.SECONDS)
+ .connectTimeout(Constants.DEFAULT_TIMEOUT, TimeUnit.SECONDS)
+ .build()
+ }
+
+ @Provides
+ fun provideRetrofit(moshi: Moshi, client: OkHttpClient): Retrofit {
+ return Retrofit.Builder()
+ .addConverterFactory(MoshiConverterFactory.create(moshi))
+ .addCallAdapterFactory(ResultCallAdapterFactory.create())
+ .client(client)
+ .baseUrl(BuildVars.BASE_URL)
+ .build()
+ }
+
+ @Provides
+ fun provideErrorHandler(): ErrorHandler {
+ return ErrorHandler()
+ }
+
+ @Provides
+ fun provideApi(retrofit: Retrofit): Api {
+ return retrofit.create(Api::class.java)
+ }
+
+ @Provides
+ fun providePreferences(@ApplicationContext context: Context): Preferences {
+ return Preferences(context)
+ }
+}
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/di/modules/NetworkModule.kt b/app/src/main/java/tj/rsdevteam/inmuslim/di/modules/NetworkModule.kt
deleted file mode 100644
index 6460423..0000000
--- a/app/src/main/java/tj/rsdevteam/inmuslim/di/modules/NetworkModule.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-package tj.rsdevteam.inmuslim.di.modules
-
-import com.squareup.moshi.Moshi
-import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
-import dagger.Module
-import dagger.Provides
-import dagger.hilt.InstallIn
-import dagger.hilt.components.SingletonComponent
-import okhttp3.OkHttpClient
-import okhttp3.logging.HttpLoggingInterceptor
-import retrofit2.Retrofit
-import retrofit2.converter.moshi.MoshiConverterFactory
-import tj.rsdevteam.inmuslim.config.BuildType
-import tj.rsdevteam.inmuslim.config.BuildVars
-import tj.rsdevteam.inmuslim.data.api.Api
-import tj.rsdevteam.inmuslim.data.constants.Constants
-import tj.rsdevteam.inmuslim.data.repositories.ErrorHandler
-import java.util.concurrent.TimeUnit
-
-/**
- * Created by Rustam Safarov on 8/13/23.
- * github.com/rustamsafarovrs
- */
-
-@Module
-@InstallIn(SingletonComponent::class)
-class NetworkModule {
-
- @Provides
- fun provideMoshi() = Moshi.Builder()
- .add(KotlinJsonAdapterFactory())
- .build()
-
- @Provides
- fun provideLoggingInterceptor() =
- HttpLoggingInterceptor().apply {
- level = if (BuildVars.BUILD_TYPE == BuildType.TEST) {
- HttpLoggingInterceptor.Level.BODY
- } else {
- HttpLoggingInterceptor.Level.NONE
- }
- }
-
- @Provides
- fun provideOkhttp(
- loggingInterceptor: HttpLoggingInterceptor
- ) = OkHttpClient.Builder()
- .addInterceptor(loggingInterceptor)
- .readTimeout(Constants.DEFAULT_TIMEOUT, TimeUnit.SECONDS)
- .connectTimeout(Constants.DEFAULT_TIMEOUT, TimeUnit.SECONDS)
- .build()
-
- @Provides
- fun provideRetrofit(moshi: Moshi, client: OkHttpClient) = Retrofit.Builder()
- .addConverterFactory(MoshiConverterFactory.create(moshi))
- .client(client)
- .baseUrl(BuildVars.BASE_URL)
- .build()
-
- @Provides
- fun provideErrorHandler(moshi: Moshi) = ErrorHandler(moshi)
-
- @Provides
- fun provideApi(retrofit: Retrofit) = retrofit.create(Api::class.java)
-}
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/di/modules/PreferencesModule.kt b/app/src/main/java/tj/rsdevteam/inmuslim/di/modules/PreferencesModule.kt
deleted file mode 100644
index 9dcca00..0000000
--- a/app/src/main/java/tj/rsdevteam/inmuslim/di/modules/PreferencesModule.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package tj.rsdevteam.inmuslim.di.modules
-
-import android.content.Context
-import dagger.Module
-import dagger.Provides
-import dagger.hilt.InstallIn
-import dagger.hilt.android.qualifiers.ApplicationContext
-import dagger.hilt.components.SingletonComponent
-import tj.rsdevteam.inmuslim.data.preferences.Preferences
-
-/**
- * Created by Rustam Safarov on 8/13/23.
- * github.com/rustamsafarovrs
- */
-
-@Module
-@InstallIn(SingletonComponent::class)
-class PreferencesModule {
-
- @Provides
- fun providePreferences(@ApplicationContext context: Context) = Preferences(context)
-}
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/ui/common/Components.kt b/app/src/main/java/tj/rsdevteam/inmuslim/ui/common/Components.kt
index 679b955..ed5c3c2 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/ui/common/Components.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/ui/common/Components.kt
@@ -11,6 +11,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.unit.dp
import tj.rsdevteam.inmuslim.ui.theme.InmuslimTypography
@@ -34,11 +35,11 @@ fun PrimaryButton(text: String, onClick: () -> Unit) {
}
@Composable
-fun ProgressBar() {
+fun ProgressIndicator() {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
- CircularProgressIndicator()
+ CircularProgressIndicator(strokeCap = StrokeCap.Round)
}
}
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/ui/home/HomeScreens.kt b/app/src/main/java/tj/rsdevteam/inmuslim/ui/home/HomeScreens.kt
index a148072..9c01d12 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/ui/home/HomeScreens.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/ui/home/HomeScreens.kt
@@ -18,9 +18,11 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@@ -28,10 +30,12 @@ import androidx.hilt.navigation.compose.hiltViewModel
import tj.rsdevteam.inmuslim.R
import tj.rsdevteam.inmuslim.data.models.Timing
import tj.rsdevteam.inmuslim.ui.common.ErrorDialog
-import tj.rsdevteam.inmuslim.ui.common.ProgressBar
+import tj.rsdevteam.inmuslim.ui.common.ProgressIndicator
import tj.rsdevteam.inmuslim.ui.theme.InmuslimShapes
import tj.rsdevteam.inmuslim.ui.theme.InmuslimTheme
import tj.rsdevteam.inmuslim.ui.theme.InmuslimTypography
+import tj.rsdevteam.inmuslim.utils.findActivity
+import tj.rsdevteam.inmuslim.utils.launchInAppReview
/**
* Created by Rustam Safarov on 8/13/23.
@@ -60,6 +64,14 @@ fun HomeScreen(
viewModel: HomeViewModel = hiltViewModel(),
navigateToSettings: () -> Unit
) {
+ val context = LocalContext.current
+
+ LaunchedEffect(key1 = Unit) {
+ if (!viewModel.isReviewShown) {
+ context.findActivity().launchInAppReview { viewModel.reviewShowed() }
+ }
+ }
+
Scaffold(
topBar = {
TopAppBar(
@@ -73,7 +85,7 @@ fun HomeScreen(
) { paddingValues ->
ErrorDialog(viewModel.dialogState.value)
if (viewModel.showLoading.value) {
- ProgressBar()
+ ProgressIndicator()
}
Column(
modifier = Modifier
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/ui/home/HomeViewModel.kt b/app/src/main/java/tj/rsdevteam/inmuslim/ui/home/HomeViewModel.kt
index 4b040b6..178ba3f 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/ui/home/HomeViewModel.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/ui/home/HomeViewModel.kt
@@ -6,9 +6,8 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import tj.rsdevteam.inmuslim.data.models.DialogState
+import tj.rsdevteam.inmuslim.data.models.Resource
import tj.rsdevteam.inmuslim.data.models.Timing
-import tj.rsdevteam.inmuslim.data.models.network.RegisterUserBody
-import tj.rsdevteam.inmuslim.data.models.network.Status
import tj.rsdevteam.inmuslim.data.repositories.TimingRepository
import tj.rsdevteam.inmuslim.data.repositories.UserRepository
import tj.rsdevteam.inmuslim.utils.Utils
@@ -33,6 +32,8 @@ class HomeViewModel
private set
var timing = mutableStateOf(null)
private set
+ val isReviewShown: Boolean
+ get() = userRepository.isReviewShown()
// endregion
init {
@@ -49,24 +50,24 @@ class HomeViewModel
viewModelScope.launch {
timingRepository.getTiming()
.collect { rs ->
- when (rs.status) {
- Status.LOADING -> Unit
- Status.SUCCESS -> timing.value = rs.data!!.timing
- Status.ERROR -> dialogState.value = DialogState(rs.message)
+ when (rs) {
+ is Resource.InProgress -> Unit
+ is Resource.Success -> timing.value = rs.data
+ is Resource.Error -> dialogState.value = DialogState(rs.error?.message)
}
- showLoading.value = rs.status == Status.LOADING
+ showLoading.value = rs is Resource.InProgress
}
}
}
private fun registerUser() {
viewModelScope.launch {
- userRepository.registerUser(RegisterUserBody(Utils.getDeviceInfo()))
+ userRepository.registerUser(Utils.getDeviceInfo())
.collect { rs ->
- when (rs.status) {
- Status.LOADING -> Unit
- Status.SUCCESS -> updateMessagingId()
- Status.ERROR -> Unit
+ when (rs) {
+ is Resource.InProgress -> Unit
+ is Resource.Success -> updateMessagingId()
+ is Resource.Error -> Unit
}
}
}
@@ -76,10 +77,10 @@ class HomeViewModel
viewModelScope.launch {
userRepository.updateMessagingId()
.collect { rs ->
- when (rs.status) {
- Status.LOADING -> Unit
- Status.SUCCESS -> Unit
- Status.ERROR -> Unit
+ when (rs) {
+ is Resource.InProgress -> Unit
+ is Resource.Success -> Unit
+ is Resource.Error -> Unit
}
}
}
@@ -92,4 +93,8 @@ class HomeViewModel
registerUser()
}
}
+
+ fun reviewShowed() {
+ userRepository.saveReviewShown()
+ }
}
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/ui/region/RegionScreens.kt b/app/src/main/java/tj/rsdevteam/inmuslim/ui/region/RegionScreens.kt
index 5a706a4..98f5e65 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/ui/region/RegionScreens.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/ui/region/RegionScreens.kt
@@ -24,7 +24,7 @@ import tj.rsdevteam.inmuslim.R
import tj.rsdevteam.inmuslim.data.models.Region
import tj.rsdevteam.inmuslim.ui.common.ErrorDialog
import tj.rsdevteam.inmuslim.ui.common.PrimaryButton
-import tj.rsdevteam.inmuslim.ui.common.ProgressBar
+import tj.rsdevteam.inmuslim.ui.common.ProgressIndicator
import tj.rsdevteam.inmuslim.ui.theme.InmuslimTypography
/**
@@ -59,7 +59,7 @@ fun RegionScreen(viewModel: RegionViewModel = hiltViewModel(), onSelected: () ->
ErrorDialog(dialogState = viewModel.dialogState.value)
Column {
if (viewModel.showLoading.value) {
- ProgressBar()
+ ProgressIndicator()
} else {
Spacer(modifier = Modifier.height(30.dp))
Text(
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/ui/region/RegionViewModel.kt b/app/src/main/java/tj/rsdevteam/inmuslim/ui/region/RegionViewModel.kt
index fc6c947..e5db48f 100644
--- a/app/src/main/java/tj/rsdevteam/inmuslim/ui/region/RegionViewModel.kt
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/ui/region/RegionViewModel.kt
@@ -4,11 +4,10 @@ import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
-import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import tj.rsdevteam.inmuslim.data.models.DialogState
import tj.rsdevteam.inmuslim.data.models.Region
-import tj.rsdevteam.inmuslim.data.models.network.Status
+import tj.rsdevteam.inmuslim.data.models.Resource
import tj.rsdevteam.inmuslim.data.repositories.RegionRepository
import javax.inject.Inject
@@ -40,12 +39,12 @@ class RegionViewModel
private fun getRegions() {
viewModelScope.launch {
regionRepository.getRegions().collect { rs ->
- when (rs.status) {
- Status.LOADING -> Unit
- Status.SUCCESS -> list.value = rs.data!!
- Status.ERROR -> dialogState.value = DialogState(rs.message)
+ when (rs) {
+ is Resource.InProgress -> Unit
+ is Resource.Success -> list.value = rs.data
+ is Resource.Error -> dialogState.value = DialogState(rs.error?.message)
}
- showLoading.value = rs.status == Status.LOADING
+ showLoading.value = rs is Resource.InProgress
}
}
}
diff --git a/app/src/main/java/tj/rsdevteam/inmuslim/utils/AndroidExt.kt b/app/src/main/java/tj/rsdevteam/inmuslim/utils/AndroidExt.kt
new file mode 100644
index 0000000..cce4fc7
--- /dev/null
+++ b/app/src/main/java/tj/rsdevteam/inmuslim/utils/AndroidExt.kt
@@ -0,0 +1,20 @@
+package tj.rsdevteam.inmuslim.utils
+
+import android.app.Activity
+import com.google.android.play.core.review.ReviewManagerFactory
+
+/**
+ * Created by Rustam Safarov on 6/25/24.
+ * github.com/rustamsafarovrs
+ */
+
+fun Activity.launchInAppReview(
+ onComplete: (() -> Unit)? = null,
+) {
+ val reviewManager = ReviewManagerFactory.create(this)
+ reviewManager.requestReviewFlow().addOnCompleteListener { task ->
+ if (task.isSuccessful) {
+ reviewManager.launchReviewFlow(this, task.result).addOnCompleteListener { onComplete?.invoke() }
+ }
+ }
+}
diff --git a/build.gradle b/build.gradle
deleted file mode 100644
index e0c3c75..0000000
--- a/build.gradle
+++ /dev/null
@@ -1,29 +0,0 @@
-buildscript {
- dependencies {
- classpath 'com.google.gms:google-services:4.3.15'
- classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.8'
- }
-}
-
-plugins {
- id 'com.android.application' version '8.1.0' apply false
- id 'org.jetbrains.kotlin.android' version '1.8.10' apply false
- id 'com.google.dagger.hilt.android' version '2.44' apply false
- id 'io.gitlab.arturbosch.detekt' version '1.23.0' apply false
-}
-
-subprojects {
- afterEvaluate {
- def detektTaskProvider = tasks.named("detekt")
- detektTaskProvider.configure {
- reports {
- html.required.set(true)
- sarif.required.set(false)
- xml.required.set(false)
- txt.required.set(false)
- md.required.set(false)
- }
- }
- tasks.getByName("preBuild").finalizedBy(detektTaskProvider)
- }
-}
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
new file mode 100644
index 0000000..80908a3
--- /dev/null
+++ b/build.gradle.kts
@@ -0,0 +1,25 @@
+import io.gitlab.arturbosch.detekt.extensions.DetektExtension
+
+plugins {
+ alias(libs.plugins.android.application) apply false
+ alias(libs.plugins.jetbrains.kotlin.android) apply false
+ alias(libs.plugins.jetbrains.kotlin.kapt) apply false
+ alias(libs.plugins.ksp) apply false
+ alias(libs.plugins.dagger.hilt.android) apply false
+ alias(libs.plugins.detekt) apply false
+ alias(libs.plugins.google.services) apply false
+ alias(libs.plugins.firebase.crashlytics) apply false
+}
+
+allprojects.onEach { project ->
+ project.afterEvaluate {
+ if (project.plugins.hasPlugin("org.jetbrains.kotlin.android")) {
+ project.plugins.apply("io.gitlab.arturbosch.detekt")
+ project.extensions.configure {
+ config.setFrom(rootProject.files("config/detekt/detekt.yml"))
+ baseline = rootProject.file("config/detekt/baseline.xml")
+ }
+ project.dependencies.add("detektPlugins", "io.gitlab.arturbosch.detekt:detekt-formatting:1.23.6")
+ }
+ }
+}
diff --git a/app/config/debug.keystore b/config/debug.keystore
similarity index 100%
rename from app/config/debug.keystore
rename to config/debug.keystore
diff --git a/config/detekt/baseline.xml b/config/detekt/baseline.xml
new file mode 100644
index 0000000..9254222
--- /dev/null
+++ b/config/detekt/baseline.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ ArgumentListWrapping:HomeScreens.kt$( title = { Text(text = stringResource(id = R.string.app_name)) }, actions = { IconButton(onClick = { navigateToSettings.invoke() }) { Icon(imageVector = Icons.Outlined.Settings, contentDescription = "Settings") } })
+ ArgumentListWrapping:Type.kt$( fontSize = 11.sp, lineHeight = 16.sp, letterSpacing = 0.5.sp, fontWeight = FontWeight.Medium )
+ ArgumentListWrapping:Type.kt$( fontSize = 12.sp, lineHeight = 16.sp, letterSpacing = 0.5.sp, fontWeight = FontWeight.Medium )
+ ArgumentListWrapping:Type.kt$( fontSize = 14.sp, lineHeight = 20.sp, letterSpacing = 0.1.sp, fontWeight = FontWeight.Medium )
+ ArgumentListWrapping:Type.kt$( fontSize = 22.sp, lineHeight = 28.sp, letterSpacing = 0.sp, lineBreak = LineBreak.Heading )
+ ArgumentListWrapping:Type.kt$( fontSize = 24.sp, lineHeight = 32.sp, letterSpacing = 0.sp, lineBreak = LineBreak.Heading )
+ ArgumentListWrapping:Type.kt$( fontSize = 28.sp, lineHeight = 36.sp, letterSpacing = 0.sp, lineBreak = LineBreak.Heading )
+ ArgumentListWrapping:Type.kt$( fontSize = 32.sp, lineHeight = 40.sp, letterSpacing = 0.sp, lineBreak = LineBreak.Heading )
+ ArgumentListWrapping:Type.kt$( fontSize = 36.sp, lineHeight = 44.sp, letterSpacing = 0.sp )
+ ArgumentListWrapping:Type.kt$( fontSize = 45.sp, lineHeight = 52.sp, letterSpacing = 0.sp )
+ ArgumentListWrapping:Type.kt$( fontSize = 57.sp, lineHeight = 64.sp, letterSpacing = (-0.25).sp )
+ ChainWrapping:MessagingService.kt$MessagingService$&&
+ ImportOrdering:MessagingService.kt$import android.app.NotificationChannel import android.app.NotificationManager import android.app.PendingIntent import android.content.Context import android.content.Intent import android.graphics.Bitmap import android.graphics.BitmapFactory import android.os.Build import android.util.Log import androidx.core.app.NotificationCompat import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage import dagger.hilt.android.AndroidEntryPoint import okhttp3.OkHttpClient import okhttp3.Request import tj.rsdevteam.inmuslim.ui.MainActivity import tj.rsdevteam.inmuslim.R import tj.rsdevteam.inmuslim.data.preferences.Preferences import java.io.IOException import javax.inject.Inject
+ SpacingAroundColon:App.kt$App$:
+ SpacingAroundCurly:MessagingService.kt$MessagingService${
+ SpacingAroundOperators:Dialogs.kt$=
+ Wrapping:HomeScreens.kt$(
+
+
diff --git a/app/config/detekt/detekt.yml b/config/detekt/detekt.yml
similarity index 78%
rename from app/config/detekt/detekt.yml
rename to config/detekt/detekt.yml
index f457f20..1322631 100644
--- a/app/config/detekt/detekt.yml
+++ b/config/detekt/detekt.yml
@@ -133,7 +133,7 @@ complexity:
active: true
functionThreshold: 6
constructorThreshold: 7
- ignoreDefaultParameters: false
+ ignoreDefaultParameters: true
ignoreDataClasses: true
ignoreAnnotatedParameter: []
MethodOverloading:
@@ -175,6 +175,7 @@ complexity:
ignoreDeprecated: false
ignorePrivate: false
ignoreOverridden: false
+ ignoreAnnotatedFunctions: ['Preview']
coroutines:
active: true
@@ -616,7 +617,7 @@ style:
- '1'
- '2'
ignoreHashCodeFunction: true
- ignorePropertyDeclaration: false
+ ignorePropertyDeclaration: true
ignoreLocalVariableDeclaration: false
ignoreConstantDeclaration: true
ignoreCompanionObjectPropertyDeclaration: true
@@ -663,8 +664,6 @@ style:
active: true
OptionalUnit:
active: false
- OptionalWhenBraces:
- active: false
PreferToOverPairSyntax:
active: false
ProtectedMemberInFinalClass:
@@ -741,6 +740,7 @@ style:
UnusedPrivateMember:
active: true
allowedNames: ''
+ ignoreAnnotated: ['Preview']
UnusedPrivateProperty:
active: true
allowedNames: '_|ignored|expected|serialVersionUID'
@@ -785,3 +785,272 @@ style:
active: true
excludeImports:
- 'java.util.*'
+
+formatting:
+ active: true
+ android: false
+ autoCorrect: true
+ AnnotationOnSeparateLine:
+ active: true
+ autoCorrect: true
+ indentSize: 4
+ AnnotationSpacing:
+ active: true
+ autoCorrect: true
+ ArgumentListWrapping:
+ active: true
+ autoCorrect: true
+ indentSize: 4
+ maxLineLength: 120
+ BlockCommentInitialStarAlignment:
+ active: true
+ autoCorrect: true
+ ChainWrapping:
+ active: true
+ autoCorrect: true
+ indentSize: 4
+ ClassName:
+ active: false
+ CommentSpacing:
+ active: true
+ autoCorrect: true
+ CommentWrapping:
+ active: true
+ autoCorrect: true
+ indentSize: 4
+ ContextReceiverMapping:
+ active: false
+ autoCorrect: true
+ maxLineLength: 120
+ indentSize: 4
+ DiscouragedCommentLocation:
+ active: false
+ autoCorrect: true
+ EnumEntryNameCase:
+ active: true
+ autoCorrect: true
+ EnumWrapping:
+ active: false
+ autoCorrect: true
+ indentSize: 4
+ Filename:
+ active: true
+ FinalNewline:
+ active: true
+ autoCorrect: true
+ insertFinalNewLine: true
+ FunKeywordSpacing:
+ active: true
+ autoCorrect: true
+ FunctionName:
+ active: false
+ FunctionReturnTypeSpacing:
+ active: true
+ autoCorrect: true
+ maxLineLength: 120
+ FunctionSignature:
+ active: false
+ autoCorrect: true
+ forceMultilineWhenParameterCountGreaterOrEqualThan: 2147483647
+ functionBodyExpressionWrapping: 'default'
+ maxLineLength: 120
+ indentSize: 4
+ FunctionStartOfBodySpacing:
+ active: true
+ autoCorrect: true
+ FunctionTypeReferenceSpacing:
+ active: true
+ autoCorrect: true
+ IfElseBracing:
+ active: false
+ autoCorrect: true
+ indentSize: 4
+ IfElseWrapping:
+ active: false
+ autoCorrect: true
+ indentSize: 4
+ ImportOrdering:
+ active: true
+ autoCorrect: true
+ layout: '*,java.**,javax.**,kotlin.**,^'
+ Indentation:
+ active: true
+ autoCorrect: true
+ indentSize: 4
+ KdocWrapping:
+ active: true
+ autoCorrect: true
+ indentSize: 4
+ MaximumLineLength:
+ active: true
+ maxLineLength: 120
+ ignoreBackTickedIdentifier: false
+ ModifierListSpacing:
+ active: true
+ autoCorrect: true
+ ModifierOrdering:
+ active: true
+ autoCorrect: true
+ MultiLineIfElse:
+ active: true
+ autoCorrect: true
+ indentSize: 4
+ MultilineExpressionWrapping:
+ active: false
+ autoCorrect: true
+ indentSize: 4
+ NoBlankLineBeforeRbrace:
+ active: true
+ autoCorrect: true
+ NoBlankLineInList:
+ active: false
+ autoCorrect: true
+ NoBlankLinesInChainedMethodCalls:
+ active: true
+ autoCorrect: true
+ NoConsecutiveBlankLines:
+ active: true
+ autoCorrect: true
+ NoConsecutiveComments:
+ active: false
+ NoEmptyClassBody:
+ active: true
+ autoCorrect: true
+ NoEmptyFirstLineInClassBody:
+ active: false
+ autoCorrect: true
+ indentSize: 4
+ NoEmptyFirstLineInMethodBlock:
+ active: true
+ autoCorrect: true
+ NoLineBreakAfterElse:
+ active: true
+ autoCorrect: true
+ NoLineBreakBeforeAssignment:
+ active: true
+ autoCorrect: true
+ NoMultipleSpaces:
+ active: true
+ autoCorrect: true
+ NoSemicolons:
+ active: true
+ autoCorrect: true
+ NoSingleLineBlockComment:
+ active: false
+ autoCorrect: true
+ indentSize: 4
+ NoTrailingSpaces:
+ active: true
+ autoCorrect: true
+ NoUnitReturn:
+ active: true
+ autoCorrect: true
+ NoUnusedImports:
+ active: true
+ autoCorrect: true
+ NoWildcardImports:
+ active: true
+ packagesToUseImportOnDemandProperty: 'java.util.*,kotlinx.android.synthetic.**'
+ NullableTypeSpacing:
+ active: true
+ autoCorrect: true
+ PackageName:
+ active: true
+ autoCorrect: true
+ ParameterListSpacing:
+ active: false
+ autoCorrect: true
+ ParameterListWrapping:
+ active: true
+ autoCorrect: true
+ maxLineLength: 120
+ indentSize: 4
+ ParameterWrapping:
+ active: true
+ autoCorrect: true
+ indentSize: 4
+ maxLineLength: 120
+ PropertyName:
+ active: false
+ PropertyWrapping:
+ active: true
+ autoCorrect: true
+ indentSize: 4
+ maxLineLength: 120
+ SpacingAroundAngleBrackets:
+ active: true
+ autoCorrect: true
+ SpacingAroundColon:
+ active: true
+ autoCorrect: true
+ SpacingAroundComma:
+ active: true
+ autoCorrect: true
+ SpacingAroundCurly:
+ active: true
+ autoCorrect: true
+ SpacingAroundDot:
+ active: true
+ autoCorrect: true
+ SpacingAroundDoubleColon:
+ active: true
+ autoCorrect: true
+ SpacingAroundKeyword:
+ active: true
+ autoCorrect: true
+ SpacingAroundOperators:
+ active: true
+ autoCorrect: true
+ SpacingAroundParens:
+ active: true
+ autoCorrect: true
+ SpacingAroundRangeOperator:
+ active: true
+ autoCorrect: true
+ SpacingAroundUnaryOperator:
+ active: true
+ autoCorrect: true
+ SpacingBetweenDeclarationsWithAnnotations:
+ active: true
+ autoCorrect: true
+ SpacingBetweenDeclarationsWithComments:
+ active: true
+ autoCorrect: true
+ SpacingBetweenFunctionNameAndOpeningParenthesis:
+ active: true
+ autoCorrect: true
+ StringTemplate:
+ active: true
+ autoCorrect: true
+ StringTemplateIndent:
+ active: false
+ autoCorrect: true
+ indentSize: 4
+ TrailingCommaOnCallSite:
+ active: false
+ autoCorrect: true
+ useTrailingCommaOnCallSite: true
+ TrailingCommaOnDeclarationSite:
+ active: false
+ autoCorrect: true
+ useTrailingCommaOnDeclarationSite: true
+ TryCatchFinallySpacing:
+ active: false
+ autoCorrect: true
+ indentSize: 4
+ TypeArgumentListSpacing:
+ active: false
+ autoCorrect: true
+ indentSize: 4
+ TypeParameterListSpacing:
+ active: false
+ autoCorrect: true
+ indentSize: 4
+ UnnecessaryParenthesesBeforeTrailingLambda:
+ active: true
+ autoCorrect: true
+ Wrapping:
+ active: true
+ autoCorrect: true
+ indentSize: 4
+ maxLineLength: 120
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
new file mode 100644
index 0000000..aa4c994
--- /dev/null
+++ b/gradle/libs.versions.toml
@@ -0,0 +1,88 @@
+[versions]
+agp = "8.5.0"
+kotlin = "1.9.24"
+java = "17"
+androidSdk = "34"
+androidMinSdk = "24"
+ksp = "1.9.24-1.0.20"
+daggerHilt = "2.51.1"
+detekt = "1.23.6"
+googleServices = "4.4.2"
+firebaseCrashlytics = "3.0.2"
+coreKtx = "1.13.1"
+composeBom = "2024.08.00"
+composeCompiler = "1.5.14"
+activityCompose = "1.9.1"
+navigationCompose = "2.7.7"
+hiltCompose = "1.2.0"
+lifecycle = "2.8.4"
+coroutines = "1.8.1"
+okhttp = "4.12.0"
+retrofit = "2.11.0"
+retrofitAdapters = "1.0.11"
+moshi = "1.15.1"
+firebaseBom = "33.1.1"
+googlePlayReview = "2.0.1"
+
+junit = "4.13.2"
+junitAndroid = "1.1.5"
+espresso = "3.5.1"
+
+[libraries]
+androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
+compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
+androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" }
+androidx-compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
+androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
+androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
+androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
+androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }
+androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
+androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }
+androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycle" }
+androidx-lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycle" }
+androidx-lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle" }
+androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle" }
+
+dagger-hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "daggerHilt" }
+dagger-hilt-android-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "daggerHilt" }
+dagger-hilt-compiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "hiltCompose" }
+dagger-hilt-navigation = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltCompose" }
+
+coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "coroutines" }
+coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "coroutines" }
+
+junit = { group = "junit", name = "junit", version.ref = "junit" }
+androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitAndroid" }
+androidx-espresso = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso" }
+androidx-compose-ui-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
+
+okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
+okhttp-logging = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp" }
+
+retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
+retrofit-moshi = { group = "com.squareup.retrofit2", name = "converter-moshi", version.ref = "retrofit" }
+retrofit-adapters-result = { group = "com.github.skydoves", name = "retrofit-adapters-result", version.ref = "retrofitAdapters" }
+
+moshi = { group = "com.squareup.moshi", name = "moshi", version.ref = "moshi" }
+moshi-kotlin = { group = "com.squareup.moshi", name = "moshi-kotlin", version.ref = "moshi" }
+moshi-kotlin-codegen = { group = "com.squareup.moshi", name = "moshi-kotlin-codegen", version.ref = "moshi" }
+
+firebase-bom = { group = "com.google.firebase", name = "firebase-bom", version.ref = "firebaseBom" }
+firebase-analytics-ktx = { group = "com.google.firebase", name = "firebase-analytics-ktx" }
+firebase-crashlytics-ktx = { group = "com.google.firebase", name = "firebase-crashlytics-ktx" }
+firebase-messaging-ktx = { group = "com.google.firebase", name = "firebase-messaging-ktx" }
+
+google-play-review-ktx = { module = "com.google.android.play:review-ktx", version.ref = "googlePlayReview" }
+
+[bundles]
+
+[plugins]
+android-application = { id = "com.android.application", version.ref = "agp" }
+jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
+jetbrains-kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" }
+ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
+dagger-hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "daggerHilt" }
+detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
+google-services = { id = "com.google.gms.google-services", version.ref = "googleServices" }
+firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebaseCrashlytics" }
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 4db538d..12512aa 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
#Sun Aug 13 23:14:57 TJT 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/settings.gradle b/settings.gradle.kts
similarity index 95%
rename from settings.gradle
rename to settings.gradle.kts
index 41e4afc..57aeb96 100644
--- a/settings.gradle
+++ b/settings.gradle.kts
@@ -14,4 +14,4 @@ dependencyResolutionManagement {
}
rootProject.name = "inmuslim-android"
-include ':app'
+include(":app")