package com.vgmlr.kerf
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.material.icons.outlined.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomeScreen(vm: NoteViewModel, nav: NavHostController) {
val notesList by vm.allNotes.collectAsState()
val ctx = LocalContext.current
val showMenu = remember { mutableStateOf(false) }
val showVersionDialog = remember { mutableStateOf(false) }
val showSearchDialog = remember { mutableStateOf(false) }
val kerfColors = LocalKerfColors.current!!
val listState = rememberLazyListState()
val importLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.OpenDocument()
) { uri ->
uri?.let {
vm.setSharedFile(KerfUtils.importNoteFromUri(ctx, it))
}
}
if (showVersionDialog.value) VersionDialog { showVersionDialog.value = false }
if (showSearchDialog.value) {
SearchDialog(
notes = notesList,
onSelect = { id ->
showSearchDialog.value = false
nav.navigate(KerfScreen.Edit.createRoute(id))
},
onDismiss = { showSearchDialog.value = false }
)
}
Scaffold(
topBar = {
TopAppBar(
title = { },
actions = {
Text(
text = "kerf",
color = MaterialTheme.colorScheme.onPrimary,
fontSize = KerfDimens.TextSizeTitle,
modifier = Modifier.padding(end = KerfDimens.PaddingLarge)
)
IconButton(onClick = { vm.addNote { nav.navigate(KerfScreen.Edit.createRoute(it)) } }) {
Icon(Icons.Default.Add, "New List", tint = MaterialTheme.colorScheme.onPrimary)
}
IconButton(onClick = { showSearchDialog.value = true }) {
Icon(Icons.Default.Search, "Search", tint = MaterialTheme.colorScheme.onPrimary)
}
Box {
IconButton(onClick = { showMenu.value = true }) { Icon(Icons.Default.MoreVert, null, tint = MaterialTheme.colorScheme.onPrimary) }
DropdownMenu(expanded = showMenu.value, onDismissRequest = { showMenu.value = false }, modifier = Modifier.background(kerfColors.menuBackground).padding(horizontal = 6.dp)) {
DropdownMenuItem(
leadingIcon = { Icon(Icons.Outlined.FileOpen, null, tint = kerfColors.menuText) },
text = { Text("Import", color = kerfColors.menuText) },
onClick = {
showMenu.value = false
importLauncher.launch(arrayOf("*/*"))
}
)
DropdownMenuItem(
leadingIcon = { Icon(Icons.Outlined.History, null, tint = kerfColors.menuText) },
text = { Text("Version", color = kerfColors.menuText) },
onClick = { showMenu.value = false; showVersionDialog.value = true }
)
}
}
},
colors = TopAppBarDefaults.topAppBarColors(containerColor = kerfColors.appTopbar)
)
},
containerColor = kerfColors.appTopbar
) { padding ->
Surface(modifier = Modifier.padding(padding).fillMaxSize(), shape = RectangleShape, color = MaterialTheme.colorScheme.background) {
LazyColumn(state = listState, contentPadding = PaddingValues(bottom = KerfDimens.PaddingLarge), modifier = Modifier.fillMaxSize()) {
items(items = notesList, key = { it.id }) { note ->
Card(
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface),
shape = RectangleShape,
modifier = Modifier
.fillMaxWidth()
.clickable { nav.navigate(KerfScreen.Edit.createRoute(note.id)) }
) {
Column {
Box(Modifier.fillMaxWidth().background(kerfColors.noteHeaderMain).padding(horizontal = KerfDimens.PaddingLarge, vertical = 12.dp)) {
Text(
text = note.title.ifBlank { "Untitled" },
fontWeight = FontWeight.Bold,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.align(Alignment.CenterStart)
)
Row(Modifier.align(Alignment.CenterEnd), verticalAlignment = Alignment.CenterVertically) {
if (note.content.length > 3) {
val itemCount = KerfUtils.countNumberedItems(note.content)
Text(text = "$itemCount / ${note.content.length}", color = MaterialTheme.colorScheme.onPrimary, fontSize = KerfDimens.TextSizeMedium)
}
if (note.isPinned) {
Icon(
imageVector = Icons.Outlined.PushPin,
contentDescription = null,
tint = MaterialTheme.colorScheme.onPrimary,
modifier = Modifier.padding(start = 12.dp).size(20.dp)
)
}
IconButton(onClick = { vm.deleteNote(note.id) }, Modifier.padding(start = 8.dp).size(24.dp)) { Icon(Icons.Default.Close, null) }
}
}
Column(Modifier.padding(KerfDimens.PaddingLarge)) {
val visibleLines = note.content.lineSequence().filter { it.isNotBlank() }.toList()
val previewLines = visibleLines.take(7)
previewLines.forEach { line ->
Text(
text = line,
color = MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.fillMaxWidth()
)
}
if (visibleLines.size > 7) {
Text(text = "[more]", color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.fillMaxWidth())
}
}
}
}
HorizontalDivider(color = Color.Gray.copy(0.2f))
}
}
}
}
}