├── .idea ├── .name ├── codeStyles │ ├── codeStyleConfig.xml │ └── Project.xml ├── vcs.xml ├── misc.xml ├── runConfigurations.xml └── gradle.xml ├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ └── styles.xml │ │ │ ├── drawable │ │ │ │ ├── ic_add.png │ │ │ │ ├── green_button.xml │ │ │ │ ├── background.xml │ │ │ │ └── ic_launcher_background.xml │ │ │ ├── drawable-hdpi │ │ │ │ ├── ic_add.png │ │ │ │ ├── ic_key.png │ │ │ │ ├── ic_close.png │ │ │ │ ├── ic_person.png │ │ │ │ ├── ic_phone.png │ │ │ │ ├── ic_save.png │ │ │ │ └── ic_person_white.png │ │ │ ├── drawable-mdpi │ │ │ │ ├── ic_add.png │ │ │ │ ├── ic_key.png │ │ │ │ ├── ic_close.png │ │ │ │ ├── ic_person.png │ │ │ │ ├── ic_phone.png │ │ │ │ ├── ic_save.png │ │ │ │ └── ic_person_white.png │ │ │ ├── drawable-xhdpi │ │ │ │ ├── ic_add.png │ │ │ │ ├── ic_close.png │ │ │ │ ├── ic_key.png │ │ │ │ ├── ic_phone.png │ │ │ │ ├── ic_save.png │ │ │ │ ├── ic_person.png │ │ │ │ └── ic_person_white.png │ │ │ ├── drawable-xxhdpi │ │ │ │ ├── ic_add.png │ │ │ │ ├── ic_key.png │ │ │ │ ├── ic_save.png │ │ │ │ ├── ic_close.png │ │ │ │ ├── ic_person.png │ │ │ │ ├── ic_phone.png │ │ │ │ └── ic_person_white.png │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── menu │ │ │ │ ├── main_activity_menu.xml │ │ │ │ └── create_contact_menu.xml │ │ │ ├── drawable-anydpi │ │ │ │ ├── ic_add.xml │ │ │ │ ├── ic_close.xml │ │ │ │ ├── ic_person.xml │ │ │ │ ├── ic_person_white.xml │ │ │ │ ├── ic_key.xml │ │ │ │ ├── ic_save.xml │ │ │ │ └── ic_phone.xml │ │ │ ├── layout │ │ │ │ ├── activity_main.xml │ │ │ │ ├── contact_menu.xml │ │ │ │ ├── activity_create_contact.xml │ │ │ │ ├── contact_layout.xml │ │ │ │ ├── edit_contact_form.xml │ │ │ │ └── activity_sign_in.xml │ │ │ └── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ ├── java │ │ │ └── app │ │ │ │ └── cansol │ │ │ │ └── phonebook │ │ │ │ ├── Model │ │ │ │ ├── Contact.kt │ │ │ │ └── User.kt │ │ │ │ ├── Interface │ │ │ │ └── ResultListener.kt │ │ │ │ ├── AppData │ │ │ │ ├── AppData.kt │ │ │ │ └── UserData.kt │ │ │ │ ├── Network │ │ │ │ └── Network.kt │ │ │ │ ├── ViewModel │ │ │ │ └── ContactViewModel.kt │ │ │ │ ├── RetrofitAPI │ │ │ │ └── PhoneBookApi.kt │ │ │ │ ├── Adapter │ │ │ │ └── ContactListAdapter.kt │ │ │ │ ├── Controllers │ │ │ │ ├── SignInActivity.kt │ │ │ │ ├── CreateContactActivity.kt │ │ │ │ └── MainActivity.kt │ │ │ │ └── Repository │ │ │ │ └── ContactRepository.kt │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── app │ │ │ └── cansol │ │ │ └── phonebook │ │ │ └── ExampleUnitTest.kt │ └── androidTest │ │ └── java │ │ └── app │ │ └── cansol │ │ └── phonebook │ │ └── ExampleInstrumentedTest.kt ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── Image.jpg ├── images ├── edit.jpg ├── main.jpg ├── menu.jpg ├── create.jpg └── signin.png ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── gradle.properties ├── README.md ├── gradlew.bat └── gradlew /.idea/.name: -------------------------------------------------------------------------------- 1 | Phone Book -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | rootProject.name='Phone Book' 3 | -------------------------------------------------------------------------------- /Image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/Image.jpg -------------------------------------------------------------------------------- /images/edit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/images/edit.jpg -------------------------------------------------------------------------------- /images/main.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/images/main.jpg -------------------------------------------------------------------------------- /images/menu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/images/menu.jpg -------------------------------------------------------------------------------- /images/create.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/images/create.jpg -------------------------------------------------------------------------------- /images/signin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/images/signin.png -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Phone Book 3 | 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable/ic_add.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-hdpi/ic_add.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-hdpi/ic_key.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-mdpi/ic_add.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-mdpi/ic_key.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-hdpi/ic_close.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_person.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-hdpi/ic_person.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-hdpi/ic_phone.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-hdpi/ic_save.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-mdpi/ic_close.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_person.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-mdpi/ic_person.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-mdpi/ic_phone.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-mdpi/ic_save.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-xhdpi/ic_add.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-xhdpi/ic_close.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-xhdpi/ic_key.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-xhdpi/ic_phone.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-xhdpi/ic_save.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-xxhdpi/ic_add.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-xxhdpi/ic_key.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-xxhdpi/ic_save.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_person.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-xhdpi/ic_person.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-xxhdpi/ic_close.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_person.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-xxhdpi/ic_person.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-xxhdpi/ic_phone.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_person_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-hdpi/ic_person_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_person_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-mdpi/ic_person_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_person_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-xhdpi/ic_person_white.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_person_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/drawable-xxhdpi/ic_person_white.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedasad/Phonebook/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #036BC7 4 | #A41A0AEB 5 | #1B96D8 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/java/app/cansol/phonebook/Model/Contact.kt: -------------------------------------------------------------------------------- 1 | package app.cansol.phonebook.Model 2 | 3 | /** 4 | * contact Model**/ 5 | data class Contact(val id:String?,val user_id:String,val contact_name:String, val contact_number:String) { 6 | constructor():this("","","","") 7 | } -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /app/src/main/java/app/cansol/phonebook/Interface/ResultListener.kt: -------------------------------------------------------------------------------- 1 | package app.cansol.phonebook.Interface 2 | 3 | /** 4 | * Interface used proived result on specific occasion**/ 5 | interface ResultListener { 6 | fun onSuccess(message:String) 7 | fun onFailure(message: String) 8 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Feb 11 12:41:15 PKT 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 7 | -------------------------------------------------------------------------------- /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/menu/main_activity_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/green_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/menu/create_contact_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_add.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/java/app/cansol/phonebook/Model/User.kt: -------------------------------------------------------------------------------- 1 | package app.cansol.phonebook.Model 2 | 3 | import com.google.gson.annotations.SerializedName 4 | 5 | /** 6 | * user Model 7 | **/ 8 | class User( 9 | val id: String, @SerializedName("name") val userName: String, 10 | val email: String, @SerializedName("phone_number") val phoneNumber: String, 11 | val password:String 12 | ) { 13 | constructor():this("","","","","") 14 | } -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/app/cansol/phonebook/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package app.cansol.phonebook 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 | } 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_close.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_person.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_person_white.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_key.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_save.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/java/app/cansol/phonebook/AppData/AppData.kt: -------------------------------------------------------------------------------- 1 | package app.cansol.phonebook.AppData 2 | 3 | import android.content.Context 4 | 5 | 6 | /** 7 | SharedPreference class this basically holds data of user to keep him signIn 8 | and data will also use as credential for web services 9 | **/ 10 | class AppData(val context: Context) { 11 | private val PREFS_FILE = "pref" 12 | val pref = context.getSharedPreferences(PREFS_FILE,0) 13 | 14 | private val id = "userId" 15 | 16 | var userId:String? 17 | get() = pref.getString(id,"") 18 | set(value) = pref.edit().putString(id,value).apply() 19 | 20 | 21 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_phone.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/androidTest/java/app/cansol/phonebook/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package app.cansol.phonebook 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("app.cansol.phonebook", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /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 22 | -------------------------------------------------------------------------------- /app/src/main/java/app/cansol/phonebook/Network/Network.kt: -------------------------------------------------------------------------------- 1 | package app.cansol.phonebook.Network 2 | 3 | import android.content.Context 4 | import android.net.ConnectivityManager 5 | import android.net.NetworkInfo 6 | import androidx.core.content.ContextCompat 7 | import java.lang.NullPointerException 8 | 9 | 10 | /** 11 | * This will check if device hase network connection or not**/ 12 | object Network { 13 | fun checkNetwork(context: Context):Boolean { 14 | try { 15 | val manager = ContextCompat.getSystemService(context, ConnectivityManager::class.java) 16 | var networkInfo: NetworkInfo? = null 17 | if(manager != null){ 18 | networkInfo = manager.activeNetworkInfo 19 | } 20 | return networkInfo != null && networkInfo.isConnected 21 | 22 | }catch (e: NullPointerException){ 23 | return false 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /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=-Xmx1536m 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 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | -------------------------------------------------------------------------------- /app/src/main/java/app/cansol/phonebook/ViewModel/ContactViewModel.kt: -------------------------------------------------------------------------------- 1 | package app.cansol.phonebook.ViewModel 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.lifecycle.ViewModel 5 | import app.cansol.phonebook.Model.Contact 6 | import app.cansol.phonebook.Repository.ContactRepository 7 | 8 | /** 9 | * ViewModel class one of the component of MVVM 10 | * it communicate with repository 11 | * and also provide necessary data UI to display accordingly 12 | **/ 13 | class ContactViewModel(id:String): ViewModel() { 14 | private var repository:ContactRepository = ContactRepository() 15 | private var allContact:LiveData> 16 | 17 | fun list():LiveData>{ 18 | return allContact 19 | } 20 | 21 | init{ 22 | repository = ContactRepository() 23 | allContact = repository.getAllContacts(id) 24 | 25 | } 26 | 27 | fun createContact(contact:Contact,userId:String){ 28 | allContact = repository.createContact(contact,userId) 29 | 30 | } 31 | 32 | fun updateContact(contact:Contact,userId:String){ 33 | allContact = repository.updateContact(contact,userId) 34 | 35 | } 36 | 37 | fun deleteContact(contact:Contact,userId:String){ 38 | allContact = repository.deleteCont(userId,contact) 39 | 40 | } 41 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 15 | 17 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/java/app/cansol/phonebook/AppData/UserData.kt: -------------------------------------------------------------------------------- 1 | package app.cansol.phonebook.AppData 2 | 3 | import app.cansol.phonebook.Interface.ResultListener 4 | import app.cansol.phonebook.Model.User 5 | 6 | /** 7 | * it contains dummy users 8 | * findUser() performs search against provided credentials 9 | **/ 10 | object UserData { 11 | 12 | val users: ArrayList = ArrayList() 13 | 14 | var currentUser: User? = null 15 | fun initUsers() { 16 | users.add(User("1", "John", "John@gmail.com", "03482524444", "thisisJohn")) 17 | users.add(User("2", "Mike", "mike@gmail.com", "03482521111", "thisisMike")) 18 | users.add(User("3", "alex", "alex@gmail.com", "03482523333", "thisisAlex")) 19 | } 20 | 21 | fun findUser(phoneNumber: String, password: String, listener: ResultListener){ 22 | 23 | for (user in users) { 24 | if (user.phoneNumber == phoneNumber) { 25 | if (user.password == password) { 26 | currentUser = user 27 | listener.onSuccess("Success") 28 | return 29 | } else { 30 | listener.onFailure("Number/Password is wrong!") 31 | return 32 | } 33 | } 34 | } 35 | listener.onFailure("Account doesn't exist!") 36 | } 37 | 38 | 39 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 19 | 20 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/java/app/cansol/phonebook/RetrofitAPI/PhoneBookApi.kt: -------------------------------------------------------------------------------- 1 | package app.cansol.phonebook.RetrofitAPI 2 | 3 | import app.cansol.phonebook.Model.Contact 4 | import app.cansol.phonebook.Model.User 5 | import retrofit2.Call 6 | import retrofit2.Retrofit 7 | import retrofit2.converter.gson.GsonConverterFactory 8 | import retrofit2.http.* 9 | 10 | /** 11 | * Retrofit contract that contains the operation details 12 | * **/ 13 | interface PhoneBookApi { 14 | 15 | @GET("users") 16 | fun getUser():Call> 17 | 18 | @GET("users/{id}/contacts") 19 | fun getContacts(@Path("id") id: String): Call> 20 | 21 | @POST("users/{id}/contacts") 22 | fun createContact(@Body contact: Contact, @Path("id") userId: String):Call 23 | 24 | @PUT("users/{id}/contacts/{contact_id}") 25 | fun updateContact( 26 | @Body contact: Contact, 27 | @Path("id") userId: String, 28 | @Path("contact_id") contactId: String 29 | ): Call 30 | 31 | @DELETE("users/{id}/contacts/{contact_id}") 32 | fun deleteContact( 33 | @Path("id") userId: String, 34 | @Path("contact_id") contactId: String 35 | ): Call 36 | 37 | 38 | companion object { 39 | operator fun invoke(): PhoneBookApi { 40 | return Retrofit.Builder() 41 | .baseUrl("https://5e425f20f6128600148ad36c.mockapi.io/pb/") 42 | .addConverterFactory(GsonConverterFactory.create()) 43 | .build() 44 | .create(PhoneBookApi::class.java) 45 | } 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /app/src/main/java/app/cansol/phonebook/Adapter/ContactListAdapter.kt: -------------------------------------------------------------------------------- 1 | package app.cansol.phonebook.Adapter 2 | 3 | import android.content.Context 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import android.widget.TextView 8 | import androidx.recyclerview.widget.RecyclerView 9 | import app.cansol.phonebook.Model.Contact 10 | import app.cansol.phonebook.R 11 | 12 | /** 13 | Contact Adapter using Recycler View 14 | **/ 15 | 16 | class ContactListAdapter(val context: Context,val contacts:List): RecyclerView.Adapter() { 17 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder { 18 | val view = LayoutInflater.from(context).inflate(R.layout.contact_layout,parent,false) 19 | return Holder(view) 20 | } 21 | 22 | override fun getItemCount(): Int { 23 | return contacts.count() 24 | } 25 | 26 | override fun onBindViewHolder(holder: Holder, position: Int) { 27 | holder.bindView(context,contacts[position]) 28 | } 29 | 30 | inner class Holder(itemView: View):RecyclerView.ViewHolder(itemView){ 31 | fun bindView(context: Context,contact: Contact){ 32 | val contactName = itemView.findViewById(R.id.txtContactName) 33 | val contactNumber = itemView.findViewById(R.id.txtContactNumber) 34 | 35 | 36 | contactName.text = contact.contact_name 37 | contactNumber.text = contact.contact_number 38 | } 39 | } 40 | 41 | /** 42 | the function is used to return the contact on certain index/position 43 | **/ 44 | fun getContactAt(position: Int):Contact{ 45 | return contacts.get(position) 46 | } 47 | 48 | 49 | } -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | apply plugin: 'kotlin-android-extensions' 6 | 7 | apply plugin: 'kotlin-kapt' 8 | 9 | android { 10 | compileSdkVersion 29 11 | buildToolsVersion "29.0.1" 12 | defaultConfig { 13 | applicationId "app.cansol.phonebook" 14 | minSdkVersion 24 15 | targetSdkVersion 29 16 | versionCode 1 17 | versionName "1.0" 18 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 19 | } 20 | buildTypes { 21 | release { 22 | minifyEnabled false 23 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 24 | } 25 | } 26 | } 27 | 28 | dependencies { 29 | implementation fileTree(dir: 'libs', include: ['*.jar']) 30 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 31 | implementation 'androidx.appcompat:appcompat:1.1.0' 32 | implementation 'androidx.core:core-ktx:1.2.0' 33 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 34 | testImplementation 'junit:junit:4.12' 35 | androidTestImplementation 'androidx.test:runner:1.2.0' 36 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 37 | 38 | implementation 'com.squareup.retrofit2:converter-gson:2.4.0' 39 | implementation 'com.squareup.retrofit2:retrofit:2.4.0' 40 | implementation 'com.google.android.material:material:1.1.0' 41 | 42 | 43 | def lifecycle_version = "2.2.0" 44 | implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" 45 | implementation "android.arch.lifecycle:extensions:$lifecycle_version" 46 | implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" 47 | kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version" 48 | } 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Phonebook 2 | The personalize phone directory to help person maintain contacts info. 3 | The contacts are arranged in ALPHABETIC order 4 | 5 |

Highlights

6 |

7 | Application developed with Kotlin.
8 | The application has been built to demonstrate implementation of MVVM architecture with web services using Retrofit.
9 | It has been designed using Android Architecture components.
10 | The application is built in such a way that whenever there is a remote service call, the result will be observed. 11 |

12 | 13 |

Architecture

14 |

The whole application is built based on the MVVM architectural pattern.
15 | The main advantage of using MVVM, there is no two way dependency between ViewModel and Model unlike MVP. Here the view can observe the data changes in the viewmodel as we are using LiveData which is lifecycle aware. The viewmodel to view communication is achieved through Observer Pattern (basically observing the state changes of the data in the viewmodel). 16 |

17 | 18 | 19 |

App Review

20 |
    21 |
  • user can login in into his account
  • 22 |
  • User will stay login until user logout from account himself
  • 23 |
  • Application will keep checking for internet connection to avoid any crash during operations
  • 24 |
  • user can view all the contacts
  • 25 |
  • User can create new contact
  • 26 |
  • User can delete existing account
  • 27 |
  • User can perform these operations by swapping item to the left side
  • 28 |
  • User can edit contact information
  • 29 |
30 | 31 | 32 |

Images

33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/app/cansol/phonebook/Controllers/SignInActivity.kt: -------------------------------------------------------------------------------- 1 | package app.cansol.phonebook.Controllers 2 | 3 | import android.content.Intent 4 | import androidx.appcompat.app.AppCompatActivity 5 | import android.os.Bundle 6 | import android.view.View 7 | import android.widget.EditText 8 | import android.widget.Toast 9 | import app.cansol.phonebook.AppData.UserData 10 | import app.cansol.phonebook.Interface.ResultListener 11 | import app.cansol.phonebook.Network.Network 12 | import app.cansol.phonebook.R 13 | 14 | class SignInActivity : AppCompatActivity(), ResultListener { 15 | 16 | /** 17 | initialize hardcoded users in oncreate method**/ 18 | override fun onCreate(savedInstanceState: Bundle?) { 19 | super.onCreate(savedInstanceState) 20 | setContentView(R.layout.activity_sign_in) 21 | 22 | UserData.initUsers() 23 | } 24 | 25 | /** 26 | it simply call the method from for searching user against provided credentials 27 | **/ 28 | fun signIn(view: View) { 29 | val number = findViewById(R.id.edTxtSignInPhoneNumber).text 30 | val password = findViewById(R.id.edTxtSignInPassword).text 31 | 32 | if (number.trim().isNotEmpty() && password.isNotEmpty()) { 33 | if (Network.checkNetwork(this)) { 34 | UserData.findUser(number.toString(), password.toString(), this) 35 | } else Toast.makeText(this, "Check network connection", Toast.LENGTH_SHORT).show() 36 | } else Toast.makeText(this, "Field(s) is empty!", Toast.LENGTH_SHORT).show() 37 | 38 | } 39 | 40 | /** 41 | following both are Interface method implementation 42 | **/ 43 | override fun onSuccess(message: String) { 44 | app.cansol.phonebook.AppData.AppData(this).userId = UserData.currentUser!!.id 45 | val intent = Intent(this, MainActivity::class.java) 46 | intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK 47 | startActivity(intent) 48 | finish() 49 | } 50 | 51 | override fun onFailure(message: String) { 52 | Toast.makeText(this, message, Toast.LENGTH_SHORT).show() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/res/layout/contact_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 23 | 24 | 38 | 39 | 52 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /app/src/main/java/app/cansol/phonebook/Controllers/CreateContactActivity.kt: -------------------------------------------------------------------------------- 1 | package app.cansol.phonebook.Controllers 2 | 3 | import android.app.Activity 4 | import android.content.Intent 5 | import androidx.appcompat.app.AppCompatActivity 6 | import android.os.Bundle 7 | import android.view.Menu 8 | import android.view.MenuItem 9 | import android.widget.EditText 10 | import android.widget.Toast 11 | import app.cansol.phonebook.Network.Network 12 | import app.cansol.phonebook.R 13 | 14 | class CreateContactActivity : AppCompatActivity() { 15 | 16 | /** 17 | two fields for contact creation 18 | **/ 19 | lateinit var name:EditText 20 | lateinit var number:EditText 21 | 22 | override fun onCreate(savedInstanceState: Bundle?) { 23 | super.onCreate(savedInstanceState) 24 | setContentView(R.layout.activity_create_contact) 25 | 26 | 27 | supportActionBar!!.setHomeAsUpIndicator(R.drawable.ic_close) 28 | setTitle("Create Contact") 29 | 30 | name = findViewById(R.id.edittextName) 31 | number = findViewById(R.id.edittxtPhoneNum) 32 | 33 | } 34 | 35 | override fun onCreateOptionsMenu(menu: Menu?): Boolean { 36 | val menuInflater = getMenuInflater() 37 | menuInflater.inflate(R.menu.create_contact_menu, menu) 38 | return super.onCreateOptionsMenu(menu) 39 | 40 | } 41 | 42 | override fun onOptionsItemSelected(item: MenuItem): Boolean { 43 | 44 | when (item.itemId) { 45 | R.id.save_contact -> { 46 | 47 | if (Network.checkNetwork(this)) { 48 | saveContact() 49 | return true 50 | } 51 | else{ 52 | Toast.makeText(this, "Check network connection", Toast.LENGTH_SHORT).show() 53 | return false 54 | } 55 | 56 | } 57 | else -> { 58 | if (name.text.isNotEmpty() && number.text.trim().isNotEmpty()) { 59 | Toast.makeText(this,"Contact didn't save",Toast.LENGTH_SHORT).show() 60 | } 61 | return super.onOptionsItemSelected(item) 62 | } 63 | } 64 | } 65 | 66 | /** 67 | takes data from edittext fields and send them through intent using putExtra function**/ 68 | private fun saveContact() { 69 | if (name.text.isNotEmpty() && number.text.trim().isNotEmpty()) { 70 | val data = Intent() 71 | data.putExtra("EXTRA_NAME", "${name.text}") 72 | data.putExtra("EXTRA_NUMBER", "${number.text}") 73 | setResult(Activity.RESULT_OK, data) 74 | finish() 75 | } else { 76 | Toast.makeText(this, "Provide Complete Data", Toast.LENGTH_SHORT).show() 77 | } 78 | 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_create_contact.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 27 | 28 | 44 | 45 | 60 | 61 | -------------------------------------------------------------------------------- /app/src/main/res/layout/contact_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 22 | 23 | 27 | 28 | 45 | 46 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /app/src/main/res/layout/edit_contact_form.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 22 | 23 | 34 | 35 | 49 | 50 | 61 | 62 | 73 | -------------------------------------------------------------------------------- /app/src/main/java/app/cansol/phonebook/Repository/ContactRepository.kt: -------------------------------------------------------------------------------- 1 | package app.cansol.phonebook.Repository 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import androidx.core.content.ContextCompat 5 | import androidx.lifecycle.LiveData 6 | import androidx.lifecycle.MutableLiveData 7 | import app.cansol.phonebook.Model.Contact 8 | import app.cansol.phonebook.RetrofitAPI.PhoneBookApi 9 | import retrofit2.Call 10 | import retrofit2.Callback 11 | import retrofit2.Response 12 | 13 | 14 | /** 15 | * Repository class one of the component of MVVM 16 | * it will communicate with web services for crud operations 17 | * **/ 18 | class ContactRepository { 19 | 20 | private val responseContact = MutableLiveData>() 21 | private val contactList = ArrayList() 22 | 23 | fun getAllContacts(id:String):LiveData>{ 24 | PhoneBookApi().getContacts(id).enqueue(object:Callback>{ 25 | override fun onFailure(call: Call>, t: Throwable) {} 26 | 27 | override fun onResponse(call: Call>, response: Response>) { 28 | if(!response.isSuccessful) return 29 | contactList.removeAll(contactList) 30 | contactList.addAll(response.body()!!) 31 | responseContact.value = contactList.sortedWith(compareBy({it.contact_name})) 32 | 33 | } 34 | }) 35 | return responseContact 36 | } 37 | 38 | fun createContact(contact:Contact,userId:String):LiveData>{ 39 | PhoneBookApi() 40 | .createContact(contact,userId).enqueue(object : Callback{ 41 | override fun onFailure(call: Call, t: Throwable) {} 42 | 43 | override fun onResponse(call: Call, response: Response) { 44 | if(!response.isSuccessful) { 45 | println("didnt done...") 46 | return 47 | } 48 | contactList.add(response.body()!!) 49 | responseContact.value = contactList.sortedWith(compareBy({it.contact_name})) 50 | println("done....") 51 | } 52 | 53 | }) 54 | return responseContact 55 | } 56 | 57 | fun updateContact(contact:Contact,userId:String):LiveData>{ 58 | PhoneBookApi() 59 | .updateContact(contact,userId,contact.id!!).enqueue(object: Callback{ 60 | override fun onFailure(call: Call, t: Throwable) {} 61 | 62 | override fun onResponse(call: Call, response: Response) { 63 | if(!response.isSuccessful) return 64 | contactList.removeIf{ 65 | it.id == contact.id 66 | } 67 | contactList.add(response.body()!!) 68 | responseContact.value = contactList.sortedWith(compareBy({it.contact_name})) 69 | } 70 | }) 71 | return responseContact 72 | } 73 | 74 | fun deleteCont(userId:String,contact:Contact):LiveData>{ 75 | PhoneBookApi() 76 | .deleteContact(userId,contact.id!!).enqueue(object: Callback{ 77 | override fun onFailure(call: Call, t: Throwable) {} 78 | 79 | override fun onResponse(call: Call, response: Response) { 80 | if(!response.isSuccessful) return 81 | contactList.removeIf { 82 | it.id == contact.id 83 | } 84 | responseContact.value = contactList.sortedWith(compareBy({it.contact_name})) 85 | 86 | } 87 | }) 88 | return responseContact 89 | } 90 | 91 | 92 | } -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | xmlns:android 17 | 18 | ^$ 19 | 20 | 21 | 22 |
23 |
24 | 25 | 26 | 27 | xmlns:.* 28 | 29 | ^$ 30 | 31 | 32 | BY_NAME 33 | 34 |
35 |
36 | 37 | 38 | 39 | .*:id 40 | 41 | http://schemas.android.com/apk/res/android 42 | 43 | 44 | 45 |
46 |
47 | 48 | 49 | 50 | .*:name 51 | 52 | http://schemas.android.com/apk/res/android 53 | 54 | 55 | 56 |
57 |
58 | 59 | 60 | 61 | name 62 | 63 | ^$ 64 | 65 | 66 | 67 |
68 |
69 | 70 | 71 | 72 | style 73 | 74 | ^$ 75 | 76 | 77 | 78 |
79 |
80 | 81 | 82 | 83 | .* 84 | 85 | ^$ 86 | 87 | 88 | BY_NAME 89 | 90 |
91 |
92 | 93 | 94 | 95 | .* 96 | 97 | http://schemas.android.com/apk/res/android 98 | 99 | 100 | ANDROID_ATTRIBUTE_ORDER 101 | 102 |
103 |
104 | 105 | 106 | 107 | .* 108 | 109 | .* 110 | 111 | 112 | BY_NAME 113 | 114 |
115 |
116 |
117 |
118 | 119 | 121 |
122 |
-------------------------------------------------------------------------------- /app/src/main/res/layout/activity_sign_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 21 | 22 | 40 | 41 | 57 | 58 |