├── .gitignore
├── .idea
├── .gitignore
├── compiler.xml
├── gradle.xml
├── misc.xml
└── vcs.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── azamovhudstc
│ │ └── bookappwithcache
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── azamovhudstc
│ │ │ └── bookappwithcache
│ │ │ ├── app
│ │ │ └── App.kt
│ │ │ ├── data
│ │ │ ├── local
│ │ │ │ ├── database
│ │ │ │ │ ├── appDatabase
│ │ │ │ │ │ └── AppDatabase.kt
│ │ │ │ │ ├── dao
│ │ │ │ │ │ └── BookDao.kt
│ │ │ │ │ └── entites
│ │ │ │ │ │ └── BookEntities.kt
│ │ │ │ └── sharedpref
│ │ │ │ │ └── AppReference.kt
│ │ │ └── remote
│ │ │ │ └── retrofit2
│ │ │ │ ├── cilent
│ │ │ │ └── ApiClient.kt
│ │ │ │ ├── request
│ │ │ │ ├── auth
│ │ │ │ │ ├── AuthRequest.kt
│ │ │ │ │ └── VerifyRequest.kt
│ │ │ │ └── book
│ │ │ │ │ ├── AddBookRequest.kt
│ │ │ │ │ ├── DeleteBookRequest.kt
│ │ │ │ │ ├── EditBookRequest.kt
│ │ │ │ │ ├── FavouriteBookRequest.kt
│ │ │ │ │ ├── GetUserBooksResponse.kt
│ │ │ │ │ ├── GetUserBooksResponseItem.kt
│ │ │ │ │ └── RateBookRequest.kt
│ │ │ │ ├── response
│ │ │ │ ├── auth
│ │ │ │ │ ├── AuthResponse.kt
│ │ │ │ │ ├── ErrorResponse.kt
│ │ │ │ │ └── VerifyResponse.kt
│ │ │ │ └── book
│ │ │ │ │ ├── AddBookResponse.kt
│ │ │ │ │ ├── BooksResponse.kt
│ │ │ │ │ ├── BooksResponseItem.kt
│ │ │ │ │ ├── GetSocialUserResponse.kt
│ │ │ │ │ ├── GetSocialUserResponseItem.kt
│ │ │ │ │ ├── GetUserBookItem.kt
│ │ │ │ │ └── GetUserBookResponse.kt
│ │ │ │ └── service
│ │ │ │ ├── auth
│ │ │ │ └── AuthService.kt
│ │ │ │ └── book
│ │ │ │ └── BookService.kt
│ │ │ ├── repo
│ │ │ ├── AuthRepository.kt
│ │ │ ├── BookRepository.kt
│ │ │ └── impl
│ │ │ │ ├── AuthRepositoryImpl.kt
│ │ │ │ └── BookRepositoryImpl.kt
│ │ │ ├── ui
│ │ │ ├── activity
│ │ │ │ └── MainActivity.kt
│ │ │ ├── adapter
│ │ │ │ └── BooksAdapter.kt
│ │ │ └── screens
│ │ │ │ ├── auth
│ │ │ │ ├── LoginFragment.kt
│ │ │ │ ├── RegisterFragment.kt
│ │ │ │ ├── SplashFragment.kt
│ │ │ │ └── VerifyFragment.kt
│ │ │ │ └── book
│ │ │ │ ├── AddBookScreen.kt
│ │ │ │ ├── BookScreen.kt
│ │ │ │ ├── EditBookScreen.kt
│ │ │ │ └── ShowBookScreen.kt
│ │ │ ├── usecase
│ │ │ ├── auth
│ │ │ │ ├── LoginUseCase.kt
│ │ │ │ ├── RegisterUseCase.kt
│ │ │ │ ├── VerifyUseCase.kt
│ │ │ │ └── impl
│ │ │ │ │ ├── LoginUseCaseImpl.kt
│ │ │ │ │ ├── RegisterUseCaseImpl.kt
│ │ │ │ │ └── VerifyUseCaseImpl.kt
│ │ │ └── book
│ │ │ │ ├── BookScreenUseCase.kt
│ │ │ │ └── imp
│ │ │ │ └── BookScreenUseCaseImp.kt
│ │ │ ├── utils
│ │ │ ├── Cases.kt
│ │ │ ├── ConnetctionUtil.kt
│ │ │ ├── MediatorLiveDataExtension.kt
│ │ │ └── MyUtils.kt
│ │ │ └── viewmodel
│ │ │ ├── AddScreenViewModel.kt
│ │ │ ├── EditScreenViewModel.kt
│ │ │ ├── HomeScreenViewModel.kt
│ │ │ ├── LoginViewModel.kt
│ │ │ ├── VerifyScreenViewModel.kt
│ │ │ └── imp
│ │ │ ├── AddScreenViewModelImp.kt
│ │ │ ├── EditScreenViewModelImpl.kt
│ │ │ ├── HomeScreenViewModelImp.kt
│ │ │ ├── LoginViewModelImp.kt
│ │ │ ├── RegisterViewModelImpl.kt
│ │ │ └── VerifyScreenViewModelImp.kt
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ ├── backs.xml
│ │ ├── bg_button.xml
│ │ ├── bg_circle.xml
│ │ ├── bg_dialog.xml
│ │ ├── bg_ed.xml
│ │ ├── bg_edit.xml
│ │ ├── bg_edit_text.xml
│ │ ├── bg_like.png
│ │ ├── bg_pin.xml
│ │ ├── books.png
│ │ ├── edit_phone.xml
│ │ ├── ic_back.xml
│ │ ├── ic_backspace.xml
│ │ ├── ic_baseline_access_time_24.xml
│ │ ├── ic_baseline_add_24.xml
│ │ ├── ic_baseline_arrow_back_ios_24.xml
│ │ ├── ic_baseline_edit_24.xml
│ │ ├── ic_baseline_favorite_24.xml
│ │ ├── ic_baseline_favorite_border_24.xml
│ │ ├── ic_baseline_home_24.xml
│ │ ├── ic_baseline_keyboard_voice_24.xml
│ │ ├── ic_baseline_refresh_24.xml
│ │ ├── ic_baseline_thumb_down_24.xml
│ │ ├── ic_baseline_thumb_up_24.xml
│ │ ├── ic_check.xml
│ │ ├── ic_clear.xml
│ │ ├── ic_close.xml
│ │ ├── ic_delete.xml
│ │ ├── ic_edit.xml
│ │ ├── ic_home.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── ic_search.xml
│ │ ├── img.png
│ │ ├── like.xml
│ │ ├── like_un.xml
│ │ ├── logout.png
│ │ ├── rounded_dialog.xml
│ │ ├── unlike.png
│ │ ├── viewbg.xml
│ │ └── viewpager_background.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── books_item.xml
│ │ ├── fragment_add_book_screen.xml
│ │ ├── fragment_edit.xml
│ │ ├── fragment_home.xml
│ │ ├── fragment_login.xml
│ │ ├── fragment_register.xml
│ │ ├── fragment_show_book.xml
│ │ ├── fragment_splash.xml
│ │ └── fragment_verify.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── navigation
│ │ └── app_graph.xml
│ │ ├── raw
│ │ ├── book.json
│ │ ├── coin.json
│ │ ├── coin1.json
│ │ ├── lottie_delivery_boy_bumpy_ride.json
│ │ ├── lottie_developer.json
│ │ ├── lottie_girl_with_a_notebook.json
│ │ ├── optvertification.json
│ │ ├── privacy.json
│ │ ├── splash.json
│ │ ├── transfer.json
│ │ └── welcome.json
│ │ ├── values-night
│ │ └── themes.xml
│ │ ├── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── themes.xml
│ │ └── xml
│ │ ├── backup_rules.xml
│ │ └── data_extraction_rules.xml
│ └── test
│ └── java
│ └── com
│ └── azamovhudstc
│ └── bookappwithcache
│ └── ExampleUnitTest.kt
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | local.properties
16 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BookAppWithCache-Clean-Architecture
2 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'org.jetbrains.kotlin.android'
4 | id 'kotlin-kapt'
5 | id 'kotlin-android-extensions'
6 |
7 | }
8 |
9 | android {
10 | compileSdk 32
11 |
12 | defaultConfig {
13 | applicationId "com.azamovhudstc.bookappwithcache"
14 | minSdk 24
15 | targetSdk 32
16 | versionCode 1
17 | versionName "1.0"
18 |
19 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
20 | }
21 |
22 | buildTypes {
23 | release {
24 | minifyEnabled false
25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
26 | }
27 | }
28 | compileOptions {
29 | sourceCompatibility JavaVersion.VERSION_1_8
30 | targetCompatibility JavaVersion.VERSION_1_8
31 | }
32 | kotlinOptions {
33 | jvmTarget = '1.8'
34 | }
35 | }
36 |
37 | dependencies {
38 | def lottieVersion = "3.4.0"//lottieVersion
39 | def room_version = "2.4.3"//roomVersion
40 | //noinspection GradleDependency
41 | implementation 'androidx.core:core-ktx:1.7.0'
42 | implementation 'androidx.appcompat:appcompat:1.5.1'
43 | implementation 'com.google.android.material:material:1.7.0'
44 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
45 | testImplementation 'junit:junit:4.13.2'
46 | androidTestImplementation 'androidx.test.ext:junit:1.1.4'
47 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
48 | implementation 'com.squareup.retrofit2:retrofit:2.9.0'//Retrofit2
49 | implementation 'com.squareup.retrofit2:converter-gson:2.9.0'//Retrofit2
50 | implementation 'de.hdodenhof:circleimageview:3.1.0'//CircleImageView
51 | implementation 'io.github.vicmikhailau:MaskedEditText:4.0.7'//Mask Edittext
52 | implementation 'androidx.navigation:navigation-fragment:2.5.3'//FragmentNavigation
53 | implementation("com.squareup.okhttp3:okhttp:5.0.0-alpha.3")//Okhttp3
54 | implementation 'de.hdodenhof:circleimageview:3.1.0'//CircleImageView
55 | implementation 'com.github.ismaeldivita:chip-navigation-bar:1.4.0'//ChipNavigationBar
56 | //noinspection GradleDependency
57 | implementation "com.airbnb.android:lottie:$lottieVersion"//LottieAnimation
58 | implementation 'com.facebook.shimmer:shimmer:0.5.0'//FacebookShimmer
59 | implementation("com.tbuonomo:dotsindicator:4.3")//DotsIndicator
60 | implementation 'com.github.scottyab:showhidepasswordedittext:0.8'//PasswordEditText
61 | implementation 'com.github.pdrozz:pinview:1.0.2'//PinView
62 | debugImplementation 'com.readystatesoftware.chuck:library:1.1.0'
63 | releaseImplementation 'com.readystatesoftware.chuck:library-no-op:1.1.0'
64 | implementation 'com.github.st235:expandablebottombar:1.5.1'
65 | implementation 'com.github.ibrahimsn98:SmoothBottomBar:1.7.9'
66 | //room
67 | implementation "androidx.room:room-runtime:$room_version"
68 | kapt "androidx.room:room-compiler:$room_version"
69 | implementation "androidx.room:room-ktx:$room_version"
70 |
71 | //Glide
72 | implementation 'com.github.bumptech.glide:glide:4.14.2'
73 | annotationProcessor 'com.github.bumptech.glide:compiler:4.14.2'
74 |
75 |
76 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/azamovhudstc/bookappwithcache/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.ext.junit.runners.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22 | assertEquals("com.azamovhudstc.bookappwithcache", appContext.packageName)
23 | }
24 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
20 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/app/App.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.app
2 |
3 | import android.app.Application
4 | import com.azamovhudstc.bookappwithcache.data.local.database.appDatabase.AppDatabase
5 | import com.azamovhudstc.bookappwithcache.data.local.sharedpref.AppReference
6 |
7 | class App : Application() {
8 | companion object {
9 | lateinit var instance: App
10 | }
11 |
12 | override fun onCreate() {
13 | super.onCreate()
14 | instance = this
15 | AppReference.init(this)
16 | AppDatabase.init(this)
17 | }
18 |
19 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/local/database/appDatabase/AppDatabase.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.local.database.appDatabase
2 |
3 | import android.content.Context
4 | import androidx.room.Database
5 | import androidx.room.Room
6 | import androidx.room.RoomDatabase
7 | import com.azamovhudstc.bookappwithcache.data.local.database.dao.BookDao
8 | import com.azamovhudstc.bookappwithcache.data.local.database.entites.BookEntities
9 |
10 | @Database(entities = [BookEntities::class], version = 1, exportSchema = false)
11 | abstract class AppDatabase: RoomDatabase() {
12 | abstract fun bookDao():BookDao
13 |
14 | companion object {
15 | private var instance:AppDatabase? = null
16 | fun init(context: Context) {
17 | instance = Room.databaseBuilder(context,AppDatabase::class.java,"books_app.db")
18 | .build()
19 | }
20 | fun getInstance() = instance!!
21 | }
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/local/database/dao/BookDao.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.local.database.dao
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.room.*
5 | import com.azamovhudstc.bookappwithcache.data.local.database.entites.BookEntities
6 |
7 | @Dao
8 | interface BookDao {
9 |
10 | @Query("SELECT * FROM BookEntities WHERE state=0 or state = 1 OR state = 2")
11 | fun getBooks(): LiveData>
12 |
13 | @Query("SELECT * FROM BookEntities")
14 | suspend fun getAllBooks(): List
15 |
16 | @Query("DELETE FROM BookEntities")
17 | suspend fun clear()
18 |
19 | @Query("SELECT * FROM BookEntities WHERE localId = :id")
20 | suspend fun getBook(id: Int): BookEntities
21 |
22 | @Delete
23 | suspend fun delete(localData: BookEntities)
24 |
25 | @Insert
26 | suspend fun insert(localData: BookEntities)
27 |
28 | @Insert
29 | suspend fun insert(list: List)
30 |
31 | @Update
32 | suspend fun update(localData: BookEntities)
33 |
34 | @Transaction
35 | suspend fun updateWholeDB(newList: List) {
36 | clear()
37 | insert(newList)
38 | }
39 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/local/database/entites/BookEntities.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.local.database.entites
2 |
3 | import androidx.room.Entity
4 | import androidx.room.PrimaryKey
5 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.AddBookRequest
6 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.EditBookRequest
7 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.response.book.BooksResponseItem
8 | import java.io.Serializable
9 |
10 | @Entity
11 | data class BookEntities(
12 | val id: Int,
13 | var author: String,
14 | var description: String,
15 | var fav: Boolean,
16 | var pageCount: Int,
17 | var title: String,
18 | @PrimaryKey(autoGenerate = true)
19 | val localId: Int,
20 | var state: Int
21 | ) : Serializable {
22 | fun toUpdate(): EditBookRequest = EditBookRequest(author, description, id, pageCount, title)
23 | fun toAdd(): AddBookRequest = AddBookRequest(author, description, pageCount, title)
24 | fun toDelete(): BooksResponseItem = BooksResponseItem(author, description, fav, id, pageCount, title,)
25 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/local/sharedpref/AppReference.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.local.sharedpref
2 |
3 |
4 | import android.content.Context
5 | import android.content.Context.MODE_PRIVATE
6 | import android.content.SharedPreferences
7 |
8 | class AppReference private constructor() {
9 |
10 | companion object {
11 | private lateinit var sharedPref: SharedPreferences
12 | private lateinit var editor: SharedPreferences.Editor
13 | private var shp: AppReference? = null
14 |
15 | fun init(context: Context) {
16 | shp = AppReference()
17 | sharedPref = context.getSharedPreferences("auth", MODE_PRIVATE)
18 | editor = sharedPref.edit()
19 | }
20 |
21 | fun getInstance() = shp!!
22 | }
23 |
24 | fun setToken(token: String) {
25 | editor.putString("TOKEN", token)
26 | editor.apply()
27 | }
28 |
29 | fun getToken(): String? {
30 | return sharedPref.getString("TOKEN", "")
31 | }
32 |
33 | var startScreen: String
34 | set(value) = sharedPref.edit().putString("INTRO", value).apply()
35 | get() = sharedPref.getString("INTRO", "INTRO")!!
36 |
37 | var userName: String
38 | set(value) = sharedPref.edit().putString("USERNAME", value).apply()
39 | get() = sharedPref.getString("USERNAME", "USERNAME")!!
40 |
41 | var verifyToken: String
42 | set(value) = sharedPref.edit().putString("VERIFY_TOKEN", value).apply()
43 | get() = sharedPref.getString("VERIFY_TOKEN", "")!!
44 |
45 | fun clear() {
46 | editor.clear()
47 | }
48 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/cilent/ApiClient.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.retrofit2.cilent
2 |
3 | import com.azamovhudstc.bookappwithcache.app.App
4 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.service.auth.AuthService
5 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.service.book.BookService
6 | import com.readystatesoftware.chuck.ChuckInterceptor
7 | import okhttp3.OkHttpClient
8 | import retrofit2.Retrofit
9 | import retrofit2.converter.gson.GsonConverterFactory
10 |
11 | object ApiClient {
12 |
13 | private val myClient = OkHttpClient.Builder()
14 | .addInterceptor(ChuckInterceptor(App.instance))
15 | .build()
16 |
17 | private val retrofit: Retrofit = Retrofit.Builder()
18 | .baseUrl("http://143.198.48.222:82")
19 | .client(myClient)
20 | .addConverterFactory(GsonConverterFactory.create())
21 | .build()
22 |
23 | fun getAuthApi(): AuthService = retrofit.create(AuthService::class.java)
24 | fun getBookApi(): BookService = retrofit.create(BookService::class.java)
25 |
26 |
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/request/auth/AuthRequest.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.request.auth
2 |
3 | import com.google.gson.annotations.SerializedName
4 | import java.io.Serializable
5 |
6 | sealed class AuthRequest {
7 | data class RegisterRequest(
8 | @SerializedName("firstName")
9 | val firstName: String,
10 | @SerializedName("lastName")
11 | val lastName: String,
12 | @SerializedName("password")
13 | val password: String,
14 | @SerializedName("phone")
15 | val phone: String
16 | ):Serializable
17 |
18 | data class LoginRequest(
19 | @SerializedName("password")
20 | val password: String,
21 | @SerializedName("phone")
22 | val phone: String
23 | ):Serializable
24 |
25 |
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/request/auth/VerifyRequest.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.request.auth
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class VerifyRequest(
7 | @SerializedName("code")
8 | val code: String
9 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/request/book/AddBookRequest.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book
2 |
3 |
4 | import com.azamovhudstc.bookappwithcache.data.local.database.entites.BookEntities
5 | import com.google.gson.annotations.SerializedName
6 |
7 | data class AddBookRequest(
8 | @SerializedName("author")
9 | val author: String,
10 | @SerializedName("description")
11 | val description: String,
12 | @SerializedName("pageCount")
13 | val pageCount: Int,
14 | @SerializedName("title")
15 | val title: String
16 | ){
17 | fun toAddRoom():BookEntities=
18 | BookEntities(id = 0,author,description,fav = false,pageCount,title,0,1)
19 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/request/book/DeleteBookRequest.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class DeleteBookRequest(
7 | @SerializedName("bookId")
8 | val bookId: Int
9 | )
10 |
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/request/book/EditBookRequest.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book
2 |
3 |
4 | import com.azamovhudstc.bookappwithcache.data.local.database.entites.BookEntities
5 | import com.google.gson.annotations.SerializedName
6 |
7 | data class EditBookRequest(
8 | @SerializedName("author")
9 | val author: String,
10 | @SerializedName("description")
11 | val description: String,
12 | @SerializedName("id")
13 | val id: Int,
14 | @SerializedName("pageCount")
15 | val pageCount: Int,
16 | @SerializedName("title")
17 | val title: String
18 | ) {
19 | fun toEntity(): BookEntities =
20 | BookEntities(id, author, description, false, pageCount, title, 0, 2)
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/request/book/FavouriteBookRequest.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.request.book
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class FavouriteBookRequest(
7 | @SerializedName("bookId")
8 | val bookId: Int
9 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/request/book/GetUserBooksResponse.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.request.book
2 |
3 |
4 | class GetUserBooksResponse : ArrayList()
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/request/book/GetUserBooksResponseItem.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.request.book
2 |
3 |
4 | import java.io.Serializable
5 |
6 | data class GetUserBooksResponseItem(
7 | val author: String,
8 | val description: String,
9 | val disLikeCount: Int,
10 | val fav: Boolean,
11 | val id: Int,
12 | val isLike: Boolean,
13 | val likeCount: Int,
14 | val pageCount: Int,
15 | val title: String
16 | ) : Serializable {
17 | override fun equals(other: Any?): Boolean {
18 | if (this === other) return true
19 | if (javaClass != other?.javaClass) return false
20 |
21 | other as GetUserBooksResponseItem
22 |
23 | if (author != other.author) return false
24 | if (description != other.description) return false
25 | if (disLikeCount != other.disLikeCount) return false
26 | if (fav != other.fav) return false
27 | if (id != other.id) return false
28 | if (isLike != other.isLike) return false
29 | if (likeCount != other.likeCount) return false
30 | if (pageCount != other.pageCount) return false
31 | if (title != other.title) return false
32 |
33 | return true
34 | }
35 |
36 | override fun hashCode(): Int {
37 | var result = author.hashCode()
38 | result = 31 * result + description.hashCode()
39 | result = 31 * result + disLikeCount
40 | result = 31 * result + fav.hashCode()
41 | result = 31 * result + id
42 | result = 31 * result + isLike.hashCode()
43 | result = 31 * result + likeCount
44 | result = 31 * result + pageCount
45 | result = 31 * result + title.hashCode()
46 | return result
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/request/book/RateBookRequest.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.request.book
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class RateBookRequest(
7 | @SerializedName("bookId")
8 | val bookId: Int,
9 | @SerializedName("isLike")
10 | val isLike: Boolean
11 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/response/auth/AuthResponse.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.retrofit2.response.auth
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 | import java.io.Serializable
6 |
7 | sealed class AuthResponse{
8 | data class RegisterResponse(
9 | @SerializedName("token")
10 | val token: String
11 | )
12 |
13 | data class LoginResponse(
14 | @SerializedName("token")
15 | val token: String
16 | ):Serializable
17 |
18 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/response/auth/ErrorResponse.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.retrofit2.response.auth
2 |
3 | import com.google.gson.annotations.SerializedName
4 | import java.io.Serializable
5 |
6 | data class ErrorResponse(
7 | val message: String
8 | ): Serializable
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/response/auth/VerifyResponse.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.response.auth
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class VerifyResponse(
7 | @SerializedName("token")
8 | val token: String
9 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/response/book/AddBookResponse.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.response.book
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class AddBookResponse(
7 | @SerializedName("author")
8 | val author: String,
9 | @SerializedName("description")
10 | val description: String,
11 | @SerializedName("fav")
12 | val fav: Boolean,
13 | @SerializedName("id")
14 | val id: Int,
15 | @SerializedName("pageCount")
16 | val pageCount: Int,
17 | @SerializedName("title")
18 | val title: String
19 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/response/book/BooksResponse.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.retrofit2.response.book
2 |
3 |
4 | class BooksResponse : ArrayList()
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/response/book/BooksResponseItem.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.retrofit2.response.book
2 |
3 |
4 | import com.azamovhudstc.bookappwithcache.data.local.database.entites.BookEntities
5 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.DeleteBookRequest
6 | import com.google.gson.annotations.SerializedName
7 | import java.io.Serializable
8 |
9 | data class BooksResponseItem(
10 | @SerializedName("author")
11 | val author: String,
12 | @SerializedName("description")
13 | val description: String,
14 | @SerializedName("fav")
15 | var fav: Boolean,
16 | @SerializedName("id")
17 | val id: Int,
18 | @SerializedName("pageCount")
19 | val pageCount: Int,
20 | @SerializedName("title")
21 | val title: String
22 | ) : Serializable {
23 | fun toDeleteRequest(): DeleteBookRequest = DeleteBookRequest(id)
24 | fun toBookEntity(): BookEntities =
25 | BookEntities(id, author, description, fav, pageCount, title, 0, 0)
26 |
27 | fun toBookDelete():BookEntities= BookEntities(id, author, description, fav, pageCount, title,state=-1, localId = 0)
28 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/response/book/GetSocialUserResponse.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.response.book
2 |
3 |
4 | class GetSocialUserResponse : ArrayList()
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/response/book/GetSocialUserResponseItem.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.response.book
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class GetSocialUserResponseItem(
7 | @SerializedName("firstName")
8 | val firstName: String,
9 | @SerializedName("id")
10 | val id: Int,
11 | @SerializedName("lastName")
12 | val lastName: String
13 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/response/book/GetUserBookItem.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.response.book
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class GetUserBookItem(
7 | @SerializedName("author")
8 | val author: String,
9 | @SerializedName("description")
10 | val description: String,
11 | @SerializedName("disLikeCount")
12 | val disLikeCount: Int,
13 | @SerializedName("fav")
14 | val fav: Boolean,
15 | @SerializedName("id")
16 | val id: Int,
17 | @SerializedName("isLike")
18 | val isLike: Boolean?,
19 | @SerializedName("likeCount")
20 | val likeCount: Int,
21 | @SerializedName("pageCount")
22 | val pageCount: Int,
23 | @SerializedName("title")
24 | val title: String
25 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/response/book/GetUserBookResponse.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.response.book
2 |
3 |
4 | class GetUserBookResponse : ArrayList()
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/service/auth/AuthService.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.retrofit2.service.auth
2 |
3 | import com.azamovhudstc.bookappwithcache.data.remote.request.auth.AuthRequest
4 | import com.azamovhudstc.bookappwithcache.data.remote.request.auth.VerifyRequest
5 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.response.auth.AuthResponse
6 | import com.azamovhudstc.bookappwithcache.data.remote.response.auth.VerifyResponse
7 | import retrofit2.Call
8 | import retrofit2.Response
9 | import retrofit2.http.Body
10 | import retrofit2.http.Header
11 | import retrofit2.http.POST
12 |
13 | interface AuthService {
14 |
15 | @POST("/auth/sign-up")
16 | suspend fun register(@Body data: AuthRequest.RegisterRequest): Response
17 |
18 | @POST("/auth/sign-in")
19 | suspend fun login(@Body data: AuthRequest.LoginRequest): Response
20 |
21 | @POST("/auth/sign-up/verify")
22 | suspend fun verify(
23 | @Header("Authorization") authorization: String,
24 | @Body code: VerifyRequest
25 | ): Response
26 |
27 | @POST("/auth/sign-in/verify")
28 | suspend fun verifySign(
29 | @Header("Authorization") authorization: String,
30 | @Body code: VerifyRequest
31 | ): Response
32 |
33 |
34 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/data/remote/retrofit2/service/book/BookService.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.data.remote.retrofit2.service.book
2 |
3 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.AddBookRequest
4 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.DeleteBookRequest
5 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.EditBookRequest
6 | import com.azamovhudstc.bookappwithcache.data.remote.request.book.FavouriteBookRequest
7 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.response.auth.ErrorResponse
8 | import com.azamovhudstc.bookappwithcache.data.remote.response.book.AddBookResponse
9 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.response.book.BooksResponse
10 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.response.book.BooksResponseItem
11 | import retrofit2.Response
12 | import retrofit2.http.*
13 |
14 | interface BookService {
15 |
16 | @GET("/books")
17 | suspend fun getAllBooks(@Header("Authorization") token: String): Response
18 |
19 | @POST("/book")
20 | suspend fun addBook(
21 | @Header("Authorization") token: String,
22 | @Body addBookRequest: AddBookRequest
23 | ): Response
24 |
25 |
26 | @PUT("/book")
27 | suspend fun editBook(
28 | @Header("Authorization") token: String,
29 | @Body data: EditBookRequest
30 | ): Response
31 |
32 | @HTTP(method = "DELETE", path = "/book", hasBody = true)
33 | suspend fun deleteBook(
34 | @Header("Authorization") token: String,
35 | @Body body: DeleteBookRequest
36 | ): Response
37 |
38 | @POST("book/change-fav")
39 | suspend fun addFavouriteBook(
40 | @Header("Authorization") token: String,
41 | @Body favouriteBookRequest: FavouriteBookRequest
42 | ): Response
43 |
44 |
45 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/repo/AuthRepository.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.repo
2 |
3 | import androidx.lifecycle.LiveData
4 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.response.auth.AuthResponse
5 | import kotlinx.coroutines.flow.Flow
6 |
7 | interface AuthRepository {
8 | fun login(password: String, phone: String): Flow>
9 | fun register(name: String, password: String, phone: String, lastName: String): Flow
10 | fun verify(token: String, phone: String): Flow
11 | fun verifySign(token: String, phone: String): Flow
12 |
13 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/repo/BookRepository.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.repo
2 |
3 | import androidx.lifecycle.LiveData
4 | import com.azamovhudstc.bookappwithcache.data.local.database.entites.BookEntities
5 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.AddBookRequest
6 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.EditBookRequest
7 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.response.book.BooksResponseItem
8 | import kotlinx.coroutines.flow.Flow
9 |
10 | interface BookRepository {
11 | fun getAllBook(token: String): Flow>>
12 | suspend fun deleteBook(token: String, booksResponseItem: Int, id:Int)
13 | suspend fun addBook(token: String, bookRequest: AddBookRequest)
14 | suspend fun editBook(token: String, id: Int, requestData: EditBookRequest, localId: Int)
15 |
16 | suspend fun reLoadLocalData():Boolean
17 | suspend fun internetState(): Flow
18 |
19 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/repo/impl/AuthRepositoryImpl.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.repo.impl
2 |
3 | import com.azamovhudstc.bookappwithcache.data.local.database.appDatabase.AppDatabase
4 | import com.azamovhudstc.bookappwithcache.data.local.sharedpref.AppReference
5 | import com.azamovhudstc.bookappwithcache.data.remote.request.auth.AuthRequest
6 | import com.azamovhudstc.bookappwithcache.data.remote.request.auth.VerifyRequest
7 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.cilent.ApiClient
8 | import com.azamovhudstc.bookappwithcache.repo.AuthRepository
9 | import kotlinx.coroutines.Dispatchers
10 | import kotlinx.coroutines.flow.Flow
11 | import kotlinx.coroutines.flow.catch
12 | import kotlinx.coroutines.flow.flow
13 | import kotlinx.coroutines.flow.flowOn
14 |
15 | class AuthRepositoryImpl : AuthRepository {
16 | private val authApi = ApiClient.getAuthApi()
17 |
18 |
19 | override fun login(
20 | password: String,
21 | phone: String
22 | ): Flow> = flow> {
23 | val response = authApi.login(AuthRequest.LoginRequest(password, phone))
24 | if (response.isSuccessful) {
25 | response.body()?.let {
26 | val token: String = response.body()!!.token
27 | AppReference.getInstance().verifyToken = token!!
28 | emit(Result.success(Unit))
29 | }
30 | } else {
31 | emit(Result.failure(Exception(response.errorBody()?.toString())))
32 | }
33 | }.catch {
34 | emit(Result.failure(Exception(it.message)))
35 | }.flowOn(Dispatchers.IO)
36 |
37 | override fun register(
38 | name: String,
39 | password: String,
40 | phone: String,
41 | lastName: String
42 | ) = flow {
43 | var response =
44 | authApi.register(AuthRequest.RegisterRequest(name, lastName, password, phone))
45 | if (response.isSuccessful) {
46 | if (response.body() != null) {
47 | val token: String = response.body()!!.token
48 | AppReference.getInstance().verifyToken = token!!
49 | emit(true)
50 | }
51 | emit(false)
52 | }
53 | emit(false)
54 |
55 | }.flowOn(Dispatchers.IO)
56 |
57 | override fun verify(token: String, phone: String) = flow {
58 | var response = authApi.verify("Bearer $token", VerifyRequest(phone))
59 | if (response.isSuccessful && response.body() != null) {
60 | val responseToken: String = response.body()!!.token
61 | AppReference.getInstance().setToken(responseToken)
62 | emit(true)
63 | }
64 |
65 | emit(false)
66 | }.flowOn(Dispatchers.IO)
67 |
68 | override fun verifySign(token: String, phone: String): Flow = flow {
69 | var response = authApi.verifySign("Bearer $token", VerifyRequest(phone))
70 | if (response.isSuccessful && response.body() != null) {
71 | val token: String = response.body()!!.token
72 | AppReference.getInstance().setToken(token)
73 | emit(true)
74 |
75 | }
76 |
77 | emit(false)
78 | }.flowOn(Dispatchers.IO)
79 |
80 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/repo/impl/BookRepositoryImpl.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.repo.impl
2 |
3 | import android.util.Log
4 | import androidx.lifecycle.LiveData
5 | import androidx.lifecycle.MediatorLiveData
6 | import com.azamovhudstc.bookappwithcache.data.local.database.appDatabase.AppDatabase
7 | import com.azamovhudstc.bookappwithcache.data.local.database.entites.BookEntities
8 | import com.azamovhudstc.bookappwithcache.data.local.sharedpref.AppReference
9 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.DeleteBookRequest
10 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.AddBookRequest
11 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.EditBookRequest
12 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.response.book.BooksResponseItem
13 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.cilent.ApiClient
14 | import com.azamovhudstc.bookappwithcache.repo.BookRepository
15 | import com.azamovhudstc.bookappwithcache.utils.hasConnection
16 | import kotlinx.coroutines.Dispatchers
17 | import kotlinx.coroutines.flow.Flow
18 | import kotlinx.coroutines.flow.flow
19 | import kotlinx.coroutines.flow.flowOn
20 | import kotlinx.coroutines.flow.launchIn
21 |
22 | class BookRepositoryImpl : BookRepository {
23 | var database = AppDatabase.getInstance()
24 | private val bookApi = ApiClient.getBookApi()
25 | private val mediatorLiveData = MediatorLiveData()
26 |
27 | init {
28 | mediatorLiveData.observeForever {
29 | }
30 | }
31 |
32 | override fun getAllBook(token: String): Flow>> = flow {
33 | if (hasConnection()) {
34 | reLoadLocalData()
35 | }
36 | emit(database.bookDao().getBooks())
37 | }.flowOn(Dispatchers.IO)
38 |
39 | override suspend fun deleteBook(token: String, booksResponseItem: Int, id: Int) {
40 | if (hasConnection()) {
41 | bookApi.deleteBook("Bearer " + token, DeleteBookRequest(id))
42 | loadData(token)
43 |
44 | } else {
45 | var book = database.bookDao().getBook(booksResponseItem)
46 | Log.d("TTT", "deleteBook: $book")
47 | val data = BookEntities(
48 | book.id,
49 | book.author,
50 | book.description,
51 | false,
52 | book.pageCount,
53 | book.title,
54 | book.localId, -1
55 | )
56 |
57 | database.bookDao().update(data)
58 |
59 | }
60 | }
61 |
62 |
63 | override suspend fun addBook(token: String, bookRequest: AddBookRequest) {
64 | if (hasConnection()) {
65 | bookApi.addBook("Bearer $token", bookRequest)
66 | loadData(token)
67 | } else {
68 |
69 | database.bookDao().insert(bookRequest.toAddRoom())
70 |
71 | }
72 |
73 | }
74 |
75 | override suspend fun editBook(
76 | token: String,
77 | id: Int,
78 | bookRequest: EditBookRequest,
79 | localId: Int
80 | ) {
81 | if (hasConnection()) {
82 | bookApi.editBook("Bearer $token", bookRequest)
83 | loadData(token)
84 | } else {
85 | var data = database.bookDao().getBook(localId)
86 | var entity = BookEntities(
87 | data.id,
88 | bookRequest.author,
89 | bookRequest.description,
90 | false,
91 | bookRequest.pageCount,
92 | bookRequest.title,
93 | data.localId,
94 | 2
95 | )
96 | database.bookDao().update(entity)
97 | }
98 |
99 |
100 | }
101 |
102 |
103 | override suspend fun reLoadLocalData():Boolean {
104 | if (hasConnection()) {
105 | loadData(token = AppReference.getInstance().getToken()!!)
106 | return true
107 | }
108 | return false
109 |
110 | }
111 |
112 |
113 | override suspend fun internetState(): Flow = flow {
114 | emit(hasConnection())
115 | }.flowOn(Dispatchers.IO)
116 |
117 | private suspend fun loadData(token: String) {
118 | //Tekshirish
119 | var list = database.bookDao().getAllBooks() as ArrayList
120 | list.filter {
121 | it.state == 1
122 | }.forEach { add ->
123 | bookApi.addBook("Bearer $token", add.toAdd())
124 | }
125 | list.filter {
126 | it.state == 2
127 | }.forEach { update ->
128 | bookApi.editBook("Bearer $token", update.toUpdate())
129 | }
130 | list.filter {
131 | it.state == -1
132 | }.forEach { delete ->
133 | bookApi.deleteBook("Bearer $token", delete.toDelete().toDeleteRequest())
134 | }
135 |
136 | val getAllBook = bookApi.getAllBooks("Bearer $token")
137 | if (getAllBook.isSuccessful) {
138 | val body = getAllBook.body()
139 | database.bookDao().updateWholeDB(body?.map { it.toBookEntity() }!!)
140 |
141 | }
142 | }
143 |
144 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/ui/activity/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.ui.activity
2 |
3 | import androidx.appcompat.app.AppCompatActivity
4 | import android.os.Bundle
5 | import com.azamovhudstc.bookappwithcache.R
6 |
7 | class MainActivity : AppCompatActivity() {
8 | override fun onCreate(savedInstanceState: Bundle?) {
9 | super.onCreate(savedInstanceState)
10 | setContentView(R.layout.activity_main)
11 | }
12 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/ui/adapter/BooksAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.ui.adapter
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import android.util.Log
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import androidx.recyclerview.widget.DiffUtil
10 | import androidx.recyclerview.widget.ListAdapter
11 | import androidx.recyclerview.widget.RecyclerView
12 | import com.azamovhudstc.bookappwithcache.R
13 | import com.azamovhudstc.bookappwithcache.data.local.database.entites.BookEntities
14 | import kotlinx.android.synthetic.main.books_item.view.*
15 |
16 | class BooksAdapter(var setLongClickListener: ContactItemCallBack.SetLongClickListener) :
17 | ListAdapter(ContactItemCallBack) {
18 | inner class Wh(view: View) : RecyclerView.ViewHolder(view) {
19 | @SuppressLint("NewApi", "SetTextI18n")
20 | fun onBind(contact: BookEntities, position: Int) {
21 | itemView.name.text = contact.title
22 | itemView.author.text = contact.author
23 | itemView.delete.setOnClickListener {
24 | setLongClickListener.deleteClick(contact)
25 | }
26 | itemView.edit.setOnClickListener {
27 | setLongClickListener.editItemClick(contact)
28 | }
29 | itemView.setOnClickListener {
30 | setLongClickListener.showClick(contact)
31 | }
32 |
33 | }
34 | }
35 |
36 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Wh {
37 | return Wh(LayoutInflater.from(parent.context).inflate(R.layout.books_item, parent, false))
38 | }
39 |
40 | override fun onBindViewHolder(holder: Wh, position: Int) {
41 | holder.onBind(getItem(position), position)
42 | }
43 |
44 | object ContactItemCallBack : DiffUtil.ItemCallback() {
45 | override fun areItemsTheSame(
46 | oldItem: BookEntities,
47 | newItem: BookEntities
48 | ): Boolean {
49 | return oldItem.id == newItem.id
50 | }
51 |
52 | override fun areContentsTheSame(
53 | oldItem: BookEntities,
54 | newItem: BookEntities
55 | ): Boolean {
56 | return oldItem == newItem
57 | }
58 |
59 |
60 | interface SetLongClickListener {
61 | fun deleteClick(contact: BookEntities)
62 | fun showClick(contact: BookEntities)
63 | fun editItemClick(contact: BookEntities)
64 | fun likedClick(contact: BookEntities)
65 | }
66 |
67 | }
68 |
69 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/ui/screens/auth/LoginFragment.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.ui.screens.auth
2 |
3 | import android.os.Bundle
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import androidx.fragment.app.Fragment
8 | import androidx.fragment.app.viewModels
9 | import androidx.lifecycle.Observer
10 | import androidx.navigation.NavOptions
11 | import androidx.navigation.fragment.findNavController
12 | import com.azamovhudstc.bookappwithcache.R
13 | import com.azamovhudstc.bookappwithcache.data.remote.request.auth.AuthRequest
14 | import com.azamovhudstc.bookappwithcache.utils.showToast
15 | import com.azamovhudstc.bookappwithcache.utils.state
16 | import com.azamovhudstc.bookappwithcache.viewmodel.LoginViewModel
17 | import com.azamovhudstc.bookappwithcache.viewmodel.imp.LoginViewModelImp
18 | import com.azamovhudstc.bookappwithcache.viewmodel.imp.RegisterViewModelImpl
19 | import kotlinx.android.synthetic.main.fragment_login.*
20 | import kotlinx.android.synthetic.main.fragment_register.*
21 |
22 | class LoginFragment : Fragment(R.layout.fragment_login) {
23 | private val viewModel: LoginViewModel by viewModels()
24 | private lateinit var bundle: Bundle
25 | override fun onCreate(savedInstanceState: Bundle?) {
26 | super.onCreate(savedInstanceState)
27 | bundle = Bundle()
28 | viewModel.openVerifyScreenLiveData.observe(this) {
29 | findNavController().navigate(
30 | R.id.verifyFragment,
31 | bundle,
32 | NavOptions.Builder().setPopUpTo(R.id.loginFragment, true).build()
33 | )
34 | }
35 | viewModel.progressLiveData.observe(this, progressObserver)
36 | viewModel.errorLiveData.observe(this) {
37 | showToast(it)
38 | }
39 | viewModel.notConnectionLiveData.observe(this) { showToast("No Connection !") }
40 | }
41 |
42 | private val progressObserver = Observer {
43 | if (it) progressLogin.show() else progressLogin.hide()
44 | }
45 |
46 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
47 | super.onViewCreated(view, savedInstanceState)
48 | startRegister.setOnClickListener {
49 | findNavController().navigate(R.id.registerFragment)
50 | }
51 | viewModel.changeButtonStatusLiveData.value =
52 | !(phone.unMaskedText.toString().isEmpty() || passwordLogin.text.trim().toString()
53 | .isEmpty())
54 |
55 | buttonLogin.setOnClickListener {
56 | if (phone.unMaskedText.toString().isEmpty() || passwordLogin.text.trim().toString()
57 | .isEmpty()
58 | ) {
59 | viewModel.changeButtonStatusLiveData.value = false
60 | showToast("Maydon Bo`sh")
61 | } else {
62 |
63 | viewModel.changeButtonStatusLiveData.value = true
64 | bundle.putString("login", "login")
65 |
66 | viewModel.login(
67 | password = passwordLogin.text.toString(),
68 | phone = "+998" + phone.unMaskedText.toString()
69 | )
70 | bundle.putString("login", "login")
71 | bundle.putSerializable(
72 | "data",
73 | AuthRequest.LoginRequest(
74 | passwordLogin.text.toString(), "+998${phone.unMaskedText.toString()}"
75 | )
76 | )
77 | }
78 | }
79 | }
80 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/ui/screens/auth/RegisterFragment.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.ui.screens.auth
2 |
3 | import android.os.Bundle
4 | import androidx.fragment.app.Fragment
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 | import androidx.fragment.app.viewModels
9 | import androidx.lifecycle.Observer
10 | import androidx.navigation.NavOptions
11 | import androidx.navigation.fragment.findNavController
12 | import com.azamovhudstc.bookappwithcache.R
13 | import com.azamovhudstc.bookappwithcache.data.remote.request.auth.AuthRequest
14 | import com.azamovhudstc.bookappwithcache.utils.showToast
15 | import com.azamovhudstc.bookappwithcache.utils.state
16 | import com.azamovhudstc.bookappwithcache.viewmodel.imp.RegisterViewModelImpl
17 | import kotlinx.android.synthetic.main.fragment_login.*
18 | import kotlinx.android.synthetic.main.fragment_register.*
19 | import kotlinx.android.synthetic.main.fragment_register.buttonRegister
20 |
21 | class RegisterFragment : Fragment(R.layout.fragment_register) {
22 | private val viewModel by viewModels()
23 | lateinit var bundle: Bundle
24 |
25 | override fun onCreate(savedInstanceState: Bundle?) {
26 | super.onCreate(savedInstanceState)
27 | bundle = Bundle()
28 | viewModel.messageLIveData.observe(this) {
29 | showToast(it)
30 | }
31 | viewModel.notConnectionLiveData.observe(this) {
32 | showToast("No internet Connected")
33 |
34 | }
35 | viewModel.backLoginLiveData.observe(this) {
36 | findNavController().popBackStack()
37 | }
38 | viewModel.changeButtonStatusLiveData.observe(this) {
39 | buttonRegister.isEnabled = it
40 | }
41 |
42 | viewModel.progressLiveData.observe(this,progressObserver)
43 | viewModel.openVerifyScreenLiveData.observe(this) {
44 | findNavController().navigate(
45 | R.id.verifyFragment,
46 | bundle,
47 | NavOptions.Builder().setPopUpTo(R.id.registerFragment, true).build()
48 | )
49 |
50 | }
51 | }
52 | private val progressObserver = Observer { if(it) progress.show() else progress.hide()
53 | }
54 |
55 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
56 | super.onViewCreated(view, savedInstanceState)
57 | backBtn.setOnClickListener {
58 | viewModel.backLogin()
59 | }
60 | buttonRegister.setOnClickListener {
61 | if (inputFirstName.text.toString().isEmpty() || lastName.text?.trim().toString()
62 | .isEmpty() || lastName.text?.trim().toString().isEmpty()
63 | ) {
64 | showToast("Maydonlarni To`ldiring")
65 | } else {
66 | bundle.putString("login", "register")
67 | viewModel.register(
68 | inputFirstName.text.toString(),
69 | password.text.toString(),
70 | "+998" + inputPhone.unMaskedText.toString(),
71 | lastName.text.toString()
72 | )
73 | bundle.putSerializable(
74 | "data",
75 | AuthRequest.RegisterRequest(
76 | inputFirstName.text.toString(),
77 | lastName.text.toString(),
78 | password.text.toString(),
79 | "+998${inputPhone.unMaskedText.toString()}"
80 | )
81 | )
82 |
83 | }
84 | }
85 | }
86 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/ui/screens/auth/SplashFragment.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.ui.screens.auth
2 |
3 | import android.os.Bundle
4 | import android.os.Handler
5 | import androidx.fragment.app.Fragment
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import androidx.lifecycle.lifecycleScope
10 | import androidx.navigation.NavOptions
11 | import androidx.navigation.fragment.findNavController
12 | import com.azamovhudstc.bookappwithcache.R
13 | import com.azamovhudstc.bookappwithcache.data.local.sharedpref.AppReference
14 | import kotlinx.coroutines.Dispatchers
15 | import kotlinx.coroutines.coroutineScope
16 | import kotlinx.coroutines.delay
17 | import kotlinx.coroutines.launch
18 |
19 |
20 | class SplashFragment : Fragment() {
21 |
22 | override fun onCreateView(
23 | inflater: LayoutInflater, container: ViewGroup?,
24 | savedInstanceState: Bundle?
25 | ): View? {
26 | // Inflate the layout for this fragment
27 | return inflater.inflate(R.layout.fragment_splash, container, false)
28 | }
29 |
30 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
31 | super.onViewCreated(view, savedInstanceState)
32 |
33 | lifecycleScope.launch {
34 | delay(1500)
35 | if (AppReference.getInstance().getToken().toString().isEmpty()) {
36 | findNavController().navigate(
37 | R.id.loginFragment,
38 | null,
39 | NavOptions.Builder().setPopUpTo(R.id.splashFragment, true).build()
40 | )
41 |
42 | }
43 | else {
44 | findNavController().navigate(
45 | R.id.homeFragment,
46 | null,
47 | NavOptions.Builder().setPopUpTo(R.id.splashFragment, true).build()
48 | )
49 | }
50 | }
51 |
52 |
53 |
54 | }
55 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/ui/screens/auth/VerifyFragment.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.ui.screens.auth
2 |
3 | import android.annotation.SuppressLint
4 | import android.os.Bundle
5 | import android.os.CountDownTimer
6 | import androidx.fragment.app.Fragment
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.view.ViewGroup
10 | import androidx.fragment.app.viewModels
11 | import androidx.lifecycle.Observer
12 | import androidx.navigation.NavOptions
13 | import androidx.navigation.fragment.findNavController
14 | import com.azamovhudstc.bookappwithcache.R
15 | import com.azamovhudstc.bookappwithcache.data.local.sharedpref.AppReference
16 | import com.azamovhudstc.bookappwithcache.data.remote.request.auth.AuthRequest
17 | import com.azamovhudstc.bookappwithcache.utils.showToast
18 | import com.azamovhudstc.bookappwithcache.utils.state
19 | import com.azamovhudstc.bookappwithcache.viewmodel.VerifyScreenViewModel
20 | import com.azamovhudstc.bookappwithcache.viewmodel.imp.RegisterViewModelImpl
21 | import com.azamovhudstc.bookappwithcache.viewmodel.imp.VerifyScreenViewModelImp
22 | import kotlinx.android.synthetic.main.fragment_login.*
23 | import kotlinx.android.synthetic.main.fragment_register.*
24 | import kotlinx.android.synthetic.main.fragment_verify.*
25 | import java.io.Serializable
26 | import java.text.DecimalFormat
27 |
28 |
29 | class VerifyFragment : Fragment(R.layout.fragment_verify) {
30 | lateinit var data: Serializable
31 | lateinit var timer: CountDownTimer
32 | private val viewModel: VerifyScreenViewModel by viewModels()
33 |
34 | override fun onCreate(savedInstanceState: Bundle?) {
35 | super.onCreate(savedInstanceState)
36 | viewModel.openHomeScreenLiveData.observe(this) {
37 | findNavController().navigate(
38 | R.id.homeFragment,
39 | null,
40 | NavOptions.Builder().setPopUpTo(R.id.verifyFragment, true).build()
41 | )
42 | }
43 | viewModel.notConnectionLiveData.observe(this) {
44 | showToast("No connection !")
45 | }
46 | viewModel.errorMessageLiveData.observe(this) {
47 | showToast(it)
48 | }
49 | viewModel.progressLiveData.observe(this, progressObserver)
50 | }
51 |
52 | private val progressObserver = Observer { if(it) verfied_progress.show() else verfied_progress.hide()
53 | }
54 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
55 | super.onViewCreated(view, savedInstanceState)
56 | val isChecker = arguments?.getString("login")
57 | button_send.setOnClickListener {
58 | if (isChecker == "login") {
59 | if (getOtp.text.toString().isEmpty() || getOtp.text?.length!! > 6) {
60 | showToast("Iltimos kod 6 bo`lishi kerak ")
61 | } else {
62 |
63 | viewModel.verifySign(
64 | getOtp.text.toString(),
65 | )
66 | resent_code.visibility = View.INVISIBLE
67 |
68 | }
69 | } else {
70 | if (getOtp.text.toString().isEmpty() || getOtp.text?.length!! > 6) {
71 | showToast("Iltimos kod 6 bo`lishi kerak ")
72 | } else {
73 | viewModel.verifySignUp(getOtp.text.toString())
74 |
75 | }
76 | }
77 | }
78 |
79 | timer = object : CountDownTimer(60000, 1000) {
80 | @SuppressLint("SetTextI18n")
81 | override fun onTick(millisUntilFinished: Long) {
82 | var f = DecimalFormat("00");
83 | val hour = millisUntilFinished / 3600000 % 24
84 | val min = millisUntilFinished / 60000 % 60
85 | val sec = millisUntilFinished / 1000 % 60
86 | countDown.text = f.format(hour) + ":" + f.format(min) + ":" + f.format(sec)
87 |
88 | }
89 |
90 | override fun onFinish() {
91 |
92 | resent_code.visibility = View.VISIBLE
93 | countDown.text = "00:00:00"
94 |
95 |
96 | }
97 | }
98 | timer.start()
99 |
100 | if (isChecker == "login") {
101 | data = arguments?.getSerializable("data") as AuthRequest.LoginRequest
102 | var phone = (data as AuthRequest.LoginRequest).phone
103 | val phoneNumber = phone!!.substring(phone.length - 4, phone.length - 2)
104 | val phoneNumberTwo = phone.substring(phone.length - 2, phone.length)
105 | getPhones.text =
106 | "+998(##)-###-$phoneNumber-$phoneNumberTwo telefon raqamga Tasdiqlash Kodi Yubordik"
107 |
108 | } else {
109 | data = arguments?.getSerializable("data") as AuthRequest.RegisterRequest
110 |
111 | var phone = (data as AuthRequest.RegisterRequest).phone
112 | val phoneNumber = phone!!.substring(phone.length - 4, phone.length - 2)
113 | val phoneNumberTwo = phone.substring(phone.length - 2, phone.length)
114 | getPhones.text =
115 | "+998(##)-###-$phoneNumber-$phoneNumberTwo telefon raqamga Tasdiqlash Kodi Yubordik"
116 |
117 | }
118 | resent_code.setOnClickListener {
119 | if (isChecker == "login") {
120 | viewModel.login(
121 | (data as AuthRequest.LoginRequest).password,
122 | (data as AuthRequest.LoginRequest).phone
123 | )
124 | timer.start()
125 | resent_code.visibility = View.INVISIBLE
126 |
127 | } else {
128 | viewModel.register(
129 | (data as AuthRequest.RegisterRequest).firstName,
130 | (data as AuthRequest.RegisterRequest).password,
131 | (data as AuthRequest.RegisterRequest).phone,
132 | (data as AuthRequest.RegisterRequest).lastName,
133 | )
134 | timer.start()
135 | resent_code.visibility = View.INVISIBLE
136 |
137 |
138 | }
139 |
140 | }
141 |
142 | resent_code.visibility = View.GONE
143 | }
144 |
145 | override fun onDestroyView() {
146 | timer.cancel()
147 | super.onDestroyView()
148 |
149 | }
150 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/ui/screens/book/AddBookScreen.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.ui.screens.book
2 |
3 | import android.os.Bundle
4 | import androidx.fragment.app.Fragment
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 | import android.widget.Toast
9 | import androidx.fragment.app.viewModels
10 | import androidx.navigation.fragment.findNavController
11 | import com.azamovhudstc.bookappwithcache.R
12 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.AddBookRequest
13 | import com.azamovhudstc.bookappwithcache.utils.showSnack
14 | import com.azamovhudstc.bookappwithcache.utils.showToast
15 | import com.azamovhudstc.bookappwithcache.viewmodel.AddScreenViewModel
16 | import com.azamovhudstc.bookappwithcache.viewmodel.HomeScreenViewModel
17 | import com.azamovhudstc.bookappwithcache.viewmodel.imp.AddScreenViewModelImp
18 | import com.azamovhudstc.bookappwithcache.viewmodel.imp.HomeScreenViewModelImp
19 | import kotlinx.android.synthetic.main.fragment_add_book_screen.*
20 | import kotlinx.android.synthetic.main.fragment_home.*
21 |
22 | class AddBookScreen : Fragment(R.layout.fragment_add_book_screen) {
23 | private val viewModel: AddScreenViewModel by viewModels()
24 |
25 | override fun onCreate(savedInstanceState: Bundle?) {
26 | super.onCreate(savedInstanceState)
27 | viewModel.successBackLiveData.observe(this) {
28 | findNavController().popBackStack()
29 | showSnack("Muffaqyatli qo`shildi !")
30 | }
31 | viewModel.progressStatusLiveData.observe(this) {
32 | if (it) addBookProgress.show() else addBookProgress.hide()
33 | }
34 | viewModel.errorLiveData.observe(this) {
35 | showToast(it)
36 | }
37 | }
38 |
39 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
40 | super.onViewCreated(view, savedInstanceState)
41 | toolbar2_.setNavigationOnClickListener {
42 | findNavController().popBackStack()
43 |
44 | }
45 | addBook.setOnClickListener {
46 | if (addBookAuthor.text.trim().toString().isEmpty() || addBookDes.text.toString().trim()
47 | .isEmpty() || addBookName.text.trim().toString().isEmpty() ||
48 | addBookPage.text.toString().trim().isEmpty()
49 | ) {
50 | Toast.makeText(requireContext(), "Maydonlar bo`sh", Toast.LENGTH_SHORT).show()
51 | } else {
52 | viewModel.addBook(
53 | AddBookRequest(
54 | author = addBookAuthor.text.toString(),
55 | addBookDes.text.toString(),
56 | pageCount = addBookPage.text.toString().toInt(),
57 | addBookName.text.toString()
58 | )
59 | )
60 | }
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/ui/screens/book/BookScreen.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.ui.screens.book
2 |
3 | import android.os.Bundle
4 | import android.util.Log
5 | import androidx.fragment.app.Fragment
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import androidx.fragment.app.viewModels
10 | import androidx.lifecycle.Observer
11 | import androidx.navigation.fragment.findNavController
12 | import com.azamovhudstc.bookappwithcache.R
13 | import com.azamovhudstc.bookappwithcache.data.local.database.entites.BookEntities
14 | import com.azamovhudstc.bookappwithcache.ui.adapter.BooksAdapter
15 | import com.azamovhudstc.bookappwithcache.utils.showSnack
16 | import com.azamovhudstc.bookappwithcache.viewmodel.HomeScreenViewModel
17 | import com.azamovhudstc.bookappwithcache.viewmodel.LoginViewModel
18 | import com.azamovhudstc.bookappwithcache.viewmodel.imp.HomeScreenViewModelImp
19 | import com.azamovhudstc.bookappwithcache.viewmodel.imp.LoginViewModelImp
20 | import kotlinx.android.synthetic.main.fragment_home.*
21 | import kotlinx.android.synthetic.main.fragment_login.*
22 |
23 |
24 | class BookScreen : Fragment(R.layout.fragment_home),
25 | BooksAdapter.ContactItemCallBack.SetLongClickListener {
26 | private val adapter by lazy { BooksAdapter(this) }
27 | private var size = 0
28 | private val viewModel: HomeScreenViewModel by viewModels()
29 | override fun onCreate(savedInstanceState: Bundle?) {
30 | super.onCreate(savedInstanceState)
31 | viewModel.statusLiveData.observe(this) {
32 | toolbar.title = it
33 | }
34 | viewModel.messageLiveData.observe(this) {
35 | showSnack(it)
36 | }
37 | viewModel.editBookLiveData.observe(this) {
38 |
39 | }
40 | viewModel.getAllBooksLiveData.observe(this, getAllBookObserver)
41 | viewModel.addBookLiveData.observe(this) {
42 | findNavController().navigate(R.id.addBookScreen)
43 | }
44 | viewModel.progressLiveData.observe(this, progressObserver)
45 | }
46 |
47 | private val progressObserver = Observer {
48 | if (it) progressHome.show() else progressHome.hide()
49 | }
50 | private val getAllBookObserver = Observer> {
51 | adapter.submitList(it)
52 | size = it.size
53 | }
54 |
55 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
56 | super.onViewCreated(view, savedInstanceState)
57 | rv_book.adapter = adapter
58 |
59 | btnRefresh.setOnClickListener {
60 | viewModel.reloadData()
61 | }
62 | viewModel.status()
63 | viewModel.getAllBooks()
64 | buttonAdd.setOnClickListener {
65 | viewModel.addBook()
66 | }
67 | }
68 |
69 | override fun deleteClick(contact: BookEntities) {
70 | viewModel.delete(contact)
71 | }
72 |
73 | override fun showClick(contact: BookEntities) {
74 | var bundle = Bundle()
75 | bundle.putSerializable("data", contact)
76 | findNavController().navigate(R.id.showBookScreen,bundle)
77 |
78 | }
79 |
80 | override fun editItemClick(contact: BookEntities) {
81 | var bundle = Bundle()
82 | bundle.putSerializable("data", contact)
83 | findNavController().navigate(R.id.editBookScreen,bundle)
84 | }
85 |
86 | override fun likedClick(contact: BookEntities) {
87 |
88 | }
89 |
90 |
91 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/ui/screens/book/EditBookScreen.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.ui.screens.book
2 |
3 | import android.os.Bundle
4 | import android.view.View
5 | import android.widget.Toast
6 | import androidx.fragment.app.Fragment
7 | import androidx.fragment.app.viewModels
8 | import androidx.navigation.fragment.findNavController
9 | import com.azamovhudstc.bookappwithcache.R
10 | import com.azamovhudstc.bookappwithcache.data.local.database.entites.BookEntities
11 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.AddBookRequest
12 | import com.azamovhudstc.bookappwithcache.utils.showSnack
13 | import com.azamovhudstc.bookappwithcache.utils.showToast
14 | import com.azamovhudstc.bookappwithcache.viewmodel.EditScreenViewModel
15 | import com.azamovhudstc.bookappwithcache.viewmodel.imp.EditScreenViewModelImpl
16 | import kotlinx.android.synthetic.main.fragment_add_book_screen.*
17 | import kotlinx.android.synthetic.main.fragment_edit.*
18 |
19 | class EditBookScreen : Fragment(R.layout.fragment_edit) {
20 | private val viewModel: EditScreenViewModel by viewModels()
21 |
22 | override fun onCreate(savedInstanceState: Bundle?) {
23 | super.onCreate(savedInstanceState)
24 | viewModel.successBackLiveData.observe(this) {
25 | findNavController().popBackStack()
26 | showSnack("Muffaqyatli qo`shildi !")
27 | }
28 | viewModel.progressStatusLiveData.observe(this) {
29 | if (it) editBookProgress.show() else editBookProgress.hide()
30 | }
31 | viewModel.errorLiveData.observe(this) {
32 | showToast(it)
33 | }
34 | }
35 |
36 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
37 | super.onViewCreated(view, savedInstanceState)
38 | val serializable = arguments?.getSerializable("data") as BookEntities
39 | editBookAuthor.setText(serializable.author)
40 | editBookDes.setText(serializable.description)
41 | editBookName.setText(serializable.title)
42 | editBookPage.setText(serializable.pageCount.toString())
43 |
44 | toolbar2_edit.setNavigationOnClickListener {
45 | findNavController().popBackStack()
46 | }
47 | edit.setOnClickListener {
48 | if (editBookAuthor.text.trim().toString().isEmpty() || editBookDes.text.toString()
49 | .trim()
50 | .isEmpty() || editBookName.text.trim().toString().isEmpty() ||
51 | editBookPage.text.toString().trim().isEmpty()
52 | ) {
53 | Toast.makeText(requireContext(), "Maydonlar bo`sh", Toast.LENGTH_SHORT).show()
54 | } else {
55 | serializable.description = editBookDes.text.toString()
56 | serializable.author = editBookAuthor.text.toString()
57 | serializable.pageCount = editBookPage.text.toString().toInt()
58 | serializable.title = editBookName.text.toString()
59 | serializable.state = 2
60 | viewModel.editBook(
61 | serializable
62 | )
63 | }
64 | }
65 |
66 | }
67 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/ui/screens/book/ShowBookScreen.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.ui.screens.book
2 |
3 | import android.os.Bundle
4 | import android.view.View
5 | import androidx.fragment.app.Fragment
6 | import com.azamovhudstc.bookappwithcache.R
7 | import com.azamovhudstc.bookappwithcache.data.local.database.entites.BookEntities
8 | import kotlinx.android.synthetic.main.fragment_edit.*
9 | import kotlinx.android.synthetic.main.fragment_show_book.*
10 |
11 | class ShowBookScreen : Fragment(R.layout.fragment_show_book) {
12 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
13 | super.onViewCreated(view, savedInstanceState)
14 | val serializable = arguments?.getSerializable("data") as BookEntities
15 | show_title.title = serializable.title
16 | show_author.text = "Muallif: ${serializable.author}"
17 | show_des.text = serializable.description
18 | show_page.text = "Hajmi: ${serializable.pageCount} Bet"
19 |
20 | }
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/usecase/auth/LoginUseCase.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.usecase.auth
2 |
3 | import kotlinx.coroutines.flow.Flow
4 |
5 |
6 | interface LoginUseCase {
7 | fun login( password:String, phone:String): Flow>
8 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/usecase/auth/RegisterUseCase.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.usecase.auth
2 |
3 | interface RegisterUseCase {
4 | fun check(name: String, password: String): Boolean
5 | fun register(name: String, password: String, phone: String, lastName: String):Boolean
6 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/usecase/auth/VerifyUseCase.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.usecase.auth
2 |
3 | import kotlinx.coroutines.flow.Flow
4 |
5 | interface VerifyUseCase {
6 | fun login(phone: String, password: String):Flow>
7 | fun verifySign(code: String):Flow
8 | fun verifySignUp(code: String):Flow
9 | fun register(name: String, password: String, phone: String, lastName: String):Flow
10 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/usecase/auth/impl/LoginUseCaseImpl.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.usecase.auth.impl
2 |
3 | import androidx.lifecycle.ViewModel
4 | import androidx.lifecycle.viewModelScope
5 | import com.azamovhudstc.bookappwithcache.repo.impl.AuthRepositoryImpl
6 | import com.azamovhudstc.bookappwithcache.usecase.auth.LoginUseCase
7 | import kotlinx.coroutines.flow.Flow
8 | import kotlinx.coroutines.flow.launchIn
9 | import kotlinx.coroutines.flow.onEach
10 |
11 | class LoginUseCaseImpl(var authRepositoryImpl: AuthRepositoryImpl) :
12 | LoginUseCase {
13 | override fun login(password: String, phone: String): Flow> {
14 | return authRepositoryImpl.login(password, phone)
15 | }
16 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/usecase/auth/impl/RegisterUseCaseImpl.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.usecase.auth.impl
2 |
3 | import androidx.lifecycle.ViewModel
4 | import androidx.lifecycle.viewModelScope
5 | import com.azamovhudstc.bookappwithcache.repo.impl.AuthRepositoryImpl
6 | import com.azamovhudstc.bookappwithcache.usecase.auth.RegisterUseCase
7 | import kotlinx.coroutines.Dispatchers
8 | import kotlinx.coroutines.flow.first
9 | import kotlinx.coroutines.launch
10 |
11 | class RegisterUseCaseImpl(var authRepositoryImpl: AuthRepositoryImpl, var viewModel: ViewModel) :
12 | RegisterUseCase {
13 | override fun register(
14 | name: String,
15 | password: String,
16 | phone: String,
17 | lastName: String
18 | ): Boolean {
19 | var boolean = false
20 | if (check(name, password)) {
21 | boolean = true
22 | viewModel.viewModelScope.launch(Dispatchers.IO) {
23 | boolean = authRepositoryImpl.register(name, password, phone, lastName).first()
24 | }
25 | }
26 | return boolean
27 | }
28 |
29 | override fun check(name: String, password: String): Boolean =
30 | (name.length > 3 && password.length > 3)
31 |
32 |
33 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/usecase/auth/impl/VerifyUseCaseImpl.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.usecase.auth.impl
2 |
3 | import androidx.lifecycle.ViewModel
4 | import androidx.lifecycle.viewModelScope
5 | import com.azamovhudstc.bookappwithcache.data.local.sharedpref.AppReference
6 | import com.azamovhudstc.bookappwithcache.repo.impl.AuthRepositoryImpl
7 | import com.azamovhudstc.bookappwithcache.usecase.auth.VerifyUseCase
8 | import com.azamovhudstc.bookappwithcache.viewmodel.VerifyScreenViewModel
9 | import kotlinx.coroutines.Dispatchers
10 | import kotlinx.coroutines.flow.Flow
11 | import kotlinx.coroutines.flow.launchIn
12 | import kotlinx.coroutines.flow.onEach
13 |
14 | class VerifyUseCaseImpl(var repo: AuthRepositoryImpl) : VerifyUseCase {
15 | override fun login(phone: String, password: String): Flow> {
16 | return repo.login(password, phone)
17 | }
18 |
19 | override fun verifySign(code: String): Flow {
20 | return repo.verifySign(AppReference.getInstance().verifyToken, code)
21 | }
22 |
23 | override fun verifySignUp(code: String): Flow {
24 | return repo.verify(AppReference.getInstance().verifyToken, code)
25 | }
26 |
27 | override fun register(
28 | name: String,
29 | password: String,
30 | phone: String,
31 | lastName: String
32 | ): Flow {
33 | return repo.register(name, password, phone, lastName)
34 | }
35 |
36 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/usecase/book/BookScreenUseCase.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.usecase.book
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.lifecycle.MediatorLiveData
5 | import androidx.lifecycle.MutableLiveData
6 | import com.azamovhudstc.bookappwithcache.data.local.database.entites.BookEntities
7 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.AddBookRequest
8 | import com.azamovhudstc.bookappwithcache.utils.Cases
9 | import kotlinx.coroutines.flow.Flow
10 |
11 | interface BookScreenUseCase {
12 |
13 | fun editBook(bookEntities: BookEntities)
14 | fun delete(deleteBookRequest: BookEntities)
15 | fun addBook(bookRequest: AddBookRequest)
16 | fun reloadData(): Boolean
17 | fun getAllBooks(): Flow>>
18 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/usecase/book/imp/BookScreenUseCaseImp.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.usecase.book.imp
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.lifecycle.ViewModel
5 | import androidx.lifecycle.viewModelScope
6 | import com.azamovhudstc.bookappwithcache.data.local.database.entites.BookEntities
7 | import com.azamovhudstc.bookappwithcache.data.local.sharedpref.AppReference
8 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.AddBookRequest
9 | import com.azamovhudstc.bookappwithcache.repo.impl.AuthRepositoryImpl
10 | import com.azamovhudstc.bookappwithcache.repo.impl.BookRepositoryImpl
11 | import com.azamovhudstc.bookappwithcache.usecase.book.BookScreenUseCase
12 | import com.azamovhudstc.bookappwithcache.utils.Cases
13 | import kotlinx.coroutines.Dispatchers
14 | import kotlinx.coroutines.flow.Flow
15 | import kotlinx.coroutines.flow.first
16 | import kotlinx.coroutines.launch
17 |
18 | class BookScreenUseCaseImp(var bookRepositoryImpl: BookRepositoryImpl, var viewModel: ViewModel) :
19 | BookScreenUseCase {
20 | override fun editBook(bookEntities: BookEntities) {
21 | var unit = Unit
22 | viewModel.viewModelScope.launch {
23 | unit = bookRepositoryImpl.editBook(
24 | AppReference.getInstance().getToken()!!,
25 | bookEntities.id,
26 | bookEntities.toUpdate(),
27 | bookEntities.localId
28 | )
29 | }
30 | return unit
31 |
32 | }
33 |
34 |
35 | override fun delete(deleteBookRequest: BookEntities) {
36 | var unit = Unit
37 | viewModel.viewModelScope.launch {
38 |
39 | unit = bookRepositoryImpl.deleteBook(
40 | AppReference.getInstance().getToken()!!,
41 | deleteBookRequest.localId,
42 | deleteBookRequest.id
43 | )
44 | }
45 | return unit
46 | }
47 |
48 | override fun addBook(bookRequest: AddBookRequest) {
49 | var unit = Unit
50 |
51 | viewModel.viewModelScope.launch {
52 | unit = bookRepositoryImpl.addBook(AppReference.getInstance().getToken()!!, bookRequest)
53 | }
54 | return unit
55 | }
56 |
57 | override fun reloadData(): Boolean {
58 | var boolean = false
59 | viewModel.viewModelScope.launch {
60 | boolean = bookRepositoryImpl.reLoadLocalData()
61 | }
62 | return boolean
63 |
64 | }
65 |
66 | override fun getAllBooks(): Flow>> {
67 | return bookRepositoryImpl.getAllBook(AppReference.getInstance().getToken()!!)
68 | }
69 |
70 |
71 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/utils/Cases.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.utils
2 |
3 | enum class Cases {
4 | SUCCESS,
5 | ERROR,
6 | CONNECTION,
7 | DISCONNECTION,
8 | ADD,
9 | DELETE,
10 | EDIT,
11 |
12 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/utils/ConnetctionUtil.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.utils
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import android.net.ConnectivityManager
6 | import android.net.NetworkCapabilities
7 | import android.os.Build
8 | import com.azamovhudstc.bookappwithcache.app.App
9 |
10 | fun hasConnection(): Boolean = App.instance.isAvailableNetwork()
11 |
12 | @SuppressLint("MissingPermission")
13 | private fun Context.isAvailableNetwork(): Boolean {
14 | var result = false
15 | val connectivityManager =
16 | getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
17 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
18 | val networkCapabilities = connectivityManager.activeNetwork ?: return false
19 | val actNw =
20 | connectivityManager.getNetworkCapabilities(networkCapabilities) ?: return false
21 | result = when {
22 | actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
23 | actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
24 | actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
25 | else -> false
26 | }
27 | } else {
28 | connectivityManager.run {
29 | connectivityManager.activeNetworkInfo?.run {
30 | result = when (type) {
31 | ConnectivityManager.TYPE_WIFI -> true
32 | ConnectivityManager.TYPE_MOBILE -> true
33 | ConnectivityManager.TYPE_ETHERNET -> true
34 | else -> false
35 | }
36 |
37 | }
38 | }
39 | }
40 | return result
41 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/utils/MediatorLiveDataExtension.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.utils
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.lifecycle.MediatorLiveData
5 | import androidx.lifecycle.Observer
6 |
7 | fun MediatorLiveData<*>.addDisposable(liveData: LiveData, observer: Observer){
8 | addSource(liveData) {
9 | observer.onChanged(it)
10 | removeSource(liveData)
11 | }
12 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/utils/MyUtils.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.utils
2 |
3 | import android.util.Log
4 | import android.widget.Toast
5 | import androidx.appcompat.widget.AppCompatEditText
6 | import androidx.core.widget.ContentLoadingProgressBar
7 | import androidx.core.widget.addTextChangedListener
8 | import androidx.fragment.app.Fragment
9 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.response.auth.ErrorResponse
10 | import com.google.android.material.snackbar.Snackbar
11 | import com.google.gson.Gson
12 | import com.google.gson.JsonSyntaxException
13 | import retrofit2.Callback
14 | import retrofit2.Response
15 |
16 | fun T.myApply(block: T.() -> Unit) {
17 | block(this)
18 | }
19 |
20 | fun Fragment.showToast(message: String, duration: Int = Toast.LENGTH_SHORT) {
21 | Toast.makeText(requireContext(), message, duration).show()
22 | }
23 |
24 | fun Fragment.showSnack(message: String, duration: Int = Toast.LENGTH_SHORT) {
25 | Snackbar.make(requireView(), message, duration).show()
26 | }
27 |
28 |
29 | fun AppCompatEditText.myAddTextChangedListener(block: (String) -> Unit) {
30 | this.addTextChangedListener {
31 | it?.let {
32 | block.invoke(it.toString())
33 | }
34 | }
35 | }
36 |
37 | fun ContentLoadingProgressBar.state(bool: Boolean) {
38 | if (bool) this.show()
39 | else this.hide()
40 | }
41 |
42 |
43 | fun AppCompatEditText.amount(): String = this.text.toString()
44 |
45 | fun Callback.showApiError(response: Response): String {
46 | val gson = Gson()
47 | var message = ""
48 | response.errorBody()?.let {
49 | try {
50 | val error = gson.fromJson(it.string(), ErrorResponse::class.java)
51 | Log.d("TTT", error.message)
52 | message = error.message
53 | } catch (e: JsonSyntaxException) {
54 | return "server o'chirilgan"
55 | }
56 | }
57 | return message
58 | }
59 |
60 | fun AppCompatEditText.clear() {
61 | setText("")
62 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/viewmodel/AddScreenViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.viewmodel
2 |
3 | import androidx.lifecycle.MutableLiveData
4 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.AddBookRequest
5 |
6 | interface AddScreenViewModel {
7 | val successBackLiveData: MutableLiveData
8 | val errorLiveData: MutableLiveData
9 | val progressStatusLiveData: MutableLiveData
10 | fun addBook(bookRequest: AddBookRequest)
11 |
12 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/viewmodel/EditScreenViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.viewmodel
2 |
3 | import androidx.lifecycle.MutableLiveData
4 | import com.azamovhudstc.bookappwithcache.data.local.database.entites.BookEntities
5 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.AddBookRequest
6 |
7 | interface EditScreenViewModel {
8 | val successBackLiveData: MutableLiveData
9 | val errorLiveData: MutableLiveData
10 | val progressStatusLiveData: MutableLiveData
11 | fun editBook(bookRequest: BookEntities)
12 |
13 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/viewmodel/HomeScreenViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.viewmodel
2 |
3 | import androidx.lifecycle.MediatorLiveData
4 | import androidx.lifecycle.MutableLiveData
5 | import com.azamovhudstc.bookappwithcache.data.local.database.entites.BookEntities
6 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.DeleteBookRequest
7 |
8 | interface HomeScreenViewModel {
9 | val addBookLiveData: MediatorLiveData
10 | val messageLiveData: MediatorLiveData
11 | val statusLiveData:MutableLiveData
12 | val getAllBooksLiveData: MutableLiveData>
13 | val editBookLiveData: MediatorLiveData
14 | val progressLiveData: MutableLiveData
15 | fun editBook(bookEntities: BookEntities)
16 | fun status()
17 | fun delete(deleteBookRequest:BookEntities)
18 | fun addBook()
19 | fun reloadData()
20 | fun getAllBooks()
21 |
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/viewmodel/LoginViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.viewmodel
2 |
3 | import androidx.lifecycle.MutableLiveData
4 |
5 | interface LoginViewModel {
6 | val errorLiveData: MutableLiveData
7 | fun login(phone: String, password: String)
8 | val changeButtonStatusLiveData :MutableLiveData
9 | val progressLiveData:MutableLiveData
10 | val notConnectionLiveData: MutableLiveData
11 | val openVerifyScreenLiveData: MutableLiveData
12 |
13 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/viewmodel/VerifyScreenViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.viewmodel
2 |
3 | import androidx.lifecycle.MutableLiveData
4 |
5 | interface VerifyScreenViewModel {
6 | val openHomeScreenLiveData:MutableLiveData
7 | val errorMessageLiveData:MutableLiveData
8 | val notConnectionLiveData: MutableLiveData
9 | val changeButtonStatusLiveData : MutableLiveData
10 | val progressLiveData : MutableLiveData
11 | fun login(phone:String,password:String)
12 | fun verifySign(code:String)
13 | fun verifySignUp(code: String)
14 | fun register(name: String, password: String, phone: String, lastName: String)
15 |
16 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/viewmodel/imp/AddScreenViewModelImp.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.viewmodel.imp
2 |
3 | import androidx.lifecycle.MutableLiveData
4 | import androidx.lifecycle.ViewModel
5 | import androidx.lifecycle.viewModelScope
6 | import com.azamovhudstc.bookappwithcache.data.local.sharedpref.AppReference
7 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.AddBookRequest
8 | import com.azamovhudstc.bookappwithcache.repo.impl.BookRepositoryImpl
9 | import com.azamovhudstc.bookappwithcache.usecase.book.imp.BookScreenUseCaseImp
10 | import com.azamovhudstc.bookappwithcache.viewmodel.AddScreenViewModel
11 | import kotlinx.coroutines.Dispatchers
12 | import kotlinx.coroutines.launch
13 |
14 | class AddScreenViewModelImp : AddScreenViewModel, ViewModel() {
15 | override val successBackLiveData: MutableLiveData = MutableLiveData()
16 | override val errorLiveData: MutableLiveData = MutableLiveData()
17 | override val progressStatusLiveData: MutableLiveData = MutableLiveData()
18 | private val bookScreenUseCase = BookRepositoryImpl()
19 |
20 |
21 | override fun addBook(bookRequest: AddBookRequest) {
22 | progressStatusLiveData.value = true
23 | var token = AppReference.getInstance().getToken()
24 | if (checker(bookRequest)) {
25 | progressStatusLiveData.value = false
26 | viewModelScope.launch(Dispatchers.IO) {
27 | bookScreenUseCase.addBook(AppReference.getInstance().getToken()!!, bookRequest)
28 | .let {
29 |
30 | }
31 | successBackLiveData.postValue(Unit)
32 | }
33 | } else {
34 | progressStatusLiveData.value = false
35 |
36 | errorLiveData.value = "Maydonlar Hato to`ldirilgan"
37 | }
38 | }
39 |
40 | private fun checker(bookRequest: AddBookRequest): Boolean {
41 | return bookRequest.author.length > 10 && bookRequest.description.length > 30
42 |
43 | }
44 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/viewmodel/imp/EditScreenViewModelImpl.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.viewmodel.imp
2 |
3 | import androidx.lifecycle.MutableLiveData
4 | import androidx.lifecycle.ViewModel
5 | import androidx.lifecycle.viewModelScope
6 | import com.azamovhudstc.bookappwithcache.data.local.database.entites.BookEntities
7 | import com.azamovhudstc.bookappwithcache.data.local.sharedpref.AppReference
8 | import com.azamovhudstc.bookappwithcache.data.remote.retrofit2.request.book.EditBookRequest
9 | import com.azamovhudstc.bookappwithcache.repo.impl.BookRepositoryImpl
10 | import com.azamovhudstc.bookappwithcache.viewmodel.EditScreenViewModel
11 | import kotlinx.coroutines.Dispatchers
12 | import kotlinx.coroutines.launch
13 |
14 | class EditScreenViewModelImpl : EditScreenViewModel, ViewModel() {
15 | override val successBackLiveData: MutableLiveData = MutableLiveData()
16 | override val errorLiveData: MutableLiveData = MutableLiveData()
17 | override val progressStatusLiveData: MutableLiveData = MutableLiveData()
18 | private val bookScreenUseCaseImp = BookRepositoryImpl()
19 |
20 | override fun editBook(bookRequest: BookEntities) {
21 | progressStatusLiveData.value = true
22 | var token = AppReference.getInstance().getToken()
23 |
24 |
25 | if (checker(bookRequest.toUpdate())) {
26 | progressStatusLiveData.value = false
27 | viewModelScope.launch(Dispatchers.IO) {
28 | bookScreenUseCaseImp.editBook(token!!, bookRequest.id, bookRequest.toUpdate(), bookRequest.localId)
29 | successBackLiveData.postValue(Unit)
30 | }
31 | } else {
32 | progressStatusLiveData.value = false
33 |
34 | errorLiveData.value = "Maydonlar Hato to`ldirilgan"
35 | }
36 | }
37 |
38 | private fun checker(bookRequest: EditBookRequest): Boolean {
39 | return bookRequest.author.length > 10 && bookRequest.description.length > 30
40 |
41 | }
42 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/viewmodel/imp/HomeScreenViewModelImp.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.viewmodel.imp
2 |
3 | import android.util.Log
4 | import androidx.lifecycle.*
5 | import com.azamovhudstc.bookappwithcache.data.local.database.entites.BookEntities
6 | import com.azamovhudstc.bookappwithcache.repo.impl.BookRepositoryImpl
7 | import com.azamovhudstc.bookappwithcache.usecase.book.imp.BookScreenUseCaseImp
8 | import com.azamovhudstc.bookappwithcache.utils.hasConnection
9 | import com.azamovhudstc.bookappwithcache.viewmodel.HomeScreenViewModel
10 | import kotlinx.coroutines.Dispatchers
11 | import kotlinx.coroutines.flow.launchIn
12 | import kotlinx.coroutines.flow.onEach
13 | import kotlinx.coroutines.launch
14 | import java.net.SocketTimeoutException
15 |
16 | class HomeScreenViewModelImp : HomeScreenViewModel, ViewModel() {
17 | override val addBookLiveData: MediatorLiveData = MediatorLiveData()
18 | override val messageLiveData: MediatorLiveData = MediatorLiveData()
19 | override val statusLiveData: MutableLiveData = MediatorLiveData()
20 | private val bookScreenUseCaseImp = BookScreenUseCaseImp(BookRepositoryImpl(),this)
21 | override var getAllBooksLiveData: MutableLiveData> = MutableLiveData()
22 | override val editBookLiveData: MediatorLiveData = MediatorLiveData()
23 | override val progressLiveData: MutableLiveData = MutableLiveData()
24 | private var viewLiveData: LiveData> = MutableLiveData()
25 |
26 | init {
27 | getAllBooks()
28 | }
29 |
30 | override fun editBook(bookEntities: BookEntities) {
31 | }
32 |
33 | override fun status() {
34 | viewModelScope.launch {
35 | if (hasConnection()) statusLiveData.value = "Online"
36 | else statusLiveData.value =
37 | "Offline"
38 | }
39 | }
40 |
41 | override fun delete(deleteBookRequest: BookEntities) {
42 | viewModelScope.launch(Dispatchers.IO) {
43 | bookScreenUseCaseImp.delete(deleteBookRequest)
44 |
45 | }
46 | }
47 |
48 | override fun addBook() {
49 | addBookLiveData.value = Unit
50 | }
51 |
52 | override fun reloadData() {
53 | try {
54 | if (hasConnection()) {
55 | viewModelScope.launch(Dispatchers.IO) {
56 | bookScreenUseCaseImp.reloadData()
57 | }
58 | } else {
59 | messageLiveData.value = "Iltimos Internetni yoqing !"
60 | }
61 | status()
62 | } catch (e: SocketTimeoutException) {
63 | Log.d("!@#", "reloadData: ${e.message}")
64 | }
65 |
66 | }
67 |
68 | override fun getAllBooks() {
69 | progressLiveData.value = true
70 |
71 | viewModelScope.launch(Dispatchers.Main) {
72 | bookScreenUseCaseImp.getAllBooks().onEach { it ->
73 | editBookLiveData.addSource(it) {
74 | getAllBooksLiveData.value = it
75 |
76 | }
77 | }.launchIn(viewModelScope)
78 | progressLiveData.value = false
79 |
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/viewmodel/imp/LoginViewModelImp.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.viewmodel.imp
2 |
3 | import androidx.lifecycle.MutableLiveData
4 | import androidx.lifecycle.ViewModel
5 | import androidx.lifecycle.viewModelScope
6 | import com.azamovhudstc.bookappwithcache.repo.AuthRepository
7 | import com.azamovhudstc.bookappwithcache.repo.impl.AuthRepositoryImpl
8 | import com.azamovhudstc.bookappwithcache.usecase.auth.LoginUseCase
9 | import com.azamovhudstc.bookappwithcache.usecase.auth.impl.LoginUseCaseImpl
10 | import com.azamovhudstc.bookappwithcache.utils.hasConnection
11 | import com.azamovhudstc.bookappwithcache.viewmodel.LoginViewModel
12 | import kotlinx.coroutines.Dispatchers
13 | import kotlinx.coroutines.flow.*
14 | import kotlinx.coroutines.launch
15 |
16 | class LoginViewModelImp : LoginViewModel, ViewModel() {
17 | override val errorLiveData: MutableLiveData = MutableLiveData()
18 | override val changeButtonStatusLiveData: MutableLiveData = MutableLiveData()
19 | private val repo: LoginUseCase = LoginUseCaseImpl(AuthRepositoryImpl())
20 | override val progressLiveData: MutableLiveData = MutableLiveData()
21 | override val notConnectionLiveData: MutableLiveData = MutableLiveData()
22 |
23 | override val openVerifyScreenLiveData: MutableLiveData = MutableLiveData()
24 | override fun login(phone: String, password: String) {
25 | progressLiveData.value = true
26 | if (!hasConnection()) {
27 | progressLiveData.value = false
28 | notConnectionLiveData.value = Unit
29 | return
30 | }
31 |
32 |
33 | repo.login(password, phone).onEach {
34 | it.onSuccess {
35 | progressLiveData.value = false
36 | openVerifyScreenLiveData.value = Unit
37 | }
38 | it.onFailure {
39 | progressLiveData.value = false
40 | errorLiveData.value = it.message
41 | }
42 | }.launchIn(viewModelScope)
43 |
44 |
45 | // viewModelScope.launch {
46 | // repo.login(password,phone).flowOn(Dispatchers.Main).collect{
47 | // it.onSuccess {
48 | // progressLiveData.value=false
49 | // openVerifyScreenLiveData.value=Unit
50 | // }
51 | // it.onFailure {
52 | // progressLiveData.value=false
53 | // errorLiveData.value=it.message
54 | // }
55 | // }
56 | // }
57 | }
58 |
59 |
60 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/viewmodel/imp/RegisterViewModelImpl.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.viewmodel.imp
2 |
3 | import androidx.lifecycle.MutableLiveData
4 | import androidx.lifecycle.ViewModel
5 | import com.azamovhudstc.bookappwithcache.data.local.sharedpref.AppReference
6 | import com.azamovhudstc.bookappwithcache.repo.impl.AuthRepositoryImpl
7 | import com.azamovhudstc.bookappwithcache.usecase.auth.RegisterUseCase
8 | import com.azamovhudstc.bookappwithcache.usecase.auth.impl.RegisterUseCaseImpl
9 | import com.azamovhudstc.bookappwithcache.utils.hasConnection
10 |
11 | class RegisterViewModelImpl() : ViewModel() {
12 | val openVerifyScreenLiveData = MutableLiveData()
13 | val notConnectionLiveData = MutableLiveData()
14 | val messageLIveData = MutableLiveData()
15 | val backLoginLiveData = MutableLiveData()
16 | val changeButtonStatusLiveData = MutableLiveData()
17 | val progressLiveData = MutableLiveData()
18 |
19 | private val registerUseCase: RegisterUseCase = RegisterUseCaseImpl(AuthRepositoryImpl(), this)
20 | private val shP: AppReference = AppReference.getInstance()
21 | fun register(name: String, password: String, phone: String, lastName: String) {
22 | changeButtonStatusLiveData.value = false
23 | progressLiveData.value = true
24 | if (!hasConnection()) {
25 | notConnectionLiveData.value = Unit
26 | return
27 | } else {
28 | if (registerUseCase.check(name, password)) {
29 | if (registerUseCase.register(name, password, phone, lastName)) {
30 | changeButtonStatusLiveData.value = true
31 | shP.userName = name
32 | messageLIveData.value = "registered in successfully"
33 | progressLiveData.value = false
34 | openVerifyScreenLiveData.value = Unit
35 |
36 | } else {
37 | progressLiveData.value = false
38 | changeButtonStatusLiveData.value = true
39 | messageLIveData.value = "Maydonlarda xatolik mavjud"
40 | }
41 | } else {
42 | progressLiveData.value = false
43 |
44 | messageLIveData.value = "Maydonlarda xatolik mavjud"
45 |
46 | }
47 |
48 | }
49 | }
50 |
51 |
52 | fun backLogin() {
53 | backLoginLiveData.value = Unit
54 | }
55 |
56 |
57 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/azamovhudstc/bookappwithcache/viewmodel/imp/VerifyScreenViewModelImp.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache.viewmodel.imp
2 |
3 | import androidx.lifecycle.MutableLiveData
4 | import androidx.lifecycle.ViewModel
5 | import androidx.lifecycle.viewModelScope
6 | import com.azamovhudstc.bookappwithcache.data.local.sharedpref.AppReference
7 | import com.azamovhudstc.bookappwithcache.repo.impl.AuthRepositoryImpl
8 | import com.azamovhudstc.bookappwithcache.usecase.auth.VerifyUseCase
9 | import com.azamovhudstc.bookappwithcache.usecase.auth.impl.VerifyUseCaseImpl
10 | import com.azamovhudstc.bookappwithcache.utils.hasConnection
11 | import com.azamovhudstc.bookappwithcache.viewmodel.VerifyScreenViewModel
12 | import kotlinx.coroutines.Dispatchers
13 | import kotlinx.coroutines.flow.first
14 | import kotlinx.coroutines.flow.flowOn
15 | import kotlinx.coroutines.launch
16 |
17 | class VerifyScreenViewModelImp : VerifyScreenViewModel, ViewModel() {
18 | private val verifyUSeCase: VerifyUseCase = VerifyUseCaseImpl(AuthRepositoryImpl())
19 | private val shP: AppReference = AppReference.getInstance()
20 |
21 | override val openHomeScreenLiveData: MutableLiveData = MutableLiveData()
22 | override val errorMessageLiveData: MutableLiveData = MutableLiveData()
23 | override val notConnectionLiveData: MutableLiveData = MutableLiveData()
24 | override val changeButtonStatusLiveData: MutableLiveData = MutableLiveData()
25 | override val progressLiveData: MutableLiveData = MutableLiveData()
26 | override fun login(phone: String, password: String) {
27 | progressLiveData.value = true
28 | if (!hasConnection()) {
29 | progressLiveData.value = false
30 | notConnectionLiveData.value = Unit
31 | return
32 | }
33 |
34 | viewModelScope.launch {
35 | verifyUSeCase.login(password, phone).flowOn(Dispatchers.Main).collect {
36 | it.onSuccess {
37 | progressLiveData.value = false
38 |
39 | }
40 | it.onFailure {
41 | progressLiveData.value = false
42 | errorMessageLiveData.value = it.message
43 | }
44 | }
45 | }
46 | }
47 |
48 | override fun verifySign(code: String) {
49 | progressLiveData.value = true
50 | if (!hasConnection()) {
51 | progressLiveData.value = false
52 | notConnectionLiveData.value = Unit
53 | return
54 | } else {
55 | viewModelScope.launch(Dispatchers.IO) {
56 | if (verifyUSeCase.verifySign(code).first()) {
57 | viewModelScope.launch(Dispatchers.Main) {
58 | openHomeScreenLiveData.value = Unit
59 | progressLiveData.value = false
60 |
61 | }
62 | } else {
63 | viewModelScope.launch(Dispatchers.Main) {
64 | changeButtonStatusLiveData.value = true
65 |
66 | progressLiveData.value = false
67 |
68 | }
69 | }
70 |
71 | }
72 | }
73 |
74 | }
75 |
76 | override fun verifySignUp(code: String) {
77 | if (!hasConnection()) {
78 | notConnectionLiveData.value = Unit
79 | } else {
80 | val verifyToken = AppReference.getInstance().verifyToken
81 | viewModelScope.launch(Dispatchers.IO) {
82 | if (verifyUSeCase.verifySignUp(code).first()) {
83 | viewModelScope.launch(Dispatchers.Main) {
84 | openHomeScreenLiveData.value = Unit
85 |
86 | }
87 | } else {
88 | viewModelScope.launch(Dispatchers.Main) {
89 | errorMessageLiveData.value = "Kod Hato !"
90 |
91 | }
92 | }
93 |
94 | }
95 | }
96 |
97 | }
98 |
99 | override fun register(name: String, password: String, phone: String, lastName: String) {
100 | if (!hasConnection()) {
101 | notConnectionLiveData.value = Unit
102 | return
103 | } else {
104 |
105 | viewModelScope.launch(Dispatchers.IO) {
106 | if (verifyUSeCase.register(name, password, phone, lastName).first()) {
107 | viewModelScope.launch(Dispatchers.Main) {
108 | changeButtonStatusLiveData.value = true
109 | shP.userName = name
110 | progressLiveData.value = false
111 |
112 | }
113 | }
114 | }
115 | }
116 |
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/backs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 |
10 | -
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_circle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_ed.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
15 |
16 |
20 |
21 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_edit.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
12 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_edit_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_like.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/professorDeveloper/BookAppWithCache-Clean-Architecture/ee7e2aa18c75111df4d613397680f8f6b97c7e8f/app/src/main/res/drawable/bg_like.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_pin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 |
10 | -
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/books.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/professorDeveloper/BookAppWithCache-Clean-Architecture/ee7e2aa18c75111df4d613397680f8f6b97c7e8f/app/src/main/res/drawable/books.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/edit_phone.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_back.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_backspace.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_access_time_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_add_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_arrow_back_ios_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_edit_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_favorite_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_favorite_border_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_home_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_keyboard_voice_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_refresh_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_thumb_down_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_thumb_up_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_check.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_clear.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_close.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_delete.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_edit.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_home.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_search.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/professorDeveloper/BookAppWithCache-Clean-Architecture/ee7e2aa18c75111df4d613397680f8f6b97c7e8f/app/src/main/res/drawable/img.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/like.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/like_un.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/logout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/professorDeveloper/BookAppWithCache-Clean-Architecture/ee7e2aa18c75111df4d613397680f8f6b97c7e8f/app/src/main/res/drawable/logout.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/rounded_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/unlike.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/professorDeveloper/BookAppWithCache-Clean-Architecture/ee7e2aa18c75111df4d613397680f8f6b97c7e8f/app/src/main/res/drawable/unlike.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/viewbg.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
16 |
17 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/viewpager_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/books_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
18 |
19 |
27 |
28 |
29 |
30 |
31 |
35 |
36 |
51 |
52 |
67 |
68 |
78 |
79 |
87 |
88 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_add_book_screen.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
12 |
13 |
27 |
28 |
29 |
45 |
46 |
65 |
66 |
83 |
84 |
103 |
115 |
116 |
127 |
128 |
129 |
140 |
141 |
154 |
155 |
156 |
157 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
12 |
13 |
27 |
28 |
29 |
30 |
45 |
46 |
63 |
64 |
80 |
81 |
98 |
110 |
111 |
122 |
123 |
124 |
136 |
137 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_home.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
20 |
21 |
34 |
35 |
47 |
48 |
61 |
62 |
75 |
76 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_login.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
25 |
26 |
40 |
41 |
50 |
51 |
59 |
60 |
72 |
73 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_register.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
29 |
30 |
41 |
42 |
54 |
55 |
69 |
70 |
82 |
83 |
84 |
93 |
94 |
106 |
107 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_show_book.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
27 |
28 |
34 |
35 |
36 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
53 |
54 |
57 |
58 |
59 |
73 |
74 |
85 |
86 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_splash.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
24 |
25 |
26 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/professorDeveloper/BookAppWithCache-Clean-Architecture/ee7e2aa18c75111df4d613397680f8f6b97c7e8f/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/professorDeveloper/BookAppWithCache-Clean-Architecture/ee7e2aa18c75111df4d613397680f8f6b97c7e8f/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/professorDeveloper/BookAppWithCache-Clean-Architecture/ee7e2aa18c75111df4d613397680f8f6b97c7e8f/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/professorDeveloper/BookAppWithCache-Clean-Architecture/ee7e2aa18c75111df4d613397680f8f6b97c7e8f/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/professorDeveloper/BookAppWithCache-Clean-Architecture/ee7e2aa18c75111df4d613397680f8f6b97c7e8f/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/professorDeveloper/BookAppWithCache-Clean-Architecture/ee7e2aa18c75111df4d613397680f8f6b97c7e8f/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/professorDeveloper/BookAppWithCache-Clean-Architecture/ee7e2aa18c75111df4d613397680f8f6b97c7e8f/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/professorDeveloper/BookAppWithCache-Clean-Architecture/ee7e2aa18c75111df4d613397680f8f6b97c7e8f/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/professorDeveloper/BookAppWithCache-Clean-Architecture/ee7e2aa18c75111df4d613397680f8f6b97c7e8f/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/professorDeveloper/BookAppWithCache-Clean-Architecture/ee7e2aa18c75111df4d613397680f8f6b97c7e8f/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/navigation/app_graph.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
16 |
19 |
20 |
25 |
28 |
31 |
34 |
35 |
40 |
43 |
44 |
49 |
52 |
53 |
58 |
61 |
64 |
65 |
70 |
74 |
78 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/splash.json:
--------------------------------------------------------------------------------
1 | {"v":"5.5.7","meta":{"g":"LottieFiles AE 0.1.21","a":"","k":"","d":"","tc":""},"fr":60,"ip":0,"op":360,"w":400,"h":400,"nm":"Loader","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Left Eye","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.555,"y":1},"o":{"x":1,"y":0},"t":60,"s":[800,627.5,0],"to":[-4.5,2.083,0],"ti":[4.5,-2.083,0]},{"i":{"x":0.335,"y":0.335},"o":{"x":0.167,"y":0.167},"t":120,"s":[773,640,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.763,"y":1},"o":{"x":1,"y":0},"t":257,"s":[773,640,0],"to":[4.5,-2.083,0],"ti":[-4.5,2.083,0]},{"t":310,"s":[800,627.5,0]}],"ix":2},"a":{"a":0,"k":[20,-36,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[0,0,100]},{"i":{"x":[0.555,0.555,0.667],"y":[1,1,1]},"o":{"x":[1,1,0.333],"y":[0,0,0]},"t":60,"s":[140,140,100]},{"i":{"x":[0.497,0.497,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":120,"s":[100,100,100]},{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[1,1,0.167],"y":[0,0,0]},"t":257,"s":[100,100,100]},{"i":{"x":[0.117,0.117,0.833],"y":[1,1,1]},"o":{"x":[0.14,0.14,0.333],"y":[0,0,0]},"t":310,"s":[140,140,100]},{"t":359,"s":[0,0,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[35,35],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":124,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.094117647059,0.250980392157,0.160784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[20,-36],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Right Eye","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.555,"y":1},"o":{"x":1,"y":0},"t":60,"s":[800,627.5,0],"to":[4.667,2.083,0],"ti":[-4.667,-2.083,0]},{"i":{"x":0.76,"y":0.76},"o":{"x":0.167,"y":0.167},"t":120,"s":[828,640,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.769,"y":1},"o":{"x":1,"y":0},"t":257,"s":[828,640,0],"to":[-4.667,-2.083,0],"ti":[4.667,2.083,0]},{"t":310,"s":[800,627.5,0]}],"ix":2},"a":{"a":0,"k":[20,-36,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[0,0,100]},{"i":{"x":[0.555,0.555,0.667],"y":[1,1,1]},"o":{"x":[1,1,0.333],"y":[0,0,0]},"t":60,"s":[140,140,100]},{"i":{"x":[0.497,0.497,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":120,"s":[100,100,100]},{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[1,1,0.167],"y":[0,0,0]},"t":257,"s":[100,100,100]},{"i":{"x":[0.112,0.112,0.833],"y":[1,1,1]},"o":{"x":[0.141,0.141,0.333],"y":[0,0,0]},"t":310,"s":[140,140,100]},{"t":359,"s":[0,0,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0,0.457],"y":[1,1]},"o":{"x":[0.936,0.455],"y":[0,0]},"t":150,"s":[35,35]},{"i":{"x":[0.748,0.667],"y":[1,1]},"o":{"x":[0.862,0.333],"y":[0,0]},"t":170,"s":[35,12]},{"i":{"x":[0,0.457],"y":[1,1]},"o":{"x":[0.392,0.855],"y":[0,0]},"t":182,"s":[38,10]},{"i":{"x":[0.107,0.667],"y":[1,1]},"o":{"x":[0.862,0.333],"y":[0,0]},"t":193,"s":[35,12]},{"t":213,"s":[35,35]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":124,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.094117647059,0.250980392157,0.160784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[20,-36],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Smile Lip","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.239],"y":[1]},"o":{"x":[0.373],"y":[0]},"t":60,"s":[-180]},{"i":{"x":[0.452],"y":[1]},"o":{"x":[0.877],"y":[0]},"t":77,"s":[-210]},{"i":{"x":[0.381],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":120,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.015],"y":[0]},"t":230,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.836],"y":[0]},"t":247,"s":[-20]},{"t":310,"s":[180]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.761,"y":0.761},"o":{"x":0.167,"y":0.167},"t":120,"s":[800,640,0],"to":[0,0,0],"ti":[0,0,0]},{"t":230,"s":[800,640,0]}],"ix":2},"a":{"a":0,"k":[-136.248,-44.248,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.761,0.761,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":120,"s":[100.678,100,100]},{"t":230,"s":[100.678,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[147.503,147.503],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":124,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.094117647059,0.250980392157,0.160784313725,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":16,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-136.248,-44.248],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[11]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":60,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.134],"y":[0]},"t":230,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":310,"s":[0]},{"t":359,"s":[11]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[11]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":60,"s":[23]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.134],"y":[0]},"t":230,"s":[23]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":310,"s":[23]},{"t":359,"s":[11]}],"ix":2},"o":{"a":0,"k":48,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":600,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Smile_lottie","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,144,0],"ix":2},"a":{"a":0,"k":[800,600,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"w":1600,"h":1200,"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"BG","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[202.25,204,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[800,600],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.9215686274509803,0.23529411764705882,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[]}
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #166BFA
10 | #35373A
11 | #2196F3
12 | #35373A
13 | #67686A
14 | #63D0DB
15 | #9D9FA1
16 | #FFFFFFFF
17 | #66d7ef
18 | #F44336
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | BookAppWithCache
3 |
4 | Hello blank fragment
5 | Welcome to Onboarding App !
6 | Here is an open-source project which shows sweet & original onboarding ViewPagers that follows Material Design Guidelines
7 |
8 | Try AirBnB Lottie
9 | We use Lottie Animations on our Intro to make it interactive & pleasant. Did you already tried it ? If no, let\'s start now. It\'s just awesome
10 |
11 | Code beautiful apps
12 | Our mission is to make useful & subtle apps. We love help people to save time with open-source stuffs, but we also make life easier by creating new things. Good Coding!
13 |
14 | By continuing on this application you agree to our Terms of Use and Privacy Policy
15 | Bu Ilova insonlarga qulaylik uchun yaratilgan !
16 | Siz ro`yxatdan o`tish orqali bizning maxfiylik siyosatimizga rozi bo`lasiz. biz sizning malumotlaringizn albatta ximoya qilamiz !
17 | Siz bizning ishonchli va xavfsiz transferlarimizdan foydalanishingiz mumkin.Obuna bo`ling va bizning sifatli xizmatimizdan foydalaning!
18 | Qulay dizayn.
19 |
20 | start
21 | Skip
22 | finish
23 | next
24 | back
25 | +998-##-###-##-##
26 | OTP kod yuborildi optni kiriting.
27 | O’zbekiston xalq yozuvchisi, bolalarning sevimli adibi Xudoyberdi To’xtaboyevning asalari nafaqat respublikamizda, balki chetellarda ham ma’lum va mashhurdir. Qo’lingizdagi “Sariq devni minib” sarguzasht romani bolalar hayotidan olib yozilgan bo’lib, ularning sevimli kitoblaridandir. Bu asarda orzu-havasga eltadigan chinakam yo’l halol mehnat, yaxshi xulq-odob va qunt bilan o’qishda ekanligi ta’kidlanadi.
28 |
29 | "Material is the metaphor.\n\n"
30 |
31 | "A material metaphor is the unifying theory of a rationalized space and a system of motion."
32 | "The material is grounded in tactile reality, inspired by the study of paper and ink, yet "
33 | "technologically advanced and open to imagination and magic.\n"
34 | "Surfaces and edges of the material provide visual cues that are grounded in reality. The "
35 | "use of familiar tactile attributes helps users quickly understand affordances. Yet the "
36 | "flexibility of the material creates new affordances that supercede those in the physical "
37 | "world, without breaking the rules of physics.\n"
38 | "The fundamentals of light, surface, and movement are key to conveying how objects move, "
39 | "interact, and exist in space and in relation to each other. Realistic lighting shows "
40 | "seams, divides space, and indicates moving parts.\n\n"
41 |
42 | "Bold, graphic, intentional.\n\n"
43 |
44 | "The foundational elements of print based design typography, grids, space, scale, color, "
45 | "and use of imagery guide visual treatments. These elements do far more than please the "
46 | "eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge "
47 | "imagery, large scale typography, and intentional white space create a bold and graphic "
48 | "interface that immerse the user in the experience.\n"
49 | "An emphasis on user actions makes core functionality immediately apparent and provides "
50 | "waypoints for the user.\n\n"
51 |
52 | "Motion provides meaning.\n\n"
53 |
54 | "Motion respects and reinforces the user as the prime mover. Primary user actions are "
55 | "inflection points that initiate motion, transforming the whole design.\n"
56 | "All action takes place in a single environment. Objects are presented to the user without "
57 | "breaking the continuity of experience even as they transform and reorganize.\n"
58 | "Motion is meaningful and appropriate, serving to focus attention and maintain continuity. "
59 | "Feedback is subtle yet clear. Transitions are efficient yet coherent.\n\n"
60 |
61 | "3D world.\n\n"
62 |
63 | "The material environment is a 3D space, which means all objects have x, y, and z "
64 | "dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the "
65 | "positive z-axis extending towards the viewer. Every sheet of material occupies a single "
66 | "position along the z-axis and has a standard 1dp thickness.\n"
67 | "On the web, the z-axis is used for layering and not for perspective. The 3D world is "
68 | "emulated by manipulating the y-axis.\n\n"
69 |
70 | "Light and shadow.\n\n"
71 |
72 | "Within the material environment, virtual lights illuminate the scene. Key lights create "
73 | "directional shadows, while ambient light creates soft shadows from all angles.\n"
74 | "Shadows in the material environment are cast by these two light sources. In Android "
75 | "development, shadows occur when light sources are blocked by sheets of material at "
76 | "various positions along the z-axis. On the web, shadows are depicted by manipulating the "
77 | "y-axis only. The following example shows the card with a height of 6dp.\n\n"
78 |
79 | "Resting elevation.\n\n"
80 |
81 | "All material objects, regardless of size, have a resting elevation, or default elevation "
82 | "that does not change. If an object changes elevation, it should return to its resting "
83 | "elevation as soon as possible.\n\n"
84 |
85 | "Component elevations.\n\n"
86 |
87 | "The resting elevation for a component type is consistent across apps (e.g., FAB elevation "
88 | "does not vary from 6dp in one app to 16dp in another app).\n"
89 | "Components may have different resting elevations across platforms, depending on the depth "
90 | "of the environment (e.g., TV has a greater depth than mobile or desktop).\n\n"
91 |
92 | "Responsive elevation and dynamic elevation offsets.\n\n"
93 |
94 | "Some component types have responsive elevation, meaning they change elevation in response "
95 | "to user input (e.g., normal, focused, and pressed) or system events. These elevation "
96 | "changes are consistently implemented using dynamic elevation offsets.\n"
97 | "Dynamic elevation offsets are the goal elevation that a component moves towards, relative "
98 | "to the component’s resting state. They ensure that elevation changes are consistent "
99 | "across actions and component types. For example, all components that lift on press have "
100 | "the same elevation change relative to their resting elevation.\n"
101 | "Once the input event is completed or cancelled, the component will return to its resting "
102 | "elevation.\n\n"
103 |
104 | "Avoiding elevation interference.\n\n"
105 |
106 | "Components with responsive elevations may encounter other components as they move between "
107 | "their resting elevations and dynamic elevation offsets. Because material cannot pass "
108 | "through other material, components avoid interfering with one another any number of ways, "
109 | "whether on a per component basis or using the entire app layout.\n"
110 | "On a component level, components can move or be removed before they cause interference. "
111 | "For example, a floating action button (FAB) can disappear or move off screen before a "
112 | "user picks up a card, or it can move if a snackbar appears.\n"
113 | "On the layout level, design your app layout to minimize opportunities for interference. "
114 | "For example, position the FAB to one side of stream of a cards so the FAB won’t interfere "
115 | "when a user tries to pick up one of cards.\n\n"
116 |
117 |
118 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
17 |
20 |
21 |
25 |
26 |
27 |
31 |
32 |
35 |
36 |
39 |
40 |
47 |
48 |
49 |
55 |
56 |
57 |
65 |
66 |
71 |
72 |
82 |
83 |
86 |
87 |
90 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/app/src/test/java/com/azamovhudstc/bookappwithcache/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.azamovhudstc.bookappwithcache
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | plugins {
3 | id 'com.android.application' version '7.2.2' apply false
4 | id 'com.android.library' version '7.2.2' apply false
5 | id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
6 | }
7 |
8 | task clean(type: Delete) {
9 | delete rootProject.buildDir
10 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Kotlin code style for this project: "official" or "obsolete":
19 | kotlin.code.style=official
20 | android.enableJetifier=true
21 | # Enables namespacing of each library's R class so that its R class includes only the
22 | # resources declared in the library itself and none from the library's dependencies,
23 | # thereby reducing the size of the R class for that library
24 | android.nonTransitiveRClass=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/professorDeveloper/BookAppWithCache-Clean-Architecture/ee7e2aa18c75111df4d613397680f8f6b97c7e8f/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 05 23:58:30 UZT 2022
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | google()
5 | mavenCentral()
6 | maven { url 'https://jitpack.io' }
7 |
8 | }
9 | }
10 | dependencyResolutionManagement {
11 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
12 | repositories {
13 | google()
14 | mavenCentral()
15 | maven { url 'https://jitpack.io' }
16 | }
17 | }
18 | rootProject.name = "BookAppWithCache"
19 | include ':app'
20 |
--------------------------------------------------------------------------------