Initial commit
							
								
								
									
										14
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,14 @@ | |||||||
|  | *.iml | ||||||
|  | .gradle | ||||||
|  | /local.properties | ||||||
|  | /.idea/caches | ||||||
|  | /.idea/libraries | ||||||
|  | /.idea/modules.xml | ||||||
|  | /.idea/workspace.xml | ||||||
|  | /.idea/navEditor.xml | ||||||
|  | /.idea/assetWizardSettings.xml | ||||||
|  | .DS_Store | ||||||
|  | /build | ||||||
|  | /captures | ||||||
|  | .externalNativeBuild | ||||||
|  | .cxx | ||||||
							
								
								
									
										1
									
								
								.idea/.name
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1 @@ | |||||||
|  | ToDo App | ||||||
							
								
								
									
										122
									
								
								.idea/codeStyles/Project.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,122 @@ | |||||||
|  | <component name="ProjectCodeStyleConfiguration"> | ||||||
|  |   <code_scheme name="Project" version="173"> | ||||||
|  |     <JetCodeStyleSettings> | ||||||
|  |       <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> | ||||||
|  |     </JetCodeStyleSettings> | ||||||
|  |     <codeStyleSettings language="XML"> | ||||||
|  |       <indentOptions> | ||||||
|  |         <option name="CONTINUATION_INDENT_SIZE" value="4" /> | ||||||
|  |       </indentOptions> | ||||||
|  |       <arrangement> | ||||||
|  |         <rules> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>xmlns:android</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>^$</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>xmlns:.*</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>^$</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |               <order>BY_NAME</order> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>.*:id</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>.*:name</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>name</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>^$</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>style</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>^$</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>.*</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>^$</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |               <order>BY_NAME</order> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>.*</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |               <order>ANDROID_ATTRIBUTE_ORDER</order> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>.*</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>.*</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |               <order>BY_NAME</order> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |         </rules> | ||||||
|  |       </arrangement> | ||||||
|  |     </codeStyleSettings> | ||||||
|  |     <codeStyleSettings language="kotlin"> | ||||||
|  |       <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> | ||||||
|  |     </codeStyleSettings> | ||||||
|  |   </code_scheme> | ||||||
|  | </component> | ||||||
							
								
								
									
										5
									
								
								.idea/codeStyles/codeStyleConfig.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,5 @@ | |||||||
|  | <component name="ProjectCodeStyleConfiguration"> | ||||||
|  |   <state> | ||||||
|  |     <option name="USE_PER_PROJECT_SETTINGS" value="true" /> | ||||||
|  |   </state> | ||||||
|  | </component> | ||||||
							
								
								
									
										21
									
								
								.idea/gradle.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,21 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project version="4"> | ||||||
|  |   <component name="GradleMigrationSettings" migrationVersion="1" /> | ||||||
|  |   <component name="GradleSettings"> | ||||||
|  |     <option name="linkedExternalProjectsSettings"> | ||||||
|  |       <GradleProjectSettings> | ||||||
|  |         <option name="testRunner" value="PLATFORM" /> | ||||||
|  |         <option name="distributionType" value="DEFAULT_WRAPPED" /> | ||||||
|  |         <option name="externalProjectPath" value="$PROJECT_DIR$" /> | ||||||
|  |         <option name="gradleJvm" value="1.8" /> | ||||||
|  |         <option name="modules"> | ||||||
|  |           <set> | ||||||
|  |             <option value="$PROJECT_DIR$" /> | ||||||
|  |             <option value="$PROJECT_DIR$/app" /> | ||||||
|  |           </set> | ||||||
|  |         </option> | ||||||
|  |         <option name="resolveModulePerSourceSet" value="false" /> | ||||||
|  |       </GradleProjectSettings> | ||||||
|  |     </option> | ||||||
|  |   </component> | ||||||
|  | </project> | ||||||
							
								
								
									
										25
									
								
								.idea/jarRepositories.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,25 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project version="4"> | ||||||
|  |   <component name="RemoteRepositoriesConfiguration"> | ||||||
|  |     <remote-repository> | ||||||
|  |       <option name="id" value="central" /> | ||||||
|  |       <option name="name" value="Maven Central repository" /> | ||||||
|  |       <option name="url" value="https://repo1.maven.org/maven2" /> | ||||||
|  |     </remote-repository> | ||||||
|  |     <remote-repository> | ||||||
|  |       <option name="id" value="jboss.community" /> | ||||||
|  |       <option name="name" value="JBoss Community repository" /> | ||||||
|  |       <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" /> | ||||||
|  |     </remote-repository> | ||||||
|  |     <remote-repository> | ||||||
|  |       <option name="id" value="BintrayJCenter" /> | ||||||
|  |       <option name="name" value="BintrayJCenter" /> | ||||||
|  |       <option name="url" value="https://jcenter.bintray.com/" /> | ||||||
|  |     </remote-repository> | ||||||
|  |     <remote-repository> | ||||||
|  |       <option name="id" value="Google" /> | ||||||
|  |       <option name="name" value="Google" /> | ||||||
|  |       <option name="url" value="https://dl.google.com/dl/android/maven2/" /> | ||||||
|  |     </remote-repository> | ||||||
|  |   </component> | ||||||
|  | </project> | ||||||
							
								
								
									
										9
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,9 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project version="4"> | ||||||
|  |   <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK"> | ||||||
|  |     <output url="file://$PROJECT_DIR$/build/classes" /> | ||||||
|  |   </component> | ||||||
|  |   <component name="ProjectType"> | ||||||
|  |     <option name="id" value="Android" /> | ||||||
|  |   </component> | ||||||
|  | </project> | ||||||
							
								
								
									
										12
									
								
								.idea/runConfigurations.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,12 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project version="4"> | ||||||
|  |   <component name="RunConfigurationProducerService"> | ||||||
|  |     <option name="ignoredProducers"> | ||||||
|  |       <set> | ||||||
|  |         <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" /> | ||||||
|  |         <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" /> | ||||||
|  |         <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" /> | ||||||
|  |       </set> | ||||||
|  |     </option> | ||||||
|  |   </component> | ||||||
|  | </project> | ||||||
							
								
								
									
										1
									
								
								app/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1 @@ | |||||||
|  | /build | ||||||
							
								
								
									
										80
									
								
								app/build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,80 @@ | |||||||
|  | apply plugin: 'com.android.application' | ||||||
|  | apply plugin: 'kotlin-android' | ||||||
|  | apply plugin: 'kotlin-android-extensions' | ||||||
|  | apply plugin: 'kotlin-kapt' | ||||||
|  | apply plugin: "androidx.navigation.safeargs.kotlin" | ||||||
|  | 
 | ||||||
|  | android { | ||||||
|  |     compileSdkVersion 29 | ||||||
|  |     buildToolsVersion "30.0.0" | ||||||
|  | 
 | ||||||
|  |     defaultConfig { | ||||||
|  |         applicationId "com.example.todoapp" | ||||||
|  |         minSdkVersion 26 | ||||||
|  |         targetSdkVersion 29 | ||||||
|  |         versionCode 1 | ||||||
|  |         versionName "1.0" | ||||||
|  | 
 | ||||||
|  |         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     buildTypes { | ||||||
|  |         release { | ||||||
|  |             minifyEnabled false | ||||||
|  |             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     buildFeatures{ | ||||||
|  |         dataBinding = true | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     compileOptions { | ||||||
|  |         sourceCompatibility JavaVersion.VERSION_1_8 | ||||||
|  |         targetCompatibility JavaVersion.VERSION_1_8 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     kotlinOptions { | ||||||
|  |         jvmTarget = JavaVersion.VERSION_1_8.toString() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | dependencies { | ||||||
|  |     implementation fileTree(dir: "libs", include: ["*.jar"]) | ||||||
|  |     implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" | ||||||
|  |     implementation 'androidx.core:core-ktx:1.3.0' | ||||||
|  |     implementation 'androidx.appcompat:appcompat:1.1.0' | ||||||
|  |     implementation 'androidx.constraintlayout:constraintlayout:1.1.3' | ||||||
|  |     implementation 'androidx.legacy:legacy-support-v4:1.0.0' | ||||||
|  |     testImplementation 'junit:junit:4.13' | ||||||
|  |     androidTestImplementation 'androidx.test.ext:junit:1.1.1' | ||||||
|  |     androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' | ||||||
|  | 
 | ||||||
|  |     // Navigation Component | ||||||
|  |     implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0' | ||||||
|  |     implementation 'androidx.navigation:navigation-ui-ktx:2.3.0' | ||||||
|  | 
 | ||||||
|  |     // Room components | ||||||
|  |     implementation "androidx.room:room-runtime:2.2.5" | ||||||
|  |     kapt "androidx.room:room-compiler:2.2.5" | ||||||
|  |     implementation "androidx.room:room-ktx:2.2.5" | ||||||
|  |     androidTestImplementation "androidx.room:room-testing:2.2.5" | ||||||
|  | 
 | ||||||
|  |     // Lifecycle components | ||||||
|  |     implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" | ||||||
|  |     implementation "androidx.lifecycle:lifecycle-common-java8:2.2.0" | ||||||
|  |     implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0" | ||||||
|  | 
 | ||||||
|  |     // Kotlin components | ||||||
|  |     implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72" | ||||||
|  |     api "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.5" | ||||||
|  |     api "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.5" | ||||||
|  | 
 | ||||||
|  |     // DataBinding | ||||||
|  |     kapt "com.android.databinding:compiler:3.2.0-alpha10" | ||||||
|  |     kapt "androidx.databinding:databinding-common:4.0.0" | ||||||
|  | 
 | ||||||
|  |     // RecyclerView Animator | ||||||
|  |     implementation 'jp.wasabeef:recyclerview-animators:3.0.0' | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								app/proguard-rules.pro
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,21 @@ | |||||||
|  | # Add project specific ProGuard rules here. | ||||||
|  | # You can control the set of applied configuration files using the | ||||||
|  | # proguardFiles setting in build.gradle. | ||||||
|  | # | ||||||
|  | # For more details, see | ||||||
|  | #   http://developer.android.com/guide/developing/tools/proguard.html | ||||||
|  | 
 | ||||||
|  | # If your project uses WebView with JS, uncomment the following | ||||||
|  | # and specify the fully qualified class name to the JavaScript interface | ||||||
|  | # class: | ||||||
|  | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||||||
|  | #   public *; | ||||||
|  | #} | ||||||
|  | 
 | ||||||
|  | # Uncomment this to preserve the line number information for | ||||||
|  | # debugging stack traces. | ||||||
|  | #-keepattributes SourceFile,LineNumberTable | ||||||
|  | 
 | ||||||
|  | # If you keep the line number information, uncomment this to | ||||||
|  | # hide the original source file name. | ||||||
|  | #-renamesourcefileattribute SourceFile | ||||||
| @ -0,0 +1,24 @@ | |||||||
|  | package com.example.todoapp | ||||||
|  | 
 | ||||||
|  | import androidx.test.platform.app.InstrumentationRegistry | ||||||
|  | import androidx.test.ext.junit.runners.AndroidJUnit4 | ||||||
|  | 
 | ||||||
|  | import org.junit.Test | ||||||
|  | import org.junit.runner.RunWith | ||||||
|  | 
 | ||||||
|  | import org.junit.Assert.* | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Instrumented test, which will execute on an Android device. | ||||||
|  |  * | ||||||
|  |  * See [testing documentation](http://d.android.com/tools/testing). | ||||||
|  |  */ | ||||||
|  | @RunWith(AndroidJUnit4::class) | ||||||
|  | class ExampleInstrumentedTest { | ||||||
|  |     @Test | ||||||
|  |     fun useAppContext() { | ||||||
|  |         // Context of the app under test. | ||||||
|  |         val appContext = InstrumentationRegistry.getInstrumentation().targetContext | ||||||
|  |         assertEquals("com.example.todoapp", appContext.packageName) | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								app/src/main/AndroidManifest.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,20 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     package="com.example.todoapp"> | ||||||
|  | 
 | ||||||
|  |     <application | ||||||
|  |         android:allowBackup="true" | ||||||
|  |         android:icon="@mipmap/ic_launcher" | ||||||
|  |         android:label="@string/app_name" | ||||||
|  |         android:roundIcon="@mipmap/ic_launcher_round" | ||||||
|  |         android:supportsRtl="true" | ||||||
|  |         android:theme="@style/AppTheme"> | ||||||
|  |         <activity android:name=".MainActivity"> | ||||||
|  |             <intent-filter> | ||||||
|  |                 <action android:name="android.intent.action.MAIN" /> | ||||||
|  |                 <category android:name="android.intent.category.LAUNCHER" /> | ||||||
|  |             </intent-filter> | ||||||
|  |         </activity> | ||||||
|  |     </application> | ||||||
|  | 
 | ||||||
|  | </manifest> | ||||||
							
								
								
									
										21
									
								
								app/src/main/java/com/example/todoapp/MainActivity.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,21 @@ | |||||||
|  | package com.example.todoapp | ||||||
|  | 
 | ||||||
|  | import androidx.appcompat.app.AppCompatActivity | ||||||
|  | import android.os.Bundle | ||||||
|  | import androidx.navigation.findNavController | ||||||
|  | import androidx.navigation.ui.setupActionBarWithNavController | ||||||
|  | 
 | ||||||
|  | class MainActivity : AppCompatActivity() { | ||||||
|  |     override fun onCreate(savedInstanceState: Bundle?) { | ||||||
|  |         super.onCreate(savedInstanceState) | ||||||
|  |         setContentView(R.layout.activity_main) | ||||||
|  | 
 | ||||||
|  |         setupActionBarWithNavController(findNavController(R.id.navHostFragment)) | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun onSupportNavigateUp(): Boolean { | ||||||
|  |         val navController = findNavController(R.id.navHostFragment) | ||||||
|  |         return navController.navigateUp() || super.onSupportNavigateUp() | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								app/src/main/java/com/example/todoapp/data/Converter.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,18 @@ | |||||||
|  | package com.example.todoapp.data | ||||||
|  | 
 | ||||||
|  | import androidx.room.TypeConverter | ||||||
|  | import com.example.todoapp.data.models.Priority | ||||||
|  | 
 | ||||||
|  | class Converter { | ||||||
|  | 
 | ||||||
|  |     @TypeConverter | ||||||
|  |     fun fromPriority(priority: Priority): String { | ||||||
|  |         return priority.name | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @TypeConverter | ||||||
|  |     fun toPriority(priority: String): Priority { | ||||||
|  |         return Priority.valueOf(priority) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										34
									
								
								app/src/main/java/com/example/todoapp/data/ToDoDao.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,34 @@ | |||||||
|  | package com.example.todoapp.data | ||||||
|  | 
 | ||||||
|  | import androidx.lifecycle.LiveData | ||||||
|  | import androidx.room.* | ||||||
|  | import com.example.todoapp.data.models.ToDoData | ||||||
|  | 
 | ||||||
|  | @Dao | ||||||
|  | interface ToDoDao { | ||||||
|  | 
 | ||||||
|  |     @Query("SELECT * FROM todo_table ORDER BY id ASC") | ||||||
|  |     fun getAllData(): LiveData<List<ToDoData>> | ||||||
|  | 
 | ||||||
|  |     @Insert(onConflict = OnConflictStrategy.IGNORE) | ||||||
|  |     suspend fun insertData(toDoData: ToDoData) | ||||||
|  | 
 | ||||||
|  |     @Update | ||||||
|  |     suspend fun updateData(toDoData: ToDoData) | ||||||
|  | 
 | ||||||
|  |     @Delete | ||||||
|  |     suspend fun deleteItem(toDoData: ToDoData) | ||||||
|  | 
 | ||||||
|  |     @Query("DELETE FROM todo_table") | ||||||
|  |     suspend fun deleteAll() | ||||||
|  | 
 | ||||||
|  |     @Query("SELECT * FROM todo_table WHERE title LIKE :searchQuery") | ||||||
|  |     fun searchDatabase(searchQuery: String): LiveData<List<ToDoData>> | ||||||
|  | 
 | ||||||
|  |     @Query("SELECT * FROM todo_table ORDER BY CASE WHEN priority LIKE 'H%' THEN 1 WHEN priority LIKE 'M%' THEN 2 WHEN priority LIKE 'L%' THEN 3 END") | ||||||
|  |     fun sortByHighPriority(): LiveData<List<ToDoData>> | ||||||
|  | 
 | ||||||
|  |     @Query("SELECT * FROM todo_table ORDER BY CASE WHEN priority LIKE 'L%' THEN 1 WHEN priority LIKE 'M%' THEN 2 WHEN priority LIKE 'H%' THEN 3 END") | ||||||
|  |     fun sortByLowPriority(): LiveData<List<ToDoData>> | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										37
									
								
								app/src/main/java/com/example/todoapp/data/ToDoDatabase.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,37 @@ | |||||||
|  | package com.example.todoapp.data | ||||||
|  | 
 | ||||||
|  | import android.content.Context | ||||||
|  | import androidx.room.Database | ||||||
|  | import androidx.room.Room | ||||||
|  | import androidx.room.RoomDatabase | ||||||
|  | import androidx.room.TypeConverters | ||||||
|  | import com.example.todoapp.data.models.ToDoData | ||||||
|  | 
 | ||||||
|  | @Database(entities = [ToDoData::class], version = 1, exportSchema = false) | ||||||
|  | @TypeConverters(Converter::class) | ||||||
|  | abstract class ToDoDatabase: RoomDatabase() { | ||||||
|  | 
 | ||||||
|  |     abstract fun toDoDao(): ToDoDao | ||||||
|  | 
 | ||||||
|  |     companion object { | ||||||
|  |         @Volatile | ||||||
|  |         private var INSTANCE: ToDoDatabase? = null | ||||||
|  | 
 | ||||||
|  |         fun getDatabase(context: Context): ToDoDatabase { | ||||||
|  |             val tempInstance = INSTANCE | ||||||
|  |             if(tempInstance != null){ | ||||||
|  |                 return tempInstance | ||||||
|  |             } | ||||||
|  |             synchronized(this){ | ||||||
|  |                 val instance = Room.databaseBuilder( | ||||||
|  |                     context.applicationContext, | ||||||
|  |                     ToDoDatabase::class.java, | ||||||
|  |                     "todo_database" | ||||||
|  |                 ).build() | ||||||
|  |                 INSTANCE = instance | ||||||
|  |                 return instance | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,7 @@ | |||||||
|  | package com.example.todoapp.data.models | ||||||
|  | 
 | ||||||
|  | enum class Priority { | ||||||
|  |     HIGH, | ||||||
|  |     MEDIUM, | ||||||
|  |     LOW | ||||||
|  | } | ||||||
| @ -0,0 +1,16 @@ | |||||||
|  | package com.example.todoapp.data.models | ||||||
|  | 
 | ||||||
|  | import android.os.Parcelable | ||||||
|  | import androidx.room.Entity | ||||||
|  | import androidx.room.PrimaryKey | ||||||
|  | import kotlinx.android.parcel.Parcelize | ||||||
|  | 
 | ||||||
|  | @Entity(tableName = "todo_table") | ||||||
|  | @Parcelize | ||||||
|  | data class ToDoData( | ||||||
|  |     @PrimaryKey(autoGenerate = true) | ||||||
|  |     var id: Int, | ||||||
|  |     var title: String, | ||||||
|  |     var priority: Priority, | ||||||
|  |     var description: String | ||||||
|  | ): Parcelable | ||||||
| @ -0,0 +1,33 @@ | |||||||
|  | package com.example.todoapp.data.repository | ||||||
|  | 
 | ||||||
|  | import androidx.lifecycle.LiveData | ||||||
|  | import com.example.todoapp.data.ToDoDao | ||||||
|  | import com.example.todoapp.data.models.ToDoData | ||||||
|  | 
 | ||||||
|  | class ToDoRepository(private val toDoDao: ToDoDao) { | ||||||
|  | 
 | ||||||
|  |     val getAllData: LiveData<List<ToDoData>> = toDoDao.getAllData() | ||||||
|  |     val sortByHighPriority: LiveData<List<ToDoData>> = toDoDao.sortByHighPriority() | ||||||
|  |     val sortByLowPriority: LiveData<List<ToDoData>> = toDoDao.sortByLowPriority() | ||||||
|  | 
 | ||||||
|  |     suspend fun insertData(toDoData: ToDoData){ | ||||||
|  |         toDoDao.insertData(toDoData) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     suspend fun updateData(toDoData: ToDoData){ | ||||||
|  |         toDoDao.updateData(toDoData) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     suspend fun deleteItem(toDoData: ToDoData){ | ||||||
|  |         toDoDao.deleteItem(toDoData) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     suspend fun deleteAll(){ | ||||||
|  |         toDoDao.deleteAll() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun searchDatabase(searchQuery: String): LiveData<List<ToDoData>> { | ||||||
|  |         return toDoDao.searchDatabase(searchQuery) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,59 @@ | |||||||
|  | package com.example.todoapp.data.viewmodel | ||||||
|  | 
 | ||||||
|  | import android.app.Application | ||||||
|  | import androidx.lifecycle.AndroidViewModel | ||||||
|  | import androidx.lifecycle.LiveData | ||||||
|  | import androidx.lifecycle.viewModelScope | ||||||
|  | import com.example.todoapp.data.ToDoDatabase | ||||||
|  | import com.example.todoapp.data.models.ToDoData | ||||||
|  | import com.example.todoapp.data.repository.ToDoRepository | ||||||
|  | import kotlinx.coroutines.Dispatchers | ||||||
|  | import kotlinx.coroutines.launch | ||||||
|  | 
 | ||||||
|  | class ToDoViewModel(application: Application) : AndroidViewModel(application) { | ||||||
|  | 
 | ||||||
|  |     private val toDoDao = ToDoDatabase.getDatabase( | ||||||
|  |         application | ||||||
|  |     ).toDoDao() | ||||||
|  |     private val repository: ToDoRepository | ||||||
|  | 
 | ||||||
|  |     val getAllData: LiveData<List<ToDoData>> | ||||||
|  |     val sortByHighPriority: LiveData<List<ToDoData>> | ||||||
|  |     val sortByLowPriority: LiveData<List<ToDoData>> | ||||||
|  | 
 | ||||||
|  |     init { | ||||||
|  |         repository = ToDoRepository(toDoDao) | ||||||
|  |         getAllData = repository.getAllData | ||||||
|  |         sortByHighPriority = repository.sortByHighPriority | ||||||
|  |         sortByLowPriority = repository.sortByLowPriority | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun insertData(toDoData: ToDoData) { | ||||||
|  |         viewModelScope.launch(Dispatchers.IO) { | ||||||
|  |             repository.insertData(toDoData) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun updateData(toDoData: ToDoData) { | ||||||
|  |         viewModelScope.launch(Dispatchers.IO) { | ||||||
|  |             repository.updateData(toDoData) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun deleteItem(toDoData: ToDoData) { | ||||||
|  |         viewModelScope.launch(Dispatchers.IO) { | ||||||
|  |             repository.deleteItem(toDoData) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun deleteAll() { | ||||||
|  |         viewModelScope.launch(Dispatchers.IO) { | ||||||
|  |             repository.deleteAll() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun searchDatabase(searchQuery: String): LiveData<List<ToDoData>>{ | ||||||
|  |         return repository.searchDatabase(searchQuery) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,66 @@ | |||||||
|  | package com.example.todoapp.fragments | ||||||
|  | 
 | ||||||
|  | import android.view.View | ||||||
|  | import android.widget.Spinner | ||||||
|  | import androidx.cardview.widget.CardView | ||||||
|  | import androidx.constraintlayout.widget.ConstraintLayout | ||||||
|  | import androidx.databinding.BindingAdapter | ||||||
|  | import androidx.lifecycle.MutableLiveData | ||||||
|  | import androidx.navigation.findNavController | ||||||
|  | import com.example.todoapp.R | ||||||
|  | import com.example.todoapp.data.models.Priority | ||||||
|  | import com.example.todoapp.data.models.ToDoData | ||||||
|  | import com.example.todoapp.fragments.list.ListFragmentDirections | ||||||
|  | import com.google.android.material.floatingactionbutton.FloatingActionButton | ||||||
|  | 
 | ||||||
|  | class BindingAdapters { | ||||||
|  | 
 | ||||||
|  |     companion object{ | ||||||
|  | 
 | ||||||
|  |         @BindingAdapter("android:navigateToAddFragment") | ||||||
|  |         @JvmStatic | ||||||
|  |         fun navigateToAddFragment(view: FloatingActionButton, navigate: Boolean){ | ||||||
|  |             view.setOnClickListener { | ||||||
|  |                 if(navigate){ | ||||||
|  |                     view.findNavController().navigate(R.id.action_listFragment_to_addFragment) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         @BindingAdapter("android:emptyDatabase") | ||||||
|  |         @JvmStatic | ||||||
|  |         fun emptyDatabase(view: View, emptyDatabase: MutableLiveData<Boolean>){ | ||||||
|  |             when(emptyDatabase.value){ | ||||||
|  |                 true -> view.visibility = View.VISIBLE | ||||||
|  |                 false -> view.visibility = View.INVISIBLE | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         @BindingAdapter("android:parsePriorityToInt") | ||||||
|  |         @JvmStatic | ||||||
|  |         fun parsePriorityToInt(view: Spinner, priority: Priority){ | ||||||
|  |             when(priority){ | ||||||
|  |                 Priority.HIGH -> { view.setSelection(0) } | ||||||
|  |                 Priority.MEDIUM -> { view.setSelection(1) } | ||||||
|  |                 Priority.LOW -> { view.setSelection(2) } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         @BindingAdapter("android:parsePriorityColor") | ||||||
|  |         @JvmStatic | ||||||
|  |         fun parsePriorityColor(cardView: CardView, priority: Priority){ | ||||||
|  |             when(priority){ | ||||||
|  |                 Priority.HIGH -> { cardView.setCardBackgroundColor(cardView.context.getColor(R.color.red)) } | ||||||
|  |                 Priority.MEDIUM -> { cardView.setCardBackgroundColor(cardView.context.getColor(R.color.yellow)) } | ||||||
|  |                 Priority.LOW -> { cardView.setCardBackgroundColor(cardView.context.getColor(R.color.green)) } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         @BindingAdapter("android:sendDataToUpdateFragment") | ||||||
|  |         @JvmStatic | ||||||
|  |         fun sendDataToUpdateFragment(view: ConstraintLayout, currentItem: ToDoData){ | ||||||
|  |             view.setOnClickListener { | ||||||
|  |                 val action = ListFragmentDirections.actionListFragmentToUpdateFragment(currentItem) | ||||||
|  |                 view.findNavController().navigate(action) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,59 @@ | |||||||
|  | package com.example.todoapp.fragments | ||||||
|  | 
 | ||||||
|  | import android.app.Application | ||||||
|  | import android.text.TextUtils | ||||||
|  | import android.view.View | ||||||
|  | import android.widget.AdapterView | ||||||
|  | import android.widget.TextView | ||||||
|  | import androidx.core.content.ContextCompat | ||||||
|  | import androidx.lifecycle.AndroidViewModel | ||||||
|  | import androidx.lifecycle.MutableLiveData | ||||||
|  | import com.example.todoapp.R | ||||||
|  | import com.example.todoapp.data.models.Priority | ||||||
|  | import com.example.todoapp.data.models.ToDoData | ||||||
|  | 
 | ||||||
|  | class SharedViewModel(application: Application): AndroidViewModel(application) { | ||||||
|  | 
 | ||||||
|  |     /** ============================= List Fragment ============================= */ | ||||||
|  | 
 | ||||||
|  |     val emptyDatabase: MutableLiveData<Boolean> = MutableLiveData(false) | ||||||
|  | 
 | ||||||
|  |     fun checkIfDatabaseEmpty(toDoData: List<ToDoData>){ | ||||||
|  |         emptyDatabase.value = toDoData.isEmpty() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** ============================= Add/Update Fragment ============================= */ | ||||||
|  | 
 | ||||||
|  |     val listener: AdapterView.OnItemSelectedListener = object : | ||||||
|  |         AdapterView.OnItemSelectedListener{ | ||||||
|  |         override fun onNothingSelected(p0: AdapterView<*>?) {} | ||||||
|  |         override fun onItemSelected( | ||||||
|  |             parent: AdapterView<*>?, | ||||||
|  |             view: View?, | ||||||
|  |             position: Int, | ||||||
|  |             id: Long | ||||||
|  |         ) { | ||||||
|  |             when(position){ | ||||||
|  |                 0 -> { (parent?.getChildAt(0) as TextView).setTextColor(ContextCompat.getColor(application, R.color.red)) } | ||||||
|  |                 1 -> { (parent?.getChildAt(0) as TextView).setTextColor(ContextCompat.getColor(application, R.color.yellow)) } | ||||||
|  |                 2 -> { (parent?.getChildAt(0) as TextView).setTextColor(ContextCompat.getColor(application, R.color.green)) } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun verifyDataFromUser(title: String, description: String): Boolean { | ||||||
|  |         return if(TextUtils.isEmpty(title) || TextUtils.isEmpty(description)){ | ||||||
|  |             false | ||||||
|  |         } else !(title.isEmpty() || description.isEmpty()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun parsePriority(priority: String): Priority { | ||||||
|  |         return when(priority){ | ||||||
|  |             "High Priority" -> { Priority.HIGH } | ||||||
|  |             "Medium Priority" -> { Priority.MEDIUM } | ||||||
|  |             "Low Priority" -> { Priority.LOW } | ||||||
|  |             else -> Priority.LOW | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,71 @@ | |||||||
|  | package com.example.todoapp.fragments.add | ||||||
|  | 
 | ||||||
|  | import android.os.Bundle | ||||||
|  | import android.view.* | ||||||
|  | import android.widget.Toast | ||||||
|  | import androidx.fragment.app.Fragment | ||||||
|  | import androidx.fragment.app.viewModels | ||||||
|  | import androidx.navigation.fragment.findNavController | ||||||
|  | import com.example.todoapp.R | ||||||
|  | import com.example.todoapp.data.models.ToDoData | ||||||
|  | import com.example.todoapp.data.viewmodel.ToDoViewModel | ||||||
|  | import com.example.todoapp.fragments.SharedViewModel | ||||||
|  | import kotlinx.android.synthetic.main.fragment_add.* | ||||||
|  | import kotlinx.android.synthetic.main.fragment_add.view.* | ||||||
|  | 
 | ||||||
|  | class AddFragment : Fragment() { | ||||||
|  | 
 | ||||||
|  |     private val mToDoViewModel: ToDoViewModel by viewModels() | ||||||
|  |     private val mSharedViewModel: SharedViewModel by viewModels() | ||||||
|  | 
 | ||||||
|  |     override fun onCreateView( | ||||||
|  |         inflater: LayoutInflater, container: ViewGroup?, | ||||||
|  |         savedInstanceState: Bundle? | ||||||
|  |     ): View? { | ||||||
|  |         // Inflate the layout for this fragment | ||||||
|  |         val view = inflater.inflate(R.layout.fragment_add, container, false) | ||||||
|  | 
 | ||||||
|  |         // Set Menu | ||||||
|  |         setHasOptionsMenu(true) | ||||||
|  | 
 | ||||||
|  |         // Spinner Item Selected Listener | ||||||
|  |         view.priorities_spinner.onItemSelectedListener = mSharedViewModel.listener | ||||||
|  | 
 | ||||||
|  |         return view | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { | ||||||
|  |         inflater.inflate(R.menu.add_fragment_menu, menu) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun onOptionsItemSelected(item: MenuItem): Boolean { | ||||||
|  |         if(item.itemId == R.id.menu_add){ | ||||||
|  |             insertDataToDb() | ||||||
|  |         } | ||||||
|  |         return super.onOptionsItemSelected(item) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private fun insertDataToDb() { | ||||||
|  |         val mTitle = title_et.text.toString() | ||||||
|  |         val mPriority = priorities_spinner.selectedItem.toString() | ||||||
|  |         val mDescription = description_et.text.toString() | ||||||
|  | 
 | ||||||
|  |         val validation = mSharedViewModel.verifyDataFromUser(mTitle, mDescription) | ||||||
|  |         if(validation){ | ||||||
|  |             // Insert Data to Database | ||||||
|  |             val newData = ToDoData( | ||||||
|  |                 0, | ||||||
|  |                 mTitle, | ||||||
|  |                 mSharedViewModel.parsePriority(mPriority), | ||||||
|  |                 mDescription | ||||||
|  |             ) | ||||||
|  |             mToDoViewModel.insertData(newData) | ||||||
|  |             Toast.makeText(requireContext(), "Successfully added!", Toast.LENGTH_SHORT).show() | ||||||
|  |             // Navigate Back | ||||||
|  |             findNavController().navigate(R.id.action_addFragment_to_listFragment) | ||||||
|  |         }else{ | ||||||
|  |             Toast.makeText(requireContext(), "Please fill out all fields.", Toast.LENGTH_SHORT).show() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,158 @@ | |||||||
|  | package com.example.todoapp.fragments.list | ||||||
|  | 
 | ||||||
|  | import android.app.AlertDialog | ||||||
|  | import android.os.Bundle | ||||||
|  | import android.view.* | ||||||
|  | import androidx.appcompat.widget.SearchView | ||||||
|  | import android.widget.Toast | ||||||
|  | import androidx.fragment.app.Fragment | ||||||
|  | import androidx.fragment.app.viewModels | ||||||
|  | import androidx.lifecycle.Observer | ||||||
|  | import androidx.recyclerview.widget.* | ||||||
|  | import com.example.todoapp.R | ||||||
|  | import com.example.todoapp.data.models.ToDoData | ||||||
|  | import com.example.todoapp.data.viewmodel.ToDoViewModel | ||||||
|  | import com.example.todoapp.databinding.FragmentListBinding | ||||||
|  | import com.example.todoapp.fragments.SharedViewModel | ||||||
|  | import com.example.todoapp.fragments.list.adapter.ListAdapter | ||||||
|  | import com.google.android.material.snackbar.Snackbar | ||||||
|  | import jp.wasabeef.recyclerview.animators.SlideInUpAnimator | ||||||
|  | 
 | ||||||
|  | class ListFragment : Fragment(), SearchView.OnQueryTextListener { | ||||||
|  | 
 | ||||||
|  |     private val mToDoViewModel: ToDoViewModel by viewModels() | ||||||
|  |     private val mSharedViewModel: SharedViewModel by viewModels() | ||||||
|  | 
 | ||||||
|  |     private var _binding: FragmentListBinding? = null | ||||||
|  |     private val binding get() = _binding!! | ||||||
|  | 
 | ||||||
|  |     private val adapter: ListAdapter by lazy { ListAdapter() } | ||||||
|  | 
 | ||||||
|  |     override fun onCreateView( | ||||||
|  |         inflater: LayoutInflater, container: ViewGroup?, | ||||||
|  |         savedInstanceState: Bundle? | ||||||
|  |     ): View? { | ||||||
|  |         // Data binding | ||||||
|  |         _binding = FragmentListBinding.inflate(inflater, container, false) | ||||||
|  |         binding.lifecycleOwner = this | ||||||
|  |         binding.mSharedViewModel = mSharedViewModel | ||||||
|  | 
 | ||||||
|  |         // Setup RecyclerView | ||||||
|  |         setupRecyclerview() | ||||||
|  | 
 | ||||||
|  |         // Observe LiveData | ||||||
|  |         mToDoViewModel.getAllData.observe(viewLifecycleOwner, Observer { data -> | ||||||
|  |             mSharedViewModel.checkIfDatabaseEmpty(data) | ||||||
|  |             adapter.setData(data) | ||||||
|  |         }) | ||||||
|  | 
 | ||||||
|  |         // Set Menu | ||||||
|  |         setHasOptionsMenu(true) | ||||||
|  | 
 | ||||||
|  |         return binding.root | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private fun setupRecyclerview() { | ||||||
|  |         val recyclerView = binding.recyclerView | ||||||
|  |         recyclerView.adapter = adapter | ||||||
|  |         recyclerView.layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL) | ||||||
|  |         recyclerView.itemAnimator = SlideInUpAnimator().apply { | ||||||
|  |             addDuration = 300 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Swipe to Delete | ||||||
|  |         swipeToDelete(recyclerView) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private fun swipeToDelete(recyclerView: RecyclerView) { | ||||||
|  |         val swipeToDeleteCallback = object : SwipeToDelete() { | ||||||
|  |             override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { | ||||||
|  |                 val deletedItem = adapter.dataList[viewHolder.adapterPosition] | ||||||
|  |                 // Delete Item | ||||||
|  |                 mToDoViewModel.deleteItem(deletedItem) | ||||||
|  |                 adapter.notifyItemRemoved(viewHolder.adapterPosition) | ||||||
|  |                 // Restore Deleted Item | ||||||
|  |                 restoreDeletedData(viewHolder.itemView, deletedItem, viewHolder.adapterPosition) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         val itemTouchHelper = ItemTouchHelper(swipeToDeleteCallback) | ||||||
|  |         itemTouchHelper.attachToRecyclerView(recyclerView) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private fun restoreDeletedData(view: View, deletedItem: ToDoData, position: Int) { | ||||||
|  |         val snackBar = Snackbar.make( | ||||||
|  |             view, "Deleted '${deletedItem.title}'", | ||||||
|  |             Snackbar.LENGTH_LONG | ||||||
|  |         ) | ||||||
|  |         snackBar.setAction("Undo") { | ||||||
|  |             mToDoViewModel.insertData(deletedItem) | ||||||
|  |             adapter.notifyItemChanged(position) | ||||||
|  |         } | ||||||
|  |         snackBar.show() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { | ||||||
|  |         inflater.inflate(R.menu.list_fragment_menu, menu) | ||||||
|  | 
 | ||||||
|  |         val search = menu.findItem(R.id.menu_search) | ||||||
|  |         val searchView = search.actionView as? SearchView | ||||||
|  |         searchView?.isSubmitButtonEnabled = true | ||||||
|  |         searchView?.setOnQueryTextListener(this) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun onOptionsItemSelected(item: MenuItem): Boolean { | ||||||
|  |         when (item.itemId) { | ||||||
|  |             R.id.menu_delete_all -> confirmRemoval() | ||||||
|  |             R.id.menu_priority_high -> mToDoViewModel.sortByHighPriority.observe(this, Observer { adapter.setData(it) }) | ||||||
|  |             R.id.menu_priority_low -> mToDoViewModel.sortByLowPriority.observe(this, Observer { adapter.setData(it) }) | ||||||
|  |         } | ||||||
|  |         return super.onOptionsItemSelected(item) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun onQueryTextSubmit(query: String?): Boolean { | ||||||
|  |         if (query != null) { | ||||||
|  |             searchThroughDatabase(query) | ||||||
|  |         } | ||||||
|  |         return true | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun onQueryTextChange(query: String?): Boolean { | ||||||
|  |         if (query != null) { | ||||||
|  |             searchThroughDatabase(query) | ||||||
|  |         } | ||||||
|  |         return true | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private fun searchThroughDatabase(query: String) { | ||||||
|  |         val searchQuery = "%$query%" | ||||||
|  | 
 | ||||||
|  |         mToDoViewModel.searchDatabase(searchQuery).observe(this, Observer { list -> | ||||||
|  |             list?.let { | ||||||
|  |                 adapter.setData(it) | ||||||
|  |             } | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Show AlertDialog to Confirm Removal of All Items from Database Table | ||||||
|  |     private fun confirmRemoval() { | ||||||
|  |         val builder = AlertDialog.Builder(requireContext()) | ||||||
|  |         builder.setPositiveButton("Yes") { _, _ -> | ||||||
|  |             mToDoViewModel.deleteAll() | ||||||
|  |             Toast.makeText( | ||||||
|  |                 requireContext(), | ||||||
|  |                 "Successfully Removed Everything!", | ||||||
|  |                 Toast.LENGTH_SHORT | ||||||
|  |             ).show() | ||||||
|  |         } | ||||||
|  |         builder.setNegativeButton("No") { _, _ -> } | ||||||
|  |         builder.setTitle("Delete everything?") | ||||||
|  |         builder.setMessage("Are you sure you want to remove everything?") | ||||||
|  |         builder.create().show() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun onDestroyView() { | ||||||
|  |         super.onDestroyView() | ||||||
|  |         _binding = null | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,14 @@ | |||||||
|  | package com.example.todoapp.fragments.list | ||||||
|  | 
 | ||||||
|  | import androidx.recyclerview.widget.ItemTouchHelper | ||||||
|  | import androidx.recyclerview.widget.RecyclerView | ||||||
|  | 
 | ||||||
|  | abstract class SwipeToDelete: ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) { | ||||||
|  |     override fun onMove( | ||||||
|  |         recyclerView: RecyclerView, | ||||||
|  |         viewHolder: RecyclerView.ViewHolder, | ||||||
|  |         target: RecyclerView.ViewHolder | ||||||
|  |     ): Boolean { | ||||||
|  |         return false | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,53 @@ | |||||||
|  | package com.example.todoapp.fragments.list.adapter | ||||||
|  | 
 | ||||||
|  | import android.view.LayoutInflater | ||||||
|  | import android.view.ViewGroup | ||||||
|  | import androidx.recyclerview.widget.DiffUtil | ||||||
|  | import androidx.recyclerview.widget.RecyclerView | ||||||
|  | import com.example.todoapp.data.models.ToDoData | ||||||
|  | import com.example.todoapp.databinding.RowLayoutBinding | ||||||
|  | 
 | ||||||
|  | class ListAdapter : RecyclerView.Adapter<ListAdapter.MyViewHolder>() { | ||||||
|  | 
 | ||||||
|  |     var dataList = emptyList<ToDoData>() | ||||||
|  | 
 | ||||||
|  |     class MyViewHolder(private val binding: RowLayoutBinding) : RecyclerView.ViewHolder(binding.root){ | ||||||
|  | 
 | ||||||
|  |         fun bind(toDoData: ToDoData){ | ||||||
|  |             binding.toDoData = toDoData | ||||||
|  |             binding.executePendingBindings() | ||||||
|  |         } | ||||||
|  |         companion object{ | ||||||
|  |             fun from(parent: ViewGroup): MyViewHolder { | ||||||
|  |                 val layoutInflater = LayoutInflater.from(parent.context) | ||||||
|  |                 val binding = RowLayoutBinding.inflate(layoutInflater, parent, false) | ||||||
|  |                 return MyViewHolder( | ||||||
|  |                     binding | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { | ||||||
|  |         return MyViewHolder.from( | ||||||
|  |             parent | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun getItemCount(): Int { | ||||||
|  |         return dataList.size | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun onBindViewHolder(holder: MyViewHolder, position: Int) { | ||||||
|  |         val currentItem = dataList[position] | ||||||
|  |         holder.bind(currentItem) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun setData(toDoData: List<ToDoData>){ | ||||||
|  |         val toDoDiffUtil = ToDoDiffUtil(dataList, toDoData) | ||||||
|  |         val toDoDiffResult = DiffUtil.calculateDiff(toDoDiffUtil) | ||||||
|  |         this.dataList = toDoData | ||||||
|  |         toDoDiffResult.dispatchUpdatesTo(this) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,29 @@ | |||||||
|  | package com.example.todoapp.fragments.list.adapter | ||||||
|  | 
 | ||||||
|  | import androidx.recyclerview.widget.DiffUtil | ||||||
|  | import com.example.todoapp.data.models.ToDoData | ||||||
|  | 
 | ||||||
|  | class ToDoDiffUtil( | ||||||
|  |     private val oldList: List<ToDoData>, | ||||||
|  |     private val newList: List<ToDoData> | ||||||
|  | ): DiffUtil.Callback() { | ||||||
|  | 
 | ||||||
|  |     override fun getOldListSize(): Int { | ||||||
|  |         return oldList.size | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun getNewListSize(): Int { | ||||||
|  |         return newList.size | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { | ||||||
|  |         return oldList[oldItemPosition] === newList[newItemPosition] | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { | ||||||
|  |         return oldList[oldItemPosition].id == newList[newItemPosition].id | ||||||
|  |                 && oldList[oldItemPosition].title == newList[newItemPosition].title | ||||||
|  |                 && oldList[oldItemPosition].description == newList[newItemPosition].description | ||||||
|  |                 && oldList[oldItemPosition].priority == newList[newItemPosition].priority | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,104 @@ | |||||||
|  | package com.example.todoapp.fragments.update | ||||||
|  | 
 | ||||||
|  | import android.app.AlertDialog | ||||||
|  | import android.os.Bundle | ||||||
|  | import android.view.* | ||||||
|  | import android.widget.Toast | ||||||
|  | import androidx.fragment.app.Fragment | ||||||
|  | import androidx.fragment.app.viewModels | ||||||
|  | import androidx.navigation.fragment.findNavController | ||||||
|  | import androidx.navigation.fragment.navArgs | ||||||
|  | import com.example.todoapp.R | ||||||
|  | import com.example.todoapp.data.models.ToDoData | ||||||
|  | import com.example.todoapp.data.viewmodel.ToDoViewModel | ||||||
|  | import com.example.todoapp.databinding.FragmentUpdateBinding | ||||||
|  | import com.example.todoapp.fragments.SharedViewModel | ||||||
|  | import kotlinx.android.synthetic.main.fragment_update.* | ||||||
|  | import kotlinx.android.synthetic.main.fragment_update.view.* | ||||||
|  | 
 | ||||||
|  | class UpdateFragment : Fragment() { | ||||||
|  | 
 | ||||||
|  |     private val args by navArgs<UpdateFragmentArgs>() | ||||||
|  | 
 | ||||||
|  |     private val mSharedViewModel: SharedViewModel by viewModels() | ||||||
|  |     private val mToDoViewModel: ToDoViewModel by viewModels() | ||||||
|  | 
 | ||||||
|  |     private var _binding: FragmentUpdateBinding? = null | ||||||
|  |     private val binding get() = _binding!! | ||||||
|  | 
 | ||||||
|  |     override fun onCreateView( | ||||||
|  |         inflater: LayoutInflater, container: ViewGroup?, | ||||||
|  |         savedInstanceState: Bundle? | ||||||
|  |     ): View? { | ||||||
|  |         // Data binding | ||||||
|  |         _binding = FragmentUpdateBinding.inflate(inflater, container, false) | ||||||
|  |         binding.args = args | ||||||
|  | 
 | ||||||
|  |         // Set Menu | ||||||
|  |         setHasOptionsMenu(true) | ||||||
|  | 
 | ||||||
|  |         // Spinner Item Selected Listener | ||||||
|  |         binding.currentPrioritiesSpinner.onItemSelectedListener = mSharedViewModel.listener | ||||||
|  | 
 | ||||||
|  |         return binding.root | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { | ||||||
|  |         inflater.inflate(R.menu.update_fragment_menu, menu) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun onOptionsItemSelected(item: MenuItem): Boolean { | ||||||
|  |         when (item.itemId) { | ||||||
|  |             R.id.menu_save -> updateItem() | ||||||
|  |             R.id.menu_delete -> confirmItemRemoval() | ||||||
|  |         } | ||||||
|  |         return super.onOptionsItemSelected(item) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private fun updateItem() { | ||||||
|  |         val title = current_title_et.text.toString() | ||||||
|  |         val description = current_description_et.text.toString() | ||||||
|  |         val getPriority = current_priorities_spinner.selectedItem.toString() | ||||||
|  | 
 | ||||||
|  |         val validation = mSharedViewModel.verifyDataFromUser(title, description) | ||||||
|  |         if (validation) { | ||||||
|  |             // Update Current Item | ||||||
|  |             val updatedItem = ToDoData( | ||||||
|  |                 args.currentItem.id, | ||||||
|  |                 title, | ||||||
|  |                 mSharedViewModel.parsePriority(getPriority), | ||||||
|  |                 description | ||||||
|  |             ) | ||||||
|  |             mToDoViewModel.updateData(updatedItem) | ||||||
|  |             Toast.makeText(requireContext(), "Successfully updated!", Toast.LENGTH_SHORT).show() | ||||||
|  |             // Navigate back | ||||||
|  |             findNavController().navigate(R.id.action_updateFragment_to_listFragment) | ||||||
|  |         } else { | ||||||
|  |             Toast.makeText(requireContext(), "Please fill out all fields.", Toast.LENGTH_SHORT) | ||||||
|  |                 .show() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Show AlertDialog to Confirm Item Removal | ||||||
|  |     private fun confirmItemRemoval() { | ||||||
|  |         val builder = AlertDialog.Builder(requireContext()) | ||||||
|  |         builder.setPositiveButton("Yes") { _, _ -> | ||||||
|  |             mToDoViewModel.deleteItem(args.currentItem) | ||||||
|  |             Toast.makeText( | ||||||
|  |                 requireContext(), | ||||||
|  |                 "Successfully Removed: ${args.currentItem.title}", | ||||||
|  |                 Toast.LENGTH_SHORT | ||||||
|  |             ).show() | ||||||
|  |             findNavController().navigate(R.id.action_updateFragment_to_listFragment) | ||||||
|  |         } | ||||||
|  |         builder.setNegativeButton("No") { _, _ -> } | ||||||
|  |         builder.setTitle("Delete '${args.currentItem.title}'?") | ||||||
|  |         builder.setMessage("Are you sure you want to remove '${args.currentItem.title}'?") | ||||||
|  |         builder.create().show() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun onDestroyView() { | ||||||
|  |         super.onDestroyView() | ||||||
|  |         _binding = null | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										6
									
								
								app/src/main/res/anim/from_left.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,6 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||||||
|  | 
 | ||||||
|  |     <translate android:fromXDelta="-100%" android:toXDelta="0%" android:duration="300"/> | ||||||
|  | 
 | ||||||
|  | </set> | ||||||
							
								
								
									
										6
									
								
								app/src/main/res/anim/from_right.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,6 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||||||
|  | 
 | ||||||
|  |     <translate android:fromXDelta="100%" android:toXDelta="0%" android:duration="300"/> | ||||||
|  | 
 | ||||||
|  | </set> | ||||||
							
								
								
									
										6
									
								
								app/src/main/res/anim/to_left.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,6 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||||||
|  | 
 | ||||||
|  |     <translate android:fromXDelta="0%" android:toXDelta="-100%" android:duration="300"/> | ||||||
|  | 
 | ||||||
|  | </set> | ||||||
							
								
								
									
										6
									
								
								app/src/main/res/anim/to_right.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,6 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||||||
|  | 
 | ||||||
|  |     <translate android:fromXDelta="0%" android:toXDelta="100%" android:duration="300"/> | ||||||
|  | 
 | ||||||
|  | </set> | ||||||
							
								
								
									
										30
									
								
								app/src/main/res/drawable-v24/ic_launcher_foreground.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,30 @@ | |||||||
|  | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     xmlns:aapt="http://schemas.android.com/aapt" | ||||||
|  |     android:width="108dp" | ||||||
|  |     android:height="108dp" | ||||||
|  |     android:viewportWidth="108" | ||||||
|  |     android:viewportHeight="108"> | ||||||
|  |     <path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z"> | ||||||
|  |         <aapt:attr name="android:fillColor"> | ||||||
|  |             <gradient | ||||||
|  |                 android:endX="85.84757" | ||||||
|  |                 android:endY="92.4963" | ||||||
|  |                 android:startX="42.9492" | ||||||
|  |                 android:startY="49.59793" | ||||||
|  |                 android:type="linear"> | ||||||
|  |                 <item | ||||||
|  |                     android:color="#44000000" | ||||||
|  |                     android:offset="0.0" /> | ||||||
|  |                 <item | ||||||
|  |                     android:color="#00000000" | ||||||
|  |                     android:offset="1.0" /> | ||||||
|  |             </gradient> | ||||||
|  |         </aapt:attr> | ||||||
|  |     </path> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#FFFFFF" | ||||||
|  |         android:fillType="nonZero" | ||||||
|  |         android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z" | ||||||
|  |         android:strokeWidth="1" | ||||||
|  |         android:strokeColor="#00000000" /> | ||||||
|  | </vector> | ||||||
							
								
								
									
										20
									
								
								app/src/main/res/drawable/custom_input.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,20 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||||||
|  | 
 | ||||||
|  |     <item android:state_enabled="true" android:state_focused="true"> | ||||||
|  |         <shape android:shape="rectangle"> | ||||||
|  |             <solid android:color="@color/white"/> | ||||||
|  |             <stroke android:width="1dp" android:color="@color/colorPrimary"/> | ||||||
|  |             <corners android:radius="5dp"/> | ||||||
|  |         </shape> | ||||||
|  |     </item> | ||||||
|  | 
 | ||||||
|  |     <item android:state_enabled="true"> | ||||||
|  |         <shape android:shape="rectangle"> | ||||||
|  |             <solid android:color="@color/white"/> | ||||||
|  |             <stroke android:width="1dp" android:color="@color/lightGray"/> | ||||||
|  |             <corners android:radius="5dp"/> | ||||||
|  |         </shape> | ||||||
|  |     </item> | ||||||
|  | 
 | ||||||
|  | </selector> | ||||||
							
								
								
									
										10
									
								
								app/src/main/res/drawable/ic_add.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,10 @@ | |||||||
|  | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     android:width="24dp" | ||||||
|  |     android:height="24dp" | ||||||
|  |     android:viewportWidth="24" | ||||||
|  |     android:viewportHeight="24" | ||||||
|  |     android:tint="?attr/colorControlNormal"> | ||||||
|  |   <path | ||||||
|  |       android:fillColor="@android:color/white" | ||||||
|  |       android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/> | ||||||
|  | </vector> | ||||||
							
								
								
									
										10
									
								
								app/src/main/res/drawable/ic_check.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,10 @@ | |||||||
|  | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     android:width="24dp" | ||||||
|  |     android:height="24dp" | ||||||
|  |     android:viewportWidth="24" | ||||||
|  |     android:viewportHeight="24" | ||||||
|  |     android:tint="?attr/colorControlNormal"> | ||||||
|  |   <path | ||||||
|  |       android:fillColor="@android:color/white" | ||||||
|  |       android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/> | ||||||
|  | </vector> | ||||||
							
								
								
									
										170
									
								
								app/src/main/res/drawable/ic_launcher_background.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,170 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     android:width="108dp" | ||||||
|  |     android:height="108dp" | ||||||
|  |     android:viewportWidth="108" | ||||||
|  |     android:viewportHeight="108"> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#3DDC84" | ||||||
|  |         android:pathData="M0,0h108v108h-108z" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M9,0L9,108" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M19,0L19,108" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M29,0L29,108" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M39,0L39,108" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M49,0L49,108" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M59,0L59,108" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M69,0L69,108" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M79,0L79,108" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M89,0L89,108" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M99,0L99,108" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M0,9L108,9" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M0,19L108,19" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M0,29L108,29" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M0,39L108,39" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M0,49L108,49" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M0,59L108,59" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M0,69L108,69" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M0,79L108,79" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M0,89L108,89" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M0,99L108,99" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M19,29L89,29" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M19,39L89,39" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M19,49L89,49" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M19,59L89,59" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M19,69L89,69" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M19,79L89,79" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M29,19L29,89" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M39,19L39,89" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M49,19L49,89" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M59,19L59,89" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M69,19L69,89" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  |     <path | ||||||
|  |         android:fillColor="#00000000" | ||||||
|  |         android:pathData="M79,19L79,89" | ||||||
|  |         android:strokeWidth="0.8" | ||||||
|  |         android:strokeColor="#33FFFFFF" /> | ||||||
|  | </vector> | ||||||
							
								
								
									
										9
									
								
								app/src/main/res/drawable/ic_no_data.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,9 @@ | |||||||
|  | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     android:width="146dp" | ||||||
|  |     android:height="116dp" | ||||||
|  |     android:viewportWidth="146" | ||||||
|  |     android:viewportHeight="116"> | ||||||
|  |   <path | ||||||
|  |       android:fillColor="@color/lightGray" | ||||||
|  |       android:pathData="M123.87,2.693A4.052,4.052 0,0 0,120.045 0L25.956,0a4.052,4.052 0,0 0,-3.826 2.693L0.23,64.613A3.993,3.993 0,0 0,0 65.948v46.024A4.042,4.042 0,0 0,4.056 116L141.945,116A4.042,4.042 0,0 0,146 111.972L146,65.948a3.994,3.994 0,0 0,-0.23 -1.335ZM9.78,61.916l19.049,-53.86h88.341l19.049,53.86Z"/> | ||||||
|  | </vector> | ||||||
							
								
								
									
										10
									
								
								app/src/main/res/drawable/ic_save.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,10 @@ | |||||||
|  | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     android:width="24dp" | ||||||
|  |     android:height="24dp" | ||||||
|  |     android:viewportWidth="24" | ||||||
|  |     android:viewportHeight="24" | ||||||
|  |     android:tint="?attr/colorControlNormal"> | ||||||
|  |   <path | ||||||
|  |       android:fillColor="@android:color/white" | ||||||
|  |       android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z"/> | ||||||
|  | </vector> | ||||||
							
								
								
									
										10
									
								
								app/src/main/res/drawable/ic_search.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,10 @@ | |||||||
|  | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     android:width="24dp" | ||||||
|  |     android:height="24dp" | ||||||
|  |     android:viewportWidth="24" | ||||||
|  |     android:viewportHeight="24" | ||||||
|  |     android:tint="?attr/colorControlNormal"> | ||||||
|  |   <path | ||||||
|  |       android:fillColor="@android:color/white" | ||||||
|  |       android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/> | ||||||
|  | </vector> | ||||||
							
								
								
									
										8
									
								
								app/src/main/res/drawable/item_background.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,8 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <shape xmlns:android="http://schemas.android.com/apk/res/android"> | ||||||
|  | 
 | ||||||
|  |     <solid android:color="@color/white"/> | ||||||
|  |     <stroke android:width="1dp" android:color="@color/lightGray"/> | ||||||
|  |     <corners android:radius="16dp"/> | ||||||
|  | 
 | ||||||
|  | </shape> | ||||||
							
								
								
									
										21
									
								
								app/src/main/res/layout/activity_main.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,21 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||||
|  |     xmlns:tools="http://schemas.android.com/tools" | ||||||
|  |     android:layout_width="match_parent" | ||||||
|  |     android:layout_height="match_parent" | ||||||
|  |     tools:context=".MainActivity"> | ||||||
|  | 
 | ||||||
|  |     <fragment | ||||||
|  |         android:id="@+id/navHostFragment" | ||||||
|  |         android:name="androidx.navigation.fragment.NavHostFragment" | ||||||
|  |         android:layout_width="409dp" | ||||||
|  |         android:layout_height="729dp" | ||||||
|  |         app:defaultNavHost="true" | ||||||
|  |         app:layout_constraintBottom_toBottomOf="parent" | ||||||
|  |         app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |         app:layout_constraintHorizontal_bias="0.5" | ||||||
|  |         app:layout_constraintStart_toStartOf="parent" | ||||||
|  |         app:layout_constraintTop_toTopOf="parent" | ||||||
|  |         app:navGraph="@navigation/my_nav" /> | ||||||
|  | </androidx.constraintlayout.widget.ConstraintLayout> | ||||||
							
								
								
									
										58
									
								
								app/src/main/res/layout/fragment_add.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,58 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||||
|  |     xmlns:tools="http://schemas.android.com/tools" | ||||||
|  |     android:layout_width="match_parent" | ||||||
|  |     android:layout_height="match_parent" | ||||||
|  |     android:padding="24dp" | ||||||
|  |     tools:context=".fragments.add.AddFragment"> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     <EditText | ||||||
|  |         android:id="@+id/title_et" | ||||||
|  |         android:layout_width="0dp" | ||||||
|  |         android:layout_height="60dp" | ||||||
|  |         android:background="@android:color/transparent" | ||||||
|  |         android:ems="10" | ||||||
|  |         android:hint="@string/title" | ||||||
|  |         android:inputType="textPersonName" | ||||||
|  |         android:paddingStart="24dp" | ||||||
|  |         android:paddingEnd="24dp" | ||||||
|  |         app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |         app:layout_constraintHorizontal_bias="0.5" | ||||||
|  |         app:layout_constraintStart_toStartOf="parent" | ||||||
|  |         app:layout_constraintTop_toTopOf="parent" /> | ||||||
|  | 
 | ||||||
|  |     <Spinner | ||||||
|  |         android:id="@+id/priorities_spinner" | ||||||
|  |         android:layout_width="0dp" | ||||||
|  |         android:layout_height="60dp" | ||||||
|  |         android:layout_marginTop="8dp" | ||||||
|  |         android:background="@android:color/transparent" | ||||||
|  |         android:entries="@array/priorities" | ||||||
|  |         android:paddingStart="20dp" | ||||||
|  |         android:paddingEnd="20dp" | ||||||
|  |         app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |         app:layout_constraintHorizontal_bias="0.5" | ||||||
|  |         app:layout_constraintStart_toStartOf="parent" | ||||||
|  |         app:layout_constraintTop_toBottomOf="@+id/title_et" /> | ||||||
|  | 
 | ||||||
|  |     <EditText | ||||||
|  |         android:id="@+id/description_et" | ||||||
|  |         android:layout_width="0dp" | ||||||
|  |         android:layout_height="0dp" | ||||||
|  |         android:layout_marginTop="8dp" | ||||||
|  |         android:background="@android:color/transparent" | ||||||
|  |         android:ems="10" | ||||||
|  |         android:gravity="top|start" | ||||||
|  |         android:hint="@string/description" | ||||||
|  |         android:inputType="textMultiLine" | ||||||
|  |         android:paddingStart="24dp" | ||||||
|  |         android:paddingTop="16dp" | ||||||
|  |         android:paddingEnd="24dp" | ||||||
|  |         app:layout_constraintBottom_toBottomOf="parent" | ||||||
|  |         app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |         app:layout_constraintHorizontal_bias="0.5" | ||||||
|  |         app:layout_constraintStart_toStartOf="parent" | ||||||
|  |         app:layout_constraintTop_toBottomOf="@+id/priorities_spinner" /> | ||||||
|  | </androidx.constraintlayout.widget.ConstraintLayout> | ||||||
							
								
								
									
										72
									
								
								app/src/main/res/layout/fragment_list.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,72 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <layout xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||||
|  |     xmlns:tools="http://schemas.android.com/tools"> | ||||||
|  | 
 | ||||||
|  |     <data> | ||||||
|  |         <variable | ||||||
|  |             name="mSharedViewModel" | ||||||
|  |             type="com.example.todoapp.fragments.SharedViewModel" /> | ||||||
|  |     </data> | ||||||
|  | 
 | ||||||
|  |     <androidx.constraintlayout.widget.ConstraintLayout | ||||||
|  |         android:id="@+id/listLayout" | ||||||
|  |         android:layout_width="match_parent" | ||||||
|  |         android:layout_height="match_parent" | ||||||
|  |         tools:context=".fragments.list.ListFragment"> | ||||||
|  | 
 | ||||||
|  |         <androidx.recyclerview.widget.RecyclerView | ||||||
|  |             android:id="@+id/recyclerView" | ||||||
|  |             android:layout_width="0dp" | ||||||
|  |             android:layout_height="0dp" | ||||||
|  |             android:clipToPadding="false" | ||||||
|  |             android:paddingTop="8dp" | ||||||
|  |             app:layout_constraintBottom_toBottomOf="parent" | ||||||
|  |             app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |             app:layout_constraintHorizontal_bias="0.5" | ||||||
|  |             app:layout_constraintStart_toStartOf="parent" | ||||||
|  |             app:layout_constraintTop_toTopOf="parent" /> | ||||||
|  | 
 | ||||||
|  |         <com.google.android.material.floatingactionbutton.FloatingActionButton | ||||||
|  |             android:id="@+id/floatingActionButton" | ||||||
|  |             android:layout_width="wrap_content" | ||||||
|  |             android:layout_height="wrap_content" | ||||||
|  |             android:layout_marginEnd="24dp" | ||||||
|  |             android:layout_marginBottom="24dp" | ||||||
|  |             android:clickable="true" | ||||||
|  |             android:focusable="true" | ||||||
|  |             android:navigateToAddFragment="@{true}" | ||||||
|  |             android:src="@drawable/ic_add" | ||||||
|  |             android:tint="@color/white" | ||||||
|  |             app:layout_constraintBottom_toBottomOf="parent" | ||||||
|  |             app:layout_constraintEnd_toEndOf="parent" /> | ||||||
|  | 
 | ||||||
|  |         <ImageView | ||||||
|  |             android:id="@+id/no_data_imageView" | ||||||
|  |             android:layout_width="100dp" | ||||||
|  |             android:layout_height="100dp" | ||||||
|  |             android:emptyDatabase="@{mSharedViewModel.emptyDatabase}" | ||||||
|  |             android:src="@drawable/ic_no_data" | ||||||
|  |             android:visibility="invisible" | ||||||
|  |             app:layout_constraintBottom_toBottomOf="@+id/recyclerView" | ||||||
|  |             app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |             app:layout_constraintStart_toStartOf="@+id/recyclerView" | ||||||
|  |             app:layout_constraintTop_toTopOf="@+id/recyclerView" | ||||||
|  |             app:layout_constraintVertical_bias="0.37" /> | ||||||
|  | 
 | ||||||
|  |         <TextView | ||||||
|  |             android:id="@+id/no_data_textView" | ||||||
|  |             android:layout_width="wrap_content" | ||||||
|  |             android:layout_height="wrap_content" | ||||||
|  |             android:layout_marginTop="12dp" | ||||||
|  |             android:alpha="0.5" | ||||||
|  |             android:emptyDatabase="@{mSharedViewModel.emptyDatabase}" | ||||||
|  |             android:text="@string/no_data" | ||||||
|  |             android:textSize="16sp" | ||||||
|  |             android:visibility="invisible" | ||||||
|  |             app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |             app:layout_constraintStart_toStartOf="@+id/recyclerView" | ||||||
|  |             app:layout_constraintTop_toBottomOf="@+id/no_data_imageView" /> | ||||||
|  | 
 | ||||||
|  |     </androidx.constraintlayout.widget.ConstraintLayout> | ||||||
|  | </layout> | ||||||
							
								
								
									
										70
									
								
								app/src/main/res/layout/fragment_update.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,70 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <layout xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||||
|  |     xmlns:tools="http://schemas.android.com/tools"> | ||||||
|  | 
 | ||||||
|  |     <data> | ||||||
|  |         <variable | ||||||
|  |             name="args" | ||||||
|  |             type="com.example.todoapp.fragments.update.UpdateFragmentArgs" /> | ||||||
|  |     </data> | ||||||
|  | 
 | ||||||
|  |     <androidx.constraintlayout.widget.ConstraintLayout | ||||||
|  |         android:layout_width="match_parent" | ||||||
|  |         android:layout_height="match_parent" | ||||||
|  |         android:padding="24dp" | ||||||
|  |         tools:context=".fragments.update.UpdateFragment"> | ||||||
|  | 
 | ||||||
|  |         <EditText | ||||||
|  |             android:id="@+id/current_title_et" | ||||||
|  |             android:layout_width="0dp" | ||||||
|  |             android:layout_height="60dp" | ||||||
|  |             android:background="@drawable/custom_input" | ||||||
|  |             android:ems="10" | ||||||
|  |             android:hint="@string/title" | ||||||
|  |             android:inputType="textPersonName" | ||||||
|  |             android:paddingStart="24dp" | ||||||
|  |             android:paddingEnd="24dp" | ||||||
|  |             android:text="@{args.currentItem.title}" | ||||||
|  |             app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |             app:layout_constraintHorizontal_bias="0.5" | ||||||
|  |             app:layout_constraintStart_toStartOf="parent" | ||||||
|  |             app:layout_constraintTop_toTopOf="parent" /> | ||||||
|  | 
 | ||||||
|  |         <Spinner | ||||||
|  |             android:id="@+id/current_priorities_spinner" | ||||||
|  |             android:layout_width="0dp" | ||||||
|  |             android:layout_height="60dp" | ||||||
|  |             android:layout_marginTop="8dp" | ||||||
|  |             android:background="@drawable/custom_input" | ||||||
|  |             android:entries="@array/priorities" | ||||||
|  |             android:paddingStart="20dp" | ||||||
|  |             android:paddingEnd="20dp" | ||||||
|  |             android:parsePriorityToInt="@{args.currentItem.priority}" | ||||||
|  |             app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |             app:layout_constraintHorizontal_bias="0.5" | ||||||
|  |             app:layout_constraintStart_toStartOf="parent" | ||||||
|  |             app:layout_constraintTop_toBottomOf="@+id/current_title_et" /> | ||||||
|  | 
 | ||||||
|  |         <EditText | ||||||
|  |             android:id="@+id/current_description_et" | ||||||
|  |             android:layout_width="0dp" | ||||||
|  |             android:layout_height="0dp" | ||||||
|  |             android:layout_marginTop="8dp" | ||||||
|  |             android:background="@drawable/custom_input" | ||||||
|  |             android:ems="10" | ||||||
|  |             android:gravity="top|start" | ||||||
|  |             android:hint="@string/description" | ||||||
|  |             android:inputType="textMultiLine" | ||||||
|  |             android:paddingStart="24dp" | ||||||
|  |             android:paddingTop="16dp" | ||||||
|  |             android:paddingEnd="24dp" | ||||||
|  |             android:text="@{args.currentItem.description}" | ||||||
|  |             app:layout_constraintBottom_toBottomOf="parent" | ||||||
|  |             app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |             app:layout_constraintHorizontal_bias="0.5" | ||||||
|  |             app:layout_constraintStart_toStartOf="parent" | ||||||
|  |             app:layout_constraintTop_toBottomOf="@+id/current_priorities_spinner" /> | ||||||
|  | 
 | ||||||
|  |     </androidx.constraintlayout.widget.ConstraintLayout> | ||||||
|  | </layout> | ||||||
							
								
								
									
										75
									
								
								app/src/main/res/layout/row_layout.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,75 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <layout xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||||
|  |     xmlns:tools="http://schemas.android.com/tools"> | ||||||
|  | 
 | ||||||
|  |     <data> | ||||||
|  |         <variable | ||||||
|  |             name="toDoData" | ||||||
|  |             type="com.example.todoapp.data.models.ToDoData" /> | ||||||
|  |     </data> | ||||||
|  | 
 | ||||||
|  |     <androidx.constraintlayout.widget.ConstraintLayout | ||||||
|  |         android:layout_width="match_parent" | ||||||
|  |         android:layout_height="wrap_content" | ||||||
|  |         android:layout_margin="4dp"> | ||||||
|  | 
 | ||||||
|  |         <androidx.constraintlayout.widget.ConstraintLayout | ||||||
|  |             android:id="@+id/row_background" | ||||||
|  |             android:layout_width="match_parent" | ||||||
|  |             android:layout_height="wrap_content" | ||||||
|  |             android:background="@drawable/item_background" | ||||||
|  |             android:sendDataToUpdateFragment="@{toDoData}" | ||||||
|  |             app:layout_constraintBottom_toBottomOf="parent" | ||||||
|  |             app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |             app:layout_constraintHorizontal_bias="0.5" | ||||||
|  |             app:layout_constraintStart_toStartOf="parent" | ||||||
|  |             app:layout_constraintTop_toTopOf="parent"> | ||||||
|  | 
 | ||||||
|  |             <androidx.cardview.widget.CardView | ||||||
|  |                 android:id="@+id/priority_indicator" | ||||||
|  |                 android:layout_width="16dp" | ||||||
|  |                 android:layout_height="16dp" | ||||||
|  |                 android:layout_marginTop="16dp" | ||||||
|  |                 android:layout_marginEnd="16dp" | ||||||
|  |                 android:parsePriorityColor="@{toDoData.priority}" | ||||||
|  |                 app:cardBackgroundColor="@color/red" | ||||||
|  |                 app:cardCornerRadius="100dp" | ||||||
|  |                 app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |                 app:layout_constraintTop_toTopOf="parent" /> | ||||||
|  | 
 | ||||||
|  |             <TextView | ||||||
|  |                 android:id="@+id/title_txt" | ||||||
|  |                 android:layout_width="wrap_content" | ||||||
|  |                 android:layout_height="wrap_content" | ||||||
|  |                 android:layout_marginStart="20dp" | ||||||
|  |                 android:layout_marginTop="16dp" | ||||||
|  |                 android:maxLength="20" | ||||||
|  |                 android:text="@{toDoData.title}" | ||||||
|  |                 android:textColor="@color/darkGray" | ||||||
|  |                 android:textSize="20sp" | ||||||
|  |                 android:textStyle="bold" | ||||||
|  |                 app:layout_constraintStart_toStartOf="parent" | ||||||
|  |                 app:layout_constraintTop_toTopOf="parent" /> | ||||||
|  | 
 | ||||||
|  |             <TextView | ||||||
|  |                 android:id="@+id/description_txt" | ||||||
|  |                 android:layout_width="0dp" | ||||||
|  |                 android:layout_height="wrap_content" | ||||||
|  |                 android:layout_marginTop="8dp" | ||||||
|  |                 android:layout_marginEnd="16dp" | ||||||
|  |                 android:layout_marginBottom="16dp" | ||||||
|  |                 android:maxLength="300" | ||||||
|  |                 android:maxLines="10" | ||||||
|  |                 android:text="@{toDoData.description}" | ||||||
|  |                 android:textColor="@color/darkGray" | ||||||
|  |                 app:layout_constraintBottom_toBottomOf="parent" | ||||||
|  |                 app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |                 app:layout_constraintHorizontal_bias="0.0" | ||||||
|  |                 app:layout_constraintStart_toStartOf="@+id/title_txt" | ||||||
|  |                 app:layout_constraintTop_toBottomOf="@+id/title_txt" | ||||||
|  |                 app:layout_constraintVertical_bias="0.0" /> | ||||||
|  | 
 | ||||||
|  |         </androidx.constraintlayout.widget.ConstraintLayout> | ||||||
|  |     </androidx.constraintlayout.widget.ConstraintLayout> | ||||||
|  | </layout> | ||||||
							
								
								
									
										13
									
								
								app/src/main/res/menu/add_fragment_menu.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,13 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <menu xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     xmlns:app="http://schemas.android.com/apk/res-auto"> | ||||||
|  | 
 | ||||||
|  |     <item | ||||||
|  |         android:id="@+id/menu_add" | ||||||
|  |         android:title="@string/add" | ||||||
|  |         android:icon="@drawable/ic_check" | ||||||
|  |         android:iconTint="@color/white" | ||||||
|  |         app:showAsAction="ifRoom"/> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | </menu> | ||||||
							
								
								
									
										33
									
								
								app/src/main/res/menu/list_fragment_menu.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,33 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <menu xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     xmlns:app="http://schemas.android.com/apk/res-auto"> | ||||||
|  | 
 | ||||||
|  |     <item | ||||||
|  |         android:id="@+id/menu_search" | ||||||
|  |         android:title="@string/search" | ||||||
|  |         android:icon="@drawable/ic_search" | ||||||
|  |         android:iconTint="@color/white" | ||||||
|  |         app:showAsAction="ifRoom" | ||||||
|  |         app:actionViewClass="androidx.appcompat.widget.SearchView"/> | ||||||
|  | 
 | ||||||
|  |     <group android:checkableBehavior="single"> | ||||||
|  |         <item | ||||||
|  |             android:id="@+id/menu_sortBy" | ||||||
|  |             android:title="@string/sort_by"> | ||||||
|  |             <menu> | ||||||
|  |                 <item | ||||||
|  |                     android:id="@+id/menu_priority_high" | ||||||
|  |                     android:title="@string/priority_high"/> | ||||||
|  |                 <item | ||||||
|  |                     android:id="@+id/menu_priority_low" | ||||||
|  |                     android:title="@string/priority_low"/> | ||||||
|  |             </menu> | ||||||
|  |         </item> | ||||||
|  |     </group> | ||||||
|  | 
 | ||||||
|  |     <item | ||||||
|  |         android:id="@+id/menu_delete_all" | ||||||
|  |         android:title="@string/delete_all" | ||||||
|  |         app:showAsAction="never"/> | ||||||
|  | 
 | ||||||
|  | </menu> | ||||||
							
								
								
									
										17
									
								
								app/src/main/res/menu/update_fragment_menu.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,17 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <menu xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     xmlns:app="http://schemas.android.com/apk/res-auto"> | ||||||
|  | 
 | ||||||
|  |     <item | ||||||
|  |         android:id="@+id/menu_save" | ||||||
|  |         android:title="@string/save" | ||||||
|  |         android:icon="@drawable/ic_save" | ||||||
|  |         android:iconTint="@color/white" | ||||||
|  |         app:showAsAction="ifRoom"/> | ||||||
|  | 
 | ||||||
|  |     <item | ||||||
|  |         android:id="@+id/menu_delete" | ||||||
|  |         android:title="@string/delete" | ||||||
|  |         app:showAsAction="never"/> | ||||||
|  | 
 | ||||||
|  | </menu> | ||||||
							
								
								
									
										5
									
								
								app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,5 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> | ||||||
|  |     <background android:drawable="@drawable/ic_launcher_background" /> | ||||||
|  |     <foreground android:drawable="@drawable/ic_launcher_foreground" /> | ||||||
|  | </adaptive-icon> | ||||||
							
								
								
									
										5
									
								
								app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,5 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> | ||||||
|  |     <background android:drawable="@drawable/ic_launcher_background" /> | ||||||
|  |     <foreground android:drawable="@drawable/ic_launcher_foreground" /> | ||||||
|  | </adaptive-icon> | ||||||
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-hdpi/ic_launcher.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-hdpi/ic_launcher_round.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 5.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-mdpi/ic_launcher.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-mdpi/ic_launcher_round.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xhdpi/ic_launcher.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 7.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxhdpi/ic_launcher.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 7.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 12 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 10 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 16 KiB | 
							
								
								
									
										53
									
								
								app/src/main/res/navigation/my_nav.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,53 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <navigation xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||||
|  |     xmlns:tools="http://schemas.android.com/tools" | ||||||
|  |     android:id="@+id/my_nav" | ||||||
|  |     app:startDestination="@id/listFragment"> | ||||||
|  | 
 | ||||||
|  |     <fragment | ||||||
|  |         android:id="@+id/listFragment" | ||||||
|  |         android:name="com.example.todoapp.fragments.list.ListFragment" | ||||||
|  |         android:label="ToDo List" | ||||||
|  |         tools:layout="@layout/fragment_list" > | ||||||
|  |         <action | ||||||
|  |             android:id="@+id/action_listFragment_to_addFragment" | ||||||
|  |             app:destination="@id/addFragment" | ||||||
|  |             app:enterAnim="@anim/from_right" | ||||||
|  |             app:exitAnim="@anim/to_left" | ||||||
|  |             app:popEnterAnim="@anim/from_left" | ||||||
|  |             app:popExitAnim="@anim/to_right" /> | ||||||
|  |         <action | ||||||
|  |             android:id="@+id/action_listFragment_to_updateFragment" | ||||||
|  |             app:destination="@id/updateFragment" | ||||||
|  |             app:enterAnim="@anim/from_left" | ||||||
|  |             app:exitAnim="@anim/to_right" | ||||||
|  |             app:popEnterAnim="@anim/from_right" | ||||||
|  |             app:popExitAnim="@anim/to_left" /> | ||||||
|  |     </fragment> | ||||||
|  |     <fragment | ||||||
|  |         android:id="@+id/addFragment" | ||||||
|  |         android:name="com.example.todoapp.fragments.add.AddFragment" | ||||||
|  |         android:label="Add" | ||||||
|  |         tools:layout="@layout/fragment_add" > | ||||||
|  |         <action | ||||||
|  |             android:id="@+id/action_addFragment_to_listFragment" | ||||||
|  |             app:destination="@id/listFragment" | ||||||
|  |             app:enterAnim="@anim/from_left" | ||||||
|  |             app:exitAnim="@anim/to_right" /> | ||||||
|  |     </fragment> | ||||||
|  |     <fragment | ||||||
|  |         android:id="@+id/updateFragment" | ||||||
|  |         android:name="com.example.todoapp.fragments.update.UpdateFragment" | ||||||
|  |         android:label="Update" | ||||||
|  |         tools:layout="@layout/fragment_update" > | ||||||
|  |         <action | ||||||
|  |             android:id="@+id/action_updateFragment_to_listFragment" | ||||||
|  |             app:destination="@id/listFragment" | ||||||
|  |             app:enterAnim="@anim/from_right" | ||||||
|  |             app:exitAnim="@anim/to_left" /> | ||||||
|  |         <argument | ||||||
|  |             android:name="currentItem" | ||||||
|  |             app:argType="com.example.todoapp.data.models.ToDoData" /> | ||||||
|  |     </fragment> | ||||||
|  | </navigation> | ||||||
							
								
								
									
										13
									
								
								app/src/main/res/values/colors.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,13 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <resources> | ||||||
|  |     <color name="colorPrimary">#6200EA</color> | ||||||
|  |     <color name="colorPrimaryDark">#5502C8</color> | ||||||
|  |     <color name="colorAccent">#9D46FF</color> | ||||||
|  | 
 | ||||||
|  |     <color name="white">#FFFFFF</color> | ||||||
|  |     <color name="lightGray">#E6E6E6</color> | ||||||
|  |     <color name="darkGray">#4B4B4B</color> | ||||||
|  |     <color name="red">#FF4646</color> | ||||||
|  |     <color name="yellow">#FFC114</color> | ||||||
|  |     <color name="green">#00C980</color> | ||||||
|  | </resources> | ||||||
							
								
								
									
										22
									
								
								app/src/main/res/values/strings.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,22 @@ | |||||||
|  | <resources> | ||||||
|  |     <string name="app_name">ToDo App</string> | ||||||
|  |     <string name="hello_blank_fragment">Hello blank fragment</string> | ||||||
|  |     <string name="no_data">No Data</string> | ||||||
|  | 
 | ||||||
|  |     <string name="title">Title</string> | ||||||
|  |     <string name="description">Description</string> | ||||||
|  |     <string name="search">Search</string> | ||||||
|  |     <string name="sort_by">Sort By</string> | ||||||
|  |     <string name="priority_high">Priority High</string> | ||||||
|  |     <string name="priority_low">Priority Low</string> | ||||||
|  |     <string name="delete_all">Delete All</string> | ||||||
|  |     <string name="add">Add</string> | ||||||
|  |     <string name="save">Save</string> | ||||||
|  |     <string name="delete">Delete</string> | ||||||
|  | 
 | ||||||
|  |     <string-array name="priorities"> | ||||||
|  |         <item>High Priority</item> | ||||||
|  |         <item>Medium Priority</item> | ||||||
|  |         <item>Low Priority</item> | ||||||
|  |     </string-array> | ||||||
|  | </resources> | ||||||
							
								
								
									
										10
									
								
								app/src/main/res/values/styles.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,10 @@ | |||||||
|  | <resources> | ||||||
|  |     <!-- Base application theme. --> | ||||||
|  |     <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> | ||||||
|  |         <!-- Customize your theme here. --> | ||||||
|  |         <item name="colorPrimary">@color/colorPrimary</item> | ||||||
|  |         <item name="colorPrimaryDark">@color/colorPrimaryDark</item> | ||||||
|  |         <item name="colorAccent">@color/colorAccent</item> | ||||||
|  |     </style> | ||||||
|  | 
 | ||||||
|  | </resources> | ||||||
							
								
								
									
										17
									
								
								app/src/test/java/com/example/todoapp/ExampleUnitTest.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,17 @@ | |||||||
|  | package com.example.todoapp | ||||||
|  | 
 | ||||||
|  | import org.junit.Test | ||||||
|  | 
 | ||||||
|  | import org.junit.Assert.* | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Example local unit test, which will execute on the development machine (host). | ||||||
|  |  * | ||||||
|  |  * See [testing documentation](http://d.android.com/tools/testing). | ||||||
|  |  */ | ||||||
|  | class ExampleUnitTest { | ||||||
|  |     @Test | ||||||
|  |     fun addition_isCorrect() { | ||||||
|  |         assertEquals(4, 2 + 2) | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										32
									
								
								build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,32 @@ | |||||||
|  | // Top-level build file where you can add configuration options common to all sub-projects/modules. | ||||||
|  | buildscript { | ||||||
|  | 
 | ||||||
|  |     ext { | ||||||
|  |         kotlin_version = '1.3.72' | ||||||
|  |         nav_version = "2.3.0-beta01" | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     repositories { | ||||||
|  |         google() | ||||||
|  |         jcenter() | ||||||
|  |     } | ||||||
|  |     dependencies { | ||||||
|  |         classpath "com.android.tools.build:gradle:4.0.0" | ||||||
|  | 
 | ||||||
|  |         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" | ||||||
|  |         classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version" | ||||||
|  |         // NOTE: Do not place your application dependencies here; they belong | ||||||
|  |         // in the individual module build.gradle files | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | allprojects { | ||||||
|  |     repositories { | ||||||
|  |         google() | ||||||
|  |         jcenter() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | task clean(type: Delete) { | ||||||
|  |     delete rootProject.buildDir | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								gradle.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,21 @@ | |||||||
|  | # Project-wide Gradle settings. | ||||||
|  | # IDE (e.g. Android Studio) users: | ||||||
|  | # Gradle settings configured through the IDE *will override* | ||||||
|  | # any settings specified in this file. | ||||||
|  | # For more details on how to configure your build environment visit | ||||||
|  | # http://www.gradle.org/docs/current/userguide/build_environment.html | ||||||
|  | # Specifies the JVM arguments used for the daemon process. | ||||||
|  | # The setting is particularly useful for tweaking memory settings. | ||||||
|  | org.gradle.jvmargs=-Xmx2048m | ||||||
|  | # When configured, Gradle will run in incubating parallel mode. | ||||||
|  | # This option should only be used with decoupled projects. More details, visit | ||||||
|  | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects | ||||||
|  | # org.gradle.parallel=true | ||||||
|  | # AndroidX package structure to make it clearer which packages are bundled with the | ||||||
|  | # Android operating system, and which are packaged with your app"s APK | ||||||
|  | # https://developer.android.com/topic/libraries/support-library/androidx-rn | ||||||
|  | android.useAndroidX=true | ||||||
|  | # Automatically convert third-party libraries to use AndroidX | ||||||
|  | android.enableJetifier=true | ||||||
|  | # Kotlin code style for this project: "official" or "obsolete": | ||||||
|  | kotlin.code.style=official | ||||||
							
								
								
									
										
											BIN
										
									
								
								gradle/wrapper/gradle-wrapper.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										6
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,6 @@ | |||||||
|  | #Fri Jun 26 09:49:12 CEST 2020 | ||||||
|  | distributionBase=GRADLE_USER_HOME | ||||||
|  | distributionPath=wrapper/dists | ||||||
|  | zipStoreBase=GRADLE_USER_HOME | ||||||
|  | zipStorePath=wrapper/dists | ||||||
|  | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip | ||||||
							
								
								
									
										172
									
								
								gradlew
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,172 @@ | |||||||
|  | #!/usr/bin/env sh | ||||||
|  | 
 | ||||||
|  | ############################################################################## | ||||||
|  | ## | ||||||
|  | ##  Gradle start up script for UN*X | ||||||
|  | ## | ||||||
|  | ############################################################################## | ||||||
|  | 
 | ||||||
|  | # Attempt to set APP_HOME | ||||||
|  | # Resolve links: $0 may be a link | ||||||
|  | PRG="$0" | ||||||
|  | # Need this for relative symlinks. | ||||||
|  | while [ -h "$PRG" ] ; do | ||||||
|  |     ls=`ls -ld "$PRG"` | ||||||
|  |     link=`expr "$ls" : '.*-> \(.*\)$'` | ||||||
|  |     if expr "$link" : '/.*' > /dev/null; then | ||||||
|  |         PRG="$link" | ||||||
|  |     else | ||||||
|  |         PRG=`dirname "$PRG"`"/$link" | ||||||
|  |     fi | ||||||
|  | done | ||||||
|  | SAVED="`pwd`" | ||||||
|  | cd "`dirname \"$PRG\"`/" >/dev/null | ||||||
|  | APP_HOME="`pwd -P`" | ||||||
|  | cd "$SAVED" >/dev/null | ||||||
|  | 
 | ||||||
|  | APP_NAME="Gradle" | ||||||
|  | APP_BASE_NAME=`basename "$0"` | ||||||
|  | 
 | ||||||
|  | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | ||||||
|  | DEFAULT_JVM_OPTS="" | ||||||
|  | 
 | ||||||
|  | # Use the maximum available, or set MAX_FD != -1 to use that value. | ||||||
|  | MAX_FD="maximum" | ||||||
|  | 
 | ||||||
|  | warn () { | ||||||
|  |     echo "$*" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | die () { | ||||||
|  |     echo | ||||||
|  |     echo "$*" | ||||||
|  |     echo | ||||||
|  |     exit 1 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # OS specific support (must be 'true' or 'false'). | ||||||
|  | cygwin=false | ||||||
|  | msys=false | ||||||
|  | darwin=false | ||||||
|  | nonstop=false | ||||||
|  | case "`uname`" in | ||||||
|  |   CYGWIN* ) | ||||||
|  |     cygwin=true | ||||||
|  |     ;; | ||||||
|  |   Darwin* ) | ||||||
|  |     darwin=true | ||||||
|  |     ;; | ||||||
|  |   MINGW* ) | ||||||
|  |     msys=true | ||||||
|  |     ;; | ||||||
|  |   NONSTOP* ) | ||||||
|  |     nonstop=true | ||||||
|  |     ;; | ||||||
|  | esac | ||||||
|  | 
 | ||||||
|  | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar | ||||||
|  | 
 | ||||||
|  | # Determine the Java command to use to start the JVM. | ||||||
|  | if [ -n "$JAVA_HOME" ] ; then | ||||||
|  |     if [ -x "$JAVA_HOME/jre/sh/java" ] ; then | ||||||
|  |         # IBM's JDK on AIX uses strange locations for the executables | ||||||
|  |         JAVACMD="$JAVA_HOME/jre/sh/java" | ||||||
|  |     else | ||||||
|  |         JAVACMD="$JAVA_HOME/bin/java" | ||||||
|  |     fi | ||||||
|  |     if [ ! -x "$JAVACMD" ] ; then | ||||||
|  |         die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME | ||||||
|  | 
 | ||||||
|  | Please set the JAVA_HOME variable in your environment to match the | ||||||
|  | location of your Java installation." | ||||||
|  |     fi | ||||||
|  | else | ||||||
|  |     JAVACMD="java" | ||||||
|  |     which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | ||||||
|  | 
 | ||||||
|  | Please set the JAVA_HOME variable in your environment to match the | ||||||
|  | location of your Java installation." | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # Increase the maximum file descriptors if we can. | ||||||
|  | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then | ||||||
|  |     MAX_FD_LIMIT=`ulimit -H -n` | ||||||
|  |     if [ $? -eq 0 ] ; then | ||||||
|  |         if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then | ||||||
|  |             MAX_FD="$MAX_FD_LIMIT" | ||||||
|  |         fi | ||||||
|  |         ulimit -n $MAX_FD | ||||||
|  |         if [ $? -ne 0 ] ; then | ||||||
|  |             warn "Could not set maximum file descriptor limit: $MAX_FD" | ||||||
|  |         fi | ||||||
|  |     else | ||||||
|  |         warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" | ||||||
|  |     fi | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # For Darwin, add options to specify how the application appears in the dock | ||||||
|  | if $darwin; then | ||||||
|  |     GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # For Cygwin, switch paths to Windows format before running java | ||||||
|  | if $cygwin ; then | ||||||
|  |     APP_HOME=`cygpath --path --mixed "$APP_HOME"` | ||||||
|  |     CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` | ||||||
|  |     JAVACMD=`cygpath --unix "$JAVACMD"` | ||||||
|  | 
 | ||||||
|  |     # We build the pattern for arguments to be converted via cygpath | ||||||
|  |     ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` | ||||||
|  |     SEP="" | ||||||
|  |     for dir in $ROOTDIRSRAW ; do | ||||||
|  |         ROOTDIRS="$ROOTDIRS$SEP$dir" | ||||||
|  |         SEP="|" | ||||||
|  |     done | ||||||
|  |     OURCYGPATTERN="(^($ROOTDIRS))" | ||||||
|  |     # Add a user-defined pattern to the cygpath arguments | ||||||
|  |     if [ "$GRADLE_CYGPATTERN" != "" ] ; then | ||||||
|  |         OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" | ||||||
|  |     fi | ||||||
|  |     # Now convert the arguments - kludge to limit ourselves to /bin/sh | ||||||
|  |     i=0 | ||||||
|  |     for arg in "$@" ; do | ||||||
|  |         CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` | ||||||
|  |         CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option | ||||||
|  | 
 | ||||||
|  |         if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition | ||||||
|  |             eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` | ||||||
|  |         else | ||||||
|  |             eval `echo args$i`="\"$arg\"" | ||||||
|  |         fi | ||||||
|  |         i=$((i+1)) | ||||||
|  |     done | ||||||
|  |     case $i in | ||||||
|  |         (0) set -- ;; | ||||||
|  |         (1) set -- "$args0" ;; | ||||||
|  |         (2) set -- "$args0" "$args1" ;; | ||||||
|  |         (3) set -- "$args0" "$args1" "$args2" ;; | ||||||
|  |         (4) set -- "$args0" "$args1" "$args2" "$args3" ;; | ||||||
|  |         (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; | ||||||
|  |         (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; | ||||||
|  |         (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; | ||||||
|  |         (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; | ||||||
|  |         (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; | ||||||
|  |     esac | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # Escape application args | ||||||
|  | save () { | ||||||
|  |     for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done | ||||||
|  |     echo " " | ||||||
|  | } | ||||||
|  | APP_ARGS=$(save "$@") | ||||||
|  | 
 | ||||||
|  | # Collect all arguments for the java command, following the shell quoting and substitution rules | ||||||
|  | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" | ||||||
|  | 
 | ||||||
|  | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong | ||||||
|  | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then | ||||||
|  |   cd "$(dirname "$0")" | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | exec "$JAVACMD" "$@" | ||||||
							
								
								
									
										84
									
								
								gradlew.bat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,84 @@ | |||||||
|  | @if "%DEBUG%" == "" @echo off | ||||||
|  | @rem ########################################################################## | ||||||
|  | @rem | ||||||
|  | @rem  Gradle startup script for Windows | ||||||
|  | @rem | ||||||
|  | @rem ########################################################################## | ||||||
|  | 
 | ||||||
|  | @rem Set local scope for the variables with windows NT shell | ||||||
|  | if "%OS%"=="Windows_NT" setlocal | ||||||
|  | 
 | ||||||
|  | set DIRNAME=%~dp0 | ||||||
|  | if "%DIRNAME%" == "" set DIRNAME=. | ||||||
|  | set APP_BASE_NAME=%~n0 | ||||||
|  | set APP_HOME=%DIRNAME% | ||||||
|  | 
 | ||||||
|  | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | ||||||
|  | set DEFAULT_JVM_OPTS= | ||||||
|  | 
 | ||||||
|  | @rem Find java.exe | ||||||
|  | if defined JAVA_HOME goto findJavaFromJavaHome | ||||||
|  | 
 | ||||||
|  | set JAVA_EXE=java.exe | ||||||
|  | %JAVA_EXE% -version >NUL 2>&1 | ||||||
|  | if "%ERRORLEVEL%" == "0" goto init | ||||||
|  | 
 | ||||||
|  | echo. | ||||||
|  | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | ||||||
|  | echo. | ||||||
|  | echo Please set the JAVA_HOME variable in your environment to match the | ||||||
|  | echo location of your Java installation. | ||||||
|  | 
 | ||||||
|  | goto fail | ||||||
|  | 
 | ||||||
|  | :findJavaFromJavaHome | ||||||
|  | set JAVA_HOME=%JAVA_HOME:"=% | ||||||
|  | set JAVA_EXE=%JAVA_HOME%/bin/java.exe | ||||||
|  | 
 | ||||||
|  | if exist "%JAVA_EXE%" goto init | ||||||
|  | 
 | ||||||
|  | echo. | ||||||
|  | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% | ||||||
|  | echo. | ||||||
|  | echo Please set the JAVA_HOME variable in your environment to match the | ||||||
|  | echo location of your Java installation. | ||||||
|  | 
 | ||||||
|  | goto fail | ||||||
|  | 
 | ||||||
|  | :init | ||||||
|  | @rem Get command-line arguments, handling Windows variants | ||||||
|  | 
 | ||||||
|  | if not "%OS%" == "Windows_NT" goto win9xME_args | ||||||
|  | 
 | ||||||
|  | :win9xME_args | ||||||
|  | @rem Slurp the command line arguments. | ||||||
|  | set CMD_LINE_ARGS= | ||||||
|  | set _SKIP=2 | ||||||
|  | 
 | ||||||
|  | :win9xME_args_slurp | ||||||
|  | if "x%~1" == "x" goto execute | ||||||
|  | 
 | ||||||
|  | set CMD_LINE_ARGS=%* | ||||||
|  | 
 | ||||||
|  | :execute | ||||||
|  | @rem Setup the command line | ||||||
|  | 
 | ||||||
|  | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar | ||||||
|  | 
 | ||||||
|  | @rem Execute Gradle | ||||||
|  | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% | ||||||
|  | 
 | ||||||
|  | :end | ||||||
|  | @rem End local scope for the variables with windows NT shell | ||||||
|  | if "%ERRORLEVEL%"=="0" goto mainEnd | ||||||
|  | 
 | ||||||
|  | :fail | ||||||
|  | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of | ||||||
|  | rem the _cmd.exe /c_ return code! | ||||||
|  | if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 | ||||||
|  | exit /b 1 | ||||||
|  | 
 | ||||||
|  | :mainEnd | ||||||
|  | if "%OS%"=="Windows_NT" endlocal | ||||||
|  | 
 | ||||||
|  | :omega | ||||||
							
								
								
									
										2
									
								
								settings.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,2 @@ | |||||||
|  | include ':app' | ||||||
|  | rootProject.name = "ToDo App" | ||||||