From 4a46a0d7fb57a78e6327f44891fdbbb4b2f723a0 Mon Sep 17 00:00:00 2001 From: MahmoudRH Date: Sat, 3 Sep 2022 11:17:34 +0300 Subject: [PATCH] initial commit on compose branch --- .gitignore | 16 ++ .idea/.gitignore | 3 + .idea/.name | 1 + .idea/compiler.xml | 6 + .idea/gradle.xml | 19 ++ .idea/inspectionProfiles/Project_Default.xml | 23 ++ .idea/misc.xml | 18 ++ .idea/vcs.xml | 6 + app/.gitignore | 1 + app/build.gradle | 107 ++++++++++ app/proguard-rules.pro | 21 ++ .../roomxml/ExampleInstrumentedTest.kt | 24 +++ app/src/main/AndroidManifest.xml | 30 +++ .../roomxml/application/NotesApplication.kt | 40 ++++ .../mahmoudrh/roomxml/data/local/NoteDAO.kt | 30 +++ .../mahmoudrh/roomxml/data/local/NotesDB.kt | 14 ++ .../data/repository/NotesRepositoryImpl.kt | 33 +++ .../com/mahmoudrh/roomxml/di/AppModule.kt | 44 ++++ .../mahmoudrh/roomxml/domain/models/Note.kt | 43 ++++ .../domain/repository/NotesRepository.kt | 19 ++ .../roomxml/domain/usecases/DeleteAllNotes.kt | 9 + .../roomxml/domain/usecases/DeleteNote.kt | 10 + .../roomxml/domain/usecases/GetAllNotes.kt | 29 +++ .../roomxml/domain/usecases/InsertNote.kt | 10 + .../roomxml/domain/usecases/NoteUseCases.kt | 10 + .../roomxml/domain/usecases/SearchNotes.kt | 11 + .../roomxml/domain/usecases/UpdateNote.kt | 10 + .../mahmoudrh/roomxml/domain/utils/OrderBy.kt | 58 ++++++ .../roomxml/domain/utils/OrderType.kt | 10 + .../roomxml/presentation/MainActivity.kt | 31 +++ .../screens/all_notes/AllNotesEvent.kt | 11 + .../screens/all_notes/AllNotesScreen.kt | 106 ++++++++++ .../screens/all_notes/AllNotesViewModel.kt | 91 ++++++++ .../screens/all_notes/NotesState.kt | 13 ++ .../presentation/screens/note/NoteEvent.kt | 6 + .../presentation/screens/note/NoteScreen.kt | 84 ++++++++ .../screens/note/NoteScreenViewModel.kt | 83 ++++++++ .../screens/search/SearchScreen.kt | 70 +++++++ .../screens/search/SearchViewModel.kt | 33 +++ .../roomxml/presentation/theme/Color.kt | 11 + .../roomxml/presentation/theme/Theme.kt | 68 ++++++ .../roomxml/presentation/theme/Type.kt | 34 +++ .../presentation/ui_components/AppTopBars.kt | 96 +++++++++ .../ui_components/EmptyListScreen.kt | 44 ++++ .../ui_components/LoadingScreen.kt | 28 +++ .../presentation/ui_components/NoteItem.kt | 197 ++++++++++++++++++ .../ui_components/OrderSection.kt | 95 +++++++++ .../ui_components/SearchTextField.kt | 94 +++++++++ .../presentation/utils/DateFormatter.kt | 12 ++ app/src/main/res/drawable/ic_add.xml | 10 + app/src/main/res/drawable/ic_check.xml | 10 + app/src/main/res/drawable/ic_delete.xml | 10 + app/src/main/res/drawable/ic_dialog_icon.xml | 5 + app/src/main/res/drawable/ic_edit.xml | 10 + app/src/main/res/drawable/ic_save.xml | 10 + app/src/main/res/drawable/ic_search.xml | 10 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2850 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 4414 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 5239 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1847 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 2582 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 3206 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4146 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 6554 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 7626 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6809 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 11556 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 12343 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9931 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 17327 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 18379 bytes app/src/main/res/values/colors.xml | 12 ++ app/src/main/res/values/strings.xml | 14 ++ app/src/main/res/values/themes.xml | 4 + app/src/main/res/xml/backup_rules.xml | 13 ++ .../main/res/xml/data_extraction_rules.xml | 19 ++ .../com/mahmoudrh/roomxml/ExampleUnitTest.kt | 17 ++ build.gradle | 20 ++ gradle.properties | 23 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 185 ++++++++++++++++ gradlew.bat | 89 ++++++++ settings.gradle | 16 ++ 86 files changed, 2355 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/.name create mode 100644 .idea/compiler.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/vcs.xml create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/proguard-rules.pro create mode 100644 app/src/androidTest/java/com/mahmoudrh/roomxml/ExampleInstrumentedTest.kt create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/application/NotesApplication.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/data/local/NoteDAO.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/data/local/NotesDB.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/data/repository/NotesRepositoryImpl.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/di/AppModule.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/domain/models/Note.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/domain/repository/NotesRepository.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/DeleteAllNotes.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/DeleteNote.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/GetAllNotes.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/InsertNote.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/NoteUseCases.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/SearchNotes.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/UpdateNote.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/domain/utils/OrderBy.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/domain/utils/OrderType.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/MainActivity.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/all_notes/AllNotesEvent.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/all_notes/AllNotesScreen.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/all_notes/AllNotesViewModel.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/all_notes/NotesState.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/note/NoteEvent.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/note/NoteScreen.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/note/NoteScreenViewModel.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/search/SearchScreen.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/search/SearchViewModel.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/theme/Color.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/theme/Theme.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/theme/Type.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/AppTopBars.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/EmptyListScreen.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/LoadingScreen.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/NoteItem.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/OrderSection.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/SearchTextField.kt create mode 100644 app/src/main/java/com/mahmoudrh/roomxml/presentation/utils/DateFormatter.kt create mode 100644 app/src/main/res/drawable/ic_add.xml create mode 100644 app/src/main/res/drawable/ic_check.xml create mode 100644 app/src/main/res/drawable/ic_delete.xml create mode 100644 app/src/main/res/drawable/ic_dialog_icon.xml create mode 100644 app/src/main/res/drawable/ic_edit.xml create mode 100644 app/src/main/res/drawable/ic_save.xml create mode 100644 app/src/main/res/drawable/ic_search.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/themes.xml create mode 100644 app/src/main/res/xml/backup_rules.xml create mode 100644 app/src/main/res/xml/data_extraction_rules.xml create mode 100644 app/src/test/java/com/mahmoudrh/roomxml/ExampleUnitTest.kt create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2cf9b31 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +*.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 +local.properties +/app/release diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..a1b5ab6 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +D Note \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..fb7f4a8 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..a2d7c21 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..875a112 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,23 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..403cbaf --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..d39fcb7 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,107 @@ +plugins { + id 'com.android.application' + id 'org.jetbrains.kotlin.android' + id 'kotlin-kapt' + id 'dagger.hilt.android.plugin' + id 'com.google.devtools.ksp' version '1.7.10-1.0.6' +} + +android { + compileSdk 33 + + defaultConfig { + applicationId "com.mahmoudrh.roomxml" + minSdk 22 + targetSdk 33 + versionCode 4 + versionName "2.0.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary true + } + } + + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } + buildFeatures { + compose true + } + composeOptions { + kotlinCompilerExtensionVersion compose_version + } + packagingOptions { + resources { + excludes += '/META-INF/{AL2.0,LGPL2.1}' + } + } + + applicationVariants.all { variant -> + kotlin.sourceSets { + getByName(variant.name) { + kotlin.srcDir("build/generated/ksp/${variant.name}/kotlin") + } + } + } +} + +dependencies { + + + + //-> Material Icons + implementation "androidx.compose.material:material-icons-extended:$compose_version" + + + //-> Compose Destinations Library + implementation "io.github.raamcosta.compose-destinations:core:$nav_destinations_version" + ksp "io.github.raamcosta.compose-destinations:ksp:$nav_destinations_version" + + //-> RoomDB + implementation "androidx.room:room-runtime:$room_version" + kapt "androidx.room:room-compiler:$room_version" + implementation "androidx.room:room-ktx:$room_version" + + // ViewModel utilities for Compose + implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.6.0-alpha01" + + //-> Hilt DI + implementation "com.google.dagger:hilt-android:$hilt_version" + kapt "com.google.dagger:hilt-compiler:$hilt_version" + kapt "androidx.hilt:hilt-compiler:1.0.0" + implementation 'androidx.hilt:hilt-navigation-compose:1.0.0' + + + // ACRA crash report library + implementation "ch.acra:acra-mail:5.9.5" + implementation "ch.acra:acra-dialog:5.9.5" + + + + implementation 'androidx.core:core-ktx:1.7.0' + implementation "androidx.compose.ui:ui:$compose_version" + implementation "androidx.compose.ui:ui-util:$compose_version" + implementation 'androidx.compose.material3:material3:1.0.0-beta01' + + implementation 'androidx.appcompat:appcompat:1.5.0' + implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' + implementation 'androidx.activity:activity-compose:1.5.1' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" + debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" + debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version" +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -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 \ No newline at end of file diff --git a/app/src/androidTest/java/com/mahmoudrh/roomxml/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/mahmoudrh/roomxml/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..605c080 --- /dev/null +++ b/app/src/androidTest/java/com/mahmoudrh/roomxml/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.mahmoudrh.roomxml + +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.mahmoudrh.roomxml", appContext.packageName) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f41b85d --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/application/NotesApplication.kt b/app/src/main/java/com/mahmoudrh/roomxml/application/NotesApplication.kt new file mode 100644 index 0000000..8453bfa --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/application/NotesApplication.kt @@ -0,0 +1,40 @@ +package com.mahmoudrh.roomxml.application + +import android.app.Application +import android.content.Context +import com.mahmoudrh.roomxml.BuildConfig +import com.mahmoudrh.roomxml.R +import dagger.hilt.android.HiltAndroidApp +import org.acra.config.dialog +import org.acra.config.mailSender +import org.acra.data.StringFormat +import org.acra.ktx.initAcra + +@HiltAndroidApp +class NotesApplication: Application() { + + override fun attachBaseContext(base: Context?) { + super.attachBaseContext(base) + + initAcra { + buildConfigClass = BuildConfig::class.java + reportFormat = StringFormat.JSON + + dialog { + text = getString(R.string.dialog_text) + title = getString(R.string.dialog_title) + positiveButtonText = getString(R.string.dialog_positive) + negativeButtonText = getString(R.string.dialog_negative) + commentPrompt = getString(R.string.dialog_comment) + resIcon = R.drawable.ic_dialog_icon + resTheme = R.style.Theme_DNote + } + + mailSender { + mailTo = "dnote.developer@gmail.com" + subject = "D-Note Crash Report" + reportFileName = "Crash.txt" + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/data/local/NoteDAO.kt b/app/src/main/java/com/mahmoudrh/roomxml/data/local/NoteDAO.kt new file mode 100644 index 0000000..1dcb1aa --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/data/local/NoteDAO.kt @@ -0,0 +1,30 @@ +package com.mahmoudrh.roomxml.data.local + +import androidx.room.* +import com.mahmoudrh.roomxml.domain.models.Note +import kotlinx.coroutines.flow.Flow + +@Dao +interface NoteDAO { + + @Insert + suspend fun insertNote(note: Note) + + @Update + suspend fun updateNote(note: Note) + + @Delete + suspend fun deleteNote(note: Note) + + @Query("DELETE FROM notes") + suspend fun deleteAll() + + @Query("SELECT * FROM notes") + fun getAllNotes(): Flow> + + @Query("SELECT * FROM notes WHERE title LIKE '%' || :searchWord || '%'") + fun searchNotes(searchWord: String? = null): Flow> + + + +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/data/local/NotesDB.kt b/app/src/main/java/com/mahmoudrh/roomxml/data/local/NotesDB.kt new file mode 100644 index 0000000..867f735 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/data/local/NotesDB.kt @@ -0,0 +1,14 @@ +package com.mahmoudrh.roomxml.data.local + +import androidx.room.Database +import androidx.room.RoomDatabase +import com.mahmoudrh.roomxml.domain.models.Note + +@Database(entities = [Note::class], version = 1, exportSchema = false) +abstract class NotesDB : RoomDatabase() { + abstract val noteDAO: NoteDAO + + companion object{ + const val DATABASE_NAME = "NotesDB" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/data/repository/NotesRepositoryImpl.kt b/app/src/main/java/com/mahmoudrh/roomxml/data/repository/NotesRepositoryImpl.kt new file mode 100644 index 0000000..dcdd9a6 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/data/repository/NotesRepositoryImpl.kt @@ -0,0 +1,33 @@ +package com.mahmoudrh.roomxml.data.repository + +import com.mahmoudrh.roomxml.data.local.NoteDAO +import com.mahmoudrh.roomxml.domain.models.Note +import com.mahmoudrh.roomxml.domain.repository.NotesRepository +import kotlinx.coroutines.flow.Flow + +class NotesRepositoryImpl(private val dao: NoteDAO) : NotesRepository { + + override suspend fun insert(note: Note) { + dao.insertNote(note) + } + + override suspend fun update(note: Note) { + dao.updateNote(note) + } + + override suspend fun delete(note: Note) { + dao.deleteNote(note) + } + + override suspend fun deleteAll() { + dao.deleteAll() + } + + override fun searchNotes(searchWord: String): Flow> { + return dao.searchNotes(searchWord) + } + + override fun getAllNotes(): Flow> { + return dao.getAllNotes() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/di/AppModule.kt b/app/src/main/java/com/mahmoudrh/roomxml/di/AppModule.kt new file mode 100644 index 0000000..038c258 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/di/AppModule.kt @@ -0,0 +1,44 @@ +package com.mahmoudrh.roomxml.di + +import android.app.Application +import androidx.room.Room +import com.mahmoudrh.roomxml.data.local.NotesDB +import com.mahmoudrh.roomxml.data.repository.NotesRepositoryImpl +import com.mahmoudrh.roomxml.domain.repository.NotesRepository +import com.mahmoudrh.roomxml.domain.usecases.* +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +object AppModule { + + @Provides + @Singleton + fun provideDataBase(app:Application): NotesDB{ + return Room.databaseBuilder(app,NotesDB::class.java,NotesDB.DATABASE_NAME).build() + } + + + @Provides + @Singleton + fun provideNoteRepository(database:NotesDB): NotesRepository{ + return NotesRepositoryImpl(database.noteDAO) + } + + @Provides + @Singleton + fun provideNoteUseCases(repository:NotesRepository):NoteUseCases{ + return NoteUseCases( + getAllNotes = GetAllNotes(repository), + deleteNote = DeleteNote(repository), + updateNote = UpdateNote(repository), + searchNotes = SearchNotes(repository), + deleteAllNotes = DeleteAllNotes(repository), + insertNote = InsertNote(repository) + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/domain/models/Note.kt b/app/src/main/java/com/mahmoudrh/roomxml/domain/models/Note.kt new file mode 100644 index 0000000..637dc3c --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/domain/models/Note.kt @@ -0,0 +1,43 @@ +package com.mahmoudrh.roomxml.domain.models + +import android.os.Parcel +import android.os.Parcelable +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "notes") +data class Note( + @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") var id:Int = 0, + @ColumnInfo(name = "title") val title: String, + @ColumnInfo(name = "content") val content: String, + @ColumnInfo(name = "date") val date: String, +) : Parcelable { + constructor(parcel: Parcel) : this( + parcel.readInt(), + parcel.readString()?:"no title", + parcel.readString()?:"no content", + parcel.readString()?:"no date", + ) + + override fun writeToParcel(parcel: Parcel, flags: Int) { + parcel.writeInt(id) + parcel.writeString(title) + parcel.writeString(content) + parcel.writeString(date) + } + + override fun describeContents(): Int { + return 0 + } + + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): Note { + return Note(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } +} diff --git a/app/src/main/java/com/mahmoudrh/roomxml/domain/repository/NotesRepository.kt b/app/src/main/java/com/mahmoudrh/roomxml/domain/repository/NotesRepository.kt new file mode 100644 index 0000000..0ffc919 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/domain/repository/NotesRepository.kt @@ -0,0 +1,19 @@ +package com.mahmoudrh.roomxml.domain.repository + +import com.mahmoudrh.roomxml.domain.models.Note +import kotlinx.coroutines.flow.Flow + +interface NotesRepository { + + suspend fun insert(note: Note) + + suspend fun update(note: Note) + + suspend fun delete(note: Note) + + suspend fun deleteAll() + + fun searchNotes(searchWord: String): Flow> + + fun getAllNotes(): Flow> +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/DeleteAllNotes.kt b/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/DeleteAllNotes.kt new file mode 100644 index 0000000..3acbe14 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/DeleteAllNotes.kt @@ -0,0 +1,9 @@ +package com.mahmoudrh.roomxml.domain.usecases + +import com.mahmoudrh.roomxml.domain.repository.NotesRepository + +class DeleteAllNotes constructor(private val repository: NotesRepository) { + suspend operator fun invoke(){ + repository.deleteAll() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/DeleteNote.kt b/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/DeleteNote.kt new file mode 100644 index 0000000..79081b0 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/DeleteNote.kt @@ -0,0 +1,10 @@ +package com.mahmoudrh.roomxml.domain.usecases + +import com.mahmoudrh.roomxml.domain.models.Note +import com.mahmoudrh.roomxml.domain.repository.NotesRepository + +class DeleteNote(private val repository: NotesRepository){ + suspend operator fun invoke(note: Note){ + repository.delete(note) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/GetAllNotes.kt b/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/GetAllNotes.kt new file mode 100644 index 0000000..ecee10d --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/GetAllNotes.kt @@ -0,0 +1,29 @@ +package com.mahmoudrh.roomxml.domain.usecases + +import com.mahmoudrh.roomxml.domain.models.Note +import com.mahmoudrh.roomxml.domain.repository.NotesRepository +import com.mahmoudrh.roomxml.domain.utils.OrderBy +import com.mahmoudrh.roomxml.domain.utils.OrderType +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map + +class GetAllNotes(private val repository: NotesRepository) { + operator fun invoke(orderBy: OrderBy = OrderBy.Date(OrderType.Descending)): Flow> { + return repository.getAllNotes().map { notesList -> + when (orderBy.orderType) { + is OrderType.Descending -> { + when (orderBy) { + is OrderBy.Title -> notesList.sortedByDescending { it.title.lowercase() } + is OrderBy.Date -> notesList.sortedByDescending { it.date.toLong() } + } + } + is OrderType.Ascending -> { + when (orderBy) { + is OrderBy.Title -> notesList.sortedBy { it.title.lowercase() } + is OrderBy.Date -> notesList.sortedBy { it.date.toLong() } + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/InsertNote.kt b/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/InsertNote.kt new file mode 100644 index 0000000..c3a3e98 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/InsertNote.kt @@ -0,0 +1,10 @@ +package com.mahmoudrh.roomxml.domain.usecases + +import com.mahmoudrh.roomxml.domain.models.Note +import com.mahmoudrh.roomxml.domain.repository.NotesRepository + +class InsertNote (private val repository: NotesRepository) { + suspend operator fun invoke(note: Note){ + repository.insert(note) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/NoteUseCases.kt b/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/NoteUseCases.kt new file mode 100644 index 0000000..a30ebf4 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/NoteUseCases.kt @@ -0,0 +1,10 @@ +package com.mahmoudrh.roomxml.domain.usecases + +data class NoteUseCases( + val getAllNotes: GetAllNotes, + val deleteNote: DeleteNote, + val updateNote: UpdateNote, + val searchNotes: SearchNotes, + val deleteAllNotes: DeleteAllNotes, + val insertNote: InsertNote +) \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/SearchNotes.kt b/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/SearchNotes.kt new file mode 100644 index 0000000..9f10889 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/SearchNotes.kt @@ -0,0 +1,11 @@ +package com.mahmoudrh.roomxml.domain.usecases + +import com.mahmoudrh.roomxml.domain.models.Note +import com.mahmoudrh.roomxml.domain.repository.NotesRepository +import kotlinx.coroutines.flow.Flow + +class SearchNotes constructor(private val repository: NotesRepository) { + operator fun invoke(searchWord:String): Flow> { + return repository.searchNotes(searchWord) + } +} diff --git a/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/UpdateNote.kt b/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/UpdateNote.kt new file mode 100644 index 0000000..e888a96 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/domain/usecases/UpdateNote.kt @@ -0,0 +1,10 @@ +package com.mahmoudrh.roomxml.domain.usecases + +import com.mahmoudrh.roomxml.domain.models.Note +import com.mahmoudrh.roomxml.domain.repository.NotesRepository + +class UpdateNote(private val repository: NotesRepository) { + suspend operator fun invoke(note: Note){ + repository.update(note) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/domain/utils/OrderBy.kt b/app/src/main/java/com/mahmoudrh/roomxml/domain/utils/OrderBy.kt new file mode 100644 index 0000000..1965e05 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/domain/utils/OrderBy.kt @@ -0,0 +1,58 @@ +package com.mahmoudrh.roomxml.domain.utils + +sealed class OrderBy(val orderType: OrderType) { + class Title(orderType: OrderType) : OrderBy(orderType) + class Date(orderType: OrderType) : OrderBy(orderType) + + fun copy(orderType: OrderType): OrderBy { + return when (this) { + is Title -> Title(orderType) + is Date -> Date(orderType) + } + } + + companion object { + const val DATE = 0 + const val TITLE = 1 + + fun getOrderBy(orderType: Int, orderBy: Int): OrderBy { + val ot: OrderType = when (orderType) { + OrderType.ASCENDING -> { + OrderType.Ascending + } + OrderType.DESCENDING -> { + OrderType.Descending + } + else -> { + OrderType.Descending + } + } + val ob: OrderBy = when (orderBy) { + DATE -> { + Date(ot) + } + TITLE -> { + Title(ot) + } + else -> { + Date(ot) + } + } + + return ob + } + + fun getOrderByInt(orderBy: OrderBy): Int { + return when (orderBy) { + is Date -> DATE + is Title -> TITLE + } + } + fun getOrderTypeInt(orderBy: OrderBy): Int { + return when (orderBy.orderType) { + OrderType.Ascending -> OrderType.ASCENDING + OrderType.Descending -> OrderType.DESCENDING + } + } + } +} diff --git a/app/src/main/java/com/mahmoudrh/roomxml/domain/utils/OrderType.kt b/app/src/main/java/com/mahmoudrh/roomxml/domain/utils/OrderType.kt new file mode 100644 index 0000000..dc612b7 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/domain/utils/OrderType.kt @@ -0,0 +1,10 @@ +package com.mahmoudrh.roomxml.domain.utils + +sealed class OrderType{ + object Ascending:OrderType() + object Descending:OrderType() + companion object{ + const val DESCENDING = 0 + const val ASCENDING = 1 + } +} diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/MainActivity.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/MainActivity.kt new file mode 100644 index 0000000..3ad3bde --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/MainActivity.kt @@ -0,0 +1,31 @@ +package com.mahmoudrh.roomxml.presentation + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.ui.Modifier +import com.mahmoudrh.roomxml.presentation.screens.NavGraphs +import com.mahmoudrh.roomxml.presentation.theme.DNoteTheme +import com.ramcosta.composedestinations.DestinationsNavHost +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + DNoteTheme { + Surface( + modifier = Modifier.fillMaxSize(), + color = MaterialTheme.colorScheme.background + ) { + DestinationsNavHost(navGraph = NavGraphs.root) + } + } + } + } +} + diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/all_notes/AllNotesEvent.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/all_notes/AllNotesEvent.kt new file mode 100644 index 0000000..031c25d --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/all_notes/AllNotesEvent.kt @@ -0,0 +1,11 @@ +package com.mahmoudrh.roomxml.presentation.screens.all_notes + +import com.mahmoudrh.roomxml.domain.models.Note +import com.mahmoudrh.roomxml.domain.utils.OrderBy + +sealed class AllNotesEvent { + data class Order(val order: OrderBy): AllNotesEvent() + data class DeleteNote(val note: Note): AllNotesEvent() + object RestoreNote: AllNotesEvent() + object ToggleOrderSection: AllNotesEvent() +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/all_notes/AllNotesScreen.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/all_notes/AllNotesScreen.kt new file mode 100644 index 0000000..f6de1e2 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/all_notes/AllNotesScreen.kt @@ -0,0 +1,106 @@ +package com.mahmoudrh.roomxml.presentation.screens.all_notes + +import androidx.compose.animation.* +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.* +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import com.mahmoudrh.roomxml.presentation.screens.destinations.NoteScreenDestination +import com.mahmoudrh.roomxml.presentation.screens.destinations.SearchScreenDestination +import com.mahmoudrh.roomxml.presentation.ui_components.* +import com.ramcosta.composedestinations.annotation.Destination +import com.ramcosta.composedestinations.annotation.RootNavGraph +import com.ramcosta.composedestinations.navigation.DestinationsNavigator +import kotlinx.coroutines.launch + + +@RootNavGraph(start = true) +@Destination +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun AllNotesScreen( + viewModel: AllNotesViewModel = hiltViewModel(), + navigator: DestinationsNavigator +) { + val notesState = viewModel.notesState.value + val snackBarHostState = remember { SnackbarHostState() } + val scope = rememberCoroutineScope() + Scaffold( + topBar = { + AppTopBars.DefaultTopBar(title = "D Note", actionIcon = Icons.Default.Search) { + navigator.navigate(SearchScreenDestination) + /*TODO Navigate To Search Screen*/ + } + }, + containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp), + floatingActionButton = { + FloatingActionButton(onClick = { navigator.navigate(NoteScreenDestination.route) }) { + Icon(imageVector = Icons.Default.Add, contentDescription = "New Note") + } + }, snackbarHost = { SnackbarHost(snackBarHostState) }) + { paddingValues -> + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues), + contentPadding = PaddingValues(start = 20.dp, end = 10.dp, top = 10.dp, bottom = 10.dp) + ) { + item { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "Sort ", + ) + IconButton(onClick = { viewModel.onEvent(AllNotesEvent.ToggleOrderSection) }) { + Icon(imageVector = Icons.Default.Sort, contentDescription = "Sort") + } + } + AnimatedVisibility( + visible = notesState.isOrderSectionVisible, + enter = expandVertically(), + exit = shrinkVertically() + ) { + OrderSection( + order = notesState.order, + onOrderChange = { + viewModel.onEvent(AllNotesEvent.Order(it)) + } + ) + } + } + items(notesState.notes, key = { it.id }) { + + NoteItem( + modifier = Modifier.padding(vertical = 8.dp), + note = it, + onClick = { navigator.navigate(NoteScreenDestination(it)) }, + onSwipeOut = { noteObject -> + viewModel.onEvent(AllNotesEvent.DeleteNote(noteObject)) + scope.launch { + val result = snackBarHostState.showSnackbar( + message = "Note deleted", + actionLabel = "Undo" + ) + if (result == SnackbarResult.ActionPerformed) { + viewModel.onEvent(AllNotesEvent.RestoreNote) + } + } + } + ) + + } + } + EmptyListScreen(visibility = notesState.isListEmpty, text = "Add Some Notes!") + LoadingScreen(visibility = notesState.isListLoading) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/all_notes/AllNotesViewModel.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/all_notes/AllNotesViewModel.kt new file mode 100644 index 0000000..5600b24 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/all_notes/AllNotesViewModel.kt @@ -0,0 +1,91 @@ +package com.mahmoudrh.roomxml.presentation.screens.all_notes + +import android.app.Application +import android.content.Context +import androidx.compose.runtime.State +import androidx.compose.runtime.mutableStateOf +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.mahmoudrh.roomxml.domain.models.Note +import com.mahmoudrh.roomxml.domain.usecases.NoteUseCases +import com.mahmoudrh.roomxml.domain.utils.OrderBy +import com.mahmoudrh.roomxml.domain.utils.OrderType +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class AllNotesViewModel @Inject constructor( + private val noteUseCases: NoteUseCases, + private val application: Application +) : ViewModel() { + private val _notesState = mutableStateOf(NotesState()) + val notesState: State = _notesState + private var recentlyDeletedNote: Note? = null + private var getNotesJob: Job? = null + private val preferences = application.getSharedPreferences("OrderPreferences",Context.MODE_PRIVATE) + init { + val ob = preferences.getInt("OrderBy",OrderBy.DATE) + val ot = preferences.getInt("OrderType",OrderType.DESCENDING) + val orderPreference = OrderBy.getOrderBy(orderType = ot, orderBy = ob) + loadAllNotes(orderPreference) + } + + private fun loadAllNotes(orderBy: OrderBy) { + getNotesJob?.cancel() // cancel if already running + getNotesJob = noteUseCases.getAllNotes(orderBy).onEach { + _notesState.value = notesState.value.copy( + notes = it, + order = orderBy, + isListLoading = false, + isListEmpty = it.isEmpty() + ) + }.launchIn(viewModelScope) + } + + fun onEvent(event: AllNotesEvent) { + when (event) { + is AllNotesEvent.DeleteNote -> { + viewModelScope.launch { + noteUseCases.deleteNote(event.note) + recentlyDeletedNote = event.note + } + } + is AllNotesEvent.Order -> { + if (notesState.value.order::class == event.order::class && + notesState.value.order.orderType == event.order.orderType) { // same order and same order type + return + }else { + loadAllNotes(event.order) + saveIntoSharedPreferences(event.order) + } + } + AllNotesEvent.RestoreNote -> { + recentlyDeletedNote?.let { + viewModelScope.launch { + noteUseCases.insertNote(it) + recentlyDeletedNote = null + } + } + } + AllNotesEvent.ToggleOrderSection -> { + _notesState.value = notesState.value.copy( + isOrderSectionVisible = !notesState.value.isOrderSectionVisible + ) + } + } + } + + private fun saveIntoSharedPreferences(order: OrderBy) { + val ot = OrderBy.getOrderTypeInt(order) + val ob = OrderBy.getOrderByInt(order) + preferences.edit().apply { + putInt("OrderType",ot) + putInt("OrderBy",ob) + apply() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/all_notes/NotesState.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/all_notes/NotesState.kt new file mode 100644 index 0000000..7712423 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/all_notes/NotesState.kt @@ -0,0 +1,13 @@ +package com.mahmoudrh.roomxml.presentation.screens.all_notes + +import com.mahmoudrh.roomxml.domain.models.Note +import com.mahmoudrh.roomxml.domain.utils.OrderBy +import com.mahmoudrh.roomxml.domain.utils.OrderType + +data class NotesState( + val notes: List = emptyList(), + val order: OrderBy = OrderBy.Date(OrderType.Descending), + val isOrderSectionVisible: Boolean = false, + val isListLoading:Boolean = true, + val isListEmpty:Boolean = false +) \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/note/NoteEvent.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/note/NoteEvent.kt new file mode 100644 index 0000000..91718fa --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/note/NoteEvent.kt @@ -0,0 +1,6 @@ +package com.mahmoudrh.roomxml.presentation.screens.note + +sealed class NoteEvent { + object InsertNote :NoteEvent() + object UpdateNote :NoteEvent() +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/note/NoteScreen.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/note/NoteScreen.kt new file mode 100644 index 0000000..626476d --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/note/NoteScreen.kt @@ -0,0 +1,84 @@ +package com.mahmoudrh.roomxml.presentation.screens.note + +import android.widget.Toast +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Check +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusDirection +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import com.mahmoudrh.roomxml.domain.models.Note +import com.mahmoudrh.roomxml.presentation.ui_components.AppTopBars +import com.ramcosta.composedestinations.annotation.Destination +import com.ramcosta.composedestinations.navigation.DestinationsNavigator + +@Destination(navArgsDelegate = NoteNavArgs::class) +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun NoteScreen(viewModel: NoteViewModel = hiltViewModel(), navigator: DestinationsNavigator) { + + val focusManager = LocalFocusManager.current + val eventName = viewModel.eventName + Scaffold(topBar = { + AppTopBars.DefaultTopBar( + title = eventName.value, + onNavigateBack = { navigator.popBackStack() }, + actionIcon = Icons.Default.Check, + onActionClick = { + if (viewModel.isUpdatingNote()) { + viewModel.onEvent(NoteEvent.UpdateNote) + } else { + viewModel.onEvent(NoteEvent.InsertNote) + } + }) + }) { paddingValues -> + Column( + modifier = Modifier + .padding(paddingValues) + .padding(horizontal = 20.dp, vertical = 10.dp) + ) { + OutlinedTextField( + modifier = Modifier.fillMaxWidth(), + value = viewModel.noteTitle.value, + onValueChange = { viewModel.noteTitle.value = it }, + label = { Text(text = "Title") }, + singleLine = true, + placeholder = { Text(text = "Add some title...") }, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), + keyboardActions = KeyboardActions( + onNext = { + focusManager.moveFocus(FocusDirection.Down) + } + ), + isError = viewModel.isTitleError.value + ) + Spacer(modifier = Modifier.size(8.dp)) + OutlinedTextField( + modifier = Modifier.fillMaxSize(), + value = viewModel.noteContent.value, + onValueChange = { viewModel.noteContent.value = it }, + label = { Text(text = "Content") }, + placeholder = { Text(text = "Add some content...") }, + isError = viewModel.isContentError.value + ) + } + } + + if (viewModel.isEventSuccess.value) { + Toast.makeText(LocalContext.current, "${eventName.value} Success", Toast.LENGTH_SHORT) + .show() + navigator.popBackStack() + } + +} + + +data class NoteNavArgs(val note: Note?) \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/note/NoteScreenViewModel.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/note/NoteScreenViewModel.kt new file mode 100644 index 0000000..5dab4fc --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/note/NoteScreenViewModel.kt @@ -0,0 +1,83 @@ +package com.mahmoudrh.roomxml.presentation.screens.note + +import androidx.compose.runtime.mutableStateOf +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.mahmoudrh.roomxml.domain.models.Note +import com.mahmoudrh.roomxml.domain.usecases.NoteUseCases +import com.mahmoudrh.roomxml.presentation.screens.navArgs +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import java.util.* +import javax.inject.Inject + +@HiltViewModel +class NoteViewModel @Inject constructor( + private val noteUseCases: NoteUseCases, + handle: SavedStateHandle, +) : ViewModel() { + val noteTitle = mutableStateOf("") + val noteContent = mutableStateOf("") + val note = handle.navArgs().note + val isTitleError = mutableStateOf(false) + val isContentError = mutableStateOf(false) + val isEventSuccess = mutableStateOf(false) + val eventName = mutableStateOf("Adding New Note") + init { + note?.let { + eventName.value = "Editing Note" + noteTitle.value = it.title + noteContent.value = it.content + } + } + + fun onEvent(event: NoteEvent) { + when (event) { + is NoteEvent.InsertNote -> { + viewModelScope.launch { + isTitleError.value = isTitleEmpty() + isContentError.value = isContentEmpty() + if (isTitleEmpty() || isContentEmpty()) { + return@launch + } else { + noteUseCases.insertNote( + Note( + title = noteTitle.value, + content = noteContent.value, + date = Date().time.toString(), + ) + ) + isEventSuccess.value = true + } + + } + } + is NoteEvent.UpdateNote -> { + viewModelScope.launch { + isTitleError.value = isTitleEmpty() + isContentError.value = isContentEmpty() + if (isTitleEmpty() || isContentEmpty()) { + return@launch + } else { + note?.let { + noteUseCases.updateNote( + it.copy( + title = noteTitle.value, + content = noteContent.value, + ) + ) + isEventSuccess.value = true + } + } + } + } + } + + } + + private fun isTitleEmpty() = noteTitle.value.isEmpty() + private fun isContentEmpty() = noteContent.value.isEmpty() + fun isUpdatingNote() = note != null //if the object passed isn't null, the user is updating an existing note. + +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/search/SearchScreen.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/search/SearchScreen.kt new file mode 100644 index 0000000..39d5d9f --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/search/SearchScreen.kt @@ -0,0 +1,70 @@ +package com.mahmoudrh.roomxml.presentation.screens.search + + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.surfaceColorAtElevation +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +import com.mahmoudrh.roomxml.presentation.screens.destinations.NoteScreenDestination +import com.mahmoudrh.roomxml.presentation.ui_components.AppTopBars +import com.mahmoudrh.roomxml.presentation.ui_components.EmptyListScreen +import com.mahmoudrh.roomxml.presentation.ui_components.LoadingScreen +import com.mahmoudrh.roomxml.presentation.ui_components.NoteItem +import com.ramcosta.composedestinations.annotation.Destination +import com.ramcosta.composedestinations.navigation.DestinationsNavigator + +@Destination +@Composable +fun SearchScreen(viewModel: SearchViewModel = hiltViewModel(), navigator: DestinationsNavigator) { + val focusRequester = FocusRequester() + + Column(Modifier.fillMaxSize()) { + AppTopBars.SearchTopBar( + onNavigateBack = { navigator.popBackStack() }, + hint = "Search..", + focusRequester = focusRequester, + searchWord = viewModel.searchWord, + onSearch = { viewModel.search() } + ) + Box(Modifier.background(MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp))) { + LazyColumn( + modifier = Modifier + .fillMaxSize(), + contentPadding = PaddingValues( + start = 20.dp, + end = 10.dp, + top = 10.dp, + bottom = 10.dp + ) + ) { + items(viewModel.resultsList, key = { it.id }) { + NoteItem( + modifier = Modifier.padding(vertical = 8.dp), + note = it, + onClick = { navigator.navigate(NoteScreenDestination(it)) }, + ) + } + } + EmptyListScreen( + visibility = viewModel.isResultsListEmpty.value, + text = "Sorry, We Couldn't Find Any Results.. ", + fontSize = 20.sp + ) + LoadingScreen(visibility = viewModel.isLoading.value) + } + } + + DisposableEffect(Unit) { + focusRequester.requestFocus() + onDispose { } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/search/SearchViewModel.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/search/SearchViewModel.kt new file mode 100644 index 0000000..b7ea1cf --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/screens/search/SearchViewModel.kt @@ -0,0 +1,33 @@ +package com.mahmoudrh.roomxml.presentation.screens.search + +import androidx.compose.runtime.mutableStateOf +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.mahmoudrh.roomxml.domain.models.Note +import com.mahmoudrh.roomxml.domain.usecases.NoteUseCases +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import javax.inject.Inject + +@HiltViewModel +class SearchViewModel @Inject constructor( + private val noteUseCases: NoteUseCases + ) : ViewModel() { + val searchWord = mutableStateOf("") + var resultsList : List = emptyList() + val isLoading = mutableStateOf(false) + val isResultsListEmpty = mutableStateOf(false) + + private var searchJob:Job? = null + fun search(){ + isLoading.value = true + searchJob?.cancel() + searchJob = noteUseCases.searchNotes(searchWord.value.trim()).onEach { + resultsList = it + isLoading.value = false + isResultsListEmpty.value = it.isEmpty() + }.launchIn(viewModelScope) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/theme/Color.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/theme/Color.kt new file mode 100644 index 0000000..8bdaa8c --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/theme/Color.kt @@ -0,0 +1,11 @@ +package com.mahmoudrh.roomxml.presentation.theme + +import androidx.compose.ui.graphics.Color + +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFFEFB8C8) + +val Purple40 = Color(0xFF6650a4) +val PurpleGrey40 = Color(0xFF625b71) +val Pink40 = Color(0xFF7D5260) \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/theme/Theme.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/theme/Theme.kt new file mode 100644 index 0000000..2c51204 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/theme/Theme.kt @@ -0,0 +1,68 @@ +package com.mahmoudrh.roomxml.presentation.theme + +import android.app.Activity +import android.os.Build +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalView +import androidx.core.view.ViewCompat + +private val DarkColorScheme = darkColorScheme( + primary = Purple80, + secondary = PurpleGrey80, + tertiary = Pink80 +) + +private val LightColorScheme = lightColorScheme( + primary = Purple40, + secondary = PurpleGrey40, + tertiary = Pink40 + + /* Other default colors to override + background = Color(0xFFFFFBFE), + surface = Color(0xFFFFFBFE), + onPrimary = Color.White, + onSecondary = Color.White, + onTertiary = Color.White, + onBackground = Color(0xFF1C1B1F), + onSurface = Color(0xFF1C1B1F), + */ +) + +@Composable +fun DNoteTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + content: @Composable () -> Unit +) { + val colorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + darkTheme -> DarkColorScheme + else -> LightColorScheme + } + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + (view.context as Activity).window.statusBarColor = colorScheme.primary.toArgb() + ViewCompat.getWindowInsetsController(view)?.isAppearanceLightStatusBars = darkTheme + } + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/theme/Type.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/theme/Type.kt new file mode 100644 index 0000000..831fca0 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/theme/Type.kt @@ -0,0 +1,34 @@ +package com.mahmoudrh.roomxml.presentation.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +// Set of Material typography styles to start with +val Typography = Typography( + bodyLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ) + /* Other default text styles to override + titleLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ) + */ +) \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/AppTopBars.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/AppTopBars.kt new file mode 100644 index 0000000..e6d693e --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/AppTopBars.kt @@ -0,0 +1,96 @@ +package com.mahmoudrh.roomxml.presentation.ui_components + + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.unit.dp + + +object AppTopBars { + + @OptIn(ExperimentalMaterial3Api::class) + @Composable + fun DefaultTopBar( + title: String, + onNavigateBack: () -> Unit, + actionIcon: ImageVector, + onActionClick: () -> Unit + ) { + CenterAlignedTopAppBar( + modifier = Modifier.shadow(elevation = 8.dp), + title = { Text(text = title) }, + colors = TopAppBarDefaults.centerAlignedTopAppBarColors( + containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(15.dp), + ), + navigationIcon = { + IconButton(onClick = onNavigateBack) { + Icon(Icons.Default.ArrowBack, contentDescription = null) + } + }, + actions = { + IconButton(onClick = onActionClick) { + Icon(actionIcon, contentDescription = null) + } + } + ) + } + + @OptIn(ExperimentalMaterial3Api::class) + @Composable + fun DefaultTopBar( + title: String, + actionIcon: ImageVector, + onActionClick: () -> Unit + ) { + CenterAlignedTopAppBar( + modifier = Modifier.shadow(elevation = 8.dp), + title = { Text(text = title) }, + colors = TopAppBarDefaults.centerAlignedTopAppBarColors( + containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(15.dp), + ), + actions = { + IconButton(onClick = onActionClick) { + Icon(actionIcon, contentDescription = null) + } + } + ) + } + + @OptIn(ExperimentalMaterial3Api::class) + @Composable + fun SearchTopBar( + onNavigateBack: () -> Unit = {}, + searchWord: MutableState, + onSearch: () -> Unit = {}, + hint: String, + focusRequester: FocusRequester + ) { + SmallTopAppBar( + modifier = Modifier.shadow(elevation = 8.dp), + title = { + SearchTextField( + searchWord = searchWord, + hint = hint, + focusRequester = focusRequester + ) { + if (searchWord.value.isNotEmpty()) + onSearch() + } + }, + colors = TopAppBarDefaults.centerAlignedTopAppBarColors( + containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(15.dp), + ), + navigationIcon = { + IconButton(onClick = onNavigateBack) { + Icon(Icons.Default.ArrowBack, contentDescription = null) + } + }) + } + +} diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/EmptyListScreen.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/EmptyListScreen.kt new file mode 100644 index 0000000..1eb360e --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/EmptyListScreen.kt @@ -0,0 +1,44 @@ +package com.mahmoudrh.roomxml.presentation.ui_components + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.surfaceColorAtElevation +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.TextUnit +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +@Composable +fun EmptyListScreen(visibility: Boolean, text: String, fontSize: TextUnit = 20.sp) { + AnimatedVisibility( + visible = visibility, + enter = fadeIn(), + exit = fadeOut() + ) { + Box( + modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp)), + contentAlignment = Alignment.Center + ) { + Text( + modifier = Modifier.fillMaxWidth().padding(horizontal = 20.dp), + text = text, + fontSize = fontSize, + color = MaterialTheme.colorScheme.secondary, + fontWeight = FontWeight.Thin, + textAlign = TextAlign.Center + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/LoadingScreen.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/LoadingScreen.kt new file mode 100644 index 0000000..b962c74 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/LoadingScreen.kt @@ -0,0 +1,28 @@ +package com.mahmoudrh.roomxml.presentation.ui_components + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier + +@Composable +fun LoadingScreen(visibility: Boolean) { + AnimatedVisibility( + visible = visibility, + enter = fadeIn(), + exit = fadeOut() + ) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator(color = MaterialTheme.colorScheme.primary) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/NoteItem.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/NoteItem.kt new file mode 100644 index 0000000..85bf622 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/NoteItem.kt @@ -0,0 +1,197 @@ +package com.mahmoudrh.roomxml.presentation.ui_components + +import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.tween +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.gestures.Orientation +import androidx.compose.foundation.gestures.draggable +import androidx.compose.foundation.gestures.rememberDraggableState +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.mahmoudrh.roomxml.domain.models.Note +import com.mahmoudrh.roomxml.presentation.utils.DateFormatter +import kotlinx.coroutines.launch +import java.lang.ArithmeticException +import kotlin.math.absoluteValue + + +@Composable +fun NoteItem( + modifier: Modifier = Modifier, + note: Note, + onClick:()->Unit, + onSwipeOut:(Note)->Unit +) { + val scope = rememberCoroutineScope() + + var offsetX by mutableStateOf(0f) + var alpha by mutableStateOf(0f) + val vanishOffsetRight = remember { Animatable(250f) } + val vanishOffsetLeft = remember { Animatable(-250f) } + fun resetOffset() { + scope.launch { + val resetOffset = Animatable(offsetX) + resetOffset.animateTo(0f, tween(180)) { offsetX = value } + } + } + + fun swipeOut() { + scope.launch { + launch { + val vanishAlpha = Animatable(0.3f) + vanishAlpha.animateTo(1f, tween(80)) { alpha = value } + } + launch { + if (offsetX > 0) + vanishOffsetRight.animateTo(1030f, tween(80)) { offsetX = value } + else + vanishOffsetLeft.animateTo(-1050f, tween(80)) { offsetX = value } + } + }.invokeOnCompletion { + onSwipeOut(note) + } + } + Card( + modifier = modifier + .graphicsLayer { + alpha = try{ + (offsetX) / 1000 + }catch (e: ArithmeticException){ + 1f + } + this.alpha = (1f - alpha.absoluteValue).coerceIn(0f,1f) + this.translationX = offsetX + } + .clickable { onClick() } + .draggable( + rememberDraggableState(onDelta = { delta -> + offsetX += delta + }), + onDragStopped = { velocity -> + if (velocity.absoluteValue < 2000) { + resetOffset() + } else { + swipeOut() + } + }, + orientation = Orientation.Horizontal + ) + .wrapContentSize(), + elevation = CardDefaults.cardElevation(4.dp), + shape = RoundedCornerShape(4.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .height(IntrinsicSize.Min) + .background(MaterialTheme.colorScheme.surface) + ) { + Divider( + color = MaterialTheme.colorScheme.primary, modifier = Modifier + .fillMaxHeight() + .weight(0.2f) + ) + + Column( + modifier = Modifier + .padding(8.dp) + .weight(8f) + ) { + Text( + text = note.title, + color = MaterialTheme.colorScheme.onBackground, + fontWeight = FontWeight.Bold, + fontSize = 20.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = note.content, + color = MaterialTheme.colorScheme.onSurfaceVariant, + maxLines = 2, + overflow = TextOverflow.Ellipsis + ) + } + Text( + modifier = Modifier + .weight(2f) + .align(Alignment.Bottom) + .padding(bottom = 8.dp, end = 8.dp), + text = DateFormatter.formatDate(note.date), + textAlign = TextAlign.End, + color = Color.Gray + ) + } + } +} + +@Composable +fun NoteItem( + modifier: Modifier = Modifier, + note: Note, + onClick:()->Unit, +) { + Card( + modifier = modifier + .clickable { onClick() } + .wrapContentSize(), + elevation = CardDefaults.cardElevation(4.dp), + shape = RoundedCornerShape(4.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .height(IntrinsicSize.Min) + .background(MaterialTheme.colorScheme.surface) + ) { + Divider( + color = MaterialTheme.colorScheme.primary, modifier = Modifier + .fillMaxHeight() + .weight(0.2f) + ) + Column( + modifier = Modifier + .padding(8.dp) + .weight(8f) + ) { + Text( + text = note.title, + color = MaterialTheme.colorScheme.onBackground, + fontWeight = FontWeight.Bold, + fontSize = 20.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = note.content, + color = MaterialTheme.colorScheme.onSurfaceVariant, + maxLines = 2, + overflow = TextOverflow.Ellipsis + ) + } + Text( + modifier = Modifier + .weight(2f) + .align(Alignment.Bottom) + .padding(bottom = 8.dp, end = 8.dp), + text = DateFormatter.formatDate(note.date), + textAlign = TextAlign.End, + color = Color.Gray + ) + } + } +} diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/OrderSection.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/OrderSection.kt new file mode 100644 index 0000000..7dc9e69 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/OrderSection.kt @@ -0,0 +1,95 @@ +package com.mahmoudrh.roomxml.presentation.ui_components + + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.mahmoudrh.roomxml.domain.utils.OrderBy +import com.mahmoudrh.roomxml.domain.utils.OrderType + + +@Preview +@Composable +fun OrderSection( + order: OrderBy = OrderBy.Date(OrderType.Descending), + onOrderChange: (OrderBy) -> Unit = {} +) { + Card( + modifier = Modifier.padding(vertical = 8.dp), + elevation = CardDefaults.cardElevation(4.dp), + shape = RoundedCornerShape(4.dp), + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .height(IntrinsicSize.Min) + .background(MaterialTheme.colorScheme.surface) + ) { + Divider( + color = MaterialTheme.colorScheme.primary, modifier = Modifier + .fillMaxHeight() + .weight(0.2f) + ) + Column( + modifier = Modifier.weight(10f).padding(horizontal = 8.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text(text = "Sort By: ") + DefaultRadioButton( + text = "Title", + selected = order is OrderBy.Title, + onSelect = { onOrderChange(OrderBy.Title(order.orderType)) } + ) + DefaultRadioButton( + text = "Date", + selected = order is OrderBy.Date, + onSelect = { onOrderChange(OrderBy.Date(order.orderType)) } + ) + } + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text(text = "Sort Type: ") + DefaultRadioButton( + text = "Asc", + selected = order.orderType is OrderType.Ascending, + onSelect = { + onOrderChange(order.copy(OrderType.Ascending)) + } + ) + DefaultRadioButton( + text = "Desc", + selected = order.orderType is OrderType.Descending, + onSelect = { + onOrderChange(order.copy(OrderType.Descending)) + } + ) + } + } + } + } + +} + +@Composable +fun DefaultRadioButton(text: String, selected: Boolean, onSelect: () -> Unit) { + + Row(verticalAlignment = Alignment.CenterVertically) { + Text(text = text) + Spacer(modifier = Modifier.width(4.dp)) + RadioButton(selected = selected, onClick = onSelect) + } + +} diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/SearchTextField.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/SearchTextField.kt new file mode 100644 index 0000000..73823d1 --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/ui_components/SearchTextField.kt @@ -0,0 +1,94 @@ +package com.mahmoudrh.roomxml.presentation.ui_components + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.expandHorizontally +import androidx.compose.animation.shrinkHorizontally +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Cancel +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.focus.onFocusChanged +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.unit.sp + +@OptIn(ExperimentalComposeUiApi::class) +@Composable +fun SearchTextField( + searchWord: MutableState, + hint: String, + focusRequester: FocusRequester, + onSearch: () -> Unit = {}, +) { + val keyboardController = LocalSoftwareKeyboardController.current + BasicTextField( + modifier = Modifier + .fillMaxWidth() + .focusRequester(focusRequester) + .onFocusChanged { + if (it.isFocused) + keyboardController?.show() + }, + value = searchWord.value, + onValueChange = { searchWord.value = it }, + singleLine = true, + decorationBox = { innerTextField -> + AnimatedVisibility( + searchWord.value.isEmpty(), + enter = expandHorizontally(), + exit = shrinkHorizontally() + ) { + Text(text = hint, color = Color.Gray, fontSize = 18.sp) + } + if (searchWord.value.isNotEmpty()) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.CenterStart + ) { + IconButton( + modifier = Modifier.align(Alignment.CenterEnd), + onClick = { + searchWord.value = " " + // I Had to put the space and trim it in the view model to avoid crash caused by + // BasicTextField (https://issuetracker.google.com/issues/229378536) + }) { + Icon( + imageVector = Icons.Default.Cancel, + contentDescription = "Clear" + ) + } + innerTextField() + } + } else + innerTextField() + }, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search), + keyboardActions = KeyboardActions(onSearch = { + keyboardController?.hide() + onSearch() + }), + textStyle = TextStyle( + color = MaterialTheme.colorScheme.onBackground, + fontSize = 18.sp + ), + cursorBrush = SolidColor(MaterialTheme.colorScheme.onBackground), + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/mahmoudrh/roomxml/presentation/utils/DateFormatter.kt b/app/src/main/java/com/mahmoudrh/roomxml/presentation/utils/DateFormatter.kt new file mode 100644 index 0000000..871d0fd --- /dev/null +++ b/app/src/main/java/com/mahmoudrh/roomxml/presentation/utils/DateFormatter.kt @@ -0,0 +1,12 @@ +package com.mahmoudrh.roomxml.presentation.utils + +import java.text.SimpleDateFormat +import java.util.* + +object DateFormatter { + fun formatDate(noteDate: String): String { + val timeStamp = noteDate.toLong() + val date = Date(timeStamp) + return SimpleDateFormat("MMM dd", Locale.getDefault()).format(date) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_add.xml b/app/src/main/res/drawable/ic_add.xml new file mode 100644 index 0000000..eb23254 --- /dev/null +++ b/app/src/main/res/drawable/ic_add.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_check.xml b/app/src/main/res/drawable/ic_check.xml new file mode 100644 index 0000000..0432fa6 --- /dev/null +++ b/app/src/main/res/drawable/ic_check.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_delete.xml b/app/src/main/res/drawable/ic_delete.xml new file mode 100644 index 0000000..3c4030b --- /dev/null +++ b/app/src/main/res/drawable/ic_delete.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_dialog_icon.xml b/app/src/main/res/drawable/ic_dialog_icon.xml new file mode 100644 index 0000000..4c78355 --- /dev/null +++ b/app/src/main/res/drawable/ic_dialog_icon.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_edit.xml b/app/src/main/res/drawable/ic_edit.xml new file mode 100644 index 0000000..2844baf --- /dev/null +++ b/app/src/main/res/drawable/ic_edit.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_save.xml b/app/src/main/res/drawable/ic_save.xml new file mode 100644 index 0000000..1a8d86d --- /dev/null +++ b/app/src/main/res/drawable/ic_save.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_search.xml b/app/src/main/res/drawable/ic_search.xml new file mode 100644 index 0000000..07b76d6 --- /dev/null +++ b/app/src/main/res/drawable/ic_search.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..3048de609959d59556aaccfe9cde5194ed33a09e GIT binary patch literal 2850 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 ANdN!< literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..76c1b11af9c1d9036ac1eebdb88672fb6327b28b GIT binary patch literal 4414 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..32b40276be5e5bef467416912da530c0804ce2c5 GIT binary patch literal 1847 zcmV-72gvw|P)Sh1Ry#gb=m@Wl7lzge;J-WPz}Rkih(&|0FlLA*2N5HaOFN=9|FHJ@}q0=vX~c-Egl4(oYsYJ5ICgIIsvU$!Ma>>G>XCSDfuwEN1>XkPONaBk$V z5w{JExgm$IeX%%Bommp6nktD?8vF~@R8gEV6FIRtZfMMxMLb1zahwW@W0gAwInjN2 zgxb?y1u(&q6Z7zuqFBWY4id&HR)n$2HS)h-fO8`UT+FSh@6_?ZxV z=gp#1W3wm#AF_TW9ycflBH*`}!MT_tSKeWBbu;E-{MR*a31i2M&cPcz^l^eMAnb5@ zAe*b3u?6hZ9SHeM@GhIHoBbC7rDs%d?ZPi-nE>O=64LmEL4-Uv4f`oS>0=p2s=pdMI+ zk~0bq^4l(;UZ4S!euYlFOjb`+p#;IPX2_0hhMLS?D8JYPnGs!(7d-$4Cx@Z%lpKm2 zC_FU^S56E;PSgX)Kiv((U3!-YfJZ;c9e** zQrDPPn4v6Qfd$Zmh#M)M97@g(gKA*jDFDY;B@Pgw?jp8LK)paq0+WzbEkV(_Zt5yY z!D5iss+=U$LvxT3*+F)o--EO#6i}BsPIriT&bxsvy%V@C<@4q?DZh)4b4||&hZ%BX;D%VCo;et+ExJwTvdE{RzwdakLl06 zV0Qt``@#$DWM>-4WCI>Vz2O!qevANr=)(Hm)6TC{L-{p2EK z@tSDr#0<24oHx{^YMcUengtL+kgj z_72D&=pZ>v3~AvV&Oqi=z+jWfIeEuj66lk^B{olG`gMxEyTMpprU&dkHV5QF( z=$L}U5D{rPB#=)kHggYW0~&7DQAr=BVrvj~(Ph0IuF(iz|TJ|5Dk5&&L49jus0b zlJ61CKx&wj3c%oH(kBB>1eE=tf+;zx0vEC?@S_FPUDAMd#7yHyCe}k%bO$9b2x}wt zgTro=jS9ZnS%DFy37w=fZGgN-1Ta=@N$CvjrRY5IFwMvk+{jQ7cj=&63*%<}IL-xN z3&D^_OpMNwK$L?>sHJD*#)=uZf6GYE%6R_8c4Jy;hK909$mjLb6~}>Ne8(MizW*_u;Whj z--|ogBCjfGFS%L0UvJTsqc3>p*g-h#oUB zBVll2RZR_TCGB@Nt*-0>(3_!OViI?aS%R8#oof012W$ z+p+nfek=G_0{+)O?()B_etWAsz$MrMf<8^#&*ti8%u9pt&-3;c@)UX;v{PPil*FmY zS-j8i<)PRB>?r`v@%rY4q>#ocY^rb|3c*i*fSDVA;X8k{zJ_qy?e!HCn&Zn| zZ|r+N@chxbKQfQ^7;~fgOgT}qIsAN_VCKw<=r!`csl6Vs_dRro-w>JF!0FpFZmgJkc-dc*@nTA l6V&;fKjAfCpV$tue*jJ_TK^sQffE1#002ovPDHLkV1hfBW+DIp literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..292f9f014d0f65e9e694e33d5deed92ecd49ff17 GIT binary patch literal 2582 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 VH?oXL|MT}4ObpEps`OlA{|CJK{u}@R literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..05771007db02b830670364e821c622100504d613 GIT binary patch literal 3206 zcmV;140-d3P)f%WE1D8 zFAR>kje+GbCQf|BcH$!oHW-%6V8G@w>@GJLFgMFNo$r6|?Y@1x9F9qTX~g5b`DebF ze`fyqfAH|Q#X%l)Tec^CKYnfL?f9wvt{rM#%+-GX&W2u3-^4#Y2lXp z4Vx_wg7A!YT0RWOfGq9%Z*8~(o~mp8eVVTMKk2&WID^iTYY4M67(y*wX*%l-5T3<5 z{stcKVvbtIcVY;ZUU`N`Gj!HB(!#8#({`Z0NvhD9^V%)QM@(wLH!WO$u-h3kGAIlzzH; zc`kA{mklvNhdbThXs8A7k_WKDDMdNQwRm0(f-Hw2)+vL|9N-SaO%3(LG@T{J5iZur zG))LB63xi6#qY_XjdAXIz>~H(=6j~ z%|mp(ZJ37oZ8SMC<-`ZVyNz(ry!SD90yGW5td)DPsgx3X% z^u0ibc3+~VD?RK0$EqOQT55(VW3$=C2n9pphAYJkO<;7pV=K#(8ftz=2_2p|gXJwf z)h9d-Wn=6y)5%tf3ofQezYCPIt%yF2s-Q$&3B~wdqJ$0AbYNp05)huFR3;(qIiA#QnAA#2IV?$ zOzEQ0p-G_t;qqlt14VdWpo6>0$Wqfw{XL@$WSlC#?jeJ&37e4{FREkPEEyD5Ll=*> zIpv3Kbb?OAHPC_JI_EjS!cI*Hx>E1AD*Y#F%wi}O?GLJZL*;!jxw(2+0^dGL*}JMa zL~>~Rny=~L&T=R3RbA+z{Tr{a@_HB0?noFK-bm)kK_@x2rCk*5UrMQ=jm~p;6|kZa z-UX}Gn4L;fN^s+8X@X-z8R!|O{%#v(eSDQ;J4eKMlusd@jBT700Q9FTuY{7*X>HjMkXjL;*$8zaXN1psVReV4CPdjH9TnJ)h(laekD$; z08HG9Q&Ldv(3ZCjKLX4GyHb`C1FKfc?SfOAaAZd-m$Pf4lE8?hpc+DwHIz7(e(1&+ zMF;1J@QMq#>;iH=s>m`8-i!FR3HZ5gvGZENbM9q$-vH z_7)%GwxpoCJcUWC03J^XX|Tukv4}R28;a8M3#}rtQTI_oUFXkDd0E|dS*U2)k(X#E z=Mze@noq&D&#$b2F*{1B-ZT3y2H2oxnv1ag+eW3*3i`@$l?^b`Uf&{7BDMVUk$MFN z`bH^9UpTt~9OfLRjjuf&cCX!l58nLZmxj>BPCJtuC2A@;+3VQYc*!$&mWt{WvmOb;TYkSC#s#AS22JMyW#t<_!V{oHotcGp_?(F zzuOW2jn&sF(mz-B7%G%2|6FuzS1Wh0(mpWMKSs&#n}h-G!clF2&+`$Yl!_7RY4}Y_ z@U<>GlN&_}9eS^sH!cZ0sLa?bypOV%yue*pAvB34CwlGeM47RLc6%FzJd|VYhNu{j z5Lnf{_8;4p+YNZ`>2>!eh14%7iE+A8z=OU_y&`$c$He9K<`Ou2TZ?@)(Pqbo6{y0; zwVEjgLKDQ;tX&z z37ipbrJ`d!T#Bb?!Zt;PUvR79n=eW+T9w)M5@5qdw*9~7(i!vZ0=wKw-1hP6v%WGT zS_!we4xfI|LY+;HzNMw1PsA(|SZXm`=V%E|C_Ey8N9-4$NsN3ngV%C=%r3sF9 zT1}@pfz=0)!mrFC{-ZH^C}i@uwWo3ZOF zW(6;igo#`B^NjUw044>yk_TH?ed;GKpW86PxmaC+>dU(+!Z$~>zS^V%=r1DMsOWev zwKH&>dk1?bsQg?nrEjgLPq@wlJj(A}o(FL`oni0K;8+^?aw5WKiPN!CIi4+l;7`A1 zVfE4^*Q>+)Y{wY@G%-F&mfBvroZCg0jeR0KuH+4nrD|B*5g|;_GvPj{lD{9`-bC>m zxK;MPD7wwPz9zBx%>~|$h07V{?atyreUY#*{kKiu^Cp>PO9!lY?d;Z$_H{d_zh zjgL)oi!emF2iqv?gL)2;OI%?tidcu&5i;F$G%tYCC2tE0QB_Cc7M$%TXx6mf7P$#MrvFf@ZE$`hQ6Ls-z(!ytcVWi zO_Z=17g>3<$1j)LV5t?5Dod^imwkSv*#2eUbBBwXQbWvBqVfb*jlc3tuqUw1da!0`*bBL6SejcEu7+EVebdO-j7(F~kHS&+-+E~*s{-2ezBxK2TwqJsqBSvI2ukqmws z4&1aVD+^eFi57CXiy`L&mg>Rx-#&R`H&7{hOYW!AW#ZOA+H z9ZbtNzxjD4JPg6&&q7?6wTf?*B$?Jp=)j8VB+vg27{reIO@=%XMl1_>IbnNzV6_d( z5Sxo-hzhun6&p}#^LsI72XsRBHwLc^gwrD)kNkiiA9(&r?^k!OF_wz!L#|MEL*$EK zEx0*IE(|homIayI(3Sr439nVq1)Vn?HnR=l4D% zGXZ08XAdCDm>#}+=}-T%V%d|=Jig*@e+S_i@9<6L0Wao=QP*#H0l literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..ee5a82e523504054741ec5c8d0d91c63f887ac1b GIT binary patch literal 4146 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..a9c2a1a233a0e1b1148d72d6afeaf79ef1d1f7bd GIT binary patch literal 6809 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..69ee03e81311358ba2f9fa0f3e7a0799a22441e1 GIT binary patch literal 11556 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%0DKJh!LmlIKw)tn9byZ5~?J>Fv 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

q>*=%4#`pn4--yl?9T1q#aT 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 miU6}3sFk9;t`qPUYX1+H#u^@E)*RUY0000 + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + + #FFA479E2 + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..7b575a2 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,14 @@ + + D Note + + + Search Notes + Sorry.. Tha application crashed. Please send a report to the developers. + D Note Crashed + Send + Don\'t Send + You can add a comment here: + + + + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..f0fa75b --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,4 @@ + + +