nextNoteVault #23
@ -1,5 +1,6 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<project version="4">
 | 
			
		||||
  <component name="GradleMigrationSettings" migrationVersion="1" />
 | 
			
		||||
  <component name="GradleSettings">
 | 
			
		||||
    <option name="linkedExternalProjectsSettings">
 | 
			
		||||
      <GradleProjectSettings>
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,8 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<project version="4">
 | 
			
		||||
  <component name="ExternalStorageConfigurationManager" enabled="true" />
 | 
			
		||||
  <component name="ProjectRootManager" version="2" languageLevel="JDK_21" project-jdk-name="21" project-jdk-type="JavaSDK" />
 | 
			
		||||
  <component name="FrameworkDetectionExcludesConfiguration">
 | 
			
		||||
    <file type="web" url="file://$PROJECT_DIR$" />
 | 
			
		||||
  </component>
 | 
			
		||||
  <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK" />
 | 
			
		||||
</project>
 | 
			
		||||
							
								
								
									
										12
									
								
								.idea/runConfigurations.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								.idea/runConfigurations.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<project version="4">
 | 
			
		||||
  <component name="RunConfigurationProducerService">
 | 
			
		||||
    <option name="ignoredProducers">
 | 
			
		||||
      <set>
 | 
			
		||||
        <option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
 | 
			
		||||
        <option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
 | 
			
		||||
        <option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
 | 
			
		||||
      </set>
 | 
			
		||||
    </option>
 | 
			
		||||
  </component>
 | 
			
		||||
</project>
 | 
			
		||||
@ -1,66 +1,96 @@
 | 
			
		||||
package come.stormborntales.notevault
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import androidx.activity.ComponentActivity
 | 
			
		||||
import androidx.activity.compose.rememberLauncherForActivityResult
 | 
			
		||||
import androidx.activity.compose.setContent
 | 
			
		||||
import androidx.activity.enableEdgeToEdge
 | 
			
		||||
import androidx.activity.result.ActivityResultLauncher
 | 
			
		||||
import androidx.activity.result.PickVisualMediaRequest
 | 
			
		||||
import androidx.activity.result.contract.ActivityResultContracts
 | 
			
		||||
import androidx.compose.runtime.mutableStateListOf
 | 
			
		||||
import androidx.compose.runtime.*
 | 
			
		||||
import androidx.compose.ui.platform.LocalContext
 | 
			
		||||
import come.stormborntales.notevault.data.model.NoteEntry
 | 
			
		||||
import come.stormborntales.notevault.ui.screens.AddNoteDialog
 | 
			
		||||
import come.stormborntales.notevault.ui.screens.MainScreen
 | 
			
		||||
import come.stormborntales.notevault.ui.theme.NoteVaultTheme
 | 
			
		||||
import java.io.File
 | 
			
		||||
import java.io.InputStream
 | 
			
		||||
 | 
			
		||||
class MainActivity : ComponentActivity() {
 | 
			
		||||
    private lateinit var imagePickerLauncher: ActivityResultLauncher<PickVisualMediaRequest>
 | 
			
		||||
    // Definiere notes als MutableStateList für die gesamte Aktivität
 | 
			
		||||
    private val notes = mutableStateListOf<NoteEntry>()
 | 
			
		||||
    override fun onCreate(savedInstanceState: Bundle?) {
 | 
			
		||||
        super.onCreate(savedInstanceState)
 | 
			
		||||
        enableEdgeToEdge()
 | 
			
		||||
 | 
			
		||||
        // Launcher für die Bildauswahl einrichten
 | 
			
		||||
        imagePickerLauncher = registerForActivityResult(ActivityResultContracts.PickMultipleVisualMedia()) { uris ->
 | 
			
		||||
            if (!uris.isNullOrEmpty()) {
 | 
			
		||||
                val context: Context = applicationContext
 | 
			
		||||
                val copiedUris = uris.mapNotNull { uri ->
 | 
			
		||||
                    try {
 | 
			
		||||
                        val inputStream: InputStream? = contentResolver.openInputStream(uri)
 | 
			
		||||
                        val outputFile =
 | 
			
		||||
                            File(context.filesDir, "note_${System.currentTimeMillis()}_${uri.lastPathSegment}")
 | 
			
		||||
                        inputStream?.use { input ->
 | 
			
		||||
                            outputFile.outputStream().use { output ->
 | 
			
		||||
                                input.copyTo(output)
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        Uri.fromFile(outputFile)
 | 
			
		||||
                    } catch (e: Exception) {
 | 
			
		||||
                        e.printStackTrace()
 | 
			
		||||
                        null
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (copiedUris.isNotEmpty()) {
 | 
			
		||||
                    notes.add(NoteEntry(images = copiedUris)) // Titel optional setzen
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        setContent {
 | 
			
		||||
            NoteVaultTheme {
 | 
			
		||||
                MainScreen(
 | 
			
		||||
                    onAddNoteClicked = {
 | 
			
		||||
                        // Öffne die Galerie zum Auswählen eines Bildes
 | 
			
		||||
                        imagePickerLauncher.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageAndVideo))
 | 
			
		||||
                    },
 | 
			
		||||
                    notes = notes,
 | 
			
		||||
                val context = LocalContext.current
 | 
			
		||||
 | 
			
		||||
                // Globale Notenliste
 | 
			
		||||
                val notes = remember { mutableStateListOf<NoteEntry>() }
 | 
			
		||||
 | 
			
		||||
                // Bildauswahl + Dialog-States
 | 
			
		||||
                var selectedUris by remember { mutableStateOf<List<Uri>>(emptyList()) }
 | 
			
		||||
                var showDialog by remember { mutableStateOf(false) }
 | 
			
		||||
 | 
			
		||||
                // Launcher innerhalb von Compose
 | 
			
		||||
                val imagePickerLauncher = rememberLauncherForActivityResult(
 | 
			
		||||
                    contract = ActivityResultContracts.PickMultipleVisualMedia(),
 | 
			
		||||
                    onResult = { uris ->
 | 
			
		||||
                        if (uris.isNotEmpty()) {
 | 
			
		||||
                            selectedUris = uris
 | 
			
		||||
                            showDialog = true
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                // UI anzeigen
 | 
			
		||||
                MainScreen(
 | 
			
		||||
                    notes = notes,
 | 
			
		||||
                    onAddNoteClicked = {
 | 
			
		||||
                        imagePickerLauncher.launch(
 | 
			
		||||
                            PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageAndVideo)
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                // Dialog bei Bedarf
 | 
			
		||||
                if (showDialog) {
 | 
			
		||||
                    AddNoteDialog(
 | 
			
		||||
                        onDismiss = { showDialog = false },
 | 
			
		||||
                        onSave = { title, composer, year, genre, description ->
 | 
			
		||||
                            val copiedUris = selectedUris.mapNotNull { uri ->
 | 
			
		||||
                                try {
 | 
			
		||||
                                    val inputStream: InputStream? = context.contentResolver.openInputStream(uri)
 | 
			
		||||
                                    val outputFile = File(context.filesDir, "note_${System.currentTimeMillis()}_${uri.lastPathSegment}")
 | 
			
		||||
                                    inputStream?.use { input ->
 | 
			
		||||
                                        outputFile.outputStream().use { output ->
 | 
			
		||||
                                            input.copyTo(output)
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
                                    Uri.fromFile(outputFile)
 | 
			
		||||
                                } catch (e: Exception) {
 | 
			
		||||
                                    e.printStackTrace()
 | 
			
		||||
                                    null
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            if (copiedUris.isNotEmpty()) {
 | 
			
		||||
                                notes.add(
 | 
			
		||||
                                    NoteEntry(
 | 
			
		||||
                                        title = title,
 | 
			
		||||
                                        images = copiedUris,
 | 
			
		||||
                                        composer = composer,
 | 
			
		||||
                                        year = year,
 | 
			
		||||
                                        genre = genre,
 | 
			
		||||
                                        description = description
 | 
			
		||||
                                    )
 | 
			
		||||
                                )
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            showDialog = false
 | 
			
		||||
                        }
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -2,9 +2,9 @@ package come.stormborntales.notevault.data.model
 | 
			
		||||
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
 | 
			
		||||
class NoteEntry(images: List<Uri>) {
 | 
			
		||||
    val title: String = "Unbenannt" // oder optional
 | 
			
		||||
    val images: List<Uri> = images;
 | 
			
		||||
 | 
			
		||||
class NoteEntry(
 | 
			
		||||
    val title: String, val images: List<Uri>, val composer: String?, val year: Int?,
 | 
			
		||||
    val genre: String?, val description: String?
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,80 @@
 | 
			
		||||
package come.stormborntales.notevault.ui.screens
 | 
			
		||||
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.material3.AlertDialog
 | 
			
		||||
import androidx.compose.material3.Text
 | 
			
		||||
import androidx.compose.material3.TextButton
 | 
			
		||||
import androidx.compose.material3.OutlinedTextField
 | 
			
		||||
import androidx.compose.runtime.*
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.foundation.layout.height
 | 
			
		||||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun AddNoteDialog(
 | 
			
		||||
    onDismiss: () -> Unit,
 | 
			
		||||
    onSave: (title: String, composer: String?, year: Int?, genre: String?, description: String?) -> Unit
 | 
			
		||||
) {
 | 
			
		||||
    var title by remember { mutableStateOf("") }
 | 
			
		||||
    var composer by remember { mutableStateOf("") }
 | 
			
		||||
    var year by remember { mutableStateOf("") }
 | 
			
		||||
    var genre by remember { mutableStateOf("") }
 | 
			
		||||
    var description by remember { mutableStateOf("") }
 | 
			
		||||
 | 
			
		||||
    AlertDialog(
 | 
			
		||||
        onDismissRequest = onDismiss,
 | 
			
		||||
        title = { Text("Notenblatt hinzufügen") },
 | 
			
		||||
        text = {
 | 
			
		||||
            Column {
 | 
			
		||||
                OutlinedTextField(
 | 
			
		||||
                    value = title,
 | 
			
		||||
                    onValueChange = { title = it },
 | 
			
		||||
                    label = { Text("Titel*") },
 | 
			
		||||
                    singleLine = true
 | 
			
		||||
                )
 | 
			
		||||
                OutlinedTextField(
 | 
			
		||||
                    value = composer,
 | 
			
		||||
                    onValueChange = { composer = it },
 | 
			
		||||
                    label = { Text("Komponist") },
 | 
			
		||||
                    singleLine = true
 | 
			
		||||
                )
 | 
			
		||||
                OutlinedTextField(
 | 
			
		||||
                    value = year,
 | 
			
		||||
                    onValueChange = { year = it },
 | 
			
		||||
                    label = { Text("Erscheinungsjahr") },
 | 
			
		||||
                    singleLine = true
 | 
			
		||||
                )
 | 
			
		||||
                OutlinedTextField(
 | 
			
		||||
                    value = genre,
 | 
			
		||||
                    onValueChange = { genre = it },
 | 
			
		||||
                    label = { Text("Genre") },
 | 
			
		||||
                    singleLine = true
 | 
			
		||||
                )
 | 
			
		||||
                OutlinedTextField(
 | 
			
		||||
                    value = description,
 | 
			
		||||
                    onValueChange = { description = it },
 | 
			
		||||
                    label = { Text("Beschreibung") },
 | 
			
		||||
                    modifier = Modifier.height(100.dp)
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        confirmButton = {
 | 
			
		||||
            TextButton(
 | 
			
		||||
                onClick = {
 | 
			
		||||
                    if (title.isNotBlank()) {
 | 
			
		||||
                        val parsedYear = year.toIntOrNull()
 | 
			
		||||
                        onSave(title, composer.ifBlank { null }, parsedYear, genre.ifBlank { null }, description.ifBlank { null })
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            ) {
 | 
			
		||||
                Text("Speichern")
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        dismissButton = {
 | 
			
		||||
            TextButton(onClick = onDismiss) {
 | 
			
		||||
                Text("Abbrechen")
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user