diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 00000000..ef8486eb
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+CleanArchitectureNoteApp
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index fb7f4a8a..b589d56e 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 28422375..a269cb1a 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -2,12 +2,14 @@
+
+
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
new file mode 100644
index 00000000..5815a4a6
--- /dev/null
+++ b/.idea/kotlinc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/migrations.xml b/.idea/migrations.xml
new file mode 100644
index 00000000..f8051a6f
--- /dev/null
+++ b/.idea/migrations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index d5d35ec4..55c0ec2c 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index c121e9f1..aa561e4b 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -60,14 +60,14 @@ dependencies {
debugImplementation(libs.androidx.ui.test.manifest)
// Compose dependencies
- implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.4.0-beta01")
+ implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.7")
implementation("androidx.navigation:navigation-compose:2.8.3")
implementation("androidx.compose.material:material-icons-extended:1.7.5")
- implementation("androidx.hilt:hilt-navigation-compose:1.0.0-alpha03")
+ implementation("androidx.hilt:hilt-navigation-compose:1.2.0")
// Coroutines
- implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0")
- implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.1")
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
//Dagger - Hilt
implementation("com.google.dagger:hilt-android:2.49")
@@ -77,9 +77,11 @@ dependencies {
// Room
implementation("androidx.room:room-runtime:2.6.1")
kapt("androidx.room:room-compiler:2.6.1")
-
- // Kotlin Extensions and Coroutines support for Room
implementation("androidx.room:room-ktx:2.6.1")
+
+ // Splash Screen
+ implementation("androidx.core:core-splashscreen:1.0.0")
+
}
kapt {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 88340904..5c79f1fb 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,13 +5,13 @@
diff --git a/app/src/main/icon_launcher-playstore.png b/app/src/main/icon_launcher-playstore.png
new file mode 100644
index 00000000..94d62423
Binary files /dev/null and b/app/src/main/icon_launcher-playstore.png differ
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/MainActivity.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/MainActivity.kt
new file mode 100644
index 00000000..6656dbf2
--- /dev/null
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/MainActivity.kt
@@ -0,0 +1,34 @@
+package com.plcoding.cleanarchitecturenoteapp
+
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.compose.animation.ExperimentalAnimationApi
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Scaffold
+import androidx.compose.ui.Modifier
+import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
+import com.plcoding.cleanarchitecturenoteapp.ui.navigation.NoteNavigation
+import com.plcoding.cleanarchitecturenoteapp.ui.theme.CleanArchitectureNoteAppTheme
+import dagger.hilt.android.AndroidEntryPoint
+
+@AndroidEntryPoint
+class MainActivity : ComponentActivity() {
+ @ExperimentalAnimationApi
+ override fun onCreate(savedInstanceState: Bundle?) {
+ installSplashScreen()
+ super.onCreate(savedInstanceState)
+ setContent {
+ CleanArchitectureNoteAppTheme {
+ Scaffold (
+ modifier = Modifier.fillMaxSize()
+ ) { paddingValues ->
+ NoteNavigation(
+ modifier = Modifier.fillMaxSize().padding(paddingValues)
+ )
+ }
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/data/database/NoteDao.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/data/database/NoteDao.kt
new file mode 100644
index 00000000..db4f329e
--- /dev/null
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/data/database/NoteDao.kt
@@ -0,0 +1,21 @@
+package com.plcoding.cleanarchitecturenoteapp.data.database
+
+import androidx.room.*
+import com.plcoding.cleanarchitecturenoteapp.data.model.Note
+import kotlinx.coroutines.flow.Flow
+
+@Dao
+interface NoteDao {
+
+ @Query("SELECT * FROM note")
+ fun getAllNoteDatabase(): Flow>
+
+ @Query("SELECT * FROM note WHERE id = :id")
+ suspend fun getSingleNoteDatabase(id: Int): Note?
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ suspend fun insertNoteDatabase(note: Note)
+
+ @Delete
+ suspend fun deleteNoteDatabase(note: Note)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/data/data_source/NoteDatabase.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/data/database/NoteDatabase.kt
similarity index 61%
rename from app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/data/data_source/NoteDatabase.kt
rename to app/src/main/java/com/plcoding/cleanarchitecturenoteapp/data/database/NoteDatabase.kt
index 4dd871af..e90f45f7 100644
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/data/data_source/NoteDatabase.kt
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/data/database/NoteDatabase.kt
@@ -1,12 +1,13 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.data.data_source
+package com.plcoding.cleanarchitecturenoteapp.data.database
import androidx.room.Database
import androidx.room.RoomDatabase
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.model.Note
+import com.plcoding.cleanarchitecturenoteapp.data.model.Note
@Database(
entities = [Note::class],
- version = 1
+ version = 1,
+ exportSchema = false
)
abstract class NoteDatabase: RoomDatabase() {
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/model/Note.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/data/model/Note.kt
similarity index 86%
rename from app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/model/Note.kt
rename to app/src/main/java/com/plcoding/cleanarchitecturenoteapp/data/model/Note.kt
index b7473f7e..e29b6853 100644
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/model/Note.kt
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/data/model/Note.kt
@@ -1,4 +1,4 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.domain.model
+package com.plcoding.cleanarchitecturenoteapp.data.model
import androidx.room.Entity
import androidx.room.PrimaryKey
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/data/repository/NoteRepositoryImpl.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/data/repository/NoteRepositoryImpl.kt
new file mode 100644
index 00000000..e29bb226
--- /dev/null
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/data/repository/NoteRepositoryImpl.kt
@@ -0,0 +1,27 @@
+package com.plcoding.cleanarchitecturenoteapp.data.repository
+
+import com.plcoding.cleanarchitecturenoteapp.data.database.NoteDao
+import com.plcoding.cleanarchitecturenoteapp.data.model.Note
+import com.plcoding.cleanarchitecturenoteapp.domain.repository.NoteRepository
+import kotlinx.coroutines.flow.Flow
+
+class NoteRepositoryImpl(
+ private val noteDao: NoteDao
+) : NoteRepository {
+
+ override fun getAllNoteRepository(): Flow> {
+ return noteDao.getAllNoteDatabase()
+ }
+
+ override suspend fun getSingleNoteRepository(id: Int): Note? {
+ return noteDao.getSingleNoteDatabase(id)
+ }
+
+ override suspend fun insertNoteRepository(note: Note) {
+ noteDao.insertNoteDatabase(note)
+ }
+
+ override suspend fun deleteNoteRepository(note: Note) {
+ noteDao.deleteNoteDatabase(note)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/di/AppModule.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/di/AppModule.kt
deleted file mode 100644
index 92660b5f..00000000
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/di/AppModule.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.plcoding.cleanarchitecturenoteapp.di
-
-import android.app.Application
-import androidx.room.Room
-import com.plcoding.cleanarchitecturenoteapp.feature_note.data.data_source.NoteDatabase
-import com.plcoding.cleanarchitecturenoteapp.feature_note.data.repository.NoteRepositoryImpl
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.repository.NoteRepository
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.use_case.*
-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 provideNoteDatabase(app: Application): NoteDatabase {
- return Room.databaseBuilder(
- app,
- NoteDatabase::class.java,
- NoteDatabase.DATABASE_NAME
- ).build()
- }
-
- @Provides
- @Singleton
- fun provideNoteRepository(db: NoteDatabase): NoteRepository {
- return NoteRepositoryImpl(db.noteDao)
- }
-
- @Provides
- @Singleton
- fun provideNoteUseCases(repository: NoteRepository): NoteUseCases {
- return NoteUseCases(
- getNotes = GetNotes(repository),
- deleteNote = DeleteNote(repository),
- addNote = AddNote(repository),
- getNote = GetNote(repository)
- )
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/di/DatabaseModule.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/di/DatabaseModule.kt
new file mode 100644
index 00000000..a52384a6
--- /dev/null
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/di/DatabaseModule.kt
@@ -0,0 +1,27 @@
+package com.plcoding.cleanarchitecturenoteapp.di
+
+import android.app.Application
+import android.content.Context
+import androidx.room.Room
+import com.plcoding.cleanarchitecturenoteapp.data.database.NoteDatabase
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+object DatabaseModule {
+
+ @Provides
+ @Singleton
+ fun provideNoteDatabase(@ApplicationContext context: Context): NoteDatabase {
+ return Room.databaseBuilder(
+ context,
+ NoteDatabase::class.java,
+ NoteDatabase.DATABASE_NAME
+ ).build()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/di/RepositoryModule.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/di/RepositoryModule.kt
new file mode 100644
index 00000000..ef835ddc
--- /dev/null
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/di/RepositoryModule.kt
@@ -0,0 +1,21 @@
+package com.plcoding.cleanarchitecturenoteapp.di
+
+import com.plcoding.cleanarchitecturenoteapp.data.database.NoteDatabase
+import com.plcoding.cleanarchitecturenoteapp.data.repository.NoteRepositoryImpl
+import com.plcoding.cleanarchitecturenoteapp.domain.repository.NoteRepository
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+object RepositoryModule {
+
+ @Provides
+ @Singleton
+ fun provideNoteRepository(noteDatabase: NoteDatabase): NoteRepository {
+ return NoteRepositoryImpl(noteDatabase.noteDao)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/di/UseCaseModule.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/di/UseCaseModule.kt
new file mode 100644
index 00000000..fbaa6798
--- /dev/null
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/di/UseCaseModule.kt
@@ -0,0 +1,29 @@
+package com.plcoding.cleanarchitecturenoteapp.di
+
+import com.plcoding.cleanarchitecturenoteapp.domain.repository.NoteRepository
+import com.plcoding.cleanarchitecturenoteapp.domain.usecase.AddNote
+import com.plcoding.cleanarchitecturenoteapp.domain.usecase.DeleteNote
+import com.plcoding.cleanarchitecturenoteapp.domain.usecase.GetNote
+import com.plcoding.cleanarchitecturenoteapp.domain.usecase.GetNotes
+import com.plcoding.cleanarchitecturenoteapp.domain.usecase.NoteUseCase
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+object UseCaseModule {
+
+ @Provides
+ @Singleton
+ fun provideNoteUseCases(repository: NoteRepository): NoteUseCase {
+ return NoteUseCase(
+ getNotes = GetNotes(repository),
+ deleteNote = DeleteNote(repository),
+ addNote = AddNote(repository),
+ getNote = GetNote(repository)
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/repository/NoteRepository.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/repository/NoteRepository.kt
new file mode 100644
index 00000000..0efb28de
--- /dev/null
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/repository/NoteRepository.kt
@@ -0,0 +1,15 @@
+package com.plcoding.cleanarchitecturenoteapp.domain.repository
+
+import com.plcoding.cleanarchitecturenoteapp.data.model.Note
+import kotlinx.coroutines.flow.Flow
+
+interface NoteRepository {
+
+ fun getAllNoteRepository(): Flow>
+
+ suspend fun getSingleNoteRepository(id: Int): Note?
+
+ suspend fun insertNoteRepository(note: Note)
+
+ suspend fun deleteNoteRepository(note: Note)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/use_case/AddNote.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/usecase/AddNote.kt
similarity index 50%
rename from app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/use_case/AddNote.kt
rename to app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/usecase/AddNote.kt
index 5e243dff..912ef7d3 100644
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/use_case/AddNote.kt
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/usecase/AddNote.kt
@@ -1,10 +1,11 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.domain.use_case
+package com.plcoding.cleanarchitecturenoteapp.domain.usecase
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.model.InvalidNoteException
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.model.Note
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.repository.NoteRepository
+import com.plcoding.cleanarchitecturenoteapp.data.model.InvalidNoteException
+import com.plcoding.cleanarchitecturenoteapp.data.model.Note
+import com.plcoding.cleanarchitecturenoteapp.domain.repository.NoteRepository
+import javax.inject.Inject
-class AddNote(
+class AddNote @Inject constructor(
private val repository: NoteRepository
) {
@@ -16,6 +17,6 @@ class AddNote(
if(note.content.isBlank()) {
throw InvalidNoteException("The content of the note can't be empty.")
}
- repository.insertNote(note)
+ repository.insertNoteRepository(note)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/usecase/DeleteNote.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/usecase/DeleteNote.kt
new file mode 100644
index 00000000..51e7ab23
--- /dev/null
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/usecase/DeleteNote.kt
@@ -0,0 +1,14 @@
+package com.plcoding.cleanarchitecturenoteapp.domain.usecase
+
+import com.plcoding.cleanarchitecturenoteapp.data.model.Note
+import com.plcoding.cleanarchitecturenoteapp.domain.repository.NoteRepository
+import javax.inject.Inject
+
+class DeleteNote @Inject constructor(
+ private val repository: NoteRepository
+) {
+
+ suspend operator fun invoke(note: Note) {
+ repository.deleteNoteRepository(note)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/usecase/GetNote.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/usecase/GetNote.kt
new file mode 100644
index 00000000..c6781d29
--- /dev/null
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/usecase/GetNote.kt
@@ -0,0 +1,14 @@
+package com.plcoding.cleanarchitecturenoteapp.domain.usecase
+
+import com.plcoding.cleanarchitecturenoteapp.data.model.Note
+import com.plcoding.cleanarchitecturenoteapp.domain.repository.NoteRepository
+import javax.inject.Inject
+
+class GetNote @Inject constructor(
+ private val repository: NoteRepository
+) {
+
+ suspend operator fun invoke(id: Int): Note? {
+ return repository.getSingleNoteRepository(id)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/use_case/GetNotes.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/usecase/GetNotes.kt
similarity index 69%
rename from app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/use_case/GetNotes.kt
rename to app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/usecase/GetNotes.kt
index ac94e18f..cd878f20 100644
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/use_case/GetNotes.kt
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/usecase/GetNotes.kt
@@ -1,20 +1,21 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.domain.use_case
+package com.plcoding.cleanarchitecturenoteapp.domain.usecase
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.model.Note
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.repository.NoteRepository
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.util.NoteOrder
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.util.OrderType
+import com.plcoding.cleanarchitecturenoteapp.data.model.Note
+import com.plcoding.cleanarchitecturenoteapp.domain.repository.NoteRepository
+import com.plcoding.cleanarchitecturenoteapp.domain.util.NoteOrder
+import com.plcoding.cleanarchitecturenoteapp.domain.util.OrderType
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
+import javax.inject.Inject
-class GetNotes(
+class GetNotes @Inject constructor(
private val repository: NoteRepository
) {
operator fun invoke(
noteOrder: NoteOrder = NoteOrder.Date(OrderType.Descending)
): Flow> {
- return repository.getNotes().map { notes ->
+ return repository.getAllNoteRepository().map { notes ->
when(noteOrder.orderType) {
is OrderType.Ascending -> {
when(noteOrder) {
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/use_case/NoteUseCases.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/usecase/NoteUseCase.kt
similarity index 53%
rename from app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/use_case/NoteUseCases.kt
rename to app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/usecase/NoteUseCase.kt
index a89b00c1..9addeb7d 100644
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/use_case/NoteUseCases.kt
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/usecase/NoteUseCase.kt
@@ -1,6 +1,6 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.domain.use_case
+package com.plcoding.cleanarchitecturenoteapp.domain.usecase
-data class NoteUseCases(
+data class NoteUseCase(
val getNotes: GetNotes,
val deleteNote: DeleteNote,
val addNote: AddNote,
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/util/NoteOrder.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/util/NoteOrder.kt
similarity index 86%
rename from app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/util/NoteOrder.kt
rename to app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/util/NoteOrder.kt
index eb7fa913..aad4dd2b 100644
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/util/NoteOrder.kt
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/util/NoteOrder.kt
@@ -1,4 +1,4 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.domain.util
+package com.plcoding.cleanarchitecturenoteapp.domain.util
sealed class NoteOrder(val orderType: OrderType) {
class Title(orderType: OrderType): NoteOrder(orderType)
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/util/OrderType.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/util/OrderType.kt
new file mode 100644
index 00000000..dbc32331
--- /dev/null
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/domain/util/OrderType.kt
@@ -0,0 +1,6 @@
+package com.plcoding.cleanarchitecturenoteapp.domain.util
+
+sealed class OrderType {
+ data object Ascending: OrderType()
+ data object Descending: OrderType()
+}
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/data/data_source/NoteDao.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/data/data_source/NoteDao.kt
deleted file mode 100644
index fdcb3405..00000000
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/data/data_source/NoteDao.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.data.data_source
-
-import androidx.room.*
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.model.Note
-import kotlinx.coroutines.flow.Flow
-
-@Dao
-interface NoteDao {
-
- @Query("SELECT * FROM note")
- fun getNotes(): Flow>
-
- @Query("SELECT * FROM note WHERE id = :id")
- suspend fun getNoteById(id: Int): Note?
-
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- suspend fun insertNote(note: Note)
-
- @Delete
- suspend fun deleteNote(note: Note)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/data/repository/NoteRepositoryImpl.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/data/repository/NoteRepositoryImpl.kt
deleted file mode 100644
index 39d93125..00000000
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/data/repository/NoteRepositoryImpl.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.data.repository
-
-import com.plcoding.cleanarchitecturenoteapp.feature_note.data.data_source.NoteDao
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.model.Note
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.repository.NoteRepository
-import kotlinx.coroutines.flow.Flow
-
-class NoteRepositoryImpl(
- private val dao: NoteDao
-) : NoteRepository {
-
- override fun getNotes(): Flow> {
- return dao.getNotes()
- }
-
- override suspend fun getNoteById(id: Int): Note? {
- return dao.getNoteById(id)
- }
-
- override suspend fun insertNote(note: Note) {
- dao.insertNote(note)
- }
-
- override suspend fun deleteNote(note: Note) {
- dao.deleteNote(note)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/repository/NoteRepository.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/repository/NoteRepository.kt
deleted file mode 100644
index 471b748a..00000000
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/repository/NoteRepository.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.domain.repository
-
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.model.Note
-import kotlinx.coroutines.flow.Flow
-
-interface NoteRepository {
-
- fun getNotes(): Flow>
-
- suspend fun getNoteById(id: Int): Note?
-
- suspend fun insertNote(note: Note)
-
- suspend fun deleteNote(note: Note)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/use_case/DeleteNote.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/use_case/DeleteNote.kt
deleted file mode 100644
index e57acdfe..00000000
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/use_case/DeleteNote.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.domain.use_case
-
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.model.Note
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.repository.NoteRepository
-
-class DeleteNote(
- private val repository: NoteRepository
-) {
-
- suspend operator fun invoke(note: Note) {
- repository.deleteNote(note)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/use_case/GetNote.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/use_case/GetNote.kt
deleted file mode 100644
index 84e8978c..00000000
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/use_case/GetNote.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.domain.use_case
-
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.model.Note
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.repository.NoteRepository
-
-class GetNote(
- private val repository: NoteRepository
-) {
-
- suspend operator fun invoke(id: Int): Note? {
- return repository.getNoteById(id)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/util/OrderType.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/util/OrderType.kt
deleted file mode 100644
index de897a19..00000000
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/domain/util/OrderType.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.domain.util
-
-sealed class OrderType {
- object Ascending: OrderType()
- object Descending: OrderType()
-}
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/MainActivity.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/MainActivity.kt
deleted file mode 100644
index dd194689..00000000
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/MainActivity.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.presentation
-
-import android.os.Bundle
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.compose.animation.ExperimentalAnimationApi
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Surface
-import androidx.navigation.NavType
-import androidx.navigation.compose.NavHost
-import androidx.navigation.compose.composable
-import androidx.navigation.compose.rememberNavController
-import androidx.navigation.navArgument
-import com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.add_edit_note.AddEditNoteScreen
-import com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.notes.NotesScreen
-import com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.util.Screen
-import com.plcoding.cleanarchitecturenoteapp.ui.theme.CleanArchitectureNoteAppTheme
-import dagger.hilt.android.AndroidEntryPoint
-
-@AndroidEntryPoint
-class MainActivity : ComponentActivity() {
- @ExperimentalAnimationApi
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContent {
- CleanArchitectureNoteAppTheme {
- Surface(
- color = MaterialTheme.colorScheme.background
- ) {
- val navController = rememberNavController()
- NavHost(
- navController = navController,
- startDestination = Screen.NotesScreen.route
- ) {
- composable(route = Screen.NotesScreen.route) {
- NotesScreen(navController = navController)
- }
- composable(
- route = Screen.AddEditNoteScreen.route +
- "?noteId={noteId}¬eColor={noteColor}",
- arguments = listOf(
- navArgument(
- name = "noteId"
- ) {
- type = NavType.IntType
- defaultValue = -1
- },
- navArgument(
- name = "noteColor"
- ) {
- type = NavType.IntType
- defaultValue = -1
- },
- )
- ) {
- val color = it.arguments?.getInt("noteColor") ?: -1
- AddEditNoteScreen(
- navController = navController,
- noteColor = color
- )
- }
- }
- }
- }
- }
- }
-}
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/add_edit_note/NoteTextFieldState.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/add_edit_note/NoteTextFieldState.kt
deleted file mode 100644
index 6a488bca..00000000
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/add_edit_note/NoteTextFieldState.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.add_edit_note
-
-data class NoteTextFieldState(
- val text: String = "",
- val hint: String = "",
- val isHintVisible: Boolean = true
-)
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/NotesEvent.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/NotesEvent.kt
deleted file mode 100644
index 624c0634..00000000
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/NotesEvent.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.notes
-
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.model.Note
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.util.NoteOrder
-
-sealed class NotesEvent {
- data class Order(val noteOrder: NoteOrder): NotesEvent()
- data class DeleteNote(val note: Note): NotesEvent()
- object RestoreNote: NotesEvent()
- object ToggleOrderSection: NotesEvent()
-}
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/NotesScreen.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/NotesScreen.kt
deleted file mode 100644
index 08a547f5..00000000
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/NotesScreen.kt
+++ /dev/null
@@ -1,119 +0,0 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.notes
-
-import androidx.compose.animation.*
-import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.*
-import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.items
-import androidx.compose.material3.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Add
-import androidx.compose.material.icons.filled.Sort
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.unit.dp
-import androidx.hilt.navigation.compose.hiltViewModel
-import androidx.navigation.NavController
-import com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.notes.components.NoteItem
-import com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.notes.components.OrderSection
-import com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.util.Screen
-import kotlinx.coroutines.launch
-
-@ExperimentalAnimationApi
-@Composable
-fun NotesScreen(
- navController: NavController,
- viewModel: NotesViewModel = hiltViewModel()
-) {
- val state = viewModel.state.value
- val snackbarHostState = remember { SnackbarHostState() }
- val scope = rememberCoroutineScope()
-
- Scaffold(
- snackbarHost = { SnackbarHost(snackbarHostState) },
- floatingActionButton = {
- FloatingActionButton(
- onClick = {
- navController.navigate(Screen.AddEditNoteScreen.route)
- },
- containerColor = MaterialTheme.colorScheme.primary
- ) {
- Icon(imageVector = Icons.Default.Add, contentDescription = "Add note")
- }
- }
- ) { paddingValues ->
- Column(
- modifier = Modifier
- .fillMaxSize()
- .padding(paddingValues)
- ) {
- Row(
- modifier = Modifier.fillMaxWidth(),
- horizontalArrangement = Arrangement.SpaceBetween,
- verticalAlignment = Alignment.CenterVertically
- ) {
- Text(
- text = "Your note",
- style = MaterialTheme.typography.headlineMedium
- )
- IconButton(
- onClick = {
- viewModel.onEvent(NotesEvent.ToggleOrderSection)
- },
- ) {
- Icon(
- imageVector = Icons.Default.Sort,
- contentDescription = "Sort"
- )
- }
- }
- AnimatedVisibility(
- visible = state.isOrderSectionVisible,
- enter = fadeIn() + slideInVertically(),
- exit = fadeOut() + slideOutVertically()
- ) {
- OrderSection(
- modifier = Modifier
- .fillMaxWidth()
- .padding(vertical = 16.dp),
- noteOrder = state.noteOrder,
- onOrderChange = {
- viewModel.onEvent(NotesEvent.Order(it))
- }
- )
- }
- Spacer(modifier = Modifier.height(16.dp))
- LazyColumn(modifier = Modifier.fillMaxSize()) {
- items(state.notes) { note ->
- NoteItem(
- note = note,
- modifier = Modifier
- .fillMaxWidth()
- .clickable {
- navController.navigate(
- Screen.AddEditNoteScreen.route +
- "?noteId=${note.id}¬eColor=${note.color}"
- )
- },
- onDeleteClick = {
- viewModel.onEvent(NotesEvent.DeleteNote(note))
- scope.launch {
- val result = snackbarHostState.showSnackbar(
- message = "Note deleted",
- actionLabel = "Undo"
- )
- if(result == SnackbarResult.ActionPerformed) {
- viewModel.onEvent(NotesEvent.RestoreNote)
- }
- }
- }
- )
- Spacer(modifier = Modifier.height(16.dp))
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/NotesState.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/NotesState.kt
deleted file mode 100644
index d85bfdc2..00000000
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/NotesState.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.notes
-
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.model.Note
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.util.NoteOrder
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.util.OrderType
-
-data class NotesState(
- val notes: List = emptyList(),
- val noteOrder: NoteOrder = NoteOrder.Date(OrderType.Descending),
- val isOrderSectionVisible: Boolean = false
-)
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/components/NoteItem.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/components/NoteItem.kt
deleted file mode 100644
index 790d0af4..00000000
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/components/NoteItem.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.notes.components
-
-import androidx.compose.foundation.Canvas
-import androidx.compose.foundation.layout.*
-import androidx.compose.material3.Icon
-import androidx.compose.material3.IconButton
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Text
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Delete
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.CornerRadius
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Size
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Path
-import androidx.compose.ui.graphics.drawscope.clipPath
-import androidx.compose.ui.text.style.TextOverflow
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.dp
-import androidx.core.graphics.ColorUtils
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.model.Note
-
-@Composable
-fun NoteItem(
- note: Note,
- modifier: Modifier = Modifier,
- cornerRadius: Dp = 10.dp,
- cutCornerSize: Dp = 30.dp,
- onDeleteClick: () -> Unit
-) {
- Box(
- modifier = modifier
- ) {
- Canvas(modifier = Modifier.matchParentSize()) {
- val clipPath = Path().apply {
- lineTo(size.width - cutCornerSize.toPx(), 0f)
- lineTo(size.width, cutCornerSize.toPx())
- lineTo(size.width, size.height)
- lineTo(0f, size.height)
- close()
- }
-
- clipPath(clipPath) {
- drawRoundRect(
- color = Color(note.color),
- size = size,
- cornerRadius = CornerRadius(cornerRadius.toPx())
- )
- drawRoundRect(
- color = Color(
- ColorUtils.blendARGB(note.color, 0x000000, 0.2f)
- ),
- topLeft = Offset(size.width - cutCornerSize.toPx(), -100f),
- size = Size(cutCornerSize.toPx() + 100f, cutCornerSize.toPx() + 100f),
- cornerRadius = CornerRadius(cornerRadius.toPx())
- )
- }
- }
- Column(
- modifier = Modifier
- .fillMaxSize()
- .padding(16.dp)
- .padding(end = 32.dp)
- ) {
- Text(
- text = note.title,
- style = MaterialTheme.typography.headlineSmall,
- color = MaterialTheme.colorScheme.onSurface,
- maxLines = 1,
- overflow = TextOverflow.Ellipsis
- )
- Spacer(modifier = Modifier.height(8.dp))
- Text(
- text = note.content,
- style = MaterialTheme.typography.bodyLarge,
- color = MaterialTheme.colorScheme.onSurface,
- maxLines = 10,
- overflow = TextOverflow.Ellipsis
- )
- }
- IconButton(
- onClick = onDeleteClick,
- modifier = Modifier.align(Alignment.BottomEnd)
- ) {
- Icon(
- imageVector = Icons.Default.Delete,
- contentDescription = "Delete note",
- tint = MaterialTheme.colorScheme.onSurface
- )
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/util/Screen.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/util/Screen.kt
deleted file mode 100644
index 9a0e1d1e..00000000
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/util/Screen.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.util
-
-sealed class Screen(val route: String) {
- object NotesScreen: Screen("notes_screen")
- object AddEditNoteScreen: Screen("add_edit_note_screen")
-}
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/components/DefaultRadioButton.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/component/DefaultRadioButton.kt
similarity index 92%
rename from app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/components/DefaultRadioButton.kt
rename to app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/component/DefaultRadioButton.kt
index feb257e8..5d9a7b9a 100644
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/components/DefaultRadioButton.kt
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/component/DefaultRadioButton.kt
@@ -1,4 +1,4 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.notes.components
+package com.plcoding.cleanarchitecturenoteapp.ui.component
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/components/OrderSection.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/component/OrderSection.kt
similarity index 88%
rename from app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/components/OrderSection.kt
rename to app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/component/OrderSection.kt
index 0fdc3634..f333a018 100644
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/components/OrderSection.kt
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/component/OrderSection.kt
@@ -1,11 +1,11 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.notes.components
+package com.plcoding.cleanarchitecturenoteapp.ui.component
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.util.NoteOrder
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.util.OrderType
+import com.plcoding.cleanarchitecturenoteapp.domain.util.NoteOrder
+import com.plcoding.cleanarchitecturenoteapp.domain.util.OrderType
@Composable
fun OrderSection(
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/add_edit_note/components/TransparentHintTextField.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/component/TransparentHintTextField.kt
similarity index 92%
rename from app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/add_edit_note/components/TransparentHintTextField.kt
rename to app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/component/TransparentHintTextField.kt
index 77f262e1..e6cd0dcd 100644
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/add_edit_note/components/TransparentHintTextField.kt
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/component/TransparentHintTextField.kt
@@ -1,4 +1,4 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.add_edit_note.components
+package com.plcoding.cleanarchitecturenoteapp.ui.component
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/navigation/NoteNavigation.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/navigation/NoteNavigation.kt
new file mode 100644
index 00000000..4fb44ce8
--- /dev/null
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/navigation/NoteNavigation.kt
@@ -0,0 +1,50 @@
+package com.plcoding.cleanarchitecturenoteapp.ui.navigation
+
+import androidx.compose.animation.ExperimentalAnimationApi
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.navigation.NavType
+import androidx.navigation.compose.NavHost
+import androidx.navigation.compose.composable
+import androidx.navigation.compose.rememberNavController
+import androidx.navigation.navArgument
+import com.plcoding.cleanarchitecturenoteapp.ui.view.edit.AddEditNoteScreen
+import com.plcoding.cleanarchitecturenoteapp.ui.view.list.NoteListScreen
+
+@ExperimentalAnimationApi
+@Composable
+fun NoteNavigation(modifier: Modifier) {
+ val navController = rememberNavController()
+ NavHost(
+ modifier = modifier,
+ navController = navController,
+ startDestination = NoteScreen.NotesScreen.route
+ ) {
+ composable(route = NoteScreen.NotesScreen.route) {
+ NoteListScreen(navController = navController)
+ }
+ composable(
+ route = NoteScreen.AddEditNoteScreen.route + "?noteId={noteId}¬eColor={noteColor}",
+ arguments = listOf(
+ navArgument(
+ name = "noteId"
+ ) {
+ type = NavType.IntType
+ defaultValue = -1
+ },
+ navArgument(
+ name = "noteColor"
+ ) {
+ type = NavType.IntType
+ defaultValue = -1
+ },
+ )
+ ) {
+ val color = it.arguments?.getInt("noteColor") ?: -1
+ AddEditNoteScreen(
+ navController = navController,
+ noteColor = color
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/navigation/NoteScreen.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/navigation/NoteScreen.kt
new file mode 100644
index 00000000..04ac30e9
--- /dev/null
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/navigation/NoteScreen.kt
@@ -0,0 +1,6 @@
+package com.plcoding.cleanarchitecturenoteapp.ui.navigation
+
+sealed class NoteScreen(val route: String) {
+ data object NotesScreen: NoteScreen("notes_screen")
+ data object AddEditNoteScreen: NoteScreen("add_edit_note_screen")
+}
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/theme/Color.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/theme/Color.kt
index 9b76e750..1ebeddb0 100644
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/theme/Color.kt
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/theme/Color.kt
@@ -3,6 +3,7 @@ package com.plcoding.cleanarchitecturenoteapp.ui.theme
import androidx.compose.ui.graphics.Color
val DarkGray = Color(0xFF202020)
+val LightGray = Color(0xFFD3D3D3)
val LightBlue = Color(0xFFD7E8DE)
val RedOrange = Color(0xffffab91)
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/theme/Theme.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/theme/Theme.kt
index 2c6e1c67..7446ed5d 100644
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/theme/Theme.kt
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/theme/Theme.kt
@@ -1,11 +1,17 @@
package com.plcoding.cleanarchitecturenoteapp.ui.theme
+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.ui.graphics.Color
+import androidx.compose.ui.platform.LocalContext
-private val DarkColorPalette = darkColorScheme(
+private val DarkColorScheme = darkColorScheme(
primary = Color.White,
background = DarkGray,
onBackground = Color.White,
@@ -13,12 +19,34 @@ private val DarkColorPalette = darkColorScheme(
onSurface = DarkGray
)
+private val LightColorScheme = lightColorScheme(
+ primary = Color.White,
+ background = LightGray,
+ onBackground = Color.White,
+ surface = LightBlue,
+ onSurface = DarkGray
+)
+
@Composable
-fun CleanArchitectureNoteAppTheme(darkTheme: Boolean = true, content: @Composable() () -> Unit) {
+fun CleanArchitectureNoteAppTheme(
+ 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
+ }
+
MaterialTheme(
- colorScheme = DarkColorPalette,
+ colorScheme = colorScheme,
typography = Typography,
- shapes = Shapes,
content = content
)
}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/add_edit_note/AddEditNoteEvent.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/edit/AddEditNoteEvent.kt
similarity index 77%
rename from app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/add_edit_note/AddEditNoteEvent.kt
rename to app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/edit/AddEditNoteEvent.kt
index 84c80676..a5347565 100644
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/add_edit_note/AddEditNoteEvent.kt
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/edit/AddEditNoteEvent.kt
@@ -1,4 +1,4 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.add_edit_note
+package com.plcoding.cleanarchitecturenoteapp.ui.view.edit
import androidx.compose.ui.focus.FocusState
@@ -8,6 +8,6 @@ sealed class AddEditNoteEvent{
data class EnteredContent(val value: String): AddEditNoteEvent()
data class ChangeContentFocus(val focusState: FocusState): AddEditNoteEvent()
data class ChangeColor(val color: Int): AddEditNoteEvent()
- object SaveNote: AddEditNoteEvent()
+ data object SaveNote: AddEditNoteEvent()
}
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/add_edit_note/AddEditNoteScreen.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/edit/AddEditNoteScreen.kt
similarity index 89%
rename from app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/add_edit_note/AddEditNoteScreen.kt
rename to app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/edit/AddEditNoteScreen.kt
index a8542ce0..9f295ff8 100644
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/add_edit_note/AddEditNoteScreen.kt
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/edit/AddEditNoteScreen.kt
@@ -1,4 +1,4 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.add_edit_note
+package com.plcoding.cleanarchitecturenoteapp.ui.view.edit
import androidx.compose.animation.Animatable
import androidx.compose.animation.core.tween
@@ -22,8 +22,8 @@ import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.model.Note
-import com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.add_edit_note.components.TransparentHintTextField
+import com.plcoding.cleanarchitecturenoteapp.data.model.Note
+import com.plcoding.cleanarchitecturenoteapp.ui.component.TransparentHintTextField
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
@@ -47,12 +47,13 @@ fun AddEditNoteScreen(
LaunchedEffect(key1 = true) {
viewModel.eventFlow.collectLatest { event ->
- when(event) {
+ when (event) {
is AddEditNoteViewModel.UiEvent.ShowSnackbar -> {
snackbarHostState.showSnackbar(
message = event.message
)
}
+
is AddEditNoteViewModel.UiEvent.SaveNote -> {
navController.navigateUp()
}
@@ -67,6 +68,7 @@ fun AddEditNoteScreen(
onClick = {
viewModel.onEvent(AddEditNoteEvent.SaveNote)
},
+ shape = CircleShape,
containerColor = MaterialTheme.colorScheme.primary
) {
Icon(imageVector = Icons.Default.Save, contentDescription = "Save note")
@@ -78,6 +80,7 @@ fun AddEditNoteScreen(
.fillMaxSize()
.background(noteBackgroundAnimatable.value)
.padding(paddingValues)
+ .padding(16.dp)
) {
Row(
modifier = Modifier
@@ -116,29 +119,29 @@ fun AddEditNoteScreen(
}
Spacer(modifier = Modifier.height(16.dp))
TransparentHintTextField(
- text = titleState.text,
- hint = titleState.hint,
+ text = titleState.stateText,
+ hint = titleState.stateHint,
onValueChange = {
viewModel.onEvent(AddEditNoteEvent.EnteredTitle(it))
},
onFocusChange = {
viewModel.onEvent(AddEditNoteEvent.ChangeTitleFocus(it))
},
- isHintVisible = titleState.isHintVisible,
+ isHintVisible = titleState.stateIsHintVisible,
singleLine = true,
textStyle = MaterialTheme.typography.headlineSmall
)
Spacer(modifier = Modifier.height(16.dp))
TransparentHintTextField(
- text = contentState.text,
- hint = contentState.hint,
+ text = contentState.stateText,
+ hint = contentState.stateHint,
onValueChange = {
viewModel.onEvent(AddEditNoteEvent.EnteredContent(it))
},
onFocusChange = {
viewModel.onEvent(AddEditNoteEvent.ChangeContentFocus(it))
},
- isHintVisible = contentState.isHintVisible,
+ isHintVisible = contentState.stateIsHintVisible,
textStyle = MaterialTheme.typography.bodyLarge,
modifier = Modifier.fillMaxHeight()
)
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/add_edit_note/AddEditNoteViewModel.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/edit/AddEditNoteViewModel.kt
similarity index 62%
rename from app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/add_edit_note/AddEditNoteViewModel.kt
rename to app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/edit/AddEditNoteViewModel.kt
index 147aecf4..19ddddf5 100644
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/add_edit_note/AddEditNoteViewModel.kt
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/edit/AddEditNoteViewModel.kt
@@ -1,14 +1,15 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.add_edit_note
+package com.plcoding.cleanarchitecturenoteapp.ui.view.edit
import androidx.compose.runtime.State
+import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.graphics.toArgb
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.model.InvalidNoteException
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.model.Note
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.use_case.NoteUseCases
+import com.plcoding.cleanarchitecturenoteapp.data.model.InvalidNoteException
+import com.plcoding.cleanarchitecturenoteapp.data.model.Note
+import com.plcoding.cleanarchitecturenoteapp.domain.usecase.NoteUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
@@ -17,21 +18,17 @@ import javax.inject.Inject
@HiltViewModel
class AddEditNoteViewModel @Inject constructor(
- private val noteUseCases: NoteUseCases,
+ private val noteUseCase: NoteUseCase,
savedStateHandle: SavedStateHandle
) : ViewModel() {
- private val _noteTitle = mutableStateOf(NoteTextFieldState(
- hint = "Enter title..."
- ))
+ private val _noteTitle = mutableStateOf(NoteTextFieldState(stateHint = "Note Title"))
val noteTitle: State = _noteTitle
- private val _noteContent = mutableStateOf(NoteTextFieldState(
- hint = "Enter some content"
- ))
+ private val _noteContent = mutableStateOf(NoteTextFieldState(stateHint = "Note Description"))
val noteContent: State = _noteContent
- private val _noteColor = mutableStateOf(Note.noteColors.random().toArgb())
+ private val _noteColor = mutableIntStateOf(Note.noteColors.random().toArgb())
val noteColor: State = _noteColor
private val _eventFlow = MutableSharedFlow()
@@ -41,19 +38,19 @@ class AddEditNoteViewModel @Inject constructor(
init {
savedStateHandle.get("noteId")?.let { noteId ->
- if(noteId != -1) {
+ if (noteId != -1) {
viewModelScope.launch {
- noteUseCases.getNote(noteId)?.also { note ->
+ noteUseCase.getNote(noteId)?.also { note ->
currentNoteId = note.id
_noteTitle.value = noteTitle.value.copy(
- text = note.title,
- isHintVisible = false
+ stateText = note.title,
+ stateIsHintVisible = false
)
_noteContent.value = _noteContent.value.copy(
- text = note.content,
- isHintVisible = false
+ stateText = note.content,
+ stateIsHintVisible = false
)
- _noteColor.value = note.color
+ _noteColor.intValue = note.color
}
}
}
@@ -61,46 +58,49 @@ class AddEditNoteViewModel @Inject constructor(
}
fun onEvent(event: AddEditNoteEvent) {
- when(event) {
+ when (event) {
is AddEditNoteEvent.EnteredTitle -> {
_noteTitle.value = noteTitle.value.copy(
- text = event.value
+ stateText = event.value
)
}
+
is AddEditNoteEvent.ChangeTitleFocus -> {
_noteTitle.value = noteTitle.value.copy(
- isHintVisible = !event.focusState.isFocused &&
- noteTitle.value.text.isBlank()
+ stateIsHintVisible = !event.focusState.isFocused && noteTitle.value.stateText.isBlank()
)
}
+
is AddEditNoteEvent.EnteredContent -> {
_noteContent.value = _noteContent.value.copy(
- text = event.value
+ stateText = event.value
)
}
+
is AddEditNoteEvent.ChangeContentFocus -> {
_noteContent.value = _noteContent.value.copy(
- isHintVisible = !event.focusState.isFocused &&
- _noteContent.value.text.isBlank()
+ stateIsHintVisible = !event.focusState.isFocused && _noteContent.value.stateText.isBlank()
)
}
+
is AddEditNoteEvent.ChangeColor -> {
- _noteColor.value = event.color
+ _noteColor.intValue = event.color
}
+
is AddEditNoteEvent.SaveNote -> {
viewModelScope.launch {
try {
- noteUseCases.addNote(
+ noteUseCase.addNote(
Note(
- title = noteTitle.value.text,
- content = noteContent.value.text,
+ title = noteTitle.value.stateText,
+ content = noteContent.value.stateText,
timestamp = System.currentTimeMillis(),
color = noteColor.value,
id = currentNoteId
)
)
_eventFlow.emit(UiEvent.SaveNote)
- } catch(e: InvalidNoteException) {
+ } catch (e: InvalidNoteException) {
_eventFlow.emit(
UiEvent.ShowSnackbar(
message = e.message ?: "Couldn't save note"
@@ -113,7 +113,7 @@ class AddEditNoteViewModel @Inject constructor(
}
sealed class UiEvent {
- data class ShowSnackbar(val message: String): UiEvent()
- object SaveNote: UiEvent()
+ data class ShowSnackbar(val message: String) : UiEvent()
+ data object SaveNote : UiEvent()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/edit/NoteTextFieldState.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/edit/NoteTextFieldState.kt
new file mode 100644
index 00000000..e52cb3fa
--- /dev/null
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/edit/NoteTextFieldState.kt
@@ -0,0 +1,7 @@
+package com.plcoding.cleanarchitecturenoteapp.ui.view.edit
+
+data class NoteTextFieldState(
+ val stateText: String = "",
+ val stateHint: String = "",
+ val stateIsHintVisible: Boolean = true
+)
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/list/NoteListEvent.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/list/NoteListEvent.kt
new file mode 100644
index 00000000..4d55531d
--- /dev/null
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/list/NoteListEvent.kt
@@ -0,0 +1,11 @@
+package com.plcoding.cleanarchitecturenoteapp.ui.view.list
+
+import com.plcoding.cleanarchitecturenoteapp.data.model.Note
+import com.plcoding.cleanarchitecturenoteapp.domain.util.NoteOrder
+
+sealed class NoteListEvent {
+ data class Order(val noteOrder: NoteOrder): NoteListEvent()
+ data class DeleteNote(val note: Note): NoteListEvent()
+ data object RestoreNote: NoteListEvent()
+ data object ToggleOrderSection: NoteListEvent()
+}
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/list/NoteListScreen.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/list/NoteListScreen.kt
new file mode 100644
index 00000000..4897ab42
--- /dev/null
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/list/NoteListScreen.kt
@@ -0,0 +1,210 @@
+package com.plcoding.cleanarchitecturenoteapp.ui.view.list
+
+import androidx.compose.animation.*
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.material3.*
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Add
+import androidx.compose.material.icons.filled.Sort
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.hilt.navigation.compose.hiltViewModel
+import androidx.navigation.NavController
+import com.plcoding.cleanarchitecturenoteapp.ui.component.OrderSection
+import com.plcoding.cleanarchitecturenoteapp.ui.navigation.NoteScreen
+import kotlinx.coroutines.launch
+import androidx.compose.foundation.Canvas
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material.icons.automirrored.filled.Sort
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.material.icons.filled.Delete
+import androidx.compose.ui.geometry.CornerRadius
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Path
+import androidx.compose.ui.graphics.drawscope.clipPath
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.Dp
+import androidx.core.graphics.ColorUtils
+import com.plcoding.cleanarchitecturenoteapp.data.model.Note
+import com.plcoding.cleanarchitecturenoteapp.ui.theme.DarkGray
+
+@ExperimentalAnimationApi
+@Composable
+fun NoteListScreen(
+ navController: NavController,
+ viewModel: NoteListViewModel = hiltViewModel()
+) {
+ val state = viewModel.state.value
+ val snackbarHostState = remember { SnackbarHostState() }
+ val scope = rememberCoroutineScope()
+
+ Scaffold(
+ snackbarHost = { SnackbarHost(snackbarHostState) },
+ floatingActionButton = {
+ FloatingActionButton(
+ onClick = {
+ navController.navigate(NoteScreen.AddEditNoteScreen.route)
+ },
+ shape = CircleShape,
+ containerColor = MaterialTheme.colorScheme.primary
+ ) {
+ Icon(imageVector = Icons.Default.Add, contentDescription = "Add note")
+ }
+ }
+ ) { paddingValues ->
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(paddingValues)
+ .padding(16.dp)
+ ) {
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.SpaceBetween,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Text(
+ text = "JetNote",
+ style = MaterialTheme.typography.headlineMedium
+ )
+ IconButton(
+ onClick = {
+ viewModel.onEvent(NoteListEvent.ToggleOrderSection)
+ },
+ ) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Default.Sort,
+ contentDescription = "Sort"
+ )
+ }
+ }
+ AnimatedVisibility(
+ visible = state.isOrderSectionVisible,
+ enter = fadeIn() + slideInVertically(),
+ exit = fadeOut() + slideOutVertically()
+ ) {
+ OrderSection(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(vertical = 16.dp),
+ noteOrder = state.noteOrder,
+ onOrderChange = {
+ viewModel.onEvent(NoteListEvent.Order(it))
+ }
+ )
+ }
+ Spacer(modifier = Modifier.height(16.dp))
+ LazyColumn(modifier = Modifier.fillMaxSize()) {
+ items(state.notes) { note ->
+ NoteItem(
+ note = note,
+ modifier = Modifier
+ .fillMaxWidth()
+ .clickable {
+ navController.navigate(
+ NoteScreen.AddEditNoteScreen.route +
+ "?noteId=${note.id}¬eColor=${note.color}"
+ )
+ },
+ onDeleteClick = {
+ viewModel.onEvent(NoteListEvent.DeleteNote(note))
+ scope.launch {
+ val result = snackbarHostState.showSnackbar(
+ message = "Note deleted",
+ actionLabel = "Undo"
+ )
+ if(result == SnackbarResult.ActionPerformed) {
+ viewModel.onEvent(NoteListEvent.RestoreNote)
+ }
+ }
+ }
+ )
+ Spacer(modifier = Modifier.height(16.dp))
+ }
+ }
+ }
+ }
+}
+
+@Composable
+fun NoteItem(
+ note: Note,
+ modifier: Modifier = Modifier,
+ cornerRadius: Dp = 10.dp,
+ cutCornerSize: Dp = 30.dp,
+ onDeleteClick: () -> Unit
+) {
+ Box(
+ modifier = modifier
+ ) {
+ Canvas(modifier = Modifier.matchParentSize()) {
+ val clipPath = Path().apply {
+ lineTo(size.width - cutCornerSize.toPx(), 0f)
+ lineTo(size.width, cutCornerSize.toPx())
+ lineTo(size.width, size.height)
+ lineTo(0f, size.height)
+ close()
+ }
+
+ clipPath(clipPath) {
+ drawRoundRect(
+ color = Color(note.color),
+ size = size,
+ cornerRadius = CornerRadius(cornerRadius.toPx())
+ )
+ drawRoundRect(
+ color = Color(
+ ColorUtils.blendARGB(note.color, 0x000000, 0.2f)
+ ),
+ topLeft = Offset(size.width - cutCornerSize.toPx(), -100f),
+ size = Size(cutCornerSize.toPx() + 100f, cutCornerSize.toPx() + 100f),
+ cornerRadius = CornerRadius(cornerRadius.toPx())
+ )
+ }
+ }
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(16.dp)
+ .padding(end = 32.dp)
+ ) {
+ Text(
+ text = note.title,
+ style = MaterialTheme.typography.headlineSmall,
+ color = DarkGray,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis
+ )
+ Spacer(modifier = Modifier.height(8.dp))
+ Text(
+ text = note.content,
+ style = MaterialTheme.typography.bodyLarge,
+ color = DarkGray,
+ maxLines = 10,
+ overflow = TextOverflow.Ellipsis
+ )
+ }
+ IconButton(
+ onClick = onDeleteClick,
+ modifier = Modifier.align(Alignment.BottomEnd)
+ ) {
+ Icon(
+ imageVector = Icons.Default.Delete,
+ contentDescription = "Delete note",
+ tint = MaterialTheme.colorScheme.onSurface
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/list/NoteListState.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/list/NoteListState.kt
new file mode 100644
index 00000000..acad126f
--- /dev/null
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/list/NoteListState.kt
@@ -0,0 +1,11 @@
+package com.plcoding.cleanarchitecturenoteapp.ui.view.list
+
+import com.plcoding.cleanarchitecturenoteapp.data.model.Note
+import com.plcoding.cleanarchitecturenoteapp.domain.util.NoteOrder
+import com.plcoding.cleanarchitecturenoteapp.domain.util.OrderType
+
+data class NoteListState(
+ val notes: List = emptyList(),
+ val noteOrder: NoteOrder = NoteOrder.Date(OrderType.Descending),
+ val isOrderSectionVisible: Boolean = false
+)
diff --git a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/NotesViewModel.kt b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/list/NoteListViewModel.kt
similarity index 62%
rename from app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/NotesViewModel.kt
rename to app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/list/NoteListViewModel.kt
index bd11c8d6..31bf4faa 100644
--- a/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/feature_note/presentation/notes/NotesViewModel.kt
+++ b/app/src/main/java/com/plcoding/cleanarchitecturenoteapp/ui/view/list/NoteListViewModel.kt
@@ -1,13 +1,13 @@
-package com.plcoding.cleanarchitecturenoteapp.feature_note.presentation.notes
+package com.plcoding.cleanarchitecturenoteapp.ui.view.list
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.model.Note
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.use_case.NoteUseCases
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.util.NoteOrder
-import com.plcoding.cleanarchitecturenoteapp.feature_note.domain.util.OrderType
+import com.plcoding.cleanarchitecturenoteapp.data.model.Note
+import com.plcoding.cleanarchitecturenoteapp.domain.usecase.NoteUseCase
+import com.plcoding.cleanarchitecturenoteapp.domain.util.NoteOrder
+import com.plcoding.cleanarchitecturenoteapp.domain.util.OrderType
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
@@ -16,12 +16,12 @@ import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
-class NotesViewModel @Inject constructor(
- private val noteUseCases: NoteUseCases
+class NoteListViewModel @Inject constructor(
+ private val noteUseCase: NoteUseCase
) : ViewModel() {
- private val _state = mutableStateOf(NotesState())
- val state: State = _state
+ private val _state = mutableStateOf(NoteListState())
+ val state: State = _state
private var recentlyDeletedNote: Note? = null
@@ -31,9 +31,9 @@ class NotesViewModel @Inject constructor(
getNotes(NoteOrder.Date(OrderType.Descending))
}
- fun onEvent(event: NotesEvent) {
+ fun onEvent(event: NoteListEvent) {
when (event) {
- is NotesEvent.Order -> {
+ is NoteListEvent.Order -> {
if (state.value.noteOrder::class == event.noteOrder::class &&
state.value.noteOrder.orderType == event.noteOrder.orderType
) {
@@ -41,19 +41,22 @@ class NotesViewModel @Inject constructor(
}
getNotes(event.noteOrder)
}
- is NotesEvent.DeleteNote -> {
+
+ is NoteListEvent.DeleteNote -> {
viewModelScope.launch {
- noteUseCases.deleteNote(event.note)
+ noteUseCase.deleteNote(event.note)
recentlyDeletedNote = event.note
}
}
- is NotesEvent.RestoreNote -> {
+
+ is NoteListEvent.RestoreNote -> {
viewModelScope.launch {
- noteUseCases.addNote(recentlyDeletedNote ?: return@launch)
+ noteUseCase.addNote(recentlyDeletedNote ?: return@launch)
recentlyDeletedNote = null
}
}
- is NotesEvent.ToggleOrderSection -> {
+
+ is NoteListEvent.ToggleOrderSection -> {
_state.value = state.value.copy(
isOrderSectionVisible = !state.value.isOrderSectionVisible
)
@@ -63,7 +66,7 @@ class NotesViewModel @Inject constructor(
private fun getNotes(noteOrder: NoteOrder) {
getNotesJob?.cancel()
- getNotesJob = noteUseCases.getNotes(noteOrder)
+ getNotesJob = noteUseCase.getNotes(noteOrder)
.onEach { notes ->
_state.value = state.value.copy(
notes = notes,
diff --git a/app/src/main/res/drawable/icon_launcher_foreground.xml b/app/src/main/res/drawable/icon_launcher_foreground.xml
new file mode 100644
index 00000000..83c3cba7
--- /dev/null
+++ b/app/src/main/res/drawable/icon_launcher_foreground.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/app/src/main/res/mipmap-anydpi-v26/icon_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/icon_launcher.xml
new file mode 100644
index 00000000..519a0847
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/icon_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/icon_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/icon_launcher_round.xml
new file mode 100644
index 00000000..519a0847
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/icon_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/icon_launcher.webp b/app/src/main/res/mipmap-hdpi/icon_launcher.webp
new file mode 100644
index 00000000..0ce139e8
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icon_launcher.webp differ
diff --git a/app/src/main/res/mipmap-hdpi/icon_launcher_round.webp b/app/src/main/res/mipmap-hdpi/icon_launcher_round.webp
new file mode 100644
index 00000000..5ad44c91
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icon_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-mdpi/icon_launcher.webp b/app/src/main/res/mipmap-mdpi/icon_launcher.webp
new file mode 100644
index 00000000..27c0b414
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/icon_launcher.webp differ
diff --git a/app/src/main/res/mipmap-mdpi/icon_launcher_round.webp b/app/src/main/res/mipmap-mdpi/icon_launcher_round.webp
new file mode 100644
index 00000000..3680e68b
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/icon_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_launcher.webp b/app/src/main/res/mipmap-xhdpi/icon_launcher.webp
new file mode 100644
index 00000000..e1f712a8
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/icon_launcher_round.webp
new file mode 100644
index 00000000..d472fe8e
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-xxhdpi/icon_launcher.webp b/app/src/main/res/mipmap-xxhdpi/icon_launcher.webp
new file mode 100644
index 00000000..6f9e233f
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/icon_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xxhdpi/icon_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/icon_launcher_round.webp
new file mode 100644
index 00000000..b9c1919a
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/icon_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/icon_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/icon_launcher.webp
new file mode 100644
index 00000000..7b3c94cd
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/icon_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/icon_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/icon_launcher_round.webp
new file mode 100644
index 00000000..c8de0428
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/icon_launcher_round.webp differ
diff --git a/app/src/main/res/values/icon_launcher_background.xml b/app/src/main/res/values/icon_launcher_background.xml
new file mode 100644
index 00000000..dc8c7221
--- /dev/null
+++ b/app/src/main/res/values/icon_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #FFFFFF
+
\ No newline at end of file