diff --git a/app/build.gradle b/app/build.gradle index a417b9f8..dfbe8c5f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -27,7 +27,7 @@ def applicationName = "S-Boom" android { - compileSdkVersion 30 + compileSdkVersion 31 defaultConfig { applicationId "ru.frogogo.sboom" @@ -35,8 +35,8 @@ android { minSdkVersion 23 targetSdkVersion 30 - versionCode 8 - versionName "1.0.0" + versionCode 10 + versionName "1.0.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" setProperty("archivesBaseName", applicationName + "-v" + versionCode + "(" + versionName + ")-" + getDate()) @@ -44,6 +44,7 @@ android { buildConfigField 'int', 'API_VERSION', '1' buildConfigField 'boolean', 'DEBUG_STUFF', 'true' buildConfigField "java.util.Date", "BUILD_TIME", "new java.util.Date(" + System.currentTimeMillis() + "L)" + buildConfigField 'String', 'PHONE_PREFIX', '"+7"' } signingConfigs { @@ -72,6 +73,14 @@ android { buildConfigField 'String', 'BASE_URL', '"https://sboom.herokuapp.com"' } + zboom { + dimension 'server' + + applicationId "ru.frogogo.zboom.demo" + + buildConfigField 'String', 'BASE_URL', '"https://zboom-eu-staging.herokuapp.com"' + buildConfigField 'String', 'PHONE_PREFIX', '"+"' + } } buildTypes { @@ -120,19 +129,19 @@ kapt { dependencies { // AndroidX - implementation 'androidx.core:core-ktx:1.6.0' + implementation 'androidx.core:core-ktx:1.7.0' // AppCompat https://developer.android.com/jetpack/androidx/releases/appcompat - implementation 'androidx.appcompat:appcompat:1.3.1' + implementation 'androidx.appcompat:appcompat:1.4.0' // Fragment https://developer.android.com/jetpack/androidx/releases/fragment - implementation 'androidx.fragment:fragment-ktx:1.3.6' + implementation 'androidx.fragment:fragment-ktx:1.4.0' // ConstraintLayout https://developer.android.com/jetpack/androidx/releases/constraintlayout - implementation 'androidx.constraintlayout:constraintlayout:2.1.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.2' // ViewPager2 https://developer.android.com/jetpack/androidx/releases/viewpager2 implementation "androidx.viewpager2:viewpager2:1.0.0" // SwipeRefresh https://developer.android.com/jetpack/androidx/releases/swiperefreshlayout implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' // WorkManager https://developer.android.com/jetpack/androidx/releases/work - implementation 'androidx.work:work-runtime-ktx:2.6.0' + implementation 'androidx.work:work-runtime-ktx:2.7.1' // Google Play Services https://developers.google.com/android/guides/setup implementation 'com.google.android.gms:play-services-auth:19.2.0' @@ -148,14 +157,14 @@ dependencies { implementation "androidx.navigation:navigation-ui-ktx:$navVersion" // ViewModel and LiveData https://developer.android.com/jetpack/androidx/releases/lifecycle - def lifecycleVersion = '2.3.1' + def lifecycleVersion = '2.4.0' implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion" implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycleVersion" implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycleVersion" implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" // Adapter Delegates https://github.com/sockeqwe/AdapterDelegates - def adapterDelegatesVersion = '4.3.0' + def adapterDelegatesVersion = '4.3.1' implementation "com.hannesdorfmann:adapterdelegates4:$adapterDelegatesVersion" implementation "com.hannesdorfmann:adapterdelegates4-kotlin-dsl-viewbinding:$adapterDelegatesVersion" @@ -169,7 +178,7 @@ dependencies { implementation "com.github.hadilq.liveevent:liveevent:1.2.0" // WhatIf https://github.com/skydoves/WhatIf - implementation 'com.github.skydoves:whatif:1.1.0' + implementation 'com.github.skydoves:whatif:1.1.1' // Coroutines https://github.com/Kotlin/kotlinx.coroutines def coroutinesVersion = '1.5.2' @@ -183,10 +192,10 @@ dependencies { implementation 'com.redmadrobot:input-mask-android:6.0.0' // Coil https://github.com/coil-kt/coil/ - implementation 'io.coil-kt:coil:1.3.2' + implementation 'io.coil-kt:coil:1.4.0' // Koin https://github.com/InsertKoinIO/koin - def koinVersion = '3.1.2' + def koinVersion = '3.1.4' implementation "io.insert-koin:koin-android:$koinVersion" implementation "io.insert-koin:koin-androidx-workmanager:$koinVersion" @@ -197,7 +206,7 @@ dependencies { implementation "com.squareup.retrofit2:converter-moshi:$retrofitVersion" // OkHttp https://github.com/square/okhttp/ - def okHttpVersion = '4.9.1' + def okHttpVersion = '4.9.3' implementation "com.squareup.okhttp3:okhttp:$okHttpVersion" implementation "com.squareup.okhttp3:logging-interceptor:$okHttpVersion" @@ -216,7 +225,7 @@ dependencies { implementation 'com.github.ajalt:timberkt:1.5.1' // Firebase https://firebase.google.com/support/release-notes/android - implementation platform('com.google.firebase:firebase-bom:28.4.0') + implementation platform('com.google.firebase:firebase-bom:29.0.1') implementation 'com.google.firebase:firebase-analytics-ktx' implementation 'com.google.firebase:firebase-crashlytics-ktx' implementation 'com.google.firebase:firebase-perf-ktx' @@ -247,10 +256,10 @@ dependencies { testImplementation 'org.amshove.kluent:kluent:1.68' // Robolectric http://robolectric.org/getting-started/ - testImplementation 'org.robolectric:robolectric:4.6.1' + testImplementation 'org.robolectric:robolectric:4.7.3' // Junit 5 https://github.com/junit-team/junit5 - def junit5Version = "5.7.2" + def junit5Version = "5.8.2" testImplementation "org.junit.jupiter:junit-jupiter-api:$junit5Version" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit5Version" testImplementation "org.junit.jupiter:junit-jupiter-params:$junit5Version" @@ -263,7 +272,7 @@ dependencies { testImplementation 'androidx.arch.core:core-testing:2.1.0' // MockK https://github.com/mockk/mockk - testImplementation 'io.mockk:mockk:1.12.0' + testImplementation 'io.mockk:mockk:1.12.1' // Add field to BuildConfig android.defaultConfig.buildConfigField 'String', 'RETROFIT_VERSION', "\"$retrofitVersion\"" diff --git a/app/google-services.json b/app/google-services.json index 12e5538a..55ab7628 100644 --- a/app/google-services.json +++ b/app/google-services.json @@ -29,6 +29,51 @@ { "client_id": "99713790578-110snv82qvlm88eteflcf05sueu4o1cr.apps.googleusercontent.com", "client_type": 3 + }, + { + "client_id": "99713790578-lied9f35g5i1er1k538ef5g1444mhum6.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "ru.frogogo.WhiteLabel-iOS.sboom", + "app_store_id": "1565327032" + } + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:99713790578:android:3348cc8c23709ab5f388eb", + "android_client_info": { + "package_name": "ru.frogogo.zboom.demo" + } + }, + "oauth_client": [ + { + "client_id": "99713790578-110snv82qvlm88eteflcf05sueu4o1cr.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyBmggdVETxVr4BYmlXjfQkeeaKkR7iV2pI" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "99713790578-110snv82qvlm88eteflcf05sueu4o1cr.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "99713790578-lied9f35g5i1er1k538ef5g1444mhum6.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "ru.frogogo.WhiteLabel-iOS.sboom", + "app_store_id": "1565327032" + } } ] } diff --git a/app/src/main/java/ru/frogogo/whitelabel/core/recycler/BaseDelegationAdapter.kt b/app/src/main/java/ru/frogogo/whitelabel/core/recycler/BaseDelegationAdapter.kt index 9def2052..3f89d31c 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/core/recycler/BaseDelegationAdapter.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/core/recycler/BaseDelegationAdapter.kt @@ -17,7 +17,7 @@ open class BaseDelegationAdapter( } override fun setItems(items: MutableList) { - this.setItems(items, null) + this.setItems(items, commitCallback = null) } fun setItems(items: MutableList, commitCallback: (() -> Unit)?) { diff --git a/app/src/main/java/ru/frogogo/whitelabel/data/model/api/home/HomeProgress.kt b/app/src/main/java/ru/frogogo/whitelabel/data/model/api/home/HomeProgress.kt index 12aaf064..3fd3917b 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/data/model/api/home/HomeProgress.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/data/model/api/home/HomeProgress.kt @@ -2,11 +2,12 @@ package ru.frogogo.whitelabel.data.model.api.home import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import java.math.BigDecimal @JsonClass(generateAdapter = true) data class HomeProgress( @Json(name = "current") - val current: Int, + val current: BigDecimal, @Json(name = "target") - val target: Int, + val target: BigDecimal, ) diff --git a/app/src/main/java/ru/frogogo/whitelabel/data/model/api/home/HomePromotion.kt b/app/src/main/java/ru/frogogo/whitelabel/data/model/api/home/HomePromotion.kt index b55846db..c0cdbf19 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/data/model/api/home/HomePromotion.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/data/model/api/home/HomePromotion.kt @@ -3,6 +3,7 @@ package ru.frogogo.whitelabel.data.model.api.home import com.squareup.moshi.Json import com.squareup.moshi.JsonClass import ru.frogogo.whitelabel.data.model.api.Photo +import java.math.BigDecimal @JsonClass(generateAdapter = true) data class HomePromotion( @@ -13,7 +14,7 @@ data class HomePromotion( @Json(name = "steps") val steps: List, @Json(name = "price") - val price: Int, + val price: BigDecimal, @Json(name = "discounted_price") - val discountedPrice: Int, + val discountedPrice: BigDecimal, ) diff --git a/app/src/main/java/ru/frogogo/whitelabel/data/model/api/item/Item.kt b/app/src/main/java/ru/frogogo/whitelabel/data/model/api/item/Item.kt index d795e0a8..3fb03214 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/data/model/api/item/Item.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/data/model/api/item/Item.kt @@ -2,6 +2,7 @@ package ru.frogogo.whitelabel.data.model.api.item import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import java.math.BigDecimal @JsonClass(generateAdapter = true) data class Item( @@ -12,9 +13,9 @@ data class Item( @Json(name = "image_url") val imageUrl: String, @Json(name = "price") - val price: Int, + val price: BigDecimal, @Json(name = "discounted_price") - val discountedPrice: Int, + val discountedPrice: BigDecimal, @Json(name = "specs") val specs: String?, ) diff --git a/app/src/main/java/ru/frogogo/whitelabel/data/model/api/item/ItemInfo.kt b/app/src/main/java/ru/frogogo/whitelabel/data/model/api/item/ItemInfo.kt index 98610e27..bea5b370 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/data/model/api/item/ItemInfo.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/data/model/api/item/ItemInfo.kt @@ -2,6 +2,7 @@ package ru.frogogo.whitelabel.data.model.api.item import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import java.math.BigDecimal @JsonClass(generateAdapter = true) data class ItemInfo( @@ -12,9 +13,9 @@ data class ItemInfo( @Json(name = "image_url") val imageUrl: String, @Json(name = "price") - val price: Int, + val price: BigDecimal, @Json(name = "discounted_price") - val discountedPrice: Int, + val discountedPrice: BigDecimal, @Json(name = "specs") val specs: String?, @Json(name = "description") diff --git a/app/src/main/java/ru/frogogo/whitelabel/data/model/api/receipt/Receipt.kt b/app/src/main/java/ru/frogogo/whitelabel/data/model/api/receipt/Receipt.kt index 3e2af3d8..d922cc92 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/data/model/api/receipt/Receipt.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/data/model/api/receipt/Receipt.kt @@ -3,6 +3,7 @@ package ru.frogogo.whitelabel.data.model.api.receipt import com.squareup.moshi.Json import com.squareup.moshi.JsonClass import ru.frogogo.whitelabel.dictionary.ReceiptState +import java.math.BigDecimal import java.util.Date @JsonClass(generateAdapter = true) @@ -12,7 +13,7 @@ data class Receipt( @Json(name = "number") val number: Int, @Json(name = "sum") - val sum: Int, + val sum: BigDecimal, @Json(name = "state") val state: ReceiptState, @Json(name = "timestamp") diff --git a/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/home/HomeProgressUiModel.kt b/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/home/HomeProgressUiModel.kt index e861836e..9c59ffb2 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/home/HomeProgressUiModel.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/home/HomeProgressUiModel.kt @@ -1,10 +1,11 @@ package ru.frogogo.whitelabel.data.model.ui.home import ru.frogogo.whitelabel.core.recycler.RecyclerViewItem +import java.math.BigDecimal data class HomeProgressUiModel( - val current: Int, - val target: Int, + val current: BigDecimal, + val target: BigDecimal, ) : RecyclerViewItem { override fun getId(): Any = "item_coupon_progress" diff --git a/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/home/HomePromotionUiModel.kt b/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/home/HomePromotionUiModel.kt index ce0a66f2..9b7d625a 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/home/HomePromotionUiModel.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/home/HomePromotionUiModel.kt @@ -4,6 +4,7 @@ import android.os.Parcelable import androidx.annotation.Keep import kotlinx.parcelize.Parcelize import ru.frogogo.whitelabel.data.model.ui.PhotoUiModel +import java.math.BigDecimal @Keep @Parcelize @@ -11,6 +12,6 @@ data class HomePromotionUiModel( val name: String, val photo: PhotoUiModel, val steps: List, - val price: Int, - val priceDiscounted: Int, + val price: BigDecimal, + val priceDiscounted: BigDecimal, ) : Parcelable diff --git a/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/item/ItemInfoUiModel.kt b/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/item/ItemInfoUiModel.kt index ece964af..b27b78db 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/item/ItemInfoUiModel.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/item/ItemInfoUiModel.kt @@ -1,11 +1,13 @@ package ru.frogogo.whitelabel.data.model.ui.item +import java.math.BigDecimal + data class ItemInfoUiModel( val id: Int, val name: String, val imageUrl: String, - val price: Int, - val discountedPrice: Int, + val price: BigDecimal, + val discountedPrice: BigDecimal, val specs: String?, val description: String, ) diff --git a/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/item/ItemUiModel.kt b/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/item/ItemUiModel.kt index 4b45b637..4c3a58fd 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/item/ItemUiModel.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/item/ItemUiModel.kt @@ -1,13 +1,14 @@ package ru.frogogo.whitelabel.data.model.ui.item import ru.frogogo.whitelabel.core.recycler.RecyclerViewItem +import java.math.BigDecimal data class ItemUiModel( val id: Int, val name: String, val imageUrl: String, - val price: Int, - val discountedPrice: Int, + val price: BigDecimal, + val discountedPrice: BigDecimal, val specs: String?, ) : RecyclerViewItem { diff --git a/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/receipt/ReceiptUiModel.kt b/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/receipt/ReceiptUiModel.kt index b6394fa5..380a3c01 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/receipt/ReceiptUiModel.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/data/model/ui/receipt/ReceiptUiModel.kt @@ -5,6 +5,7 @@ import androidx.annotation.Keep import kotlinx.parcelize.Parcelize import ru.frogogo.whitelabel.core.recycler.RecyclerViewItem import ru.frogogo.whitelabel.dictionary.ReceiptState +import java.math.BigDecimal import java.util.Date @Keep @@ -13,7 +14,7 @@ data class ReceiptUiModel( val id: Int, val number: Int, val date: Date, - val value: Int, + val value: BigDecimal, val state: ReceiptState, val shopName: String, val rejectReason: ReceiptRejectReasonUiModel?, diff --git a/app/src/main/java/ru/frogogo/whitelabel/data/preferences/UserPreferences.kt b/app/src/main/java/ru/frogogo/whitelabel/data/preferences/UserPreferences.kt index 80d3b36b..ae805ad9 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/data/preferences/UserPreferences.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/data/preferences/UserPreferences.kt @@ -14,6 +14,7 @@ interface UserPreferences { // Data var user: User? + var receivedCouponsCount: Int fun clearData() diff --git a/app/src/main/java/ru/frogogo/whitelabel/data/preferences/UserPreferencesImpl.kt b/app/src/main/java/ru/frogogo/whitelabel/data/preferences/UserPreferencesImpl.kt index 31b40db5..fce7ef65 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/data/preferences/UserPreferencesImpl.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/data/preferences/UserPreferencesImpl.kt @@ -7,6 +7,7 @@ import com.squareup.moshi.Moshi import ru.frogogo.whitelabel.data.model.api.user.User import ru.frogogo.whitelabel.util.Constants import ru.frogogo.whitelabel.util.boolean +import ru.frogogo.whitelabel.util.int import ru.frogogo.whitelabel.util.json import ru.frogogo.whitelabel.util.stringNullable @@ -30,6 +31,7 @@ class UserPreferencesImpl(context: Context) : UserPreferences { // Data override var user: User? by preferences.json(moshi, KEY_USER, User::class) + override var receivedCouponsCount: Int by preferences.int(RECEIVED_COUPONS_COUNT, 0) override fun clearData() { preferences.edit { clear() } @@ -40,6 +42,7 @@ class UserPreferencesImpl(context: Context) : UserPreferences { refreshToken = null isLoggedIn = false user = null + receivedCouponsCount = 0 } companion object { @@ -53,5 +56,6 @@ class UserPreferencesImpl(context: Context) : UserPreferences { private const val KEY_ONBOARDING_COMPLETED = "onboarding_completed" private const val KEY_POLICY_ACCEPTED = "policy_accepted" private const val KEY_USER = "user" + private const val RECEIVED_COUPONS_COUNT = "received_coupons_count" } } diff --git a/app/src/main/java/ru/frogogo/whitelabel/data/repository/UserRepository.kt b/app/src/main/java/ru/frogogo/whitelabel/data/repository/UserRepository.kt index c49aaaf9..3e34d29c 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/data/repository/UserRepository.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/data/repository/UserRepository.kt @@ -14,4 +14,8 @@ interface UserRepository { fun getUser(): User? fun saveUser(user: User) + + fun getReceivedCouponsCount(): Int + + fun saveReceivedCouponsCount(count: Int) } diff --git a/app/src/main/java/ru/frogogo/whitelabel/data/repository/UserRepositoryImpl.kt b/app/src/main/java/ru/frogogo/whitelabel/data/repository/UserRepositoryImpl.kt index 8a79c5c4..f99c6089 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/data/repository/UserRepositoryImpl.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/data/repository/UserRepositoryImpl.kt @@ -32,4 +32,11 @@ class UserRepositoryImpl( override fun saveUser(user: User) { userPreferences.user = user } + + override fun getReceivedCouponsCount(): Int = + userPreferences.receivedCouponsCount + + override fun saveReceivedCouponsCount(count: Int) { + userPreferences.receivedCouponsCount = count + } } diff --git a/app/src/main/java/ru/frogogo/whitelabel/di/ScreenModuleLegacy.kt b/app/src/main/java/ru/frogogo/whitelabel/di/ScreenModuleLegacy.kt index 94af1f4b..d1f04871 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/di/ScreenModuleLegacy.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/di/ScreenModuleLegacy.kt @@ -16,6 +16,7 @@ import ru.frogogo.whitelabel.ui.profile.receipts.ReceiptsViewModel import ru.frogogo.whitelabel.ui.scanner.ScannerViewModel import ru.frogogo.whitelabel.ui.splash.SplashViewModel import ru.frogogo.whitelabel.ui.webview.WebViewViewModel +import ru.frogogo.whitelabel.view.dialog.CouponReceivedDialogFragmentCallbackViewModel import ru.frogogo.whitelabel.view.dialog.ErrorDialogFragmentCallbackViewModel @Deprecated("Use scopes") @@ -56,4 +57,5 @@ val screenModuleLegacy = module { // Stuff viewModel { ErrorDialogFragmentCallbackViewModel() } + viewModel { CouponReceivedDialogFragmentCallbackViewModel() } } diff --git a/app/src/main/java/ru/frogogo/whitelabel/di/UseCaseModule.kt b/app/src/main/java/ru/frogogo/whitelabel/di/UseCaseModule.kt index e4dcc64c..2d75d695 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/di/UseCaseModule.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/di/UseCaseModule.kt @@ -8,6 +8,7 @@ import ru.frogogo.whitelabel.usecase.auth.RefreshTokenUseCase import ru.frogogo.whitelabel.usecase.auth.RefreshTokenWorkerUseCase import ru.frogogo.whitelabel.usecase.auth.RequestConfirmationCodeUseCase import ru.frogogo.whitelabel.usecase.home.GetHomeUseCase +import ru.frogogo.whitelabel.usecase.home.WasCouponReceivedUseCase import ru.frogogo.whitelabel.usecase.item.GetItemUseCase import ru.frogogo.whitelabel.usecase.item.GetItemsUseCase import ru.frogogo.whitelabel.usecase.receipt.CreateReceiptUseCase @@ -25,6 +26,7 @@ val useCaseModule = module { // Home single { GetHomeUseCase(get(), get()) } + single { WasCouponReceivedUseCase(get()) } // User single { UpdateUserDetailsUseCase(get()) } diff --git a/app/src/main/java/ru/frogogo/whitelabel/di/scope/HomeScope.kt b/app/src/main/java/ru/frogogo/whitelabel/di/scope/HomeScope.kt index 328c290d..15c9c480 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/di/scope/HomeScope.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/di/scope/HomeScope.kt @@ -19,6 +19,7 @@ import ru.frogogo.whitelabel.ui.home.data.HomeDataFactory import ru.frogogo.whitelabel.ui.home.data.HomeDataFactoryImpl import ru.frogogo.whitelabel.ui.home.delegate.HomeClickHandlerDelegate import ru.frogogo.whitelabel.ui.home.delegate.HomeClickHandlerDelegateImpl +import ru.frogogo.whitelabel.ui.home.delegate.HomeCouponReceivedDelegate import ru.frogogo.whitelabel.ui.home.delegate.HomeDataLoadDelegate import ru.frogogo.whitelabel.ui.home.delegate.HomeDataLoadDelegateImpl import ru.frogogo.whitelabel.ui.home.delegate.HomeStateHandlerDelegate @@ -63,9 +64,13 @@ fun Module.homeScope() { mutableEffectLiveEvent = get(named(NAMED_EFFECT_LIVE_EVENT)), mutableScanButtonStateLive = get(named(NAMED_SCAN_BUTTON_STATE_LIVE)), dataFactory = get(), + couponReceivedDelegate = get(), ) } - scoped { HomeViewModel.DelegatesHolder(get(), get(), get()) } + scoped { + HomeCouponReceivedDelegate(get(), get(), get(named(NAMED_EFFECT_LIVE_EVENT))) + } + scoped { HomeViewModel.DelegatesHolder(get(), get(), get(), get()) } // Data scoped { HomeDataFactoryImpl() as HomeDataFactory } diff --git a/app/src/main/java/ru/frogogo/whitelabel/ui/auth/code/AuthCodeFragment.kt b/app/src/main/java/ru/frogogo/whitelabel/ui/auth/code/AuthCodeFragment.kt index a9b56d4b..cce86ede 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/ui/auth/code/AuthCodeFragment.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/ui/auth/code/AuthCodeFragment.kt @@ -29,7 +29,6 @@ import ru.frogogo.whitelabel.databinding.FragmentAuthCodeBinding import ru.frogogo.whitelabel.extension.binding.editText import ru.frogogo.whitelabel.extension.binding.initCodeConfirmationType import ru.frogogo.whitelabel.extension.fetchDrawable -import ru.frogogo.whitelabel.extension.formatWithMask import ru.frogogo.whitelabel.extension.hideKeyboard import ru.frogogo.whitelabel.extension.observe import ru.frogogo.whitelabel.extension.setNullableTextRes @@ -68,7 +67,7 @@ class AuthCodeFragment : BaseFragment() { showKeyboard() } - textViewPhoneNumber.text = args.phoneNumber.formatWithMask(Constants.PHONE_MASK_FULL) + textViewPhoneNumber.text = args.phoneNumber//.formatWithMask(Constants.PHONE_MASK_FULL) textViewPhoneNumberChange.setSafeOnClickListener(viewModel::navigateBack) buttonResendCode.setSafeOnClickListener(viewModel::resendConfirmationCode) textViewError.movementMethod = LinkMovementMethod.getInstance() @@ -105,7 +104,7 @@ class AuthCodeFragment : BaseFragment() { super.onStart() val intentFilter = IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION) - requireActivity().registerReceiver(smsVerificationReceiver, intentFilter) + requireActivity().registerReceiver(smsVerificationReceiver, intentFilter, SmsRetriever.SEND_PERMISSION, null) } override fun onStop() { diff --git a/app/src/main/java/ru/frogogo/whitelabel/ui/auth/phone/AuthPhoneFragment.kt b/app/src/main/java/ru/frogogo/whitelabel/ui/auth/phone/AuthPhoneFragment.kt index 8c1ab4ee..d4456686 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/ui/auth/phone/AuthPhoneFragment.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/ui/auth/phone/AuthPhoneFragment.kt @@ -15,6 +15,7 @@ import ru.frogogo.whitelabel.extension.binding.editText import ru.frogogo.whitelabel.extension.binding.initPhoneType import ru.frogogo.whitelabel.extension.observe import ru.frogogo.whitelabel.extension.setNullableTextRes +import ru.frogogo.whitelabel.extension.setSafeOnClickListener import ru.frogogo.whitelabel.util.Constants import ru.frogogo.whitelabel.util.ParallelAutoTransition import ru.frogogo.whitelabel.util.SpannableUtils @@ -29,7 +30,7 @@ class AuthPhoneFragment : BaseFragment(), private val binding: FragmentAuthPhoneBinding by viewBinding() private val args: AuthPhoneFragmentArgs by navArgs() - private var textChangedListener: MaskedTextChangedListener? = null +// private var textChangedListener: MaskedTextChangedListener? = null override fun provideConfiguration(): Configuration = Configuration( layoutId = R.layout.fragment_auth_phone, @@ -40,10 +41,11 @@ class AuthPhoneFragment : BaseFragment(), override fun initViews() { binding.textInputLayout.apply { initPhoneType() - setEditGoAction { viewModel.requestCode(text, true) } + setEditGoAction { requestCode() } showKeyboard() } binding.textViewError.movementMethod = LinkMovementMethod.getInstance() + binding.buttonContinue.setSafeOnClickListener { requestCode() } } override fun initObservers() { @@ -53,15 +55,15 @@ class AuthPhoneFragment : BaseFragment(), } } - override fun onStart() { - super.onStart() - attachFormatter() - } +// override fun onStart() { +// super.onStart() +// attachFormatter() +// } - override fun onStop() { - super.onStop() - detachFormatter() - } +// override fun onStop() { +// super.onStop() +// detachFormatter() +// } override fun onTextChanged(maskFilled: Boolean, extractedValue: String, formattedValue: String) { viewModel.requestCode(extractedValue) @@ -101,16 +103,20 @@ class AuthPhoneFragment : BaseFragment(), } } - private fun attachFormatter() { - textChangedListener = MaskedTextChangedListener.installOn( - editText = binding.textInputLayout.editText, - primaryFormat = Constants.PHONE_MASK, - valueListener = this, - autocomplete = false, // Prevent handling focus change - ) + private fun requestCode() { + viewModel.requestCode(binding.textInputLayout.text, true) } - private fun detachFormatter() { - binding.textInputLayout.editText.removeTextChangedListener(textChangedListener) - } +// private fun attachFormatter() { +// textChangedListener = MaskedTextChangedListener.installOn( +// editText = binding.textInputLayout.editText, +// primaryFormat = Constants.PHONE_MASK, +// valueListener = this, +// autocomplete = false, // Prevent handling focus change +// ) +// } + +// private fun detachFormatter() { +// binding.textInputLayout.editText.removeTextChangedListener(textChangedListener) +// } } diff --git a/app/src/main/java/ru/frogogo/whitelabel/ui/home/HomeAdapterDelegates.kt b/app/src/main/java/ru/frogogo/whitelabel/ui/home/HomeAdapterDelegates.kt index 9a800bf0..501fe40f 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/ui/home/HomeAdapterDelegates.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/ui/home/HomeAdapterDelegates.kt @@ -17,6 +17,7 @@ import ru.frogogo.whitelabel.ui.home.model.HomeReceiptsButton import ru.frogogo.whitelabel.ui.home.model.HomeScanUnavailable import ru.frogogo.whitelabel.ui.home.model.HomeSectionHeader import ru.frogogo.whitelabel.util.PriceUtils +import java.math.BigDecimal typealias OnReceiptsClickAction = () -> Unit @@ -41,8 +42,8 @@ object HomeAdapterDelegates { binding.textViewProgressCurrent.text = PriceUtils.formatPrice(item.current) binding.textViewProgressTarget.text = PriceUtils.formatPrice(item.target) binding.progressBar.apply { - max = item.target - progress = item.current + max = item.target.multiply(BigDecimal.valueOf(100)).toInt() + progress = item.current.multiply(BigDecimal.valueOf(100)).toInt() } } } diff --git a/app/src/main/java/ru/frogogo/whitelabel/ui/home/HomeEffect.kt b/app/src/main/java/ru/frogogo/whitelabel/ui/home/HomeEffect.kt index d45401cc..a0f239ea 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/ui/home/HomeEffect.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/ui/home/HomeEffect.kt @@ -1,6 +1,12 @@ package ru.frogogo.whitelabel.ui.home +import ru.frogogo.whitelabel.data.model.ui.coupon.CouponUiModel + sealed class HomeEffect { object ShowLoadingError : HomeEffect() + + data class ShowCouponReceived( + val coupon: CouponUiModel, + ) : HomeEffect() } diff --git a/app/src/main/java/ru/frogogo/whitelabel/ui/home/HomeFragment.kt b/app/src/main/java/ru/frogogo/whitelabel/ui/home/HomeFragment.kt index 62d19014..057a711f 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/ui/home/HomeFragment.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/ui/home/HomeFragment.kt @@ -7,22 +7,28 @@ import by.kirich1409.viewbindingdelegate.viewBinding import org.koin.android.ext.android.inject import org.koin.android.scope.AndroidScopeComponent import org.koin.androidx.scope.fragmentScope +import org.koin.androidx.viewmodel.ext.android.sharedViewModel import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.core.scope.Scope import ru.frogogo.whitelabel.R import ru.frogogo.whitelabel.core.recycler.BaseDelegationAdapter import ru.frogogo.whitelabel.core.ui.BaseFragment +import ru.frogogo.whitelabel.data.model.ui.coupon.CouponUiModel import ru.frogogo.whitelabel.data.model.ui.item.ItemUiModel import ru.frogogo.whitelabel.databinding.FragmentHomeBinding import ru.frogogo.whitelabel.extension.animateToGone import ru.frogogo.whitelabel.extension.animateToVisible import ru.frogogo.whitelabel.extension.observe +import ru.frogogo.whitelabel.extension.observeEvent import ru.frogogo.whitelabel.extension.setSafeOnClickListener import ru.frogogo.whitelabel.extension.setVisible import ru.frogogo.whitelabel.ui.common.CommonAdapterDelegates import ru.frogogo.whitelabel.util.ItemDecoration import ru.frogogo.whitelabel.util.analytics.AnalyticsScreen import ru.frogogo.whitelabel.util.unsafeLazy +import ru.frogogo.whitelabel.view.dialog.CouponReceivedDialogFragment +import ru.frogogo.whitelabel.view.dialog.CouponReceivedDialogFragment.Companion.showIn +import ru.frogogo.whitelabel.view.dialog.CouponReceivedDialogFragmentCallbackViewModel private const val SPAN_COUNT = 2 private const val SPAN_COUNT_ITEM = 1 @@ -32,6 +38,7 @@ class HomeFragment : BaseFragment(), override val scope: Scope by fragmentScope() override val viewModel: HomeViewModel by viewModel() + private val couponReceivedCallbackViewModel: CouponReceivedDialogFragmentCallbackViewModel by sharedViewModel() private val binding: FragmentHomeBinding by viewBinding() private val recycledViewPool: RecyclerView.RecycledViewPool by inject() @@ -64,6 +71,9 @@ class HomeFragment : BaseFragment(), observe(effectLiveEvent, ::handleEffect) observe(scanButtonStateLive, ::handleScanButtonState) } + observeEvent(couponReceivedCallbackViewModel.onShowClickedEvent) { coupon -> + viewModel.onCouponClicked(coupon) + } } private fun renderState(isLoading: Boolean = false, isError: Boolean = false) { @@ -118,6 +128,7 @@ class HomeFragment : BaseFragment(), @Exhaustive when (effect) { HomeEffect.ShowLoadingError -> showLoadingError() + is HomeEffect.ShowCouponReceived -> showCouponReceivedDialog(effect.coupon) } } @@ -136,4 +147,8 @@ class HomeFragment : BaseFragment(), binding.swipeRefreshLayout.isRefreshing = false renderState(isError = true) } + + private fun showCouponReceivedDialog(coupon: CouponUiModel) { + CouponReceivedDialogFragment.newInstance(coupon).showIn(childFragmentManager) + } } diff --git a/app/src/main/java/ru/frogogo/whitelabel/ui/home/HomeViewModel.kt b/app/src/main/java/ru/frogogo/whitelabel/ui/home/HomeViewModel.kt index e88f5864..dbd84df5 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/ui/home/HomeViewModel.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/ui/home/HomeViewModel.kt @@ -7,6 +7,7 @@ import ru.frogogo.whitelabel.core.recycler.RecyclerViewItem import ru.frogogo.whitelabel.core.ui.BaseViewModel import ru.frogogo.whitelabel.ui.home.delegate.HomeClickHandlerDelegate import ru.frogogo.whitelabel.ui.home.delegate.HomeClickHandlerDelegateImpl +import ru.frogogo.whitelabel.ui.home.delegate.HomeCouponReceivedDelegate import ru.frogogo.whitelabel.ui.home.delegate.HomeDataLoadDelegate import ru.frogogo.whitelabel.ui.home.delegate.HomeDataLoadDelegateImpl import ru.frogogo.whitelabel.ui.home.delegate.HomeStateHandlerDelegate @@ -38,6 +39,7 @@ class HomeViewModel( dataLoadDelegate.cancelJob() clicksHandlerDelegate.cancelJob() stateHandlerDelegate.cancelJob() + couponReceivedDelegate.cancelJob() } } @@ -45,6 +47,7 @@ class HomeViewModel( val dataLoadDelegate: HomeDataLoadDelegateImpl, val clicksHandlerDelegate: HomeClickHandlerDelegateImpl, val stateHandlerDelegate: HomeStateHandlerDelegate, + val couponReceivedDelegate: HomeCouponReceivedDelegate, ) data class LiveDataHolder( diff --git a/app/src/main/java/ru/frogogo/whitelabel/ui/home/delegate/HomeCouponReceivedDelegate.kt b/app/src/main/java/ru/frogogo/whitelabel/ui/home/delegate/HomeCouponReceivedDelegate.kt new file mode 100644 index 00000000..103a0e6b --- /dev/null +++ b/app/src/main/java/ru/frogogo/whitelabel/ui/home/delegate/HomeCouponReceivedDelegate.kt @@ -0,0 +1,21 @@ +package ru.frogogo.whitelabel.ui.home.delegate + +import com.hadilq.liveevent.LiveEvent +import ru.frogogo.whitelabel.core.ui.BaseViewModelDelegate +import ru.frogogo.whitelabel.data.model.ui.home.HomeState +import ru.frogogo.whitelabel.ui.home.HomeEffect +import ru.frogogo.whitelabel.usecase.home.WasCouponReceivedUseCase +import ru.frogogo.whitelabel.util.dispatcher.DispatchersProvider + +class HomeCouponReceivedDelegate( + dispatchers: DispatchersProvider, + private val wasCouponReceivedUseCase: WasCouponReceivedUseCase, + private val homeEffectLiveEvent: LiveEvent, +) : BaseViewModelDelegate(dispatchers) { + + fun showCouponReceived(state: HomeState) { + wasCouponReceivedUseCase(state)?.let { coupon -> + homeEffectLiveEvent.postValue(HomeEffect.ShowCouponReceived(coupon)) + } + } +} diff --git a/app/src/main/java/ru/frogogo/whitelabel/ui/home/delegate/HomeStateHandlerDelegate.kt b/app/src/main/java/ru/frogogo/whitelabel/ui/home/delegate/HomeStateHandlerDelegate.kt index efa7d118..9a9b9e49 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/ui/home/delegate/HomeStateHandlerDelegate.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/ui/home/delegate/HomeStateHandlerDelegate.kt @@ -21,6 +21,7 @@ class HomeStateHandlerDelegate( private val mutableEffectLiveEvent: LiveEvent, private val mutableScanButtonStateLive: MutableLiveData, private val dataFactory: HomeDataFactory, + private val couponReceivedDelegate: HomeCouponReceivedDelegate, ) : BaseViewModelDelegate(dispatchersProvider) { fun showLoader() { @@ -36,6 +37,7 @@ class HomeStateHandlerDelegate( } else { HomeScanButtonState.SHOWN_DISABLED } + couponReceivedDelegate.showCouponReceived(data) } fun showError() { diff --git a/app/src/main/java/ru/frogogo/whitelabel/usecase/home/WasCouponReceivedUseCase.kt b/app/src/main/java/ru/frogogo/whitelabel/usecase/home/WasCouponReceivedUseCase.kt new file mode 100644 index 00000000..5324dea0 --- /dev/null +++ b/app/src/main/java/ru/frogogo/whitelabel/usecase/home/WasCouponReceivedUseCase.kt @@ -0,0 +1,27 @@ +package ru.frogogo.whitelabel.usecase.home + +import ru.frogogo.whitelabel.data.model.ui.coupon.CouponUiModel +import ru.frogogo.whitelabel.data.model.ui.home.HomeState +import ru.frogogo.whitelabel.data.repository.UserRepository + +class WasCouponReceivedUseCase( + private val userRepository: UserRepository, +) { + + operator fun invoke(state: HomeState): CouponUiModel? { + if (state !is HomeState.Progress) { + return null + } + + val receivedCouponsRemote = state.coupons.size + val receivedCouponsLocal = userRepository.getReceivedCouponsCount() + val newCouponReceived = receivedCouponsLocal < receivedCouponsRemote + + return if (newCouponReceived) { + userRepository.saveReceivedCouponsCount(receivedCouponsRemote) + state.coupons.first() + } else { + null + } + } +} diff --git a/app/src/main/java/ru/frogogo/whitelabel/util/Constants.kt b/app/src/main/java/ru/frogogo/whitelabel/util/Constants.kt index b88965e4..16447bba 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/util/Constants.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/util/Constants.kt @@ -17,14 +17,13 @@ object Constants { // Urls const val HELP_SCAN_RECEIPT_URL = "https://poprobuy.ru" // TODO: 14.07.2020 Change url - const val HELP_SCAN_MACHINE_URL = "https://google.com" // TODO: 14.07.2020 Change url // Auth const val SMS_SENDER_NAME = "CodoPhone" // TODO: 19.07.2020 Change to own sender + const val PHONE_PREFIX = BuildConfig.PHONE_PREFIX const val PHONE_MASK = "([000]) [000]-[00]-[00]" - const val PHONE_MASK_FULL = "+7 ([000]) [000]-[00]-[00]" - const val PHONE_PREFIX = "+7" + const val PHONE_MASK_FULL = "$PHONE_PREFIX $PHONE_MASK" const val CONFIRMATION_CODE_LENGTH = 4 const val VENDING_MACHINE_ID_MAX_LENGTH = 8 diff --git a/app/src/main/java/ru/frogogo/whitelabel/util/PriceUtils.kt b/app/src/main/java/ru/frogogo/whitelabel/util/PriceUtils.kt index 3b91ae00..d3473007 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/util/PriceUtils.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/util/PriceUtils.kt @@ -1,5 +1,6 @@ package ru.frogogo.whitelabel.util +import java.math.BigDecimal import java.text.NumberFormat import java.util.Locale import kotlin.math.absoluteValue @@ -24,10 +25,9 @@ object PriceUtils { /** * Returns formatter price with currency symbol * @param price integer price value - * @param formatSign whether include sign or not */ - fun formatPrice(price: Int, formatSign: Boolean = false): String = - "${price.format(formatSign)} ${CURRENCY_SYMBOL[AppLocale.RU]}" + fun formatPrice(price: BigDecimal): String = + "${price.toPlainString()} €" } private sealed class AppLocale { diff --git a/app/src/main/java/ru/frogogo/whitelabel/util/Validators.kt b/app/src/main/java/ru/frogogo/whitelabel/util/Validators.kt index f5753c9f..86468dad 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/util/Validators.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/util/Validators.kt @@ -26,7 +26,7 @@ object Validators { @StringRes fun isPhone(text: String): Int? = when { // Check length - text.replace(PATTERN_NON_DIGITS, "").length < MIN_LENGTH_PHONE -> R.string.error_phone_length + // text.replace(PATTERN_NON_DIGITS, "").length < MIN_LENGTH_PHONE -> R.string.error_phone_length // Check format !Patterns.PHONE.matcher(text).matches() -> R.string.error_phone_format // All is ok @@ -42,7 +42,7 @@ object Validators { // Check length text.length !in MIN_USER_NAME_LENGTH..MAX_USER_NAME_LENGTH -> R.string.error_user_name_length // Check format - !PATTERN_USER_NAME.matches(text) -> R.string.error_user_name_format +// !PATTERN_USER_NAME.matches(text) -> R.string.error_user_name_format // All is ok else -> null } diff --git a/app/src/main/java/ru/frogogo/whitelabel/util/moshi/MoshiUtils.kt b/app/src/main/java/ru/frogogo/whitelabel/util/moshi/MoshiUtils.kt index 213bbbee..c3ecf6eb 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/util/moshi/MoshiUtils.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/util/moshi/MoshiUtils.kt @@ -3,6 +3,7 @@ package ru.frogogo.whitelabel.util.moshi import com.squareup.moshi.Moshi import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter import ru.frogogo.whitelabel.util.moshi.adapter.AuthenticationResponseAdapter +import ru.frogogo.whitelabel.util.moshi.adapter.PriceAdapter import ru.frogogo.whitelabel.util.moshi.adapter.ReceiptStateJsonAdapter import java.util.Date @@ -13,7 +14,8 @@ object MoshiUtils { fun getNetworkAdapter(): Moshi = Moshi.Builder() .add(Date::class.java, Rfc3339DateJsonAdapter()) - .add(ReceiptStateJsonAdapter()) - .add(AuthenticationResponseAdapter()) + .add(ReceiptStateJsonAdapter) + .add(AuthenticationResponseAdapter) + .add(PriceAdapter) .build() } diff --git a/app/src/main/java/ru/frogogo/whitelabel/util/moshi/adapter/AuthenticationResponseAdapter.kt b/app/src/main/java/ru/frogogo/whitelabel/util/moshi/adapter/AuthenticationResponseAdapter.kt index 2fa8bd78..628c3268 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/util/moshi/adapter/AuthenticationResponseAdapter.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/util/moshi/adapter/AuthenticationResponseAdapter.kt @@ -5,7 +5,7 @@ import ru.frogogo.whitelabel.data.mapper.toResponse import ru.frogogo.whitelabel.data.model.api.auth.AuthenticationResponse import ru.frogogo.whitelabel.data.model.api.auth.AuthenticationResponseJson -class AuthenticationResponseAdapter { +object AuthenticationResponseAdapter { @FromJson fun fromJson(response: AuthenticationResponseJson): AuthenticationResponse = response.toResponse() diff --git a/app/src/main/java/ru/frogogo/whitelabel/util/moshi/adapter/PriceAdapter.kt b/app/src/main/java/ru/frogogo/whitelabel/util/moshi/adapter/PriceAdapter.kt new file mode 100644 index 00000000..25d86a03 --- /dev/null +++ b/app/src/main/java/ru/frogogo/whitelabel/util/moshi/adapter/PriceAdapter.kt @@ -0,0 +1,18 @@ +package ru.frogogo.whitelabel.util.moshi.adapter + +import com.squareup.moshi.FromJson +import com.squareup.moshi.ToJson +import java.math.BigDecimal + +object PriceAdapter { + + @FromJson + fun fromJson(string: String): BigDecimal { + return BigDecimal(string) + } + + @ToJson + fun toJson(price: BigDecimal): String { + return price.toPlainString() + } +} diff --git a/app/src/main/java/ru/frogogo/whitelabel/util/moshi/adapter/ReceiptStateJsonAdapter.kt b/app/src/main/java/ru/frogogo/whitelabel/util/moshi/adapter/ReceiptStateJsonAdapter.kt index 49e3586e..5d66d3a8 100644 --- a/app/src/main/java/ru/frogogo/whitelabel/util/moshi/adapter/ReceiptStateJsonAdapter.kt +++ b/app/src/main/java/ru/frogogo/whitelabel/util/moshi/adapter/ReceiptStateJsonAdapter.kt @@ -4,7 +4,7 @@ import com.squareup.moshi.FromJson import ru.frogogo.whitelabel.dictionary.ReceiptState import java.util.Locale -class ReceiptStateJsonAdapter { +object ReceiptStateJsonAdapter { @FromJson fun fromJson(state: String): ReceiptState = diff --git a/app/src/main/java/ru/frogogo/whitelabel/view/dialog/CouponReceivedDialogFragment.kt b/app/src/main/java/ru/frogogo/whitelabel/view/dialog/CouponReceivedDialogFragment.kt new file mode 100644 index 00000000..e3267f20 --- /dev/null +++ b/app/src/main/java/ru/frogogo/whitelabel/view/dialog/CouponReceivedDialogFragment.kt @@ -0,0 +1,46 @@ +package ru.frogogo.whitelabel.view.dialog + +import androidx.core.os.bundleOf +import androidx.fragment.app.FragmentManager +import by.kirich1409.viewbindingdelegate.viewBinding +import org.koin.androidx.viewmodel.ext.android.sharedViewModel +import ru.frogogo.whitelabel.R +import ru.frogogo.whitelabel.core.ui.BaseDialogFragment +import ru.frogogo.whitelabel.data.model.ui.coupon.CouponUiModel +import ru.frogogo.whitelabel.databinding.DialogCouponReceivedBinding +import ru.frogogo.whitelabel.util.argument + +class CouponReceivedDialogFragment : BaseDialogFragment(R.layout.dialog_coupon_received) { + + private val binding: DialogCouponReceivedBinding by viewBinding() + private val callbackViewModel: CouponReceivedDialogFragmentCallbackViewModel by sharedViewModel() + private val coupon: CouponUiModel by argument(ARG_COUPON) + + override fun initViews() { + binding.apply { + textViewSubtitle.text = getString(R.string.home_coupon_received_text, coupon.name) + buttonContinue.setOnClickListener { + callbackViewModel.onShow(coupon) + dismissAllowingStateLoss() + } + } + } + + companion object : DialogCompanion { + + private const val TAG = "ErrorDialogFragment" + private const val ARG_COUPON = "arg:coupon" + + override fun CouponReceivedDialogFragment.showIn(fragmentManager: FragmentManager) { + show(fragmentManager, TAG) + } + + fun newInstance( + coupon: CouponUiModel, + ): CouponReceivedDialogFragment = CouponReceivedDialogFragment().apply { + arguments = bundleOf( + ARG_COUPON to coupon, + ) + } + } +} diff --git a/app/src/main/java/ru/frogogo/whitelabel/view/dialog/CouponReceivedDialogFragmentCallbackViewModel.kt b/app/src/main/java/ru/frogogo/whitelabel/view/dialog/CouponReceivedDialogFragmentCallbackViewModel.kt new file mode 100644 index 00000000..fa1aa79a --- /dev/null +++ b/app/src/main/java/ru/frogogo/whitelabel/view/dialog/CouponReceivedDialogFragmentCallbackViewModel.kt @@ -0,0 +1,20 @@ +package ru.frogogo.whitelabel.view.dialog + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.github.ajalt.timberkt.e +import ru.frogogo.whitelabel.core.Event +import ru.frogogo.whitelabel.data.model.ui.coupon.CouponUiModel +import ru.frogogo.whitelabel.extension.asLiveData +import ru.frogogo.whitelabel.extension.setEvent + +class CouponReceivedDialogFragmentCallbackViewModel : ViewModel() { + + private val _onShowClickedEvent = MutableLiveData>() + val onShowClickedEvent = _onShowClickedEvent.asLiveData() + + fun onShow(coupon: CouponUiModel) { + e { "Coupon1 $coupon" } + _onShowClickedEvent.setEvent(coupon) + } +} diff --git a/app/src/main/res/drawable/ic_coupon.xml b/app/src/main/res/drawable/ic_coupon.xml new file mode 100644 index 00000000..c2296643 --- /dev/null +++ b/app/src/main/res/drawable/ic_coupon.xml @@ -0,0 +1,22 @@ + + + + + + + diff --git a/app/src/main/res/layout/dialog_coupon_received.xml b/app/src/main/res/layout/dialog_coupon_received.xml new file mode 100644 index 00000000..d0ef912b --- /dev/null +++ b/app/src/main/res/layout/dialog_coupon_received.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_auth_phone.xml b/app/src/main/res/layout/fragment_auth_phone.xml index c2cc466f..b3d26da5 100644 --- a/app/src/main/res/layout/fragment_auth_phone.xml +++ b/app/src/main/res/layout/fragment_auth_phone.xml @@ -58,11 +58,21 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="@dimen/spacing_6" - app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintBottom_toTopOf="@id/button_continue" app:layout_constraintLeft_toLeftOf="@id/text_input_layout" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/text_input_layout" /> + + diff --git a/app/src/main/res/values/strings_profile.xml b/app/src/main/res/values/strings_profile.xml index 2db80c91..efad0723 100644 --- a/app/src/main/res/values/strings_profile.xml +++ b/app/src/main/res/values/strings_profile.xml @@ -1,28 +1,23 @@ - Версия %1$s (%2$d) от %3$s Пригласить друга Приглашайте друзей и получайте бесплатные товары - - Мои чеки + My receipts Мои купоны Выход - - Мои чеки - У вас пока нет\nотсканированных чеков - Проверяется - Принят - Выполнен - Отклонен - + My receipts + You don\'t have scanned receipts yet + Being checked + Adopted + Completed + Rejected Мои купоны У вас пока нет доступных купонов - - Сканирование нового чека недоступно, т.к. у вас есть чек в - состоянии \"Принят\" или \"Проверяется\" - + You can scan the receipt + Scanning of a new receipt is not available, because you have a + receipt in the state \"Accepted\" or \" Checked\" diff --git a/app/src/zboom/ic_launcher-playstore.png b/app/src/zboom/ic_launcher-playstore.png new file mode 100644 index 00000000..a7278301 Binary files /dev/null and b/app/src/zboom/ic_launcher-playstore.png differ diff --git a/app/src/zboom/res/drawable/ic_app_logo.xml b/app/src/zboom/res/drawable/ic_app_logo.xml new file mode 100644 index 00000000..e5d0264c --- /dev/null +++ b/app/src/zboom/res/drawable/ic_app_logo.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + diff --git a/app/src/zboom/res/drawable/ic_launcher_background.xml b/app/src/zboom/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000..cdbb5150 --- /dev/null +++ b/app/src/zboom/res/drawable/ic_launcher_background.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/app/src/zboom/res/drawable/ic_launcher_foreground.xml b/app/src/zboom/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 00000000..128e8494 --- /dev/null +++ b/app/src/zboom/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + diff --git a/app/src/zboom/res/mipmap-hdpi/ic_launcher.png b/app/src/zboom/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000..735120ca Binary files /dev/null and b/app/src/zboom/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/zboom/res/mipmap-hdpi/ic_launcher_round.png b/app/src/zboom/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 00000000..b8927868 Binary files /dev/null and b/app/src/zboom/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/zboom/res/mipmap-mdpi/ic_launcher.png b/app/src/zboom/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000..af7c45db Binary files /dev/null and b/app/src/zboom/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/zboom/res/mipmap-mdpi/ic_launcher_round.png b/app/src/zboom/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 00000000..7fdf9c9c Binary files /dev/null and b/app/src/zboom/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/zboom/res/mipmap-xhdpi/ic_launcher.png b/app/src/zboom/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 00000000..bd6b80e6 Binary files /dev/null and b/app/src/zboom/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/zboom/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/zboom/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 00000000..b0651fd5 Binary files /dev/null and b/app/src/zboom/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/zboom/res/mipmap-xxhdpi/ic_launcher.png b/app/src/zboom/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000..8f4ec950 Binary files /dev/null and b/app/src/zboom/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/zboom/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/zboom/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 00000000..125b8b0a Binary files /dev/null and b/app/src/zboom/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/zboom/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/zboom/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000..c49e38dc Binary files /dev/null and b/app/src/zboom/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/zboom/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/zboom/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 00000000..1771b9e7 Binary files /dev/null and b/app/src/zboom/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/zboom/res/values/plurals.xml b/app/src/zboom/res/values/plurals.xml new file mode 100644 index 00000000..b368f82c --- /dev/null +++ b/app/src/zboom/res/values/plurals.xml @@ -0,0 +1,9 @@ + + + + + %1$d second + %1$d seconds + + + diff --git a/app/src/zboom/res/values/strings.xml b/app/src/zboom/res/values/strings.xml new file mode 100644 index 00000000..a6863a40 --- /dev/null +++ b/app/src/zboom/res/values/strings.xml @@ -0,0 +1,6 @@ + + + + Z-Boom + + diff --git a/app/src/zboom/res/values/strings_auth.xml b/app/src/zboom/res/values/strings_auth.xml new file mode 100644 index 00000000..9cf6e631 --- /dev/null +++ b/app/src/zboom/res/values/strings_auth.xml @@ -0,0 +1,24 @@ + + + Сontinue + By using this application, you agree to the use of Cooke technologies. and with the collection and processing of personal data. \n\nThese technologies are used to analyze and improve your user experience. + Сontinue + Enter + Enter your phone number + (000) 000-00-00 + Exceeded the number of attempts to request a confirmation code + Type code + The code was sent to the number + ・・・・ + Edit + Send a new code + Sending the code + Invalid code, please try again or request a new one + Sending error + Let’s meet! + What is your name? + Your name + Fine,\n%1$s! + It remains to enter your email + Your email address + diff --git a/app/src/zboom/res/values/strings_common.xml b/app/src/zboom/res/values/strings_common.xml new file mode 100644 index 00000000..eac363fb --- /dev/null +++ b/app/src/zboom/res/values/strings_common.xml @@ -0,0 +1,25 @@ + + + + OK + Сontinue + Cancel + Yes + No + + The phone number cannot be less than 10 characters + The phone number contains invalid characters + The name must consist of 2 to 20 letters + Name contains invalid characters + The code must consist of 4 digits + The code must consist only of digits + This email not correct + Необходимо ввести номер аппарата + Отсканированный QR-код имеет неверный формат + Something went wrong! + Repeat + An internal error has occurred, log in again + + loading error + Repeat + diff --git a/app/src/zboom/res/values/strings_coupon.xml b/app/src/zboom/res/values/strings_coupon.xml new file mode 100644 index 00000000..f58fd108 --- /dev/null +++ b/app/src/zboom/res/values/strings_coupon.xml @@ -0,0 +1,7 @@ + + + Coupon № %d + Show the code to the cashier + Instructions for receiving + Show the code to the cashier + diff --git a/app/src/zboom/res/values/strings_home.xml b/app/src/zboom/res/values/strings_home.xml new file mode 100644 index 00000000..dc2d6c54 --- /dev/null +++ b/app/src/zboom/res/values/strings_home.xml @@ -0,0 +1,17 @@ + + + Remember 2 simple rules: + Scan receipts from stores that have any products from Lion Sabatier International promotional collection + After you collect the amount of the product for 38 €, you will receive a coupon for the purchase of an electric kettle Lion Sabatier International for 0,01 € + Scan the receipt + Coupon + Promotion products + When your receipt passes verification, you will be able to scan a new receipt. + Coupons + My receipts + Scan a new receipt + + You have received a coupon! + Congratulations you have received a coupon for %s + Watch + diff --git a/app/src/zboom/res/values/strings_item.xml b/app/src/zboom/res/values/strings_item.xml new file mode 100644 index 00000000..3ba7354e --- /dev/null +++ b/app/src/zboom/res/values/strings_item.xml @@ -0,0 +1,6 @@ + + + Parameter + Full price + Promotional price + diff --git a/app/src/zboom/res/values/strings_onboarding.xml b/app/src/zboom/res/values/strings_onboarding.xml new file mode 100644 index 00000000..6c0b372f --- /dev/null +++ b/app/src/zboom/res/values/strings_onboarding.xml @@ -0,0 +1,11 @@ + + + Next + Sign in + Buy it + Promotional products of Lion Sabatier Internationall + Scan it + Receipts containing promotional items + Get a coupon + You can buy a kettle for 0,01 €. After the purchase Lion Sabatier international advertising products in the amount of 38 € + diff --git a/app/src/zboom/res/values/strings_profile.xml b/app/src/zboom/res/values/strings_profile.xml new file mode 100644 index 00000000..82b6a8c5 --- /dev/null +++ b/app/src/zboom/res/values/strings_profile.xml @@ -0,0 +1,21 @@ + + + + Версия %1$s (%2$d) от %3$s + Пригласить друга + Приглашайте друзей и получайте бесплатные товары + Мои чеки + Мои купоны + Выход + + Мои чеки + У вас пока нет\nотсканированных чеков + Проверяется + Принят + Отклонен + + Мои купоны + У вас пока нет доступных купонов + Вы можете отсканировать чек + Сканирование нового чека недоступно, т.к. у вас есть чек в состоянии \"Принят\" или \"Проверяется\" + diff --git a/app/src/zboom/res/values/strings_receipt.xml b/app/src/zboom/res/values/strings_receipt.xml new file mode 100644 index 00000000..3766cb50 --- /dev/null +++ b/app/src/zboom/res/values/strings_receipt.xml @@ -0,0 +1,9 @@ + + + № %1$d + Great, the receipt has been accepted! + As soon as the total amount of receipts is equal to 38 €, you will receive a coupon for the purchase of an electric kettle Lion Sabatier International for 0,01 € + Your receipt has not been verified! + Your receipt is being checked + This usually takes a few minutes, but it is very rare when it takes more of time + diff --git a/app/src/zboom/res/values/strings_scanner.xml b/app/src/zboom/res/values/strings_scanner.xml new file mode 100644 index 00000000..685f7ddc --- /dev/null +++ b/app/src/zboom/res/values/strings_scanner.xml @@ -0,0 +1,8 @@ + + + To scan receipts, access to the camera is required + The permission must be granted in the settings + Point the camera at the QR code on the receipt + Help + How to scan a receipt + diff --git a/build.gradle b/build.gradle index 06791c7a..11a115be 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ apply from: './versions_plugin.gradle' buildscript { - ext.kotlinVersion = '1.5.30' + ext.kotlinVersion = '1.5.31' ext.detektVersion = '1.18.1' repositories { @@ -12,10 +12,10 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:7.0.2' + classpath 'com.android.tools.build:gradle:7.0.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" classpath 'com.google.gms:google-services:4.3.10' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.7.1' + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1' classpath 'com.google.firebase:perf-plugin:1.4.0' classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.5" // Detekt https://github.com/detekt/detekt