ADD: Searching for Notes
This commit is contained in:
parent
c3029c062e
commit
ad8e180134
@ -4,10 +4,10 @@
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DropdownSelection timestamp="2025-05-03T08:26:48.052108137Z">
|
||||
<DropdownSelection timestamp="2025-05-03T08:34:29.354537334Z">
|
||||
<Target type="DEFAULT_BOOT">
|
||||
<handle>
|
||||
<DeviceId pluginId="LocalEmulator" identifier="path=/home/sebastian/.android/avd/Small_Phone_API_36.avd" />
|
||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=R52N50NLGRT" />
|
||||
</handle>
|
||||
</Target>
|
||||
</DropdownSelection>
|
||||
|
@ -7,10 +7,15 @@ import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AccountCircle
|
||||
import androidx.compose.material.icons.filled.Menu
|
||||
import androidx.compose.material3.DrawerValue
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
@ -21,15 +26,19 @@ import androidx.compose.material3.NavigationDrawerItem
|
||||
import androidx.compose.material3.NavigationDrawerItemDefaults
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.rememberDrawerState
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
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
|
||||
@ -109,13 +118,69 @@ class MainActivity : ComponentActivity() {
|
||||
) {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
var searchQuery by remember { mutableStateOf("") }
|
||||
var isMenuExpanded by remember { mutableStateOf(false) }
|
||||
|
||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||
val currentRoute = navBackStackEntry?.destination?.route
|
||||
|
||||
TopAppBar(
|
||||
title = { Text("NoteVault") },
|
||||
title = {
|
||||
if(currentRoute == "main") {
|
||||
TextField(
|
||||
value = searchQuery,
|
||||
onValueChange = {
|
||||
searchQuery = it
|
||||
viewModel.searchQuery.value = it
|
||||
},
|
||||
placeholder = { Text("Suche...") },
|
||||
singleLine = true,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(end = 48.dp), // Platz für Avatar
|
||||
textStyle = MaterialTheme.typography.bodyLarge,
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
containerColor = Color.Transparent,
|
||||
unfocusedIndicatorColor = Color.Transparent,
|
||||
focusedIndicatorColor = Color.Transparent
|
||||
)
|
||||
)
|
||||
} else {
|
||||
Text("NoteVault")
|
||||
}
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = {
|
||||
scope.launch { drawerState.open() }
|
||||
}) {
|
||||
Icon(Icons.Default.Menu, contentDescription = "Menu")
|
||||
IconButton(onClick = { scope.launch { drawerState.open() } }) {
|
||||
Icon(Icons.Default.Menu, contentDescription = "Menü öffnen")
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
Box {
|
||||
IconButton(onClick = { isMenuExpanded = true }) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.AccountCircle, // Avatar-Icon
|
||||
contentDescription = "Benutzerprofil"
|
||||
)
|
||||
}
|
||||
DropdownMenu(
|
||||
expanded = isMenuExpanded,
|
||||
onDismissRequest = { isMenuExpanded = false }
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
text = { Text("Profil") },
|
||||
onClick = {
|
||||
isMenuExpanded = false
|
||||
// TODO: Navigiere ggf. zu Profilscreen
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text("Abmelden") },
|
||||
onClick = {
|
||||
isMenuExpanded = false
|
||||
// TODO: Logout-Logik
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -179,7 +244,5 @@ class MainActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -242,7 +242,7 @@ fun MainScreen(
|
||||
viewModel: NoteViewModel,
|
||||
onEditNote: (NoteEntity) -> Unit
|
||||
) {
|
||||
val notes by viewModel.notes.observeAsState(emptyList())
|
||||
val notes by viewModel.filteredNotes.collectAsState(initial = emptyList())
|
||||
Scaffold(
|
||||
floatingActionButton = {
|
||||
FloatingActionButton(
|
||||
|
@ -15,11 +15,34 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
import androidx.core.graphics.scale
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
class NoteViewModel(
|
||||
private val repository: NoteRepository,
|
||||
) : ViewModel() {
|
||||
val notes = repository.allNotes.asLiveData()
|
||||
// Sucheingabe als StateFlow
|
||||
val searchQuery = MutableStateFlow("")
|
||||
|
||||
// Alle Notizen als Flow aus der Datenbank (NICHT blockierend!)
|
||||
private val allNotes: Flow<List<NoteEntity>> = repository.allNotes
|
||||
|
||||
// Gefilterte Notizen basierend auf Sucheingabe
|
||||
val filteredNotes: StateFlow<List<NoteEntity>> = combine(searchQuery, allNotes) { query, notes ->
|
||||
if (query.isBlank()) {
|
||||
notes
|
||||
} else {
|
||||
notes.filter {
|
||||
it.title.contains(query, ignoreCase = true) ||
|
||||
it.description?.contains(query, ignoreCase = true) == true
|
||||
}
|
||||
}
|
||||
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())
|
||||
|
||||
|
||||
fun createPreviewImage(context: Context, uri: Uri): File? {
|
||||
return try {
|
||||
|
Loading…
Reference in New Issue
Block a user