├── .gitignore ├── .idea ├── .name ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── dictionaries │ └── SHaZ.xml ├── gradle.xml ├── jarRepositories.xml ├── misc.xml ├── render.experimental.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── release │ └── app-release.aab └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── decimalab │ │ └── easytask │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-playstore.png │ ├── java │ │ └── com │ │ │ └── decimalab │ │ │ └── easytask │ │ │ ├── BaseApplication.kt │ │ │ ├── model │ │ │ ├── local │ │ │ │ ├── AppPreferences.kt │ │ │ │ ├── dao │ │ │ │ │ └── TaskDao.kt │ │ │ │ ├── db │ │ │ │ │ └── AppDatabase.kt │ │ │ │ └── entity │ │ │ │ │ └── TaskEntity.kt │ │ │ ├── remote │ │ │ │ ├── EndPoints.kt │ │ │ │ ├── NetworkService.kt │ │ │ │ ├── Networking.kt │ │ │ │ ├── request │ │ │ │ │ ├── auth │ │ │ │ │ │ ├── LoginRequest.kt │ │ │ │ │ │ └── RegisterRequest.kt │ │ │ │ │ └── task │ │ │ │ │ │ ├── AddTaskRequest.kt │ │ │ │ │ │ ├── DeleteTaskRequest.kt │ │ │ │ │ │ └── EditTaskRequest.kt │ │ │ │ └── response │ │ │ │ │ ├── auth │ │ │ │ │ ├── LoginResponse.kt │ │ │ │ │ ├── RegisterResponse.kt │ │ │ │ │ └── ValidateResponse.kt │ │ │ │ │ ├── profile │ │ │ │ │ ├── EditProfileResponse.kt │ │ │ │ │ └── UserProfileResponse.kt │ │ │ │ │ └── task │ │ │ │ │ ├── AddTaskResponse.kt │ │ │ │ │ ├── EditTaskResponse.kt │ │ │ │ │ └── TaskResponse.kt │ │ │ └── repository │ │ │ │ ├── AddTaskRepository.kt │ │ │ │ ├── DeleteTaskRepository.kt │ │ │ │ ├── EditTaskRepository.kt │ │ │ │ ├── LoginRepository.kt │ │ │ │ ├── RegisterRepository.kt │ │ │ │ ├── TaskRepository.kt │ │ │ │ ├── UserProfileRepository.kt │ │ │ │ └── ValidateTokenRepository.kt │ │ │ ├── util │ │ │ ├── AppThemeMode.kt │ │ │ ├── GeneralHelper.kt │ │ │ ├── Validator.kt │ │ │ └── network │ │ │ │ ├── NetworkError.kt │ │ │ │ └── NetworkHelper.kt │ │ │ ├── view │ │ │ ├── adaptor │ │ │ │ ├── TaskAdapter.kt │ │ │ │ └── TaskCallBack.kt │ │ │ └── ui │ │ │ │ ├── auth │ │ │ │ ├── LoginActivity.kt │ │ │ │ └── SignUpActivity.kt │ │ │ │ ├── darkmode │ │ │ │ └── DarkModeFragment.kt │ │ │ │ ├── home │ │ │ │ └── HomeFragment.kt │ │ │ │ ├── main │ │ │ │ └── MainActivity.kt │ │ │ │ ├── profile │ │ │ │ ├── ProfileFragment.kt │ │ │ │ └── edit │ │ │ │ │ └── EditProfileFragment.kt │ │ │ │ ├── splash │ │ │ │ └── SplashActivity.kt │ │ │ │ └── task │ │ │ │ ├── TaskFragment.kt │ │ │ │ ├── detail │ │ │ │ └── TaskDetailFragment.kt │ │ │ │ └── edit │ │ │ │ └── EditTaskFragment.kt │ │ │ └── viewmodel │ │ │ ├── auth │ │ │ ├── LoginViewModel.kt │ │ │ └── SignUpViewModel.kt │ │ │ ├── edit │ │ │ └── EditProfileViewModel.kt │ │ │ ├── home │ │ │ └── HomeViewModel.kt │ │ │ ├── profile │ │ │ └── ProfileViewModel.kt │ │ │ ├── splash │ │ │ └── SplashViewModel.kt │ │ │ └── task │ │ │ ├── EditTaskViewModel.kt │ │ │ ├── TaskDetailViewModel.kt │ │ │ └── TaskViewModel.kt │ └── res │ │ ├── drawable-anydpi │ │ ├── ic_add.xml │ │ ├── ic_add_task.xml │ │ ├── ic_assignment.xml │ │ ├── ic_camera.xml │ │ ├── ic_confirm.xml │ │ ├── ic_delete.xml │ │ ├── ic_edit.xml │ │ ├── ic_heart.xml │ │ ├── ic_home.xml │ │ ├── ic_people.xml │ │ ├── ic_profile.xml │ │ └── ic_save.xml │ │ ├── drawable-hdpi │ │ ├── ic_add.png │ │ ├── ic_add_task.png │ │ ├── ic_assignment.png │ │ ├── ic_camera.png │ │ ├── ic_confirm.png │ │ ├── ic_delete.png │ │ ├── ic_edit.png │ │ ├── ic_heart.png │ │ ├── ic_home.png │ │ ├── ic_people.png │ │ ├── ic_profile.png │ │ └── ic_save.png │ │ ├── drawable-mdpi │ │ ├── ic_add.png │ │ ├── ic_add_task.png │ │ ├── ic_assignment.png │ │ ├── ic_camera.png │ │ ├── ic_confirm.png │ │ ├── ic_delete.png │ │ ├── ic_edit.png │ │ ├── ic_heart.png │ │ ├── ic_home.png │ │ ├── ic_people.png │ │ ├── ic_profile.png │ │ └── ic_save.png │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable-xhdpi │ │ ├── ic_add.png │ │ ├── ic_add_task.png │ │ ├── ic_assignment.png │ │ ├── ic_camera.png │ │ ├── ic_confirm.png │ │ ├── ic_delete.png │ │ ├── ic_edit.png │ │ ├── ic_heart.png │ │ ├── ic_home.png │ │ ├── ic_people.png │ │ ├── ic_profile.png │ │ └── ic_save.png │ │ ├── drawable-xxhdpi │ │ ├── ic_add.png │ │ ├── ic_add_task.png │ │ ├── ic_assignment.png │ │ ├── ic_camera.png │ │ ├── ic_confirm.png │ │ ├── ic_delete.png │ │ ├── ic_edit.png │ │ ├── ic_heart.png │ │ ├── ic_home.png │ │ ├── ic_people.png │ │ ├── ic_profile.png │ │ └── ic_save.png │ │ ├── drawable │ │ ├── fishing_splash.gif │ │ ├── ic_launcher_background.xml │ │ ├── login_user_avatar.gif │ │ ├── signup_user_avatar.gif │ │ ├── tab_color.xml │ │ └── tab_color_text.xml │ │ ├── font │ │ ├── font_family.xml │ │ ├── roboto_bold.ttf │ │ ├── roboto_medium.ttf │ │ └── roboto_regular.ttf │ │ ├── layout-night │ │ ├── activity_main.xml │ │ └── tool_bar.xml │ │ ├── layout │ │ ├── activity_login.xml │ │ ├── activity_main.xml │ │ ├── activity_sign_up.xml │ │ ├── activity_splash.xml │ │ ├── custom_task_list_view.xml │ │ ├── dark_mode_fragment.xml │ │ ├── edit_profile_fragment.xml │ │ ├── edit_task_fragment.xml │ │ ├── home_fragment.xml │ │ ├── profile_fragment.xml │ │ ├── task_detail_fragment.xml │ │ ├── task_fragment.xml │ │ └── tool_bar.xml │ │ ├── menu │ │ ├── bottom_navigation.xml │ │ ├── mode_menu.xml │ │ └── profile_edit_menu.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── navigation │ │ └── navigation_base.xml │ │ ├── raw │ │ └── note_anim.json │ │ ├── values-night │ │ └── styles.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ └── network_security_config.xml │ └── test │ └── java │ └── com │ └── decimalab │ └── easytask │ ├── ExampleUnitTest.kt │ └── util │ └── ValidatorTest.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 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | EasyTask -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 20 | 22 | 23 | 24 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | xmlns:android 33 | 34 | ^$ 35 | 36 | 37 | 38 |
39 |
40 | 41 | 42 | 43 | xmlns:.* 44 | 45 | ^$ 46 | 47 | 48 | BY_NAME 49 | 50 |
51 |
52 | 53 | 54 | 55 | .*:id 56 | 57 | http://schemas.android.com/apk/res/android 58 | 59 | 60 | 61 |
62 |
63 | 64 | 65 | 66 | .*:name 67 | 68 | http://schemas.android.com/apk/res/android 69 | 70 | 71 | 72 |
73 |
74 | 75 | 76 | 77 | name 78 | 79 | ^$ 80 | 81 | 82 | 83 |
84 |
85 | 86 | 87 | 88 | style 89 | 90 | ^$ 91 | 92 | 93 | 94 |
95 |
96 | 97 | 98 | 99 | .* 100 | 101 | ^$ 102 | 103 | 104 | BY_NAME 105 | 106 |
107 |
108 | 109 | 110 | 111 | .* 112 | 113 | http://schemas.android.com/apk/res/android 114 | 115 | 116 | ANDROID_ATTRIBUTE_ORDER 117 | 118 |
119 |
120 | 121 | 122 | 123 | .* 124 | 125 | .* 126 | 127 | 128 | BY_NAME 129 | 130 |
131 |
132 |
133 |
134 | 135 | 137 |
138 |
-------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/dictionaries/SHaZ.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | shaj 5 | shajt 6 | shakil 7 | todomvvm 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/render.experimental.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /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 | apply plugin: "androidx.navigation.safeargs" 10 | 11 | android { 12 | dataBinding { 13 | enabled = true 14 | } 15 | compileSdkVersion 30 16 | buildToolsVersion "29.0.3" 17 | defaultConfig { 18 | applicationId "com.decimalab.easytask" 19 | minSdkVersion 21 20 | targetSdkVersion 30 21 | versionCode 2 22 | versionName "1.1" 23 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 24 | 25 | kapt { 26 | arguments { 27 | arg("room.schemaLocation", "$projectDir/schemas") 28 | } 29 | } 30 | } 31 | buildTypes { 32 | debug { 33 | minifyEnabled false 34 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 35 | buildConfigField("String", "BASE_URL", "\"https://apis.decimalab.com/task/\"") 36 | buildConfigField("String", "PREF_NAME", "\"com.shajt3ch.todomvvm.pref\"") 37 | } 38 | release { 39 | minifyEnabled false 40 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 41 | buildConfigField("String", "BASE_URL", "\"https://apis.decimalab.com/task/\"") 42 | buildConfigField("String", "PREF_NAME", "\"com.shajt3ch.todomvvm.pref\"") 43 | } 44 | } 45 | 46 | //https://developer.android.com/studio/write/java8-support 47 | compileOptions { 48 | sourceCompatibility JavaVersion.VERSION_1_8 49 | targetCompatibility JavaVersion.VERSION_1_8 50 | } 51 | // For Kotlin projects 52 | kotlinOptions { 53 | jvmTarget = JavaVersion.VERSION_1_8.toString() 54 | //jvmTarget = '1.8' 55 | } 56 | } 57 | 58 | dependencies { 59 | implementation fileTree(dir: 'libs', include: ['*.jar']) 60 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 61 | implementation 'androidx.appcompat:appcompat:1.2.0' 62 | implementation 'androidx.core:core-ktx:1.3.1' 63 | implementation 'androidx.cardview:cardview:1.0.0' 64 | implementation 'androidx.constraintlayout:constraintlayout:2.0.0' 65 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 66 | implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' 67 | implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' 68 | testImplementation 'junit:junit:4.13' 69 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 70 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 71 | 72 | // https://github.com/material-components/material-components-android 73 | implementation "com.google.android.material:material:$support_library_version" 74 | 75 | //https://github.com/koral--/android-gif-drawable 76 | implementation "pl.droidsonroids.gif:android-gif-drawable:$gif_drawable" 77 | 78 | //https://github.com/Kotlin/anko 79 | implementation "org.jetbrains.anko:anko:$anko_version" 80 | 81 | //https://github.com/Kotlin/kotlinx.coroutines 82 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinx_coroutines" 83 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinx_coroutines" 84 | 85 | //https://square.github.io/retrofit/ 86 | implementation "com.squareup.retrofit2:retrofit:$retrofit_version" 87 | implementation "com.squareup.retrofit2:converter-gson:$retrofit_version" 88 | 89 | // ViewModel https://developer.android.com/jetpack/androidx/releases/lifecycle 90 | implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" 91 | // LiveData https://developer.android.com/jetpack/androidx/releases/lifecycle 92 | implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" 93 | 94 | // Kotlin 95 | //https://developer.android.com/guide/navigation/navigation-getting-started 96 | implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" 97 | implementation "androidx.navigation:navigation-ui-ktx:$nav_version" 98 | 99 | //https://github.com/jaredrummler/MaterialSpinner 100 | implementation 'com.jaredrummler:material-spinner:1.3.1' 101 | 102 | //https://github.com/bumptech/glide 103 | implementation "com.github.bumptech.glide:glide:$glide_version" 104 | kapt "com.github.bumptech.glide:compiler:$glide_version" 105 | //annotationProcessor "com.github.bumptech.glide:compiler:$glide_version" 106 | 107 | //https://github.com/Dhaval2404/ImagePicker 108 | implementation "com.github.dhaval2404:imagepicker:$imagepicker" 109 | implementation "com.github.florent37:inline-activity-result-kotlin:$inline_activity_result_kotlin" 110 | 111 | //https://airbnb.io/lottie/#/android 112 | implementation "com.airbnb.android:lottie:$lottieVersion" 113 | 114 | //https://github.com/GrenderG/Toasty 115 | implementation "com.github.GrenderG:Toasty:$tostyVersion" 116 | 117 | //https://developer.android.com/jetpack/androidx/releases/room 118 | implementation "androidx.room:room-runtime:$room_version" 119 | kapt "androidx.room:room-compiler:$room_version" 120 | //annotationProcessor "androidx.room:room-compiler:$room_version" 121 | 122 | //Kotlin Extensions and Coroutines support for Room 123 | implementation "androidx.room:room-ktx:$room_version" 124 | } 125 | -------------------------------------------------------------------------------- /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/release/app-release.aab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/release/app-release.aab -------------------------------------------------------------------------------- /app/src/androidTest/java/com/decimalab/easytask/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask 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.shajt3ch.todomvvm", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/BaseApplication.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import android.content.SharedPreferences 6 | import android.os.Build 7 | import androidx.appcompat.app.AppCompatDelegate 8 | import com.decimalab.easytask.model.local.AppPreferences 9 | import com.decimalab.easytask.util.AppThemeMode 10 | import kotlinx.coroutines.CoroutineScope 11 | import kotlinx.coroutines.Dispatchers 12 | import kotlinx.coroutines.launch 13 | 14 | /** 15 | * Created by Shakil Ahmed Shaj on 14,May,2020. 16 | * shakilahmedshaj@gmail.com 17 | */ 18 | class BaseApplication : Application() { 19 | private lateinit var appPreferences: AppPreferences 20 | private lateinit var sharedPreferences: SharedPreferences 21 | 22 | override fun onCreate() { 23 | super.onCreate() 24 | //pref 25 | sharedPreferences = this.getSharedPreferences(BuildConfig.PREF_NAME, Context.MODE_PRIVATE) 26 | appPreferences = AppPreferences(sharedPreferences) 27 | //get the theme mode from pref 28 | getThemMode() 29 | 30 | } 31 | 32 | private fun getThemMode() { 33 | 34 | CoroutineScope(Dispatchers.IO).launch { 35 | var mode = 0 36 | 37 | if (appPreferences.getThemeMode() == 0) { 38 | if (isPreAndroidTen()) { 39 | mode = AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY 40 | } else { 41 | mode = AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM 42 | } 43 | } else { 44 | mode = when (appPreferences.getThemeMode()) { 45 | AppThemeMode.LIGHT.ordinal -> AppCompatDelegate.MODE_NIGHT_NO 46 | AppThemeMode.DARK.ordinal -> AppCompatDelegate.MODE_NIGHT_YES 47 | AppThemeMode.SYSTEM.ordinal -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM 48 | AppThemeMode.BATTERY.ordinal -> AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY 49 | else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM 50 | } 51 | } 52 | AppCompatDelegate.setDefaultNightMode(mode) 53 | } 54 | } 55 | 56 | private fun isPreAndroidTen() = Build.VERSION.SDK_INT < Build.VERSION_CODES.Q 57 | 58 | 59 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/local/AppPreferences.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.local 2 | 3 | import android.content.SharedPreferences 4 | 5 | /** 6 | * Created by Shakil Ahmed Shaj on 15,April,2020. 7 | * shakilahmedshaj@gmail.com 8 | */ 9 | class AppPreferences(private val prefs: SharedPreferences) { 10 | 11 | companion object { 12 | const val KEY_ACCESS_TOKEN = "PREF_KEY_ACCESS_TOKEN" 13 | const val KEY_TOKEN_ID = "PREF_KEY_TOKEN_ID" 14 | const val KEY_USER_ID = "PREF_KEY_USER_ID" 15 | const val KEY_USER_NAME = "PREF_KEY_USER_NAME" 16 | const val KEY_USER_EMAIL = "PREF_KEY_USER_EMAIL" 17 | const val KEY_THEME_MODE = "PREF_KEY_THEME_MODE" 18 | } 19 | 20 | fun setAccessToken(access_token: String) { 21 | prefs.edit().putString(KEY_ACCESS_TOKEN, access_token).apply() 22 | } 23 | 24 | fun setTokenId(token_id: String) { 25 | prefs.edit().putString(KEY_TOKEN_ID, token_id).apply() 26 | } 27 | 28 | fun setUserId(user_id: Int) { 29 | prefs.edit().putInt(KEY_USER_ID, user_id).apply() 30 | } 31 | 32 | fun setUserName(user_name: String) { 33 | prefs.edit().putString(KEY_USER_NAME, user_name).apply() 34 | } 35 | 36 | fun setUserEmail(user_email: String) { 37 | prefs.edit().putString(KEY_USER_EMAIL, user_email).apply() 38 | } 39 | 40 | fun setThemeMode(value: Int) { 41 | prefs.edit().putInt(KEY_THEME_MODE, value).apply() 42 | } 43 | 44 | fun getAccessToken(): String? = prefs.getString(KEY_ACCESS_TOKEN, null) 45 | 46 | fun getTokenId(): String? = prefs.getString(KEY_TOKEN_ID, null) 47 | 48 | fun getUserId(): Int? = prefs.getInt(KEY_USER_ID, 0) 49 | 50 | fun getUserName(): String? = prefs.getString(KEY_USER_NAME, null) 51 | 52 | fun getUserEmail(): String? = prefs.getString(KEY_USER_EMAIL, null) 53 | 54 | fun getThemeMode(): Int = prefs.getInt(KEY_THEME_MODE, 0) 55 | 56 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/local/dao/TaskDao.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.local.dao 2 | 3 | import androidx.room.* 4 | import com.decimalab.easytask.model.local.entity.TaskEntity 5 | 6 | /** 7 | * Created by Shakil Ahmed Shaj on 26,April,2020. 8 | * shakilahmedshaj@gmail.com 9 | */ 10 | @Dao 11 | interface TaskDao { 12 | 13 | @Insert 14 | suspend fun insert(taskEntity: TaskEntity): Long 15 | 16 | @Update 17 | suspend fun update(taskEntity: TaskEntity): Int 18 | 19 | @Delete 20 | suspend fun delete(taskEntity: TaskEntity): Int 21 | 22 | @Query("DELETE FROM task_entity WHERE taskId = :task_id") 23 | suspend fun deleteTaskFromDb(task_id : String): Int 24 | 25 | @Query("SELECT * FROM task_entity ORDER BY taskId desc") 26 | suspend fun getAllTaskFromDb(): List 27 | 28 | @Query("SELECT MAX(taskId) FROM task_entity") 29 | suspend fun getMaxTaskId(): Int? 30 | 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/local/db/AppDatabase.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.local.db 2 | 3 | import android.content.Context 4 | import androidx.room.Database 5 | import androidx.room.Room 6 | import androidx.room.RoomDatabase 7 | import com.decimalab.easytask.model.local.dao.TaskDao 8 | import com.decimalab.easytask.model.local.entity.TaskEntity 9 | 10 | 11 | /** 12 | * Created by Shakil Ahmed Shaj on 26,April,2020. 13 | * shakilahmedshaj@gmail.com 14 | */ 15 | @Database(entities = [TaskEntity::class], version = 1, exportSchema = false) 16 | abstract class AppDatabase : RoomDatabase() { 17 | 18 | abstract fun taskDao(): TaskDao 19 | 20 | companion object { 21 | @Volatile 22 | private var INSTANCE: AppDatabase? = null 23 | 24 | fun getInstance(context: Context): AppDatabase { 25 | 26 | synchronized(this) 27 | { 28 | var instance = INSTANCE 29 | 30 | if (instance == null) { 31 | instance = Room.databaseBuilder( 32 | context.applicationContext, 33 | AppDatabase::class.java, 34 | "task_db" 35 | ) 36 | .fallbackToDestructiveMigration() 37 | .build() 38 | INSTANCE = instance 39 | } 40 | return instance 41 | } 42 | } 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/local/entity/TaskEntity.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.local.entity 2 | 3 | import android.widget.TextView 4 | import androidx.databinding.BindingAdapter 5 | import androidx.room.ColumnInfo 6 | import androidx.room.Entity 7 | import androidx.room.PrimaryKey 8 | 9 | /** 10 | * Created by Shakil Ahmed Shaj on 26,April,2020. 11 | * shakilahmedshaj@gmail.com 12 | */ 13 | 14 | @Entity(tableName = "task_entity") 15 | data class TaskEntity( 16 | @PrimaryKey(autoGenerate = true) 17 | val id: Long = 0L, 18 | 19 | @ColumnInfo(name = "userId") 20 | val userId: Int, // 1 21 | 22 | @ColumnInfo(name = "taskId") 23 | val taskId: Int, 24 | 25 | @ColumnInfo(name = "title") 26 | val title: String, // Task 1 27 | 28 | @ColumnInfo(name = "body") 29 | val body: String, // Body 1 30 | 31 | @ColumnInfo(name = "status") 32 | val status: String, // PENDING 33 | 34 | @ColumnInfo(name = "createdAt") 35 | val createdAt: String, // 2020-04-16 15:25:13 36 | 37 | @ColumnInfo(name = "updatedAt") 38 | val updatedAt: String, // 2020-04-16 15:25:13 39 | 40 | @ColumnInfo(name = "bg_color") 41 | var bg_color: Int = 0 42 | 43 | ) { 44 | 45 | /* 46 | later 47 | */ 48 | companion object { 49 | 50 | @JvmStatic 51 | @BindingAdapter("viewBackground") 52 | fun TextView.setBgColor(color: Int?) { 53 | if (color != null) { 54 | this.setBackgroundResource(color) 55 | } 56 | } 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/remote/EndPoints.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.remote 2 | 3 | /** 4 | * Created by Shakil Ahmed Shaj on 14,April,2020. 5 | * shakilahmedshaj@gmail.com 6 | */ 7 | object EndPoints { 8 | 9 | const val REGISTER = "api/register" 10 | const val LOGIN = "api/login" 11 | const val VALIDATE_TOKEN = "api/validate_token" 12 | const val ADD_TASK = "api/task/add_task" 13 | const val ALL_TASK = "api/task/get_all_task" 14 | const val GET_TASK_By_ID = "api/task/get_task_by_id/" //get_task_by_id 15 | const val EDIT_TASK = "api/task/update_task" 16 | const val GET_USER_PROFILE = "api/users/detail/" 17 | const val EDIT_PROFILE = "api/users/edit/user" 18 | const val DELETE_TASK = "api/task/delete_task" 19 | 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/remote/NetworkService.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.remote 2 | 3 | import com.decimalab.easytask.model.remote.request.auth.LoginRequest 4 | import com.decimalab.easytask.model.remote.request.auth.RegisterRequest 5 | import com.decimalab.easytask.model.remote.request.task.AddTaskRequest 6 | import com.decimalab.easytask.model.remote.request.task.DeleteTaskRequest 7 | import com.decimalab.easytask.model.remote.request.task.EditTaskRequest 8 | import com.decimalab.easytask.model.remote.response.auth.LoginResponse 9 | import com.decimalab.easytask.model.remote.response.auth.RegisterResponse 10 | import com.decimalab.easytask.model.remote.response.auth.ValidateResponse 11 | import com.decimalab.easytask.model.remote.response.profile.EditProfileResponse 12 | import com.decimalab.easytask.model.remote.response.profile.UserProfileResponse 13 | import com.decimalab.easytask.model.remote.response.task.AddTaskResponse 14 | import com.decimalab.easytask.model.remote.response.task.EditTaskResponse 15 | import com.decimalab.easytask.model.remote.response.task.TaskResponse 16 | import okhttp3.MultipartBody 17 | import okhttp3.RequestBody 18 | import retrofit2.Response 19 | import retrofit2.http.* 20 | 21 | /** 22 | * Created by Shakil Ahmed Shaj on 14,April,2020. 23 | * shakilahmedshaj@gmail.com 24 | */ 25 | interface NetworkService { 26 | 27 | @POST(EndPoints.REGISTER) 28 | suspend fun register(@Body registerRequest: RegisterRequest): Response 29 | 30 | @POST(EndPoints.LOGIN) 31 | suspend fun login(@Body loginRequest: LoginRequest): Response 32 | 33 | @GET(EndPoints.VALIDATE_TOKEN) 34 | suspend fun validateToken(@Header("Authorization") token: String): Response 35 | 36 | @POST(EndPoints.ADD_TASK) 37 | suspend fun addTask( 38 | @Header("Authorization") token: String, 39 | @Body addTaskRequest: AddTaskRequest 40 | ): Response 41 | 42 | @GET(EndPoints.ALL_TASK) 43 | suspend fun getAllTask(@Header("Authorization") token: String): Response> 44 | 45 | @GET("${EndPoints.GET_TASK_By_ID} {maxId}") 46 | suspend fun getTaskById( 47 | @Header( 48 | "Authorization" 49 | ) token: String, @Path("maxId") maxId: String 50 | 51 | ): Response> 52 | 53 | @POST(EndPoints.EDIT_TASK) 54 | suspend fun editTask( 55 | @Header("Authorization") token: String, 56 | @Body editTaskRequest: EditTaskRequest 57 | ): Response 58 | 59 | @GET("${EndPoints.GET_USER_PROFILE} {id}") 60 | suspend fun getUserProfile( 61 | @Header("Authorization") token: String, 62 | @Path("id") id: String 63 | ): Response 64 | 65 | @Multipart 66 | @POST(EndPoints.EDIT_PROFILE) 67 | suspend fun editProfile( 68 | @Header("Authorization") token: String, 69 | @Part("id") id: RequestBody, 70 | @Part("name") name: RequestBody, 71 | @Part("email") email: RequestBody, 72 | @Part profile_image: MultipartBody.Part? = null, 73 | @Part("bio") bio: RequestBody 74 | ): Response 75 | 76 | @POST(EndPoints.DELETE_TASK) 77 | suspend fun deleteTask( 78 | @Header("Authorization") token: String, 79 | @Body deleteTaskRequest: DeleteTaskRequest 80 | ): Response 81 | 82 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/remote/Networking.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.remote 2 | 3 | import retrofit2.Retrofit 4 | import retrofit2.converter.gson.GsonConverterFactory 5 | 6 | /** 7 | * Created by Shakil Ahmed Shaj on 14,April,2020. 8 | * shakilahmedshaj@gmail.com 9 | */ 10 | object Networking { 11 | fun create(baseUrl: String): NetworkService { 12 | return Retrofit.Builder() 13 | .baseUrl(baseUrl) 14 | .addConverterFactory(GsonConverterFactory.create()) 15 | .build() 16 | .create(NetworkService::class.java) 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/remote/request/auth/LoginRequest.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.remote.request.auth 2 | 3 | import com.google.gson.annotations.SerializedName 4 | 5 | /** 6 | * Created by Shakil Ahmed Shaj on 14,April,2020. 7 | * shakilahmedshaj@gmail.com 8 | */ 9 | data class LoginRequest( 10 | @SerializedName("email") 11 | val email: String, 12 | @SerializedName("password") 13 | val password: String 14 | ) { 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/remote/request/auth/RegisterRequest.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.remote.request.auth 2 | 3 | import com.google.gson.annotations.SerializedName 4 | 5 | /** 6 | * Created by Shakil Ahmed Shaj on 14,April,2020. 7 | * shakilahmedshaj@gmail.com 8 | */ 9 | data class RegisterRequest( 10 | @SerializedName("name") 11 | val name: String, 12 | @SerializedName("email") 13 | val email: String, 14 | @SerializedName("password") 15 | val password: String, 16 | @SerializedName("password_confirmation") 17 | val password_confirmation: String 18 | ) { 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/remote/request/task/AddTaskRequest.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.remote.request.task 2 | 3 | 4 | import com.google.gson.annotations.SerializedName 5 | 6 | data class AddTaskRequest( 7 | @SerializedName("user_id") 8 | val userId: Int, // 1 9 | @SerializedName("title") 10 | val title: String, // Title 1 11 | @SerializedName("body") 12 | val body: String, // Body 1 13 | @SerializedName("status") 14 | val status: String // PENDING 15 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/remote/request/task/DeleteTaskRequest.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.remote.request.task 2 | 3 | import com.google.gson.annotations.SerializedName 4 | 5 | /** 6 | * Created by Shakil Ahmed Shaj on 30,April,2020. 7 | * shakilahmedshaj@gmail.com 8 | */ 9 | data class DeleteTaskRequest( 10 | @SerializedName("id") 11 | val id: String, 12 | @SerializedName("user_id") 13 | val user_id: String 14 | ) { 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/remote/request/task/EditTaskRequest.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.remote.request.task 2 | 3 | 4 | import com.google.gson.annotations.SerializedName 5 | 6 | data class EditTaskRequest( 7 | @SerializedName("id") 8 | val id: Int, // 26 9 | @SerializedName("user_id") 10 | val userId: String, // 1 11 | @SerializedName("title") 12 | val title: String, // Title Update 13 | @SerializedName("body") 14 | val body: String, // Body 1 15 | @SerializedName("status") 16 | val status: String // PENDING 17 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/remote/response/auth/LoginResponse.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.remote.response.auth 2 | 3 | import com.google.gson.annotations.SerializedName 4 | 5 | data class LoginResponse( 6 | @SerializedName("access_token") 7 | val accessToken: String, 8 | @SerializedName("token_id") 9 | val tokenId: String, 10 | @SerializedName("user_id") 11 | val userId: Int, 12 | @SerializedName("name") 13 | val name: String, 14 | @SerializedName("email") 15 | val email: String 16 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/remote/response/auth/RegisterResponse.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.remote.response.auth 2 | 3 | 4 | import com.google.gson.annotations.SerializedName 5 | 6 | data class RegisterResponse( 7 | @SerializedName("name") 8 | val user_name: String, 9 | @SerializedName("email") 10 | val email: String, 11 | @SerializedName("updated_at") 12 | val updatedAt: String, 13 | @SerializedName("created_at") 14 | val createdAt: String, 15 | @SerializedName("id") 16 | val id: Int 17 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/remote/response/auth/ValidateResponse.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.remote.response.auth 2 | 3 | import com.google.gson.annotations.SerializedName 4 | 5 | /** 6 | * Created by Shakil Ahmed Shaj on 15,April,2020. 7 | * shakilahmedshaj@gmail.com 8 | */ 9 | data class ValidateResponse( 10 | @SerializedName("message") 11 | val message: String 12 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/remote/response/profile/EditProfileResponse.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.remote.response.profile 2 | 3 | 4 | import com.google.gson.annotations.SerializedName 5 | 6 | data class EditProfileResponse( 7 | @SerializedName("success") 8 | val success: Boolean // true 9 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/remote/response/profile/UserProfileResponse.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.remote.response.profile 2 | 3 | 4 | import com.google.gson.annotations.SerializedName 5 | 6 | data class UserProfileResponse( 7 | @SerializedName("id") 8 | val id: Int, // 6 9 | @SerializedName("name") 10 | val name: String, // shaj 11 | @SerializedName("email") 12 | val email: String, // shaj@gmail.com 13 | @SerializedName("profile_image") 14 | val profileImage: String, // http://localhost/storage/profile_image/default_profile.png 15 | @SerializedName("profile_image_path") 16 | val profileImagePath: String, // /storage/profile_image/default_profile.png 17 | @SerializedName("bio") 18 | val bio: String // Stay Safe from Corona !. 19 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/remote/response/task/AddTaskResponse.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.remote.response.task 2 | 3 | 4 | import com.google.gson.annotations.SerializedName 5 | 6 | data class AddTaskResponse( 7 | @SerializedName("user_id") 8 | val userId: String, // 1 9 | @SerializedName("title") 10 | val title: String, // Title 1 11 | @SerializedName("body") 12 | val body: String, // Body 1 13 | @SerializedName("status") 14 | val status: String, // PENDING 15 | @SerializedName("updated_at") 16 | val updatedAt: String, // 2020-04-16T11:37:09.000000Z 17 | @SerializedName("created_at") 18 | val createdAt: String, // 2020-04-16T11:37:09.000000Z 19 | @SerializedName("id") 20 | val id: Int // 2 21 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/remote/response/task/EditTaskResponse.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.remote.response.task 2 | 3 | 4 | import com.google.gson.annotations.SerializedName 5 | 6 | data class EditTaskResponse( 7 | @SerializedName("id") 8 | val id: Int, // 26 9 | @SerializedName("user_id") 10 | val userId: String, // 1 11 | @SerializedName("title") 12 | val title: String, // Title Update 13 | @SerializedName("body") 14 | val body: String, // Body 1 15 | @SerializedName("status") 16 | val status: String, // PENDING 17 | @SerializedName("created_at") 18 | val createdAt: String, // 2020-04-16T20:50:00.000000Z 19 | @SerializedName("updated_at") 20 | val updatedAt: String // 2020-04-18T12:08:09.000000Z 21 | 22 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/remote/response/task/TaskResponse.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.remote.response.task 2 | 3 | 4 | import android.widget.TextView 5 | import androidx.databinding.BindingAdapter 6 | import com.google.gson.annotations.SerializedName 7 | 8 | data class TaskResponse( 9 | @SerializedName("id") 10 | val id: Int, // 15 11 | @SerializedName("user_id") 12 | val userId: Int, // 1 13 | @SerializedName("title") 14 | val title: String, // Task 1 15 | @SerializedName("body") 16 | val body: String, // Body 1 17 | @SerializedName("status") 18 | val status: String, // PENDING 19 | @SerializedName("created_at") 20 | val createdAt: String, // 2020-04-16 15:25:13 21 | @SerializedName("updated_at") 22 | val updatedAt: String, // 2020-04-16 15:25:13 23 | @SerializedName("bg_color") 24 | var bg_color: Int 25 | ) { 26 | companion object { 27 | 28 | @JvmStatic 29 | @BindingAdapter("viewBackground") 30 | fun TextView.setBgColor(color: Int?) { 31 | if (color != null) { 32 | this.setBackgroundResource(color) 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/repository/AddTaskRepository.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.repository 2 | 3 | import com.decimalab.easytask.model.remote.NetworkService 4 | import com.decimalab.easytask.model.remote.request.task.AddTaskRequest 5 | 6 | /** 7 | * Created by Shakil Ahmed Shaj on 16,April,2020. 8 | * shakilahmedshaj@gmail.com 9 | */ 10 | class AddTaskRepository(private val networkService: NetworkService) { 11 | 12 | suspend fun addTask(token: String, addTaskRequest: AddTaskRequest) = 13 | networkService.addTask(token, addTaskRequest) 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/repository/DeleteTaskRepository.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.repository 2 | 3 | import com.decimalab.easytask.model.local.db.AppDatabase 4 | import com.decimalab.easytask.model.local.entity.TaskEntity 5 | import com.decimalab.easytask.model.remote.NetworkService 6 | import com.decimalab.easytask.model.remote.request.task.DeleteTaskRequest 7 | 8 | /** 9 | * Created by Shakil Ahmed Shaj on 30,April,2020. 10 | * shakilahmedshaj@gmail.com 11 | */ 12 | class DeleteTaskRepository( 13 | private val networkService: NetworkService, 14 | private val appDatabase: AppDatabase 15 | ) { 16 | 17 | suspend fun deleteTaskFromApi(token: String, deleteTaskRequest: DeleteTaskRequest) = 18 | networkService.deleteTask(token, deleteTaskRequest) 19 | 20 | suspend fun deleteTaskFromDb(taskEntity: TaskEntity) = appDatabase.taskDao().delete(taskEntity) 21 | 22 | suspend fun deleteFromDb(taskId: String) = appDatabase.taskDao().deleteTaskFromDb(taskId) 23 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/repository/EditTaskRepository.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.repository 2 | 3 | import com.decimalab.easytask.model.local.db.AppDatabase 4 | import com.decimalab.easytask.model.local.entity.TaskEntity 5 | import com.decimalab.easytask.model.remote.NetworkService 6 | import com.decimalab.easytask.model.remote.request.task.EditTaskRequest 7 | import com.decimalab.easytask.model.remote.response.task.EditTaskResponse 8 | import retrofit2.Response 9 | 10 | /** 11 | * Created by Shakil Ahmed Shaj on 18,April,2020. 12 | * shakilahmedshaj@gmail.com 13 | */ 14 | class EditTaskRepository( 15 | private val networkService: NetworkService, 16 | private val appDatabase: AppDatabase 17 | ) { 18 | 19 | suspend fun editTask( 20 | token: String, 21 | editTaskRequest: EditTaskRequest 22 | ): Response = 23 | networkService.editTask(token, editTaskRequest) 24 | 25 | suspend fun updateTask(taskEntity: TaskEntity) = appDatabase.taskDao().update(taskEntity) 26 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/repository/LoginRepository.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.repository 2 | 3 | import com.decimalab.easytask.model.local.AppPreferences 4 | import com.decimalab.easytask.model.remote.NetworkService 5 | import com.decimalab.easytask.model.remote.request.auth.LoginRequest 6 | import com.decimalab.easytask.model.remote.response.auth.LoginResponse 7 | 8 | /** 9 | * Created by Shakil Ahmed Shaj on 14,April,2020. 10 | * shakilahmedshaj@gmail.com 11 | */ 12 | class LoginRepository( 13 | private val networkService: NetworkService, 14 | private val appPreferences: AppPreferences 15 | ) { 16 | 17 | suspend fun login(loginRequest: LoginRequest) = networkService.login(loginRequest) 18 | 19 | suspend fun saveUserDetail(loginResponse: LoginResponse): Boolean { 20 | 21 | appPreferences.setAccessToken(loginResponse.accessToken) 22 | appPreferences.setTokenId(loginResponse.tokenId) 23 | appPreferences.setUserId(loginResponse.userId) 24 | appPreferences.setUserName(loginResponse.name) 25 | appPreferences.setUserEmail(loginResponse.email) 26 | 27 | return true 28 | 29 | } 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/repository/RegisterRepository.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.repository 2 | 3 | import com.decimalab.easytask.model.remote.NetworkService 4 | import com.decimalab.easytask.model.remote.request.auth.RegisterRequest 5 | 6 | /** 7 | * Created by Shakil Ahmed Shaj on 14,April,2020. 8 | * shakilahmedshaj@gmail.com 9 | */ 10 | class RegisterRepository(private val networkService: NetworkService) { 11 | 12 | suspend fun register(registerRequest: RegisterRequest) = 13 | networkService.register(registerRequest) 14 | 15 | 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/repository/TaskRepository.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.repository 2 | 3 | import com.decimalab.easytask.model.local.db.AppDatabase 4 | import com.decimalab.easytask.model.local.entity.TaskEntity 5 | import com.decimalab.easytask.model.remote.NetworkService 6 | 7 | /** 8 | * Created by Shakil Ahmed Shaj on 16,April,2020. 9 | * shakilahmedshaj@gmail.com 10 | */ 11 | class TaskRepository( 12 | private val networkService: NetworkService, 13 | private val appDatabase: AppDatabase 14 | ) { 15 | 16 | suspend fun getAllTask(token: String) = networkService.getAllTask(token) 17 | suspend fun getTaskById(token: String, maxId: String) = networkService.getTaskById(token, maxId) 18 | 19 | suspend fun insert(taskEntity: TaskEntity) = appDatabase.taskDao().insert(taskEntity) 20 | suspend fun update(taskEntity: TaskEntity) = appDatabase.taskDao().update(taskEntity) 21 | suspend fun delete(taskEntity: TaskEntity) = appDatabase.taskDao().delete(taskEntity) 22 | 23 | suspend fun getAllTaskFromDb() = appDatabase.taskDao().getAllTaskFromDb() 24 | suspend fun getMaxTaskId() = appDatabase.taskDao().getMaxTaskId() 25 | 26 | 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/repository/UserProfileRepository.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.repository 2 | 3 | import com.decimalab.easytask.model.remote.NetworkService 4 | import com.decimalab.easytask.model.remote.response.profile.EditProfileResponse 5 | import com.decimalab.easytask.model.remote.response.profile.UserProfileResponse 6 | import okhttp3.MultipartBody 7 | import okhttp3.RequestBody 8 | import retrofit2.Response 9 | 10 | /** 11 | * Created by Shakil Ahmed Shaj on 19,April,2020. 12 | * shakilahmedshaj@gmail.com 13 | */ 14 | class UserProfileRepository(private val networkService: NetworkService) { 15 | 16 | suspend fun getUserProfile(token: String, id: String): Response = networkService.getUserProfile(token, id) 17 | 18 | suspend fun editProfile( 19 | token: String, 20 | id: RequestBody, 21 | name: RequestBody, 22 | email: RequestBody, 23 | profile_image: MultipartBody.Part? = null, 24 | bio: RequestBody 25 | ): Response = networkService.editProfile( 26 | token, 27 | id, 28 | name, 29 | email, 30 | profile_image, 31 | bio 32 | ) 33 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/model/repository/ValidateTokenRepository.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.model.repository 2 | 3 | import com.decimalab.easytask.model.remote.NetworkService 4 | 5 | /** 6 | * Created by Shakil Ahmed Shaj on 15,April,2020. 7 | * shakilahmedshaj@gmail.com 8 | */ 9 | class ValidateTokenRepository(private val networkService: NetworkService) { 10 | 11 | suspend fun validateToken(token: String) = networkService.validateToken(token) 12 | 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/util/AppThemeMode.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.util 2 | 3 | /** 4 | * Created by Shakil Ahmed Shaj on 14,May,2020. 5 | * shakilahmedshaj@gmail.com 6 | */ 7 | enum class AppThemeMode { 8 | 9 | LIGHT, DARK, SYSTEM, BATTERY 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/util/GeneralHelper.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.util 2 | 3 | import android.app.Activity 4 | import android.view.WindowManager 5 | 6 | object GeneralHelper { 7 | 8 | fun hideStatusBar(activity: Activity){ 9 | activity.window.setFlags( 10 | WindowManager.LayoutParams.FLAG_FULLSCREEN, 11 | WindowManager.LayoutParams.FLAG_FULLSCREEN) 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/util/Validator.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.util 2 | 3 | import java.util.regex.Pattern 4 | 5 | /** 6 | * Created by Shakil Ahmed Shaj on 23,April,2020. 7 | * shakilahmedshaj@gmail.com 8 | */ 9 | object Validator { 10 | 11 | private const val MIN_PASSWORD_LENGTH = 4 12 | private val EMAIL_ADDRESS = Pattern.compile( 13 | "[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" + 14 | "\\@" + 15 | "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" + 16 | "(" + 17 | "\\." + 18 | "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" + 19 | ")+" 20 | ) 21 | 22 | fun validateEmail(email: String): Boolean { 23 | return when { 24 | email.isBlank() -> 25 | false 26 | !EMAIL_ADDRESS.matcher(email).matches() -> 27 | false 28 | else -> 29 | true 30 | } 31 | 32 | } 33 | 34 | fun validatePassword(password: String): Boolean { 35 | return when { 36 | password.isBlank() -> 37 | false 38 | password.length < MIN_PASSWORD_LENGTH -> 39 | false 40 | else -> 41 | true 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/util/network/NetworkError.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.util.network 2 | 3 | import com.google.gson.annotations.SerializedName 4 | 5 | /** 6 | * Created by Shakil Ahmed Shaj on 23,April,2020. 7 | * shakilahmedshaj@gmail.com 8 | */ 9 | data class NetworkError( 10 | @SerializedName("statusCode") 11 | val statusCode: Int = -1, 12 | @SerializedName("message") 13 | val message: String = "Something went wrong. Please try again." 14 | ) { 15 | 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/util/network/NetworkHelper.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.util.network 2 | 3 | import android.content.Context 4 | import android.net.ConnectivityManager 5 | import android.net.Network 6 | import android.net.NetworkCapabilities 7 | import android.os.Build 8 | import com.google.gson.JsonParser 9 | import retrofit2.Response 10 | 11 | object NetworkHelper { 12 | 13 | fun isNetworkConnected(context: Context): Boolean{ 14 | var result = false 15 | (context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).apply { 16 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 17 | result = 18 | isCapableNetwork( 19 | this, 20 | this.activeNetwork 21 | ) 22 | } else { 23 | val networkInfos = this.allNetworks 24 | for (tempNetworkInfo in networkInfos) { 25 | if(isCapableNetwork( 26 | this, 27 | tempNetworkInfo 28 | ) 29 | ) 30 | result = true 31 | } 32 | } 33 | } 34 | 35 | return result 36 | } 37 | 38 | private fun isCapableNetwork(cm: ConnectivityManager,network: Network?): Boolean{ 39 | cm.getNetworkCapabilities(network)?.also { 40 | if (it.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { 41 | return true 42 | } else if (it.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { 43 | return true 44 | } 45 | } 46 | return false 47 | } 48 | 49 | fun handelNetworkError(response: Response<*>): NetworkError { 50 | 51 | val error = response.errorBody()?.string() 52 | val message = JsonParser().parse(error) 53 | .asJsonObject["error"] 54 | .toString() 55 | 56 | return NetworkError(response.code(), message) 57 | } 58 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/view/adaptor/TaskAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.view.adaptor 2 | 3 | import android.view.LayoutInflater 4 | import android.view.View 5 | import android.view.ViewGroup 6 | import androidx.databinding.DataBindingUtil 7 | import androidx.recyclerview.widget.RecyclerView 8 | import com.decimalab.easytask.R 9 | import com.decimalab.easytask.databinding.CustomTaskListViewBinding 10 | import com.decimalab.easytask.model.local.entity.TaskEntity 11 | 12 | /** 13 | * Created by Shakil Ahmed Shaj on 16,April,2020. 14 | * shakilahmedshaj@gmail.com 15 | */ 16 | class TaskAdapter(private val taskList: ArrayList) : //ArrayList) 17 | RecyclerView.Adapter() { 18 | 19 | 20 | private lateinit var taskCallBack: TaskCallBack 21 | 22 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { 23 | 24 | val binding: CustomTaskListViewBinding = DataBindingUtil.inflate( 25 | LayoutInflater.from(parent.context), 26 | R.layout.custom_task_list_view, parent, false 27 | ) 28 | 29 | return ViewHolder(binding) 30 | 31 | } 32 | 33 | override fun getItemCount(): Int { 34 | return taskList.size 35 | } 36 | 37 | override fun onBindViewHolder(holder: ViewHolder, position: Int) { 38 | val data: TaskEntity = taskList[position] //data: TaskResponse 39 | 40 | when (data.status) { 41 | "PENDING" -> { 42 | data.bg_color = R.color.status_pending 43 | } 44 | "STARTED" -> { 45 | data.bg_color = R.color.status_started 46 | } 47 | else -> { 48 | data.bg_color = R.color.status_completed 49 | } 50 | } 51 | 52 | holder.taskListBinding.task = data 53 | 54 | holder.setTaskCallBack(taskCallBack) 55 | } 56 | 57 | fun setTaskCallBack(taskCallBack: TaskCallBack) { 58 | this.taskCallBack = taskCallBack 59 | } 60 | 61 | class ViewHolder(binding: CustomTaskListViewBinding) : RecyclerView.ViewHolder(binding.root), 62 | View.OnClickListener, View.OnLongClickListener { 63 | var taskListBinding: CustomTaskListViewBinding = binding 64 | 65 | private lateinit var taskCallBack: TaskCallBack 66 | 67 | init { 68 | taskListBinding.root.setOnClickListener(this) 69 | taskListBinding.root.setOnLongClickListener(this) 70 | } 71 | 72 | fun setTaskCallBack(taskCallBack: TaskCallBack) { 73 | this.taskCallBack = taskCallBack 74 | } 75 | 76 | override fun onClick(v: View?) { 77 | 78 | if (v != null) { 79 | taskCallBack.onTaskClick(v, adapterPosition, false) 80 | } 81 | 82 | } 83 | 84 | override fun onLongClick(v: View?): Boolean { 85 | 86 | if (v != null) { 87 | taskCallBack.onTaskClick(v, adapterPosition, true) 88 | } 89 | return false 90 | } 91 | 92 | } 93 | 94 | 95 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/view/adaptor/TaskCallBack.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.view.adaptor 2 | 3 | import android.view.View 4 | 5 | /** 6 | * Created by Shakil Ahmed Shaj on 17,April,2020. 7 | * shakilahmedshaj@gmail.com 8 | */ 9 | interface TaskCallBack { 10 | 11 | fun onTaskClick(view: View, position: Int, isLongClick: Boolean) 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/view/ui/auth/LoginActivity.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.view.ui.auth 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | import androidx.lifecycle.Observer 6 | import androidx.lifecycle.ViewModelProvider 7 | import com.decimalab.easytask.R 8 | import com.decimalab.easytask.model.remote.request.auth.LoginRequest 9 | import com.decimalab.easytask.model.remote.response.auth.LoginResponse 10 | import com.decimalab.easytask.util.Validator 11 | import com.decimalab.easytask.view.ui.main.MainActivity 12 | import com.decimalab.easytask.viewmodel.auth.LoginViewModel 13 | import kotlinx.android.synthetic.main.activity_login.* 14 | import org.jetbrains.anko.alert 15 | import org.jetbrains.anko.intentFor 16 | import org.jetbrains.anko.sdk27.coroutines.onClick 17 | 18 | class LoginActivity : AppCompatActivity() { 19 | 20 | companion object { 21 | const val TAG = "LoginActivity" 22 | } 23 | 24 | private lateinit var viewModel: LoginViewModel 25 | 26 | override fun onCreate(savedInstanceState: Bundle?) { 27 | super.onCreate(savedInstanceState) 28 | setContentView(R.layout.activity_login) 29 | 30 | viewModel = ViewModelProvider(this).get(LoginViewModel::class.java) 31 | 32 | btn_login.onClick { prepareLogin() } 33 | tv_signup.onClick { launchSignUpActivity() } 34 | 35 | observer() 36 | } 37 | 38 | private fun launchSignUpActivity() { 39 | startActivity(intentFor()) 40 | 41 | } 42 | 43 | private fun prepareLogin() { 44 | val email = txt_userId.text.toString() 45 | val password = txt_password.text.toString() 46 | 47 | if (!Validator.validateEmail(email)) { 48 | 49 | 50 | alert { 51 | isCancelable = false 52 | title = getString(R.string.email_validator_title) 53 | message = getString(R.string.validation_email_failed) 54 | positiveButton("OK") { 55 | it.dismiss() 56 | } 57 | }.show() 58 | } else if (!Validator.validatePassword(password)) { 59 | alert { 60 | isCancelable = false 61 | title = getString(R.string.password_validator_title) 62 | message = getString(R.string.validation_password_failed) 63 | positiveButton("OK") { 64 | it.dismiss() 65 | } 66 | }.show() 67 | } else { 68 | val loginRequest = LoginRequest(email, password) 69 | 70 | login(loginRequest) 71 | } 72 | 73 | 74 | } 75 | 76 | 77 | private fun login(login_request: LoginRequest) { 78 | 79 | viewModel.login(login_request).observe(this, Observer { 80 | 81 | it?.let { 82 | saveUserDetail(it) 83 | } 84 | 85 | }) 86 | } 87 | 88 | private fun saveUserDetail(loginResponse: LoginResponse) { 89 | viewModel.saveUserDetail(loginResponse).observe(this, Observer { 90 | 91 | if (it) { 92 | finish() 93 | startActivity(intentFor()) 94 | } 95 | 96 | }) 97 | } 98 | 99 | private fun observer() { 100 | viewModel.isError.observe(this, Observer { 101 | errorDialog(it) 102 | }) 103 | 104 | viewModel.isSuccess.observe(this, Observer { 105 | if (!it) { 106 | unSuccessFulDialog() 107 | } 108 | }) 109 | } 110 | 111 | 112 | private fun unSuccessFulDialog() { 113 | alert { 114 | title = getString(R.string.title_un_successful_dialog) 115 | message = viewModel.errorMsg.value.toString() 116 | isCancelable = false 117 | positiveButton(getString(R.string.btn_ok)) { dialog -> 118 | dialog.dismiss() 119 | } 120 | }.show() 121 | } 122 | 123 | private fun errorDialog(errorMsg: String) { 124 | alert { 125 | title = getString(R.string.title_error_dialog) 126 | message = errorMsg 127 | isCancelable = false 128 | positiveButton(getString(R.string.btn_ok)) { dialog -> 129 | dialog.dismiss() 130 | } 131 | }.show() 132 | 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/view/ui/auth/SignUpActivity.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.view.ui.auth 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | import android.view.View 6 | import androidx.lifecycle.Observer 7 | import androidx.lifecycle.ViewModelProvider 8 | import com.decimalab.easytask.R 9 | import com.decimalab.easytask.model.remote.request.auth.RegisterRequest 10 | import com.decimalab.easytask.util.Validator 11 | import com.decimalab.easytask.viewmodel.auth.SignUpViewModel 12 | import kotlinx.android.synthetic.main.activity_sign_up.* 13 | import org.jetbrains.anko.alert 14 | import org.jetbrains.anko.intentFor 15 | import org.jetbrains.anko.sdk27.coroutines.onClick 16 | 17 | class SignUpActivity : AppCompatActivity() { 18 | 19 | companion object { 20 | const val TAG = "SignUpActivity" 21 | } 22 | 23 | private lateinit var viewModel: SignUpViewModel 24 | 25 | override fun onCreate(savedInstanceState: Bundle?) { 26 | super.onCreate(savedInstanceState) 27 | setContentView(R.layout.activity_sign_up) 28 | 29 | viewModel = ViewModelProvider(this).get(SignUpViewModel::class.java) 30 | 31 | btn_sign_up.onClick { prepareSignUp() } 32 | tv_login.onClick { launchLoginActivity() } 33 | 34 | observer() 35 | } 36 | 37 | private fun launchLoginActivity() { 38 | startActivity(intentFor()) 39 | } 40 | 41 | private fun prepareSignUp() { 42 | val name = txt_userName.text.toString() 43 | val email = txt_email.text.toString() 44 | val password = txt_password.text.toString() 45 | val confirmPassword = txt_confirm_password.text.toString() 46 | 47 | if (name.isEmpty()) { 48 | alert { 49 | isCancelable = false 50 | title = getString(R.string.empty_user_name_title) 51 | message = getString(R.string.empty_user_name_msg) 52 | positiveButton("OK") { 53 | it.dismiss() 54 | } 55 | }.show() 56 | } else if (!Validator.validateEmail(email)) { 57 | alert { 58 | isCancelable = false 59 | title = getString(R.string.email_validator_title) 60 | message = getString(R.string.validation_email_failed) 61 | positiveButton("OK") { 62 | it.dismiss() 63 | } 64 | }.show() 65 | } else if (!Validator.validatePassword(password)) { 66 | alert { 67 | isCancelable = false 68 | title = getString(R.string.password_validator_title) 69 | message = getString(R.string.validation_password_failed) 70 | positiveButton("OK") { 71 | it.dismiss() 72 | } 73 | }.show() 74 | } else if (!Validator.validatePassword(confirmPassword)) { 75 | alert { 76 | isCancelable = false 77 | title = getString(R.string.validation_confirm_password_title) 78 | message = getString(R.string.validation_confirm_password_failed) 79 | positiveButton("OK") { 80 | it.dismiss() 81 | } 82 | }.show() 83 | } else if (password != confirmPassword) { 84 | alert { 85 | isCancelable = false 86 | title = getString(R.string.error_confirm_password_title) 87 | message = getString(R.string.error_confirm_password_msg) 88 | positiveButton("OK") { 89 | it.dismiss() 90 | } 91 | }.show() 92 | } else { 93 | val signUpData = RegisterRequest(name, email, password, confirmPassword) 94 | 95 | signUp(signUpData) 96 | } 97 | 98 | } 99 | 100 | private fun signUp(signUpData: RegisterRequest) { 101 | 102 | viewModel.register(signUpData) 103 | } 104 | 105 | private fun observer() { 106 | viewModel.isError.observe(this, Observer { 107 | errorDialog(it) 108 | }) 109 | 110 | viewModel.isSuccess.observe(this, Observer { 111 | it?.run { 112 | if (it) { 113 | successDialog() 114 | } else { 115 | unSuccessFulDialog() 116 | } 117 | } 118 | }) 119 | 120 | viewModel.loading.observe(this, Observer { 121 | pb_sign_up.visibility = if (it) View.VISIBLE else View.GONE 122 | 123 | }) 124 | } 125 | 126 | 127 | private fun successDialog() { 128 | alert { 129 | title = getString(R.string.title_successful_signup) 130 | message = getString(R.string.msg_signup_successful) 131 | isCancelable = false 132 | positiveButton(getString(R.string.btn_ok)) { dialog -> 133 | finish() 134 | dialog.dismiss() 135 | } 136 | }.show() 137 | } 138 | 139 | private fun unSuccessFulDialog() { 140 | alert { 141 | title = getString(R.string.title_un_successful_dialog) 142 | message = getString(R.string.msg_add_post_un_successful) 143 | isCancelable = false 144 | positiveButton(getString(R.string.btn_ok)) { dialog -> 145 | dialog.dismiss() 146 | } 147 | }.show() 148 | } 149 | 150 | private fun errorDialog(errorMsg: String) { 151 | alert { 152 | title = getString(R.string.title_error_dialog) 153 | message = errorMsg 154 | isCancelable = false 155 | positiveButton(getString(R.string.btn_ok)) { dialog -> 156 | dialog.dismiss() 157 | } 158 | }.show() 159 | 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/view/ui/darkmode/DarkModeFragment.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.view.ui.darkmode 2 | 3 | import android.content.Context 4 | import android.content.SharedPreferences 5 | import android.os.Build 6 | import android.os.Bundle 7 | import android.view.LayoutInflater 8 | import android.view.View 9 | import android.view.ViewGroup 10 | import android.widget.RadioGroup 11 | import androidx.appcompat.app.AppCompatDelegate 12 | import androidx.constraintlayout.widget.ConstraintLayout 13 | import androidx.fragment.app.DialogFragment 14 | import com.decimalab.easytask.BuildConfig 15 | import com.decimalab.easytask.R 16 | import com.decimalab.easytask.model.local.AppPreferences 17 | import com.decimalab.easytask.util.AppThemeMode 18 | import kotlinx.android.synthetic.main.dark_mode_fragment.* 19 | 20 | class DarkModeFragment : DialogFragment(), RadioGroup.OnCheckedChangeListener { 21 | companion object { 22 | const val TAG = "DarkModeFragment" 23 | } 24 | 25 | private lateinit var appPreferences: AppPreferences 26 | private lateinit var sharedPreferences: SharedPreferences 27 | 28 | override fun onStart() { 29 | super.onStart() 30 | dialog?.window?.setLayout( 31 | ConstraintLayout.LayoutParams.MATCH_PARENT, 32 | ConstraintLayout.LayoutParams.WRAP_CONTENT 33 | ) 34 | } 35 | 36 | override fun onCreateView( 37 | inflater: LayoutInflater, container: ViewGroup?, 38 | savedInstanceState: Bundle? 39 | ): View? { 40 | // Inflate the layout for this fragment 41 | return inflater.inflate(R.layout.dark_mode_fragment, container, false) 42 | } 43 | 44 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 45 | super.onViewCreated(view, savedInstanceState) 46 | //pref 47 | sharedPreferences = 48 | requireActivity().getSharedPreferences(BuildConfig.PREF_NAME, Context.MODE_PRIVATE) 49 | appPreferences = AppPreferences(sharedPreferences) 50 | //group check change listener 51 | groupMode.setOnCheckedChangeListener(this) 52 | 53 | //check android version 54 | if (isPreAndroidTen()) { 55 | system.text = getString(R.string.battery_mode) 56 | } 57 | 58 | //get theme mode 59 | getThemMode() 60 | } 61 | 62 | private fun getThemMode() { 63 | when (appPreferences.getThemeMode()) { 64 | AppThemeMode.LIGHT.ordinal -> light.isChecked = true 65 | AppThemeMode.DARK.ordinal -> dark.isChecked = true 66 | AppThemeMode.SYSTEM.ordinal, AppThemeMode.BATTERY.ordinal -> system.isChecked = true 67 | else -> system.isChecked = true 68 | } 69 | } 70 | 71 | override fun onCheckedChanged(group: RadioGroup?, checkedId: Int) { 72 | when (checkedId) { 73 | R.id.light -> { 74 | setThemeMode(AppCompatDelegate.MODE_NIGHT_NO, AppThemeMode.LIGHT) 75 | } 76 | R.id.dark -> { 77 | setThemeMode(AppCompatDelegate.MODE_NIGHT_YES, AppThemeMode.DARK) 78 | } 79 | R.id.system -> { 80 | if (isPreAndroidTen()) { 81 | setThemeMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY, AppThemeMode.BATTERY) 82 | } else { 83 | setThemeMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM, AppThemeMode.SYSTEM) 84 | } 85 | } 86 | } 87 | } 88 | 89 | private fun setThemeMode(mode: Int, themeMode: AppThemeMode) { 90 | AppCompatDelegate.setDefaultNightMode(mode) 91 | appPreferences.setThemeMode(themeMode.ordinal) 92 | 93 | } 94 | 95 | private fun isPreAndroidTen() = Build.VERSION.SDK_INT < Build.VERSION_CODES.Q 96 | 97 | 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/view/ui/home/HomeFragment.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.view.ui.home 2 | 3 | import android.os.Bundle 4 | import android.util.Log 5 | import android.view.* 6 | import androidx.fragment.app.Fragment 7 | import androidx.databinding.DataBindingUtil 8 | import androidx.lifecycle.Observer 9 | import androidx.lifecycle.ViewModelProvider 10 | import androidx.navigation.fragment.findNavController 11 | import androidx.recyclerview.widget.LinearLayoutManager 12 | import androidx.recyclerview.widget.RecyclerView 13 | 14 | import com.decimalab.easytask.R 15 | import com.decimalab.easytask.databinding.HomeFragmentBinding 16 | import com.decimalab.easytask.model.local.entity.TaskEntity 17 | import com.decimalab.easytask.view.adaptor.TaskAdapter 18 | import com.decimalab.easytask.view.adaptor.TaskCallBack 19 | import com.decimalab.easytask.view.ui.darkmode.DarkModeFragment 20 | import com.decimalab.easytask.viewmodel.home.HomeViewModel 21 | import kotlinx.android.synthetic.main.home_fragment.* 22 | import org.jetbrains.anko.support.v4.alert 23 | 24 | class HomeFragment : Fragment(), TaskCallBack { 25 | 26 | companion object { 27 | const val TAG = "HomeFragment" 28 | } 29 | 30 | private lateinit var viewModel: HomeViewModel 31 | private var taskList: ArrayList = ArrayList() //ArrayList 32 | 33 | //data bind 34 | private lateinit var binding: HomeFragmentBinding 35 | 36 | private lateinit var recyclerView: RecyclerView 37 | private lateinit var layoutManager: RecyclerView.LayoutManager 38 | private lateinit var taskAdapter: TaskAdapter 39 | 40 | override fun onCreateView( 41 | inflater: LayoutInflater, container: ViewGroup?, 42 | savedInstanceState: Bundle? 43 | ): View? { 44 | 45 | binding = DataBindingUtil.inflate(inflater, R.layout.home_fragment, container, false) 46 | 47 | //recyclerview 48 | recyclerView = binding.taskRecyclerView 49 | layoutManager = LinearLayoutManager(context) 50 | recyclerView.layoutManager = layoutManager 51 | 52 | 53 | return binding.root 54 | } 55 | 56 | override fun onActivityCreated(savedInstanceState: Bundle?) { 57 | super.onActivityCreated(savedInstanceState) 58 | viewModel = ViewModelProvider(this).get(HomeViewModel::class.java) 59 | 60 | setHasOptionsMenu(true) 61 | 62 | observer() 63 | } 64 | 65 | 66 | private fun setRecyclerView() { 67 | 68 | taskAdapter = TaskAdapter(taskList) 69 | recyclerView.adapter = taskAdapter 70 | 71 | taskAdapter.setTaskCallBack(this) 72 | 73 | } 74 | 75 | override fun onTaskClick(view: View, position: Int, isLongClick: Boolean) { 76 | 77 | if (isLongClick) { 78 | Log.e(TAG, "Position: $position is a long click") 79 | } else { 80 | 81 | val data = viewModel.taskListFromDb.value?.get(position) 82 | 83 | findNavController().navigate( 84 | HomeFragmentDirections.actionNavigationHomeToTaskDetailFragment( 85 | data?.createdAt.toString(), 86 | data?.title.toString(), 87 | data?.body.toString(), 88 | data?.status.toString(), 89 | data?.userId.toString(), 90 | data?.bg_color.toString(), 91 | data?.id.toString(), 92 | data?.taskId.toString() 93 | 94 | ) 95 | ) 96 | 97 | Log.e(TAG, "Position: $position is a single click") 98 | } 99 | 100 | } 101 | 102 | private fun observer() { 103 | viewModel.isError.observe(viewLifecycleOwner, Observer { 104 | errorDialog(it) 105 | }) 106 | 107 | viewModel.progress.observe(viewLifecycleOwner, Observer { 108 | pb_home.visibility = if (it) View.VISIBLE else View.GONE 109 | }) 110 | 111 | viewModel.taskListFromDb.observe(viewLifecycleOwner, Observer { 112 | taskList.clear() 113 | 114 | taskList = it!!.toCollection(taskList) 115 | 116 | setRecyclerView() 117 | }) 118 | } 119 | 120 | private fun errorDialog(errorMsg: String) { 121 | alert { 122 | title = getString(R.string.title_error_dialog) 123 | message = errorMsg 124 | isCancelable = false 125 | positiveButton(getString(R.string.btn_ok)) { dialog -> 126 | dialog.dismiss() 127 | } 128 | }.show() 129 | } 130 | 131 | override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { 132 | super.onCreateOptionsMenu(menu, inflater) 133 | inflater.inflate(R.menu.mode_menu, menu) 134 | } 135 | 136 | override fun onOptionsItemSelected(item: MenuItem): Boolean { 137 | when (item.itemId) { 138 | R.id.navigation_mode -> { 139 | val dialog = DarkModeFragment() 140 | dialog.show(requireActivity().supportFragmentManager, "DarkModeFragment") 141 | } 142 | } 143 | return super.onOptionsItemSelected(item) 144 | } 145 | 146 | } 147 | -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/view/ui/main/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.view.ui.main 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | import androidx.navigation.NavController 6 | import androidx.navigation.Navigation 7 | import androidx.navigation.ui.AppBarConfiguration 8 | import androidx.navigation.ui.NavigationUI 9 | import androidx.navigation.ui.setupWithNavController 10 | import com.google.android.material.appbar.MaterialToolbar 11 | import com.decimalab.easytask.R 12 | import kotlinx.android.synthetic.main.activity_main.* 13 | 14 | class MainActivity : AppCompatActivity() { 15 | 16 | companion object { 17 | const val TAG = "MainActivity" 18 | } 19 | 20 | private lateinit var appBarConfiguration: AppBarConfiguration 21 | private lateinit var navController: NavController 22 | private lateinit var toolbar: MaterialToolbar 23 | 24 | override fun onCreate(savedInstanceState: Bundle?) { 25 | super.onCreate(savedInstanceState) 26 | setContentView(R.layout.activity_main) 27 | 28 | toolbar = tool_bar as MaterialToolbar 29 | setSupportActionBar(toolbar) 30 | 31 | bottomNavigation() 32 | } 33 | 34 | private fun bottomNavigation() { 35 | appBarConfiguration = AppBarConfiguration.Builder( 36 | R.id.navigation_home, 37 | R.id.navigation_add_task, 38 | R.id.navigation_profile 39 | ).build() 40 | 41 | navController = Navigation.findNavController(this, R.id.nav_host_fragment) 42 | NavigationUI.setupWithNavController(bottomNavigationView, navController) 43 | 44 | toolbar.setupWithNavController(navController) 45 | } 46 | 47 | override fun onSupportNavigateUp(): Boolean { 48 | return navController.navigateUp() 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/view/ui/profile/ProfileFragment.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.view.ui.profile 2 | 3 | import android.os.Bundle 4 | import android.util.Log 5 | import android.view.* 6 | import androidx.fragment.app.Fragment 7 | import androidx.lifecycle.Observer 8 | import androidx.lifecycle.ViewModelProvider 9 | import androidx.navigation.fragment.findNavController 10 | import com.bumptech.glide.Glide 11 | import com.bumptech.glide.request.RequestOptions 12 | import com.bumptech.glide.signature.ObjectKey 13 | 14 | import com.decimalab.easytask.R 15 | import com.decimalab.easytask.viewmodel.profile.ProfileViewModel 16 | import kotlinx.android.synthetic.main.profile_fragment.* 17 | 18 | class ProfileFragment : Fragment() { 19 | 20 | companion object { 21 | const val TAG = "ProfileFragment" 22 | } 23 | 24 | private lateinit var viewModel: ProfileViewModel 25 | 26 | override fun onCreateView( 27 | inflater: LayoutInflater, container: ViewGroup?, 28 | savedInstanceState: Bundle? 29 | ): View? { 30 | return inflater.inflate(R.layout.profile_fragment, container, false) 31 | } 32 | 33 | override fun onActivityCreated(savedInstanceState: Bundle?) { 34 | super.onActivityCreated(savedInstanceState) 35 | setHasOptionsMenu(true) 36 | viewModel = ViewModelProvider(this).get(ProfileViewModel::class.java) 37 | 38 | observer() 39 | 40 | } 41 | 42 | private fun observer() { 43 | viewModel.loading.observe(viewLifecycleOwner, Observer { 44 | pb_profile.visibility = if (it) View.VISIBLE else View.GONE 45 | }) 46 | 47 | viewModel.getUserProfile().observe(viewLifecycleOwner, Observer { 48 | profileName.text = it.name 49 | profileEmail.text = it.email 50 | profileBio.text = it.bio 51 | 52 | Log.e(TAG, "glide on ") 53 | 54 | Glide.with(this) 55 | .load(it.profileImage) 56 | .apply(RequestOptions().signature(ObjectKey(System.currentTimeMillis()))) 57 | .circleCrop() 58 | .into(profileImage) 59 | 60 | Log.e(TAG, "glide off ") 61 | 62 | }) 63 | } 64 | 65 | override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { 66 | super.onCreateOptionsMenu(menu, inflater) 67 | 68 | inflater.inflate(R.menu.profile_edit_menu, menu) 69 | } 70 | 71 | override fun onOptionsItemSelected(item: MenuItem): Boolean { 72 | when (item.itemId) { 73 | R.id.navigation_edit_profile -> 74 | 75 | findNavController().navigate( 76 | ProfileFragmentDirections.actionNavigationProfileToEditProfileFragment( 77 | 78 | profileName.text.toString(), 79 | profileEmail.text.toString(), 80 | profileBio.text.toString(), 81 | viewModel.imageUrl.value.toString() 82 | ) 83 | ) 84 | 85 | } 86 | 87 | return false 88 | 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/view/ui/splash/SplashActivity.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.view.ui.splash 2 | 3 | import android.content.Intent 4 | import androidx.appcompat.app.AppCompatActivity 5 | import android.os.Bundle 6 | import android.provider.Settings 7 | import androidx.lifecycle.Observer 8 | import androidx.lifecycle.ViewModelProvider 9 | import com.decimalab.easytask.R 10 | import com.decimalab.easytask.util.GeneralHelper 11 | import com.decimalab.easytask.util.network.NetworkHelper 12 | import com.decimalab.easytask.view.ui.auth.LoginActivity 13 | import com.decimalab.easytask.view.ui.main.MainActivity 14 | import com.decimalab.easytask.viewmodel.splash.SplashViewModel 15 | import kotlinx.coroutines.* 16 | import org.jetbrains.anko.alert 17 | import org.jetbrains.anko.intentFor 18 | 19 | class SplashActivity : AppCompatActivity() { 20 | 21 | companion object { 22 | const val TAG = "SplashActivity" 23 | } 24 | 25 | private lateinit var viewModel: SplashViewModel 26 | private val mContext = this 27 | 28 | override fun onCreate(savedInstanceState: Bundle?) { 29 | super.onCreate(savedInstanceState) 30 | setContentView(R.layout.activity_splash) 31 | 32 | //hiding status bar 33 | GeneralHelper.hideStatusBar(this) 34 | 35 | viewModel = ViewModelProvider(this).get(SplashViewModel::class.java) 36 | 37 | 38 | //splash delay 39 | CoroutineScope(Dispatchers.IO).launch { 40 | checkNetwork() 41 | } 42 | } 43 | 44 | //checking for internet connection 45 | suspend fun checkNetwork() { 46 | 47 | delay(2000L) 48 | 49 | val status = NetworkHelper.isNetworkConnected(this) 50 | 51 | if (status) { 52 | 53 | withContext(Dispatchers.Main) { 54 | viewModel.token.observe(mContext, Observer { 55 | 56 | if (it.isNullOrEmpty()) { 57 | startActivity(intentFor()) 58 | } else { 59 | viewModel.validateToken().observe(mContext, Observer { 60 | 61 | if (it.code() == 200) { 62 | 63 | val msg = it.body() 64 | 65 | if (msg?.message == "true") { 66 | finish() 67 | startActivity(intentFor()) 68 | } else { 69 | startActivity(intentFor()) 70 | } 71 | } 72 | }) 73 | } 74 | }) 75 | } 76 | } else { 77 | 78 | withContext(Dispatchers.Main) { 79 | 80 | showNetworkDialogue() 81 | } 82 | } 83 | } 84 | 85 | 86 | private fun showNetworkDialogue() { 87 | alert { 88 | isCancelable = false 89 | title = getString(R.string.error_no_internet) 90 | message = getString(R.string.error_no_internet_msg) 91 | positiveButton("OK") { 92 | it.dismiss() 93 | val intent = Intent(Settings.ACTION_NETWORK_OPERATOR_SETTINGS) 94 | startActivity(intent) 95 | } 96 | }.show() 97 | } 98 | 99 | override fun onRestart() { 100 | super.onRestart() 101 | CoroutineScope(Dispatchers.IO).launch { 102 | checkNetwork() 103 | } 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/view/ui/task/TaskFragment.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.view.ui.task 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.lifecycle.Observer 9 | import androidx.lifecycle.ViewModelProvider 10 | 11 | import com.decimalab.easytask.R 12 | import com.decimalab.easytask.model.remote.request.task.AddTaskRequest 13 | import com.decimalab.easytask.viewmodel.task.TaskViewModel 14 | import kotlinx.android.synthetic.main.task_fragment.* 15 | import kotlinx.android.synthetic.main.task_fragment.view.* 16 | import kotlinx.android.synthetic.main.task_fragment.view.txt_body 17 | import kotlinx.android.synthetic.main.task_fragment.view.txt_title 18 | import org.jetbrains.anko.support.v4.alert 19 | 20 | class TaskFragment : Fragment() { 21 | 22 | companion object { 23 | const val TAG = "TaskFragment" 24 | } 25 | 26 | private lateinit var viewModel: TaskViewModel 27 | private val taskList: ArrayList = ArrayList() 28 | private var userId: Int = 0 29 | private lateinit var v: View 30 | 31 | override fun onCreateView( 32 | inflater: LayoutInflater, container: ViewGroup?, 33 | savedInstanceState: Bundle? 34 | ): View? { 35 | 36 | v = inflater.inflate(R.layout.task_fragment, container, false) 37 | 38 | resources.getStringArray(R.array.task_status_list).toCollection(taskList) 39 | 40 | v.fab_addTask.setOnClickListener { 41 | prepareAddTask(v) 42 | } 43 | 44 | return v 45 | } 46 | 47 | override fun onActivityCreated(savedInstanceState: Bundle?) { 48 | super.onActivityCreated(savedInstanceState) 49 | viewModel = ViewModelProvider(this).get(TaskViewModel::class.java) 50 | viewModel.userId.observe(viewLifecycleOwner, Observer { 51 | userId = it 52 | }) 53 | 54 | observeProgressBar(v) 55 | 56 | } 57 | 58 | private fun prepareAddTask(view: View) { 59 | 60 | val title = view.txt_title.text.toString() 61 | val body = view.txt_body.text.toString() 62 | val status = view.spinner_task.selectedItem.toString() 63 | 64 | val addTaskRequest = AddTaskRequest(userId, title, body, status) 65 | 66 | addTask(addTaskRequest) 67 | 68 | 69 | } 70 | 71 | private fun addTask(addTaskRequest: AddTaskRequest) { 72 | 73 | viewModel.addTask(addTaskRequest).observe(viewLifecycleOwner, Observer { 74 | 75 | if (it!!) { 76 | successDialog() 77 | } 78 | else 79 | { 80 | unSuccessFulDialog() 81 | } 82 | }) 83 | } 84 | 85 | private fun observeProgressBar(view: View) { 86 | 87 | viewModel.progress.observe(viewLifecycleOwner, Observer { 88 | 89 | if (it) { 90 | 91 | view.progressBar.visibility = View.VISIBLE 92 | 93 | } else { 94 | view.progressBar.visibility = View.GONE 95 | 96 | } 97 | 98 | }) 99 | 100 | viewModel.isError.observe(viewLifecycleOwner, Observer { 101 | errorDialog(it) 102 | }) 103 | 104 | } 105 | 106 | private fun successDialog() { 107 | alert { 108 | title = getString(R.string.title_success_dialog) 109 | message = getString(R.string.msg_add_post_success) 110 | isCancelable = false 111 | positiveButton(getString(R.string.btn_ok)) { dialog -> 112 | //clear the edit text 113 | txt_title.text?.clear() 114 | txt_body.text?.clear() 115 | 116 | dialog.dismiss() 117 | } 118 | }.show() 119 | } 120 | 121 | private fun unSuccessFulDialog() { 122 | alert { 123 | title = getString(R.string.title_un_successful_dialog) 124 | message = getString(R.string.msg_add_post_un_successful) 125 | isCancelable = false 126 | positiveButton(getString(R.string.btn_ok)) { dialog -> 127 | dialog.dismiss() 128 | } 129 | }.show() 130 | } 131 | 132 | private fun errorDialog(errorMsg: String) { 133 | alert { 134 | title = getString(R.string.title_error_dialog) 135 | message = errorMsg 136 | isCancelable = false 137 | positiveButton(getString(R.string.btn_ok)) { dialog -> 138 | dialog.dismiss() 139 | } 140 | }.show() 141 | 142 | } 143 | 144 | } 145 | -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/view/ui/task/detail/TaskDetailFragment.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.view.ui.task.detail 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.lifecycle.Observer 9 | import androidx.lifecycle.ViewModelProvider 10 | import androidx.navigation.fragment.findNavController 11 | 12 | import com.decimalab.easytask.R 13 | import com.decimalab.easytask.viewmodel.task.TaskDetailViewModel 14 | import kotlinx.android.synthetic.main.task_detail_fragment.* 15 | import org.jetbrains.anko.support.v4.alert 16 | 17 | class TaskDetailFragment : Fragment() { 18 | 19 | companion object { 20 | const val TAG = "TaskDetailFragment" 21 | } 22 | 23 | private lateinit var viewModel: TaskDetailViewModel 24 | 25 | override fun onCreateView( 26 | inflater: LayoutInflater, container: ViewGroup?, 27 | savedInstanceState: Bundle? 28 | ): View = inflater.inflate(R.layout.task_detail_fragment, container, false) 29 | 30 | override fun onActivityCreated(savedInstanceState: Bundle?) { 31 | super.onActivityCreated(savedInstanceState) 32 | 33 | viewModel = ViewModelProvider(this).get(TaskDetailViewModel::class.java) 34 | 35 | val args = TaskDetailFragmentArgs.fromBundle(requireArguments()) 36 | viewModel.dataTime.value = args.dateTime 37 | viewModel.title.value = args.title 38 | viewModel.body.value = args.body 39 | viewModel.status.value = args.status 40 | viewModel.userIdField.value = args.userId 41 | viewModel.bgColor.value = args.statusColor 42 | viewModel.apiTaskId.value = args.id 43 | viewModel.taskId.value = args.taskId 44 | 45 | viewModel.checkUserId() 46 | 47 | observerData() 48 | 49 | fb_edit.setOnClickListener { 50 | findNavController().navigate( 51 | TaskDetailFragmentDirections.actionTaskDetailFragmentToEditTaskFragment( 52 | viewModel.apiTaskId.value.toString(), 53 | viewModel.title.value.toString(), 54 | viewModel.body.value.toString(), 55 | viewModel.status.value.toString(), 56 | viewModel.taskId.value.toString() 57 | ) 58 | ) 59 | } 60 | 61 | fb_delete.setOnClickListener { 62 | deleteConfirmDialog() 63 | } 64 | 65 | } 66 | 67 | private fun observerData() { 68 | viewModel.apiTaskId.observe(viewLifecycleOwner, Observer { 69 | 70 | }) 71 | 72 | viewModel.dataTime.observe(viewLifecycleOwner, Observer { 73 | tv_date_time.text = it 74 | }) 75 | viewModel.title.observe(viewLifecycleOwner, Observer { 76 | tv_title.text = it 77 | }) 78 | 79 | viewModel.body.observe(viewLifecycleOwner, Observer { 80 | tv_body.text = it 81 | }) 82 | 83 | viewModel.status.observe(viewLifecycleOwner, Observer { 84 | tv_status.text = it 85 | }) 86 | 87 | viewModel.userIdField.observe(viewLifecycleOwner, Observer { 88 | tv_user_id.text = it 89 | }) 90 | 91 | viewModel.bgColor.observe(viewLifecycleOwner, Observer { 92 | status_color.setBackgroundResource(it.toInt()) 93 | 94 | }) 95 | 96 | viewModel.isValidUser.observe(viewLifecycleOwner, Observer { 97 | 98 | fb_edit.visibility = if (it) View.VISIBLE else View.GONE 99 | fb_delete.visibility = if (it) View.VISIBLE else View.GONE 100 | }) 101 | viewModel.isDeleted.observe(viewLifecycleOwner, Observer { 102 | if (it) { 103 | deleteSuccessDialog() 104 | } else { 105 | deleteErrorDialog() 106 | } 107 | }) 108 | } 109 | 110 | private fun deleteConfirmDialog() { 111 | alert { 112 | isCancelable = false 113 | title = getString(R.string.alert_delete_title) 114 | message = getString(R.string.alert_delete_msg) 115 | positiveButton("YES") { 116 | it.dismiss() 117 | viewModel.deleteTask() 118 | } 119 | negativeButton("NO") { 120 | it.dismiss() 121 | } 122 | }.show() 123 | } 124 | 125 | private fun deleteSuccessDialog() { 126 | alert { 127 | isCancelable = false 128 | title = getString(R.string.alert_success_title) 129 | message = getString(R.string.alert_delete_success) 130 | positiveButton("OK") { 131 | it.dismiss() 132 | findNavController().navigate(TaskDetailFragmentDirections.actionTaskDetailFragmentToNavigationHome()) 133 | } 134 | }.show() 135 | } 136 | 137 | private fun deleteErrorDialog() { 138 | alert { 139 | isCancelable = false 140 | title = getString(R.string.alert_error_title) 141 | message = getString(R.string.alert_delete_error) 142 | positiveButton("OK") { 143 | it.dismiss() 144 | } 145 | }.show() 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/view/ui/task/edit/EditTaskFragment.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.view.ui.task.edit 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.lifecycle.Observer 9 | import androidx.lifecycle.ViewModelProvider 10 | import androidx.navigation.fragment.findNavController 11 | 12 | import com.decimalab.easytask.R 13 | import com.decimalab.easytask.viewmodel.task.EditTaskViewModel 14 | import kotlinx.android.synthetic.main.edit_task_fragment.* 15 | import org.jetbrains.anko.support.v4.alert 16 | 17 | class EditTaskFragment : Fragment() { 18 | 19 | companion object { 20 | const val TAG = "EditTaskFragment" 21 | } 22 | 23 | private lateinit var viewModel: EditTaskViewModel 24 | 25 | override fun onCreateView( 26 | inflater: LayoutInflater, container: ViewGroup?, 27 | savedInstanceState: Bundle? 28 | ): View = inflater.inflate(R.layout.edit_task_fragment, container, false) 29 | 30 | 31 | override fun onActivityCreated(savedInstanceState: Bundle?) { 32 | super.onActivityCreated(savedInstanceState) 33 | viewModel = ViewModelProvider(this).get(EditTaskViewModel::class.java) 34 | 35 | resources.getStringArray(R.array.task_status_list).toCollection(viewModel.taskList) 36 | 37 | val args = EditTaskFragmentArgs.fromBundle(requireArguments()) 38 | viewModel.id.value = args.id 39 | viewModel.taskId.value = args.taskId 40 | viewModel.title.value = args.taskTitle 41 | viewModel.body.value = args.taskBody 42 | viewModel.status.value = args.taskStatus 43 | 44 | 45 | 46 | fab_editTask.setOnClickListener { 47 | viewModel.status.value = edit_spinner_task.selectedItem.toString() 48 | viewModel.title.value = edit_title.text.toString() 49 | viewModel.body.value = edit_body.text.toString() 50 | viewModel.editTask() 51 | } 52 | 53 | observeData() 54 | } 55 | 56 | private fun observeData() { 57 | viewModel.id.observe(viewLifecycleOwner, Observer { 58 | 59 | }) 60 | 61 | viewModel.title.observe(viewLifecycleOwner, Observer { 62 | edit_title.setText(it) 63 | 64 | }) 65 | 66 | viewModel.body.observe(viewLifecycleOwner, Observer { 67 | edit_body.setText(it) 68 | 69 | }) 70 | 71 | viewModel.status.observe(viewLifecycleOwner, Observer { 72 | viewModel.getIndexFromTaskList() 73 | edit_spinner_task.setSelection(viewModel.index.value!!) 74 | }) 75 | 76 | viewModel.loading.observe(viewLifecycleOwner, Observer { 77 | pb_editTask.visibility = if (it) View.VISIBLE else View.GONE 78 | }) 79 | 80 | viewModel.isSuccess.observe(viewLifecycleOwner, Observer { 81 | if (it) { 82 | successDialog() 83 | } else { 84 | unSuccessFullDialog() 85 | } 86 | }) 87 | viewModel.isError.observe(viewLifecycleOwner, Observer { 88 | errorDialog(it) 89 | }) 90 | } 91 | 92 | private fun successDialog() { 93 | alert { 94 | isCancelable = false 95 | title = getString(R.string.alert_success_title) 96 | message = getString(R.string.alert_edit_success_msg) 97 | positiveButton("OK") { 98 | it.dismiss() 99 | findNavController().navigate(EditTaskFragmentDirections.actionEditTaskFragmentToNavigationHome()) 100 | } 101 | }.show() 102 | } 103 | 104 | private fun unSuccessFullDialog() { 105 | alert { 106 | title = getString(R.string.title_un_successful_dialog) 107 | message = getString(R.string.msg_add_post_un_successful) 108 | isCancelable = false 109 | positiveButton(getString(R.string.btn_ok)) { dialog -> 110 | dialog.dismiss() 111 | } 112 | }.show() 113 | } 114 | 115 | private fun errorDialog(errorMsg: String) { 116 | alert { 117 | title = getString(R.string.title_error_dialog) 118 | message = errorMsg 119 | isCancelable = false 120 | positiveButton(getString(R.string.btn_ok)) { dialog -> 121 | dialog.dismiss() 122 | } 123 | }.show() 124 | 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/viewmodel/auth/LoginViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.viewmodel.auth 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import android.util.Log 6 | import androidx.lifecycle.AndroidViewModel 7 | import androidx.lifecycle.MutableLiveData 8 | import androidx.lifecycle.liveData 9 | import com.decimalab.easytask.BuildConfig 10 | import com.decimalab.easytask.model.local.AppPreferences 11 | import com.decimalab.easytask.model.remote.Networking 12 | import com.decimalab.easytask.model.remote.request.auth.LoginRequest 13 | import com.decimalab.easytask.model.remote.response.auth.LoginResponse 14 | import com.decimalab.easytask.model.repository.LoginRepository 15 | import com.decimalab.easytask.util.network.NetworkHelper 16 | import kotlinx.coroutines.Dispatchers.IO 17 | import retrofit2.HttpException 18 | import kotlin.Exception 19 | 20 | /** 21 | * Created by Shakil Ahmed Shaj on 14,April,2020. 22 | * shakilahmedshaj@gmail.com 23 | */ 24 | class LoginViewModel(application: Application) : AndroidViewModel(application) { 25 | 26 | companion object { 27 | const val TAG = "LoginViewModel" 28 | } 29 | 30 | private val networkService = Networking.create(BuildConfig.BASE_URL) 31 | private var loginRepository: LoginRepository 32 | private var sharedPreferences = application.getSharedPreferences(BuildConfig.PREF_NAME, Context.MODE_PRIVATE) 33 | private var appPreferences: AppPreferences 34 | private val loginResponse: MutableLiveData = MutableLiveData() 35 | val isSuccess: MutableLiveData = MutableLiveData() 36 | val isError: MutableLiveData = MutableLiveData() 37 | val errorMsg: MutableLiveData = MutableLiveData() 38 | 39 | init { 40 | appPreferences = AppPreferences(sharedPreferences) 41 | loginRepository = LoginRepository(networkService, appPreferences) 42 | } 43 | 44 | fun login(loginRequest: LoginRequest) = liveData(IO) { 45 | 46 | try { 47 | val data = loginRepository.login(loginRequest) 48 | if (data.code() == 200) { 49 | loginResponse.postValue(data.body()) 50 | isSuccess.postValue(true) 51 | emit(loginResponse.value) 52 | } else { 53 | val error = NetworkHelper.handelNetworkError(data) 54 | errorMsg.postValue(error.message) 55 | isSuccess.postValue(false) 56 | } 57 | } catch (httpException: HttpException) { 58 | Log.e(TAG, httpException.toString()) 59 | isError.postValue(httpException.toString()) 60 | 61 | } catch (exception: Exception) { 62 | Log.e(TAG, exception.toString()) 63 | isError.postValue(exception.toString()) 64 | } 65 | 66 | } 67 | 68 | fun saveUserDetail(loginResponse: LoginResponse) = liveData(IO) { 69 | val dataScope = loginRepository.saveUserDetail(loginResponse) 70 | emit(dataScope) 71 | } 72 | 73 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/viewmodel/auth/SignUpViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.viewmodel.auth 2 | 3 | import android.util.Log 4 | import androidx.lifecycle.MutableLiveData 5 | import androidx.lifecycle.ViewModel 6 | import androidx.lifecycle.viewModelScope 7 | import com.decimalab.easytask.BuildConfig 8 | import com.decimalab.easytask.model.remote.Networking 9 | import com.decimalab.easytask.model.remote.request.auth.RegisterRequest 10 | import com.decimalab.easytask.model.repository.RegisterRepository 11 | import kotlinx.coroutines.launch 12 | import retrofit2.HttpException 13 | 14 | /** 15 | * Created by Shakil Ahmed Shaj on 14,April,2020. 16 | * shakilahmedshaj@gmail.com 17 | */ 18 | class SignUpViewModel : ViewModel() { 19 | 20 | companion object { 21 | const val TAG = "RegisterViewModel" 22 | } 23 | 24 | private val networkService = Networking.create(BuildConfig.BASE_URL) 25 | private val registerRepository = RegisterRepository(networkService) 26 | val isSuccess: MutableLiveData = MutableLiveData() 27 | val isError: MutableLiveData = MutableLiveData() 28 | val loading: MutableLiveData = MutableLiveData() 29 | 30 | fun register(registerRequest: RegisterRequest) { 31 | loading.value = true 32 | viewModelScope.launch { 33 | try { 34 | val data = registerRepository.register(registerRequest) 35 | isSuccess.postValue(data.code() == 201) 36 | 37 | loading.postValue(false) 38 | 39 | } catch (httpException: HttpException) { 40 | Log.e(TAG, httpException.toString()) 41 | isError.postValue(httpException.toString()) 42 | loading.postValue(false) 43 | 44 | } catch (exception: Exception) { 45 | Log.e(TAG, exception.toString()) 46 | isError.postValue(exception.toString()) 47 | loading.postValue(false) 48 | } 49 | 50 | } 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/viewmodel/edit/EditProfileViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.viewmodel.edit 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import android.util.Log 6 | import androidx.lifecycle.AndroidViewModel 7 | import androidx.lifecycle.MutableLiveData 8 | import androidx.lifecycle.liveData 9 | import com.decimalab.easytask.BuildConfig 10 | import com.decimalab.easytask.model.local.AppPreferences 11 | import com.decimalab.easytask.model.remote.Networking 12 | import com.decimalab.easytask.model.remote.response.profile.EditProfileResponse 13 | import com.decimalab.easytask.model.repository.UserProfileRepository 14 | import okhttp3.MediaType 15 | import okhttp3.MultipartBody 16 | import okhttp3.RequestBody 17 | import retrofit2.HttpException 18 | import java.io.File 19 | 20 | class EditProfileViewModel(application: Application) : AndroidViewModel(application) { 21 | 22 | companion object { 23 | const val TAG = "EditProfileViewModel" 24 | } 25 | 26 | private val networkService = Networking.create(BuildConfig.BASE_URL) 27 | private var userProfileRepository: UserProfileRepository 28 | private var sharedPreferences = application.getSharedPreferences(BuildConfig.PREF_NAME, Context.MODE_PRIVATE) 29 | private var appPreferences: AppPreferences 30 | 31 | private var token: String 32 | private var userId: String 33 | 34 | val loading: MutableLiveData = MutableLiveData() 35 | val imageUrl: MutableLiveData = MutableLiveData() 36 | val nameField: MutableLiveData = MutableLiveData() 37 | val emailField: MutableLiveData = MutableLiveData() 38 | val imageField: MutableLiveData = MutableLiveData() 39 | val biolField: MutableLiveData = MutableLiveData() 40 | val profile: MutableLiveData = MutableLiveData() 41 | 42 | init { 43 | userProfileRepository = UserProfileRepository(networkService) 44 | appPreferences = AppPreferences(sharedPreferences) 45 | 46 | token = appPreferences.getAccessToken().toString() 47 | userId = appPreferences.getUserId().toString() 48 | } 49 | 50 | fun editProfile() = liveData { 51 | 52 | 53 | try { 54 | loading.postValue(true) 55 | var profileImage: MultipartBody.Part? = null 56 | 57 | val id = RequestBody.create(MediaType.parse("multipart/form-data"), userId) 58 | val name = RequestBody.create(MediaType.parse("multipart/form-data"), nameField.value!!) 59 | val email = 60 | RequestBody.create(MediaType.parse("multipart/form-data"), emailField.value!!) 61 | if (imageField.value != null) { 62 | val file: RequestBody = 63 | RequestBody.create(MediaType.parse("multipart/form-data"), imageField.value!!) 64 | profileImage = 65 | MultipartBody.Part.createFormData("profile_image", imageField.value?.name, file) 66 | } 67 | val bio = RequestBody.create(MediaType.parse("multipart/form-data"), biolField.value!!) 68 | 69 | val data = userProfileRepository.editProfile(token, id, name, email, profileImage, bio) 70 | 71 | if (data.code() == 200) { 72 | profile.postValue(data.body()) 73 | } 74 | 75 | emit(profile.value) 76 | 77 | loading.postValue(false) 78 | 79 | } catch (httpException: HttpException) { 80 | Log.e(TAG, httpException.toString()) 81 | 82 | 83 | } catch (exception: Exception) { 84 | Log.e(TAG, exception.toString()) 85 | 86 | } 87 | 88 | 89 | } 90 | 91 | 92 | } 93 | -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/viewmodel/profile/ProfileViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.viewmodel.profile 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import android.util.Log 6 | import androidx.lifecycle.AndroidViewModel 7 | import androidx.lifecycle.MutableLiveData 8 | import androidx.lifecycle.liveData 9 | import com.decimalab.easytask.BuildConfig 10 | import com.decimalab.easytask.model.local.AppPreferences 11 | import com.decimalab.easytask.model.remote.Networking 12 | import com.decimalab.easytask.model.remote.response.profile.UserProfileResponse 13 | import com.decimalab.easytask.model.repository.UserProfileRepository 14 | import retrofit2.HttpException 15 | 16 | class ProfileViewModel(application: Application) : AndroidViewModel(application) { 17 | 18 | companion object { 19 | const val TAG = "ProfileViewModel" 20 | } 21 | 22 | private val networkService = Networking.create(BuildConfig.BASE_URL) 23 | private var userProfileRepository: UserProfileRepository 24 | private var sharedPreferences = application.getSharedPreferences(BuildConfig.PREF_NAME, Context.MODE_PRIVATE) 25 | private var appPreferences: AppPreferences 26 | private var token: String 27 | private var userId: String 28 | lateinit var profile: UserProfileResponse 29 | 30 | val imageUrl: MutableLiveData = MutableLiveData() 31 | val loading: MutableLiveData = MutableLiveData() 32 | 33 | init { 34 | userProfileRepository = UserProfileRepository(networkService) 35 | appPreferences = AppPreferences(sharedPreferences) 36 | 37 | token = appPreferences.getAccessToken().toString() 38 | userId = appPreferences.getUserId().toString() 39 | } 40 | 41 | fun getUserProfile() = liveData { 42 | 43 | 44 | try { 45 | loading.postValue(true) 46 | val data = userProfileRepository.getUserProfile(token, userId) 47 | if (data.code() == 200) { 48 | profile = data.body()!! 49 | 50 | imageUrl.postValue(profile.profileImage) 51 | } 52 | 53 | emit(profile) 54 | loading.postValue(false) 55 | 56 | } catch (httpException: HttpException) { 57 | Log.e(TAG, httpException.toString()) 58 | 59 | 60 | } catch (exception: Exception) { 61 | Log.e(TAG, exception.toString()) 62 | 63 | } 64 | 65 | 66 | 67 | 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/viewmodel/splash/SplashViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.viewmodel.splash 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import android.util.Log 6 | import androidx.lifecycle.AndroidViewModel 7 | import androidx.lifecycle.MutableLiveData 8 | import androidx.lifecycle.liveData 9 | import com.decimalab.easytask.BuildConfig 10 | import com.decimalab.easytask.model.local.AppPreferences 11 | import com.decimalab.easytask.model.remote.Networking 12 | import com.decimalab.easytask.model.repository.ValidateTokenRepository 13 | import retrofit2.HttpException 14 | 15 | /** 16 | * Created by Shakil Ahmed Shaj on 15,April,2020. 17 | * shakilahmedshaj@gmail.com 18 | */ 19 | class SplashViewModel(application: Application) : AndroidViewModel(application) { 20 | 21 | companion object { 22 | const val TAG = "SplashViewModel" 23 | } 24 | 25 | private val networkService = Networking.create(BuildConfig.BASE_URL) 26 | private val validateTokenRepository = ValidateTokenRepository(networkService) 27 | private var sharedPreferences = application.getSharedPreferences(BuildConfig.PREF_NAME, Context.MODE_PRIVATE) 28 | private var appPreferences: AppPreferences 29 | var token = MutableLiveData() 30 | 31 | init { 32 | appPreferences = AppPreferences(sharedPreferences) 33 | token.value = appPreferences.getAccessToken() 34 | } 35 | 36 | 37 | fun validateToken() = liveData { 38 | 39 | try { 40 | val data = validateTokenRepository.validateToken(token.value.toString()) 41 | emit(data) 42 | 43 | } catch (httpException: HttpException) { 44 | Log.e(TAG, httpException.toString()) 45 | 46 | 47 | } catch (exception: Exception) { 48 | Log.e(TAG, exception.toString()) 49 | 50 | 51 | } 52 | 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/viewmodel/task/EditTaskViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.viewmodel.task 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import android.util.Log 6 | import androidx.lifecycle.AndroidViewModel 7 | import androidx.lifecycle.MutableLiveData 8 | import com.decimalab.easytask.BuildConfig 9 | import com.decimalab.easytask.model.local.AppPreferences 10 | import com.decimalab.easytask.model.local.db.AppDatabase 11 | import com.decimalab.easytask.model.local.entity.TaskEntity 12 | import com.decimalab.easytask.model.remote.Networking 13 | import com.decimalab.easytask.model.remote.request.task.EditTaskRequest 14 | import com.decimalab.easytask.model.remote.response.task.EditTaskResponse 15 | import com.decimalab.easytask.model.repository.EditTaskRepository 16 | import kotlinx.coroutines.CoroutineScope 17 | import kotlinx.coroutines.Dispatchers 18 | import kotlinx.coroutines.launch 19 | import retrofit2.HttpException 20 | 21 | class EditTaskViewModel(application: Application) : AndroidViewModel(application) { 22 | 23 | companion object { 24 | const val TAG = "EditTaskViewModel" 25 | } 26 | 27 | private val networkService = Networking.create(BuildConfig.BASE_URL) 28 | private var editTaskRepository: EditTaskRepository 29 | private var sharedPreferences = application.getSharedPreferences(BuildConfig.PREF_NAME, Context.MODE_PRIVATE) 30 | private var appPreferences: AppPreferences 31 | private var token: String = "" 32 | 33 | 34 | val id: MutableLiveData = MutableLiveData() 35 | val taskId: MutableLiveData = MutableLiveData() 36 | val title: MutableLiveData = MutableLiveData() 37 | val body: MutableLiveData = MutableLiveData() 38 | val status: MutableLiveData = MutableLiveData() 39 | val index: MutableLiveData = MutableLiveData() 40 | val taskList: ArrayList = ArrayList() 41 | val userId: MutableLiveData = MutableLiveData() 42 | val loading: MutableLiveData = MutableLiveData() 43 | val isSuccess: MutableLiveData = MutableLiveData() 44 | val isError: MutableLiveData = MutableLiveData() 45 | 46 | init { 47 | editTaskRepository = 48 | EditTaskRepository(networkService, AppDatabase.getInstance(application)) 49 | appPreferences = AppPreferences(sharedPreferences) 50 | token = appPreferences.getAccessToken().toString() 51 | userId.value = appPreferences.getUserId() 52 | } 53 | 54 | fun getIndexFromTaskList() { 55 | 56 | index.value = taskList.indexOf(status.value) 57 | } 58 | 59 | fun editTask() { 60 | CoroutineScope(Dispatchers.IO).launch { 61 | try { 62 | loading.postValue(true) 63 | val data = editTaskRepository.editTask( 64 | token, EditTaskRequest( 65 | taskId.value!!.toInt(), 66 | userId.value.toString(), 67 | title.value.toString(), 68 | body.value.toString(), 69 | status.value.toString() 70 | ) 71 | ) 72 | if (data.code() == 201) { 73 | 74 | /* 75 | updating to local db 76 | */ 77 | updateTask(data.body()!!) 78 | isSuccess.postValue(true) 79 | } else { 80 | isSuccess.postValue(false) 81 | } 82 | 83 | loading.postValue(false) 84 | 85 | } catch (httpException: HttpException) { 86 | Log.e(TAG, httpException.toString()) 87 | isError.postValue(httpException.toString()) 88 | 89 | } catch (exception: Exception) { 90 | Log.e(TAG, exception.toString()) 91 | isError.postValue(exception.toString()) 92 | } 93 | 94 | } 95 | 96 | } 97 | 98 | /* 99 | update in local db 100 | */ 101 | 102 | private fun updateTask(editTaskResponse: EditTaskResponse) { 103 | try { 104 | 105 | CoroutineScope(Dispatchers.IO).launch { 106 | 107 | loading.postValue(true) 108 | 109 | val id = editTaskRepository.updateTask( 110 | TaskEntity( 111 | id = id.value!!.toLong(), 112 | taskId = editTaskResponse.id, 113 | title = editTaskResponse.title, 114 | body = editTaskResponse.body, 115 | status = editTaskResponse.status, 116 | userId = editTaskResponse.userId.toInt(), 117 | createdAt = editTaskResponse.createdAt, 118 | updatedAt = editTaskResponse.updatedAt 119 | ) 120 | ) 121 | 122 | if (id > 0) { 123 | Log.e(TAG, " $id : Update Success") 124 | } 125 | loading.postValue(false) 126 | } 127 | 128 | 129 | } catch (error: Exception) { 130 | Log.e(TAG, error.message.toString()) 131 | } 132 | 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/viewmodel/task/TaskDetailViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.viewmodel.task 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import android.util.Log 6 | import androidx.lifecycle.AndroidViewModel 7 | import androidx.lifecycle.MutableLiveData 8 | import androidx.lifecycle.viewModelScope 9 | import com.decimalab.easytask.BuildConfig 10 | import com.decimalab.easytask.model.local.AppPreferences 11 | import com.decimalab.easytask.model.local.db.AppDatabase 12 | import com.decimalab.easytask.model.remote.Networking 13 | import com.decimalab.easytask.model.remote.request.task.DeleteTaskRequest 14 | import com.decimalab.easytask.model.repository.DeleteTaskRepository 15 | import kotlinx.coroutines.launch 16 | import retrofit2.HttpException 17 | 18 | class TaskDetailViewModel(application: Application) : AndroidViewModel(application) { 19 | companion object { 20 | const val TAG = "TaskDetailViewModel" 21 | } 22 | 23 | private val networkService = Networking.create(BuildConfig.BASE_URL) 24 | private lateinit var deleteTaskRepository: DeleteTaskRepository 25 | 26 | private var sharedPreferences = 27 | application.getSharedPreferences(BuildConfig.PREF_NAME, Context.MODE_PRIVATE) 28 | private var appPreferences: AppPreferences 29 | private var userId: String 30 | 31 | val apiTaskId: MutableLiveData = MutableLiveData() 32 | val taskId: MutableLiveData = MutableLiveData() 33 | val dataTime: MutableLiveData = MutableLiveData() 34 | val title: MutableLiveData = MutableLiveData() 35 | val body: MutableLiveData = MutableLiveData() 36 | val status: MutableLiveData = MutableLiveData() 37 | val userIdField: MutableLiveData = MutableLiveData() 38 | val bgColor: MutableLiveData = MutableLiveData() 39 | val isValidUser: MutableLiveData = MutableLiveData() 40 | val isDeleted: MutableLiveData = MutableLiveData() 41 | private var token: String = "" 42 | 43 | init { 44 | deleteTaskRepository = 45 | DeleteTaskRepository(networkService, AppDatabase.getInstance(application)) 46 | appPreferences = AppPreferences(sharedPreferences) 47 | userId = appPreferences.getUserId().toString() 48 | 49 | token = appPreferences.getAccessToken().toString() 50 | } 51 | 52 | 53 | fun checkUserId() { 54 | 55 | try { 56 | isValidUser.value = userIdField.value == userId 57 | 58 | } catch (httpException: HttpException) { 59 | Log.e(TAG, httpException.toString()) 60 | 61 | 62 | } catch (exception: Exception) { 63 | Log.e(TAG, exception.toString()) 64 | 65 | } 66 | 67 | } 68 | 69 | fun deleteTask() { 70 | viewModelScope.launch { 71 | val response = deleteTaskRepository.deleteTaskFromApi( 72 | token, 73 | DeleteTaskRequest(apiTaskId.value!!, userId) 74 | ) 75 | 76 | if (response.code() == 200) { 77 | response.body()?.run { 78 | 79 | val result = deleteTaskRepository.deleteFromDb(apiTaskId.value!!) 80 | 81 | if (result >= 1) { 82 | isDeleted.postValue(true) 83 | Log.d(TAG, "Deleted row : $result") 84 | } else { 85 | isDeleted.postValue(false) 86 | Log.d(TAG, "Error in Delete row") 87 | } 88 | 89 | } 90 | 91 | } 92 | } 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/java/com/decimalab/easytask/viewmodel/task/TaskViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.viewmodel.task 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import android.util.Log 6 | import androidx.lifecycle.AndroidViewModel 7 | import androidx.lifecycle.MutableLiveData 8 | import androidx.lifecycle.liveData 9 | import com.decimalab.easytask.BuildConfig 10 | import com.decimalab.easytask.model.local.AppPreferences 11 | import com.decimalab.easytask.model.remote.Networking 12 | import com.decimalab.easytask.model.remote.request.task.AddTaskRequest 13 | import com.decimalab.easytask.model.repository.AddTaskRepository 14 | import retrofit2.HttpException 15 | 16 | class TaskViewModel(application: Application) : AndroidViewModel(application) { 17 | 18 | companion object { 19 | const val TAG = "TaskViewModel" 20 | } 21 | 22 | private val networkService = Networking.create(BuildConfig.BASE_URL) 23 | private var addTaskRepository: AddTaskRepository 24 | private var sharedPreferences = application.getSharedPreferences(BuildConfig.PREF_NAME, Context.MODE_PRIVATE) 25 | private var appPreferences: AppPreferences 26 | 27 | val userId: MutableLiveData = MutableLiveData() 28 | val isError: MutableLiveData = MutableLiveData() 29 | val progress: MutableLiveData = MutableLiveData() 30 | private val isSuccess: MutableLiveData = MutableLiveData() 31 | 32 | private var token: String = "" 33 | 34 | init { 35 | addTaskRepository = AddTaskRepository(networkService) 36 | appPreferences = AppPreferences(sharedPreferences) 37 | token = appPreferences.getAccessToken().toString() 38 | userId.value = appPreferences.getUserId() 39 | } 40 | 41 | 42 | fun addTask(addTaskRequest: AddTaskRequest) = liveData { 43 | 44 | try { 45 | progress.value = true 46 | 47 | val data = addTaskRepository.addTask(token, addTaskRequest) 48 | isSuccess.value = data.code() == 201 49 | emit(isSuccess.value) 50 | 51 | progress.value = false 52 | 53 | } catch (httpException: HttpException) { 54 | Log.e(TAG, httpException.toString()) 55 | isError.value = httpException.toString() 56 | 57 | 58 | } catch (exception: Exception) { 59 | Log.e(TAG, exception.toString()) 60 | isError.value = exception.toString() 61 | 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_add.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_add_task.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_assignment.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_camera.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_confirm.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_delete.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_edit.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_heart.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_home.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_people.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_profile.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_save.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-hdpi/ic_add.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_add_task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-hdpi/ic_add_task.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_assignment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-hdpi/ic_assignment.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-hdpi/ic_camera.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_confirm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-hdpi/ic_confirm.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-hdpi/ic_delete.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-hdpi/ic_edit.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-hdpi/ic_heart.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-hdpi/ic_home.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_people.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-hdpi/ic_people.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-hdpi/ic_profile.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-hdpi/ic_save.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-mdpi/ic_add.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_add_task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-mdpi/ic_add_task.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_assignment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-mdpi/ic_assignment.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-mdpi/ic_camera.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_confirm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-mdpi/ic_confirm.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-mdpi/ic_delete.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-mdpi/ic_edit.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-mdpi/ic_heart.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-mdpi/ic_home.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_people.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-mdpi/ic_people.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-mdpi/ic_profile.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-mdpi/ic_save.png -------------------------------------------------------------------------------- /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/res/drawable-xhdpi/ic_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xhdpi/ic_add.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_add_task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xhdpi/ic_add_task.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_assignment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xhdpi/ic_assignment.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xhdpi/ic_camera.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_confirm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xhdpi/ic_confirm.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xhdpi/ic_delete.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xhdpi/ic_edit.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xhdpi/ic_heart.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xhdpi/ic_home.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_people.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xhdpi/ic_people.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xhdpi/ic_profile.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xhdpi/ic_save.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xxhdpi/ic_add.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_add_task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xxhdpi/ic_add_task.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_assignment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xxhdpi/ic_assignment.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xxhdpi/ic_camera.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_confirm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xxhdpi/ic_confirm.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xxhdpi/ic_delete.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xxhdpi/ic_edit.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xxhdpi/ic_heart.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xxhdpi/ic_home.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_people.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xxhdpi/ic_people.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xxhdpi/ic_profile.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable-xxhdpi/ic_save.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/fishing_splash.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable/fishing_splash.gif -------------------------------------------------------------------------------- /app/src/main/res/drawable/login_user_avatar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable/login_user_avatar.gif -------------------------------------------------------------------------------- /app/src/main/res/drawable/signup_user_avatar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/drawable/signup_user_avatar.gif -------------------------------------------------------------------------------- /app/src/main/res/drawable/tab_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tab_color_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/font/font_family.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/font/roboto_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/font/roboto_bold.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/roboto_medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/font/roboto_medium.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/roboto_regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/font/roboto_regular.ttf -------------------------------------------------------------------------------- /app/src/main/res/layout-night/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 13 | 23 | 24 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout-night/tool_bar.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 13 | 23 | 24 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/custom_task_list_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 23 | 24 | 25 | 38 | 39 | 40 | 43 | 44 | 56 | 57 | 68 | 69 | 80 | 81 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dark_mode_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 19 | 20 | 28 | 29 | 34 | 35 | 40 | 41 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/res/layout/edit_task_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 21 | 22 | 28 | 29 | 30 | 41 | 42 | 52 | 53 | 54 | 67 | 68 | 80 | 81 | 94 | 95 | 105 | 106 | -------------------------------------------------------------------------------- /app/src/main/res/layout/home_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 13 | 14 | 22 | 23 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/layout/task_detail_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 22 | 23 | 33 | 34 | 45 | 46 | 57 | 58 | 70 | 71 | 78 | 79 | 80 | 93 | 94 | 107 | 108 | -------------------------------------------------------------------------------- /app/src/main/res/layout/task_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 21 | 22 | 28 | 29 | 30 | 41 | 42 | 52 | 53 | 54 | 67 | 68 | 80 | 81 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /app/src/main/res/layout/tool_bar.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/menu/bottom_navigation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 12 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/menu/mode_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/menu/profile_edit_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 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/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/navigation/navigation_base.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 16 | 19 | 22 | 23 | 28 | 33 | 36 | 37 | 42 | 45 | 48 | 51 | 54 | 57 | 61 | 64 | 67 | 70 | 73 | 74 | 79 | 82 | 85 | 88 | 91 | 94 | 99 | 102 | 103 | 108 | 111 | 114 | 117 | 120 | 123 | 124 | -------------------------------------------------------------------------------- /app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | 18 | 19 | 22 | 23 | 28 | 29 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | #2196F3 9 | #304FFE 10 | #BBDEFB 11 | #42A5F5 12 | 13 | #000000 14 | #FFFFFF 15 | #FCF7F7 16 | #1C57AF 17 | #E91E63 18 | 19 | #E80E0E 20 | #2196F3 21 | #4CAF50 22 | #C3F0CA 23 | #DD5656 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18sp 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Easy Task 3 | 4 | Password 5 | Email 6 | Log In 7 | Forgot your login detail? 8 | Get help signing in 9 | No Internet! 10 | Sorry there is no network connection.Please check your network connection. 11 | 12 | OR 13 | Sign up 14 | Don\'t have account? 15 | User Name 16 | Email 17 | User Name 18 | Confirm Password 19 | Sign up 20 | Log In 21 | 22 | Empty UserName! 23 | UserName cannot be empty 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | Password Not Matched! 33 | Confirm password does not match. 34 | Wrong Email 35 | Please check your email address 36 | Weak Password! 37 | Password must be at least 4 characters! 38 | Mismatch! 39 | Password didn\'t match! 40 | 41 | 42 | Home 43 | Add Task 44 | Profile 45 | Title 46 | Body 47 | 48 | OK 49 | Success! 50 | UnSuccessful! 51 | Great! 52 | Error! 53 | Task added successfully. 54 | Sorry! Something went wrong. Please try again. 55 | Hurry! you have created a new account. Please login 56 | Ouch! 57 | There was a error please try again. 58 | Great! 59 | Successfully updated 60 | content description 61 | Posts 62 | Follower 63 | Following 64 | 0 65 | Edit 66 | Name 67 | Bio 68 | Private Information 69 | Email 70 | Email 71 | Name 72 | Bio 73 | 74 | Congratulations ! 75 | Registration Successful. Please Login. 76 | Sorry! 77 | Registration Failed. Please Try Again! 78 | 79 | 80 | 81 | PENDING 82 | STARTED 83 | COMPLETED 84 | 85 | 86 | 87 | The server could not understand the request due to invalid syntax. 88 | Unauthorized! Please login. 89 | The server can not find the requested resource. 90 | The server has encountered a situation it doesn\'t know how to handle. 91 | 92 | Warning! 93 | Do you want to delete? 94 | Successfully Deleted! 95 | Deleting Failed ! 96 | 97 | 98 | 99 | Select App Theme Mode 100 | Light 101 | Dark 102 | System 103 | Battery 104 | App Theme 105 | 106 | 107 | Hello blank fragment 108 | 109 | 110 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | 18 | 19 | 22 | 23 | 28 | 29 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/res/xml/network_security_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | apis.decimalab.com 6 | 7 | 8 | localhost 9 | 10 | 11 | 127.0.0.1 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/test/java/com/decimalab/easytask/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask 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 | @Test 19 | fun sub_isCorrect(){ 20 | assertEquals(5,3+2) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/test/java/com/decimalab/easytask/util/ValidatorTest.kt: -------------------------------------------------------------------------------- 1 | package com.decimalab.easytask.util 2 | 3 | import com.decimalab.easytask.util.Validator.validatePassword 4 | import org.junit.Assert.* 5 | import org.junit.Test 6 | 7 | /** 8 | * Created by Shakil Ahmed Shaj on 26,April,2020. 9 | * shakilahmedshaj@gmail.com 10 | */ 11 | 12 | class ValidatorTest { 13 | 14 | 15 | @Test 16 | fun validateEmail_whenValidEmail_returnTrue() { 17 | val email = "demo1@gmail.com" 18 | 19 | val result = Validator.validateEmail(email) 20 | 21 | assertEquals(true, result) 22 | } 23 | 24 | @Test 25 | fun validatePassword_whenValidPassword_returnTrue() { 26 | 27 | val password = "123456" 28 | 29 | val result = validatePassword(password) 30 | 31 | //assertEquals(true, result) 32 | assertTrue(result) 33 | 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | kotlin_version = '1.4.0' 6 | nav_version = "2.3.0-alpha04" 7 | } 8 | repositories { 9 | google() 10 | jcenter() 11 | 12 | } 13 | dependencies { 14 | classpath 'com.android.tools.build:gradle:4.0.1' 15 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 16 | classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version" 17 | 18 | // NOTE: Do not place your application dependencies here; they belong 19 | // in the individual module build.gradle files 20 | } 21 | } 22 | 23 | allprojects { 24 | repositories { 25 | google() 26 | jcenter() 27 | maven { url "https://jitpack.io" } 28 | 29 | } 30 | } 31 | 32 | task clean(type: Delete) { 33 | delete rootProject.buildDir 34 | } 35 | 36 | ext { 37 | support_library_version = '1.2.0' 38 | anko_version = '0.10.8' 39 | gif_drawable ='1.2.19' 40 | kotlinx_coroutines = '1.3.5' 41 | retrofit_version = '2.8.1' 42 | lifecycle_version = '2.2.0' 43 | nav_version = "2.3.0" 44 | glide_version = "4.11.0" 45 | imagepicker = "1.6" 46 | inline_activity_result_kotlin = "1.0.1" 47 | room_version = "2.2.5" 48 | 49 | 50 | lottieVersion = "3.4.0" 51 | tostyVersion = "1.4.2" 52 | } 53 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShakilAhmedShaj/EasyTask_MVVM_Kotlin/f87cb63848ad2ca57fbdeccbcafdfd11c4b3de6f/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Aug 30 10:43:21 BDT 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-6.1.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | rootProject.name='EasyTask' 3 | --------------------------------------------------------------------------------