Compare commits
15 Commits
master
...
nextNoteVa
Author | SHA1 | Date | |
---|---|---|---|
|
8e8eecf367 | ||
|
71d56519b2 | ||
|
2525ef9eac | ||
|
0c1bc5265e | ||
|
8989dcd21d | ||
|
6df3f756ec | ||
|
caece7bfea | ||
|
234a5a7a60 | ||
|
dd7e9dce65 | ||
|
b9fe9cf184 | ||
|
828a4e0fd3 | ||
|
a61493c272 | ||
|
4ff09a6759 | ||
|
d6588913fd | ||
|
4a44f99b86 |
@ -1,49 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="music_database" uuid="95a3c2ec-2c29-4336-900a-3993de90ae66">
|
||||
<driver-ref>sqlite.xerial</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||
<jdbc-url>jdbc:sqlite:$USER_HOME$/.cache/JetBrains/IntelliJIdea2025.1/device-explorer/samsung SM-P610/_/data/data/com.stormtales.notevault/databases/music_database</jdbc-url>
|
||||
<jdbc-additional-properties>
|
||||
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
||||
</jdbc-additional-properties>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
<libraries>
|
||||
<library>
|
||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/xerial/sqlite-jdbc/3.45.1.0/sqlite-jdbc-3.45.1.0.jar</url>
|
||||
</library>
|
||||
<library>
|
||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar</url>
|
||||
</library>
|
||||
</libraries>
|
||||
</data-source>
|
||||
<data-source source="LOCAL" name="note_database" uuid="b3770d7c-0a73-40c6-aab8-010effaa19b6">
|
||||
<driver-ref>sqlite.xerial</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||
<jdbc-url>jdbc:sqlite:$USER_HOME$/.cache/JetBrains/IntelliJIdea2025.1/device-explorer/samsung SM-P610/_/data/data/come.stormborntales.notevault/databases/note_database</jdbc-url>
|
||||
<jdbc-additional-properties>
|
||||
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
||||
</jdbc-additional-properties>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
<libraries>
|
||||
<library>
|
||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/xerial/sqlite-jdbc/3.45.1.0/sqlite-jdbc-3.45.1.0.jar</url>
|
||||
</library>
|
||||
<library>
|
||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar</url>
|
||||
</library>
|
||||
<library>
|
||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/xerial/sqlite-jdbc/3.45.1.0/sqlite-jdbc-3.45.1.0.jar</url>
|
||||
</library>
|
||||
<library>
|
||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar</url>
|
||||
</library>
|
||||
</libraries>
|
||||
</data-source>
|
||||
<data-source source="LOCAL" name="note_database [2]" uuid="ad94cfd9-e485-4151-8bf4-a080c51fa27c">
|
||||
<data-source source="LOCAL" name="note_database" uuid="669634a7-d50e-4c04-b2fe-786d18bbd166">
|
||||
<driver-ref>sqlite.xerial</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||
@ -65,6 +23,12 @@
|
||||
<library>
|
||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar</url>
|
||||
</library>
|
||||
<library>
|
||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/xerial/sqlite-jdbc/3.45.1.0/sqlite-jdbc-3.45.1.0.jar</url>
|
||||
</library>
|
||||
<library>
|
||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar</url>
|
||||
</library>
|
||||
</libraries>
|
||||
</data-source>
|
||||
</component>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DropdownSelection timestamp="2025-05-03T08:34:29.354537334Z">
|
||||
<DropdownSelection timestamp="2025-05-10T10:58:30.749991183Z">
|
||||
<Target type="DEFAULT_BOOT">
|
||||
<handle>
|
||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=R52N50NLGRT" />
|
||||
|
@ -63,4 +63,5 @@ dependencies {
|
||||
implementation(libs.compose.runtime.livedata)
|
||||
implementation(libs.coil.compose)
|
||||
ksp(libs.androidx.room.compiler)
|
||||
implementation(libs.androidx.material.icons.extended)
|
||||
}
|
@ -42,12 +42,15 @@ import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import come.stormborntales.notevault.data.local.AppDatabase
|
||||
import come.stormborntales.notevault.data.local.entity.NoteEntity
|
||||
import come.stormborntales.notevault.data.repository.CollectionRepository
|
||||
import come.stormborntales.notevault.data.repository.NoteRepository
|
||||
import come.stormborntales.notevault.ui.screens.AddNoteDialog
|
||||
import come.stormborntales.notevault.ui.screens.MainScreen
|
||||
import come.stormborntales.notevault.ui.screens.NotesScreen
|
||||
import come.stormborntales.notevault.ui.screens.notebrowser.NotesScreen
|
||||
import come.stormborntales.notevault.ui.screens.SettingsScreen
|
||||
import come.stormborntales.notevault.ui.theme.NoteVaultTheme
|
||||
import come.stormborntales.notevault.ui.viewmodel.NoteBrowserViewModel
|
||||
import come.stormborntales.notevault.ui.viewmodel.NoteBrowserViewModelFactory
|
||||
import come.stormborntales.notevault.ui.viewmodel.NoteViewModel
|
||||
import come.stormborntales.notevault.ui.viewmodel.NoteViewModelFactory
|
||||
import kotlinx.coroutines.launch
|
||||
@ -59,14 +62,16 @@ class MainActivity : ComponentActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
val applicationContext = applicationContext
|
||||
val database = AppDatabase.getDatabase(applicationContext)
|
||||
val repository = NoteRepository(database.noteDao())
|
||||
val viewModelFactory = NoteViewModelFactory(repository)
|
||||
val noteRepository = NoteRepository(database.noteDao())
|
||||
val collectionRepository = CollectionRepository(database.collectionDao())
|
||||
val viewModelFactory = NoteViewModelFactory(noteRepository)
|
||||
val noteBrowserViewModelFactory = NoteBrowserViewModelFactory(noteRepository, collectionRepository)
|
||||
|
||||
setContent {
|
||||
NoteVaultTheme {
|
||||
val navController = rememberNavController()
|
||||
val viewModel: NoteViewModel = viewModel(factory = viewModelFactory)
|
||||
|
||||
val noteBrowserViewModel: NoteBrowserViewModel = viewModel(factory = noteBrowserViewModelFactory)
|
||||
var selectedUris by remember { mutableStateOf<List<Uri>>(emptyList()) }
|
||||
var showDialog by remember { mutableStateOf(false) }
|
||||
var noteToEdit by remember { mutableStateOf<NoteEntity?>(null) }
|
||||
@ -206,7 +211,13 @@ class MainActivity : ComponentActivity() {
|
||||
SettingsScreen()
|
||||
}
|
||||
composable("notes") {
|
||||
NotesScreen()
|
||||
NotesScreen(collectionRepository, noteRepository, onImportNotes = {
|
||||
imagePickerLauncher.launch(arrayOf("image/*"))
|
||||
}, noteBrowserViewModel,
|
||||
onEditNote = {
|
||||
noteToEdit = it
|
||||
showDialog = true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,6 +235,7 @@ class MainActivity : ComponentActivity() {
|
||||
genre = genre,
|
||||
description = description,
|
||||
selectedUris = selectedUris,
|
||||
collectionID = noteBrowserViewModel.currentParentId.value,
|
||||
onDone = { showDialog = false }
|
||||
)
|
||||
} else {
|
||||
|
@ -6,6 +6,7 @@ import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.TypeConverters
|
||||
import come.stormborntales.notevault.data.local.dao.CollectionDao
|
||||
import come.stormborntales.notevault.data.local.dao.NoteDao
|
||||
import come.stormborntales.notevault.data.local.entity.NoteCollection
|
||||
import come.stormborntales.notevault.data.local.entity.NoteEntity
|
||||
@ -14,6 +15,7 @@ import come.stormborntales.notevault.data.local.entity.NoteEntity
|
||||
@TypeConverters(UriListConverter::class)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun noteDao(): NoteDao
|
||||
abstract fun collectionDao(): CollectionDao
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
|
@ -0,0 +1,32 @@
|
||||
package come.stormborntales.notevault.data.local.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import androidx.room.Update
|
||||
import come.stormborntales.notevault.data.local.entity.NoteCollection
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface CollectionDao {
|
||||
|
||||
@Query(value = "SELECT * FROM note_collections WHERE parentId IS :parentId")
|
||||
fun getCollectionsByParent(parentId: Int?): Flow<List<NoteCollection>>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertCollection(collection: NoteCollection)
|
||||
|
||||
@Update
|
||||
suspend fun updateCollection(collection: NoteCollection)
|
||||
|
||||
@Delete
|
||||
suspend fun deleteCollection(collection: NoteCollection)
|
||||
|
||||
@Query("SELECT * FROM note_collections WHERE id = :id LIMIT 1")
|
||||
suspend fun getById(id: Int): NoteCollection?
|
||||
|
||||
@Query("SELECT * FROM note_collections")
|
||||
fun getAll(): Flow<List<NoteCollection>>
|
||||
}
|
@ -22,4 +22,6 @@ interface NoteDao {
|
||||
|
||||
@Update
|
||||
suspend fun update(note: NoteEntity)
|
||||
@Query("SELECT * FROM notes WHERE collectionId IS :collectionId")
|
||||
fun getNotesForCollection(collectionId: Int?): Flow<List<NoteEntity>>
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package come.stormborntales.notevault.data.repository
|
||||
|
||||
import come.stormborntales.notevault.data.local.dao.CollectionDao
|
||||
import come.stormborntales.notevault.data.local.dao.NoteDao
|
||||
import come.stormborntales.notevault.data.local.entity.NoteCollection
|
||||
import come.stormborntales.notevault.data.local.entity.NoteEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
|
||||
class CollectionRepository(private val dao: CollectionDao) {
|
||||
fun getCollectionsByParent(parentId: Int?): Flow<List<NoteCollection>> {
|
||||
return dao.getCollectionsByParent(parentId)
|
||||
}
|
||||
|
||||
suspend fun insertCollection(collection: NoteCollection) {
|
||||
dao.insertCollection(collection)
|
||||
}
|
||||
|
||||
suspend fun updateCollection(collection: NoteCollection) {
|
||||
dao.updateCollection(collection)
|
||||
}
|
||||
|
||||
suspend fun deleteCollection(collection: NoteCollection) {
|
||||
dao.deleteCollection(collection)
|
||||
}
|
||||
|
||||
suspend fun getCollectionById(id: Int): NoteCollection? {
|
||||
return dao.getById(id)
|
||||
}
|
||||
|
||||
fun getAllCollections(): Flow<List<NoteCollection>> {
|
||||
return dao.getAll()
|
||||
}
|
||||
}
|
@ -11,4 +11,5 @@ class NoteRepository(private val dao: NoteDao) {
|
||||
suspend fun delete(note: NoteEntity) = dao.delete(note)
|
||||
|
||||
suspend fun update(note: NoteEntity) = dao.update(note);
|
||||
fun getNotesForCollection(parentId: Int?) = dao.getNotesForCollection(parentId);
|
||||
}
|
||||
|
@ -19,7 +19,8 @@ fun AddNoteDialog(
|
||||
initialComposer: String? = null,
|
||||
initialYear: Int? = null,
|
||||
initialGenre: String? = null,
|
||||
initialDescription: String? = null
|
||||
initialDescription: String? = null,
|
||||
collectionId: Int? = null
|
||||
) {
|
||||
var title by remember { mutableStateOf(initialTitle) }
|
||||
var composer by remember { mutableStateOf(initialComposer ?: "") }
|
||||
|
@ -1,24 +0,0 @@
|
||||
package come.stormborntales.notevault.ui.screens
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Divider
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
|
||||
@Composable
|
||||
fun NotesScreen() {
|
||||
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package come.stormborntales.notevault.ui.screens.notebrowser
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Slider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun DeleteCollectionDialog(
|
||||
collectionName: String,
|
||||
onDismiss: () -> Unit,
|
||||
onConfirm: () -> Unit
|
||||
) {
|
||||
var sliderPosition by remember { mutableStateOf(0f) }
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
title = {
|
||||
Text("Collection löschen", style = MaterialTheme.typography.titleLarge)
|
||||
},
|
||||
text = {
|
||||
Column {
|
||||
Text(
|
||||
text = "Bist du sicher, dass du die Collection \"$collectionName\" löschen möchtest?",
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Text(
|
||||
text = "⚠️ Alle enthaltenen Noten werden ebenfalls dauerhaft gelöscht.",
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.error
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(
|
||||
text = "Zum Bestätigen den Schieberegler ganz nach rechts ziehen.",
|
||||
style = MaterialTheme.typography.bodySmall
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Slider(
|
||||
value = sliderPosition,
|
||||
onValueChange = { sliderPosition = it },
|
||||
valueRange = 0f..1f,
|
||||
steps = 0,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 4.dp)
|
||||
)
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = {
|
||||
if(sliderPosition == 1.0f) {
|
||||
onConfirm()
|
||||
}
|
||||
}, colors = ButtonDefaults.textButtonColors(
|
||||
contentColor = MaterialTheme.colorScheme.error
|
||||
)) {
|
||||
Text("Löschen")
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = onDismiss) {
|
||||
Text("Abbrechen")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
package come.stormborntales.notevault.ui.screens.notebrowser
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowDropDown
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material.icons.filled.Edit
|
||||
import androidx.compose.material.icons.filled.Folder
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil.compose.AsyncImage
|
||||
import come.stormborntales.notevault.data.local.entity.NoteCollection
|
||||
import come.stormborntales.notevault.data.local.entity.NoteEntity
|
||||
|
||||
|
||||
@Composable
|
||||
fun CollectionItem(
|
||||
collection: NoteCollection,
|
||||
onDeleteCollection: (NoteCollection) -> Unit,
|
||||
onEditCollection: (NoteCollection) -> Unit,
|
||||
) {
|
||||
var showMenu by remember { mutableStateOf(false) }
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.height(120.dp)
|
||||
.clip(RoundedCornerShape(12.dp))
|
||||
.background(MaterialTheme.colorScheme.surfaceVariant)
|
||||
.clickable { }
|
||||
.padding(12.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Folder,
|
||||
contentDescription = "Ordner",
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.size(64.dp)
|
||||
)
|
||||
Box {
|
||||
val interactionSource = remember { MutableInteractionSource() }
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.clickable { showMenu = true }
|
||||
.padding(top = 8.dp)
|
||||
) {
|
||||
Text(
|
||||
text = collection.name,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
textAlign = TextAlign.Center,
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier
|
||||
.clickable(
|
||||
interactionSource = interactionSource,
|
||||
indication = rememberRipple(bounded = true)
|
||||
) {
|
||||
showMenu = true
|
||||
}
|
||||
)
|
||||
Icon(
|
||||
imageVector = Icons.Default.ArrowDropDown,
|
||||
contentDescription = "Mehr Optionen",
|
||||
tint = MaterialTheme.colorScheme.onSurface
|
||||
)
|
||||
}
|
||||
|
||||
DropdownMenu(
|
||||
expanded = showMenu,
|
||||
onDismissRequest = { showMenu = false },
|
||||
modifier = Modifier
|
||||
.width(240.dp)
|
||||
.background(MaterialTheme.colorScheme.background)
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
showMenu = false
|
||||
onEditCollection(collection)
|
||||
},
|
||||
text = {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Edit,
|
||||
contentDescription = "Bearbeiten",
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text("Bearbeiten", color = MaterialTheme.colorScheme.primary)
|
||||
}
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
showMenu = false
|
||||
onDeleteCollection(collection)
|
||||
},
|
||||
text = {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Delete,
|
||||
contentDescription = "Löschen",
|
||||
tint = MaterialTheme.colorScheme.error,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text("Löschen", color = MaterialTheme.colorScheme.error)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
package come.stormborntales.notevault.ui.screens.notebrowser
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowDropDown
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material.icons.filled.Edit
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil.compose.AsyncImage
|
||||
import come.stormborntales.notevault.data.local.entity.NoteEntity
|
||||
|
||||
|
||||
@Composable
|
||||
fun NoteItem(
|
||||
note: NoteEntity,
|
||||
onNoteClick: (NoteEntity) -> Unit,
|
||||
onEditTitle: () -> Unit,
|
||||
onDeleteNote: () -> Unit
|
||||
) {
|
||||
var showMenu by remember { mutableStateOf(false) }
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.height(120.dp)
|
||||
.clip(RoundedCornerShape(12.dp))
|
||||
.background(MaterialTheme.colorScheme.surfaceVariant)
|
||||
.clickable { onNoteClick(note) }
|
||||
.padding(12.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
AsyncImage(
|
||||
model = note.imagePreview,
|
||||
contentDescription = "Noten-Vorschau",
|
||||
modifier = Modifier
|
||||
.size(64.dp)
|
||||
.clip(RoundedCornerShape(8.dp)),
|
||||
contentScale = ContentScale.Crop
|
||||
)
|
||||
|
||||
Box {
|
||||
val interactionSource = remember { MutableInteractionSource() }
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.clickable { showMenu = true }
|
||||
.padding(top = 8.dp)
|
||||
) {
|
||||
Text(
|
||||
text = note.title,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
textAlign = TextAlign.Center,
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier
|
||||
.clickable(
|
||||
interactionSource = interactionSource,
|
||||
indication = rememberRipple(bounded = true)
|
||||
) {
|
||||
showMenu = true
|
||||
}
|
||||
)
|
||||
Icon(
|
||||
imageVector = Icons.Default.ArrowDropDown,
|
||||
contentDescription = "Mehr Optionen",
|
||||
tint = MaterialTheme.colorScheme.onSurface
|
||||
)
|
||||
}
|
||||
|
||||
DropdownMenu(
|
||||
expanded = showMenu,
|
||||
onDismissRequest = { showMenu = false },
|
||||
modifier = Modifier
|
||||
.width(240.dp)
|
||||
.background(MaterialTheme.colorScheme.background)
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
showMenu = false
|
||||
onEditTitle()
|
||||
},
|
||||
text = {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Edit,
|
||||
contentDescription = "Bearbeiten",
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text("Bearbeiten", color = MaterialTheme.colorScheme.primary)
|
||||
}
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
showMenu = false
|
||||
onDeleteNote()
|
||||
},
|
||||
text = {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Delete,
|
||||
contentDescription = "Löschen",
|
||||
tint = MaterialTheme.colorScheme.error,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text("Löschen", color = MaterialTheme.colorScheme.error)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,305 @@
|
||||
package come.stormborntales.notevault.ui.screens.notebrowser
|
||||
|
||||
import android.util.Log
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.lazy.grid.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.ArrowDropDown
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material.icons.filled.Edit
|
||||
import androidx.compose.material.icons.filled.Folder
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil.compose.AsyncImage
|
||||
import come.stormborntales.notevault.data.local.entity.NoteCollection
|
||||
import come.stormborntales.notevault.data.local.entity.NoteEntity
|
||||
import come.stormborntales.notevault.data.repository.CollectionRepository
|
||||
import come.stormborntales.notevault.data.repository.NoteRepository
|
||||
import come.stormborntales.notevault.ui.viewmodel.NoteBrowserViewModel
|
||||
|
||||
@Composable
|
||||
fun CreateCollectionDialog(
|
||||
editedCollection: NoteCollection?,
|
||||
onDismiss: () -> Unit,
|
||||
onCreate: (String) -> Unit
|
||||
) {
|
||||
var collectionName by remember { mutableStateOf(editedCollection?.name ?: "") }
|
||||
var isError by remember { mutableStateOf(false) }
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
title = {
|
||||
Text("Neue Collection erstellen")
|
||||
},
|
||||
text = {
|
||||
Column {
|
||||
OutlinedTextField(
|
||||
value = collectionName,
|
||||
onValueChange = {
|
||||
collectionName = it
|
||||
isError = false
|
||||
},
|
||||
label = { Text("Collection-Name") },
|
||||
isError = isError,
|
||||
singleLine = true
|
||||
)
|
||||
if (isError) {
|
||||
Text(
|
||||
text = "Name darf nicht leer sein",
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
style = MaterialTheme.typography.bodySmall
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = {
|
||||
if (collectionName.isBlank()) {
|
||||
isError = true
|
||||
} else {
|
||||
onCreate(collectionName.trim())
|
||||
onDismiss()
|
||||
}
|
||||
}) {
|
||||
Text("Erstellen")
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = onDismiss) {
|
||||
Text("Abbrechen")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CollectionBreadcrumbs(
|
||||
path: List<NoteCollection>,
|
||||
onNavigateTo: (index: Int) -> Unit
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
BreadcrumbItem(label = "Start", onClick = { onNavigateTo(-1) })
|
||||
|
||||
path.forEachIndexed { index, collection ->
|
||||
Text(" / ", style = MaterialTheme.typography.labelLarge)
|
||||
|
||||
BreadcrumbItem(label = collection.name, onClick = {
|
||||
Log.d("Breadcrumb", "BreadcrumbItem " + collection.name + " was clicked")
|
||||
onNavigateTo(index)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BreadcrumbItem(label: String, onClick: () -> Unit) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 4.dp)
|
||||
.clickable(onClick = {
|
||||
Log.d("Individual Breadcrumb", "A simple test " + label)
|
||||
onClick()
|
||||
})
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun NoteGrid(
|
||||
modifier: Modifier = Modifier,
|
||||
collections: List<NoteCollection>,
|
||||
notes: List<NoteEntity>,
|
||||
onCollectionClick: (NoteCollection) -> Unit,
|
||||
onNoteClick: (NoteEntity) -> Unit,
|
||||
onDeleteNote: (NoteEntity) -> Unit,
|
||||
onEditNote: (NoteEntity) ->Unit,
|
||||
onDeleteCollection: (NoteCollection) -> Unit,
|
||||
onEditCollection: (NoteCollection) -> Unit,
|
||||
) {
|
||||
var showCollectionConfirmationDialog by remember { mutableStateOf(false) }
|
||||
var deletedCollection: NoteCollection? by remember { mutableStateOf(null) }
|
||||
LazyVerticalGrid(
|
||||
modifier = modifier.fillMaxSize(),
|
||||
columns = GridCells.Adaptive(minSize = 240.dp),
|
||||
contentPadding = PaddingValues(8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
items(collections) { collection ->
|
||||
CollectionItem(collection, onDeleteCollection = {
|
||||
showCollectionConfirmationDialog = true
|
||||
deletedCollection = collection
|
||||
}, onEditCollection = onEditCollection)
|
||||
}
|
||||
|
||||
items(notes) { note ->
|
||||
NoteItem(note, onNoteClick = {}, onEditTitle = {onEditNote(note)}, onDeleteNote = {onDeleteNote(note)})
|
||||
}
|
||||
}
|
||||
if(showCollectionConfirmationDialog && deletedCollection != null) {
|
||||
DeleteCollectionDialog(deletedCollection!!.name , {}, {
|
||||
onDeleteCollection(deletedCollection!!)
|
||||
showCollectionConfirmationDialog = false
|
||||
})
|
||||
}
|
||||
}
|
||||
@Composable
|
||||
fun NotesScreen(
|
||||
collectionRepository: CollectionRepository,
|
||||
noteRepository: NoteRepository,
|
||||
onImportNotes: (Int?) -> Unit,
|
||||
viewModel: NoteBrowserViewModel,
|
||||
onEditNote: (NoteEntity) -> Unit
|
||||
) {
|
||||
var menuExpanded by remember { mutableStateOf(false) }
|
||||
var showDialog by remember { mutableStateOf(false) }
|
||||
var collectionToEdit by remember { mutableStateOf<NoteCollection?>(null) }
|
||||
|
||||
val collections by viewModel.currentCollections.collectAsState()
|
||||
val notes by viewModel.currentNotes.collectAsState()
|
||||
|
||||
Scaffold(
|
||||
floatingActionButton = {
|
||||
Box {
|
||||
FloatingActionButton(onClick = { menuExpanded = true }) {
|
||||
Icon(Icons.Default.Add, contentDescription = "Open menu")
|
||||
}
|
||||
|
||||
DropdownMenu(
|
||||
expanded = menuExpanded,
|
||||
onDismissRequest = { menuExpanded = false },
|
||||
modifier = Modifier
|
||||
.wrapContentWidth()
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
text = { Text("Ordner erstellen") },
|
||||
onClick = {
|
||||
menuExpanded = false
|
||||
showDialog = true
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text("Noten importieren") },
|
||||
onClick = {
|
||||
menuExpanded = false
|
||||
onImportNotes(viewModel.currentParentId.value)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
content = { innerPadding ->
|
||||
|
||||
val path by viewModel.pathStack.collectAsState()
|
||||
|
||||
BackHandler(enabled = path.isNotEmpty()) {
|
||||
viewModel.navigateUp()
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(innerPadding)
|
||||
) {
|
||||
// Breadcrumbs sichtbar & klickbar machen
|
||||
CollectionBreadcrumbs(
|
||||
path = path,
|
||||
onNavigateTo = { index ->
|
||||
Log.d("NoteBrowser", "Navigate to: $index")
|
||||
if (index == -1) viewModel.loadContentForParent(null)
|
||||
else viewModel.navigateToLevel(index)
|
||||
}
|
||||
)
|
||||
|
||||
NoteGrid(
|
||||
collections = collections,
|
||||
notes = notes,
|
||||
onCollectionClick = { viewModel.loadContentForParent(it.id, it) },
|
||||
onNoteClick = { /* TODO: Öffnen oder Bearbeiten */ },
|
||||
onDeleteNote = {
|
||||
viewModel.removeNote(noteEntity = it)
|
||||
},
|
||||
onEditNote = onEditNote,
|
||||
onDeleteCollection = {
|
||||
viewModel.removeCollection(noteCollection = it)
|
||||
},
|
||||
onEditCollection = {
|
||||
collectionToEdit = it
|
||||
showDialog = true
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (showDialog) {
|
||||
CreateCollectionDialog(
|
||||
onDismiss = { showDialog = false },
|
||||
onCreate = { name ->
|
||||
if(collectionToEdit != null) {
|
||||
viewModel.updateCollection(collectionToEdit!!, name)
|
||||
} else {
|
||||
// Handle the new collection name
|
||||
viewModel.createCollection(name)
|
||||
}
|
||||
},
|
||||
editedCollection = collectionToEdit
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
package come.stormborntales.notevault.ui.viewmodel
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import come.stormborntales.notevault.data.local.entity.NoteCollection
|
||||
import come.stormborntales.notevault.data.local.entity.NoteEntity
|
||||
import come.stormborntales.notevault.data.repository.CollectionRepository
|
||||
import come.stormborntales.notevault.data.repository.NoteRepository
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class NoteBrowserViewModel (
|
||||
private val noteRepository: NoteRepository,
|
||||
private val collectionRepository: CollectionRepository
|
||||
) : ViewModel() {
|
||||
private val _currentCollections = MutableStateFlow<List<NoteCollection>>(emptyList())
|
||||
val currentCollections: StateFlow<List<NoteCollection>> = _currentCollections.asStateFlow()
|
||||
|
||||
private val _currentNotes = MutableStateFlow<List<NoteEntity>>(emptyList())
|
||||
val currentNotes: StateFlow<List<NoteEntity>> = _currentNotes.asStateFlow()
|
||||
|
||||
private val _currentParentId = MutableStateFlow<Int?>(null)
|
||||
val currentParentId: StateFlow<Int?> = _currentParentId.asStateFlow()
|
||||
|
||||
private val _pathStack = MutableStateFlow<List<NoteCollection>>(emptyList())
|
||||
val pathStack: StateFlow<List<NoteCollection>> = _pathStack.asStateFlow()
|
||||
|
||||
init {
|
||||
loadContentForParent(null)
|
||||
}
|
||||
|
||||
fun loadContentForParent(parentId: Int?, selectedCollection: NoteCollection? = null) {
|
||||
_currentParentId.value = parentId
|
||||
viewModelScope.launch {
|
||||
launch {
|
||||
collectionRepository.getCollectionsByParent(parentId).collect {
|
||||
_currentCollections.value = it
|
||||
}
|
||||
}
|
||||
launch {
|
||||
noteRepository.getNotesForCollection(parentId).collect {
|
||||
Log.d("NoteBrowser", "Noten geladen: ${it.size}")
|
||||
_currentNotes.value = it
|
||||
}
|
||||
}
|
||||
if (selectedCollection != null) {
|
||||
_pathStack.value = _pathStack.value + selectedCollection
|
||||
} else if (parentId == null) {
|
||||
_pathStack.value = emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createCollection(name: String) {
|
||||
viewModelScope.launch {
|
||||
val newCollection = NoteCollection(name = name, parentId = _currentParentId.value)
|
||||
collectionRepository.insertCollection(newCollection)
|
||||
loadContentForParent(_currentParentId.value)
|
||||
}
|
||||
}
|
||||
|
||||
fun removeNote(noteEntity: NoteEntity) {
|
||||
viewModelScope.launch {
|
||||
noteRepository.delete(noteEntity)
|
||||
}
|
||||
}
|
||||
|
||||
fun removeCollection(noteCollection: NoteCollection) {
|
||||
viewModelScope.launch {
|
||||
collectionRepository.deleteCollection(noteCollection)
|
||||
}
|
||||
}
|
||||
|
||||
fun navigateToLevel(index: Int) {
|
||||
val newStack = _pathStack.value.take(index + 1)
|
||||
_pathStack.value = newStack
|
||||
val newParent = newStack.lastOrNull()?.id
|
||||
loadContentForParent(newParent)
|
||||
}
|
||||
|
||||
fun navigateUp() {
|
||||
val newStack = _pathStack.value.dropLast(1)
|
||||
_pathStack.value = newStack
|
||||
val newParentId = newStack.lastOrNull()?.id
|
||||
loadContentForParent(newParentId)
|
||||
}
|
||||
|
||||
fun updateCollection(collectionToEdit: NoteCollection, name: String) {
|
||||
if(name.isNotEmpty()) {
|
||||
collectionToEdit.name = name
|
||||
viewModelScope.launch {
|
||||
collectionRepository.updateCollection(collectionToEdit)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package come.stormborntales.notevault.ui.viewmodel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import come.stormborntales.notevault.data.repository.CollectionRepository
|
||||
import come.stormborntales.notevault.data.repository.NoteRepository
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class NoteBrowserViewModelFactory (
|
||||
private val noteRepository: NoteRepository,
|
||||
private val collectionRepository: CollectionRepository
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
if (modelClass.isAssignableFrom(NoteBrowserViewModel::class.java)) {
|
||||
return NoteBrowserViewModel(noteRepository, collectionRepository) as T
|
||||
}
|
||||
throw IllegalArgumentException("Unknown ViewModel class")
|
||||
}
|
||||
}
|
@ -61,7 +61,7 @@ class NoteViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
fun addNote(context: Context, title: String, composer: String?, year: Int?, genre: String?, description: String?, selectedUris: List<Uri>, onDone:() -> Unit) {
|
||||
fun addNote(context: Context, title: String, composer: String?, year: Int?, genre: String?, description: String?, selectedUris: List<Uri>, collectionID: Int?, onDone:() -> Unit) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val copiedUris = selectedUris.mapNotNull { uri ->
|
||||
try {
|
||||
@ -94,7 +94,7 @@ class NoteViewModel(
|
||||
genre = genre,
|
||||
description = description,
|
||||
imagePreview = preview_image_path.toString(),
|
||||
collectionId = null
|
||||
collectionId = collectionID
|
||||
)
|
||||
|
||||
repository.insert(note)
|
||||
|
@ -9,12 +9,14 @@ espressoCore = "3.6.1"
|
||||
lifecycleRuntimeKtx = "2.8.7"
|
||||
activityCompose = "1.8.0"
|
||||
composeBom = "2024.04.01"
|
||||
materialIconsExtended = "1.7.8"
|
||||
navigationCompose = "2.8.9"
|
||||
room = "2.7.1"
|
||||
ksp="2.1.21-RC-2.0.0"
|
||||
compose = "1.6.0" # oder was immer deine aktuelle Compose-Version ist
|
||||
|
||||
[libraries]
|
||||
androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "materialIconsExtended" }
|
||||
coil-compose = { group = "io.coil-kt", name = "coil-compose", version = "2.5.0" } # oder aktueller
|
||||
compose-runtime-livedata = { group = "androidx.compose.runtime", name = "runtime-livedata", version.ref = "compose" }
|
||||
lifecycle-livedata-ktx = "androidx.lifecycle:lifecycle-livedata-ktx:2.8.7"
|
||||
|
Loading…
Reference in New Issue
Block a user