Mengganti Preview deskripsi Note Card dan Note Dialog

This commit is contained in:
202310715082 FAZRI ABDURRAHMAN 2025-12-17 21:35:13 +07:00
parent de163a09f8
commit 900bf8b7ff
7 changed files with 86 additions and 39 deletions

View File

@ -144,7 +144,7 @@
## **Planned Features (v1.1.0)** ## **Planned Features (v1.1.0)**
* Backup & restore data * Backup & restore data
* Tags untuk catatan * Mengganti Preview deskripsi Note Card dan Note Dialog (ok)
* Rich text editor * Rich text editor
* Dark theme toggle * Dark theme toggle
* Multi-language support * Multi-language support

View File

@ -445,13 +445,13 @@ fun NotesApp() {
showNoteDialog = false showNoteDialog = false
editingNote = null editingNote = null
}, },
onSave = { title, content -> onSave = { title, description ->
if (editingNote != null) { if (editingNote != null) {
notes = notes.map { notes = notes.map {
if (it.id == editingNote!!.id) if (it.id == editingNote!!.id)
it.copy( it.copy(
title = title, title = title,
content = content, description = description,
timestamp = System.currentTimeMillis() timestamp = System.currentTimeMillis()
) )
else it else it
@ -460,11 +460,14 @@ fun NotesApp() {
notes = notes + Note( notes = notes + Note(
categoryId = selectedCategory!!.id, categoryId = selectedCategory!!.id,
title = title, title = title,
content = content description = description,
content = "" // Content kosong, akan diisi di EditableFullScreenNoteView
) )
} }
showNoteDialog = false showNoteDialog = false
editingNote = null editingNote = null
showNoteDialog = false
editingNote = null
}, },
onDelete = if (editingNote != null) { onDelete = if (editingNote != null) {
{ {

View File

@ -28,7 +28,8 @@ data class SerializableCategory(
val name: String, val name: String,
val gradientStart: Long, val gradientStart: Long,
val gradientEnd: Long, val gradientEnd: Long,
val timestamp: Long val timestamp: Long,
val isDeleted: Boolean = false // Support untuk soft delete
) )
@Serializable @Serializable
@ -36,11 +37,12 @@ data class SerializableNote(
val id: String, val id: String,
val categoryId: String, val categoryId: String,
val title: String, val title: String,
val content: String, val description: String = "", // Field baru untuk v1.1.0
val content: String = "",
val timestamp: Long, val timestamp: Long,
val isArchived: Boolean, val isArchived: Boolean = false,
val isDeleted: Boolean, val isDeleted: Boolean = false,
val isPinned: Boolean val isPinned: Boolean = false
) )
class DataStoreManager(private val context: Context) { class DataStoreManager(private val context: Context) {
@ -50,7 +52,7 @@ class DataStoreManager(private val context: Context) {
} }
private val json = Json { private val json = Json {
ignoreUnknownKeys = true ignoreUnknownKeys = true // Penting untuk backward compatibility
encodeDefaults = true encodeDefaults = true
} }
@ -66,9 +68,17 @@ class DataStoreManager(private val context: Context) {
val jsonString = preferences[CATEGORIES_KEY] ?: "[]" val jsonString = preferences[CATEGORIES_KEY] ?: "[]"
try { try {
json.decodeFromString<List<SerializableCategory>>(jsonString).map { json.decodeFromString<List<SerializableCategory>>(jsonString).map {
Category(it.id, it.name, it.gradientStart, it.gradientEnd, it.timestamp) Category(
id = it.id,
name = it.name,
gradientStart = it.gradientStart,
gradientEnd = it.gradientEnd,
timestamp = it.timestamp,
isDeleted = it.isDeleted
)
} }
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace()
emptyList() emptyList()
} }
} }
@ -86,17 +96,19 @@ class DataStoreManager(private val context: Context) {
try { try {
json.decodeFromString<List<SerializableNote>>(jsonString).map { json.decodeFromString<List<SerializableNote>>(jsonString).map {
Note( Note(
it.id, id = it.id,
it.categoryId, categoryId = it.categoryId,
it.title, title = it.title,
it.content, description = it.description, // Support field baru
it.timestamp, content = it.content,
it.isArchived, timestamp = it.timestamp,
it.isDeleted, isPinned = it.isPinned,
it.isPinned isArchived = it.isArchived,
isDeleted = it.isDeleted
) )
} }
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace()
emptyList() emptyList()
} }
} }
@ -105,7 +117,14 @@ class DataStoreManager(private val context: Context) {
try { try {
context.dataStore.edit { preferences -> context.dataStore.edit { preferences ->
val serializable = categories.map { val serializable = categories.map {
SerializableCategory(it.id, it.name, it.gradientStart, it.gradientEnd, it.timestamp) SerializableCategory(
id = it.id,
name = it.name,
gradientStart = it.gradientStart,
gradientEnd = it.gradientEnd,
timestamp = it.timestamp,
isDeleted = it.isDeleted
)
} }
preferences[CATEGORIES_KEY] = json.encodeToString(serializable) preferences[CATEGORIES_KEY] = json.encodeToString(serializable)
} }
@ -118,7 +137,17 @@ class DataStoreManager(private val context: Context) {
try { try {
context.dataStore.edit { preferences -> context.dataStore.edit { preferences ->
val serializable = notes.map { val serializable = notes.map {
SerializableNote(it.id, it.categoryId, it.title, it.content, it.timestamp, it.isArchived, it.isDeleted, it.isPinned) SerializableNote(
id = it.id,
categoryId = it.categoryId,
title = it.title,
description = it.description, // Support field baru
content = it.content,
timestamp = it.timestamp,
isPinned = it.isPinned,
isArchived = it.isArchived,
isDeleted = it.isDeleted
)
} }
preferences[NOTES_KEY] = json.encodeToString(serializable) preferences[NOTES_KEY] = json.encodeToString(serializable)
} }

View File

@ -1,13 +1,14 @@
// File: data/model/Category.kt
package com.example.notesai.data.model package com.example.notesai.data.model
import kotlinx.serialization.Serializable
import java.util.UUID import java.util.UUID
@Serializable
data class Category( data class Category(
val id: String = UUID.randomUUID().toString(), val id: String = UUID.randomUUID().toString(),
val name: String, val name: String,
val gradientStart: Long, val gradientStart: Long,
val gradientEnd: Long, val gradientEnd: Long,
val timestamp: Long = System.currentTimeMillis(), val timestamp: Long = System.currentTimeMillis(),
val isDeleted: Boolean = false // TAMBAHKAN INI val isDeleted: Boolean = false // Support soft delete
) )

View File

@ -1,15 +1,17 @@
// File: data/model/Note.kt
package com.example.notesai.data.model package com.example.notesai.data.model
import kotlinx.serialization.Serializable
import java.util.UUID import java.util.UUID
@Serializable
data class Note( data class Note(
val id: String = UUID.randomUUID().toString(), val id: String = UUID.randomUUID().toString(),
val categoryId: String, val categoryId: String,
val title: String, val title: String,
val content: String, val description: String = "", // Field baru untuk preview di NoteCard
val content: String = "", // Konten lengkap untuk EditableFullScreenNoteView
val timestamp: Long = System.currentTimeMillis(), val timestamp: Long = System.currentTimeMillis(),
val isPinned: Boolean = false,
val isArchived: Boolean = false, val isArchived: Boolean = false,
val isDeleted: Boolean = false, val isDeleted: Boolean = false
val isPinned: Boolean = false
) )

View File

@ -35,7 +35,7 @@ fun NoteDialog(
onDelete: (() -> Unit)? onDelete: (() -> Unit)?
) { ) {
var title by remember { mutableStateOf(note?.title ?: "") } var title by remember { mutableStateOf(note?.title ?: "") }
var content by remember { mutableStateOf(note?.content ?: "") } var description by remember { mutableStateOf(note?.description ?: "") }
AlertDialog( AlertDialog(
onDismissRequest = onDismiss, onDismissRequest = onDismiss,
@ -69,13 +69,14 @@ fun NoteDialog(
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))
OutlinedTextField( OutlinedTextField(
value = content, value = description,
onValueChange = { content = it }, onValueChange = { description = it },
label = { Text("Isi Catatan", color = Color(0xFF94A3B8)) }, label = { Text("Deskripsi", color = Color(0xFF94A3B8)) },
placeholder = { Text("Tambahkan deskripsi singkat...", color = Color(0xFF64748B)) },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.height(200.dp), .height(120.dp),
maxLines = 10, maxLines = 5,
colors = TextFieldDefaults.colors( colors = TextFieldDefaults.colors(
focusedTextColor = Color.White, focusedTextColor = Color.White,
unfocusedTextColor = Color.White, unfocusedTextColor = Color.White,
@ -98,7 +99,7 @@ fun NoteDialog(
Spacer(modifier = Modifier.width(8.dp)) Spacer(modifier = Modifier.width(8.dp))
} }
Button( Button(
onClick = { if (title.isNotBlank()) onSave(title, content) }, onClick = { if (title.isNotBlank()) onSave(title, description) },
enabled = title.isNotBlank(), enabled = title.isNotBlank(),
colors = ButtonDefaults.buttonColors( colors = ButtonDefaults.buttonColors(
containerColor = Color.Transparent containerColor = Color.Transparent

View File

@ -51,7 +51,7 @@ fun NoteCard(
.combinedClickable(onClick = onClick), .combinedClickable(onClick = onClick),
shape = RoundedCornerShape(16.dp), shape = RoundedCornerShape(16.dp),
colors = CardDefaults.cardColors( colors = CardDefaults.cardColors(
containerColor = Constants.AppColors.SurfaceVariant // Lebih terang dari Surface containerColor = Constants.AppColors.SurfaceVariant
), ),
elevation = CardDefaults.cardElevation( elevation = CardDefaults.cardElevation(
defaultElevation = 2.dp defaultElevation = 2.dp
@ -94,19 +94,30 @@ fun NoteCard(
} }
} }
// Content Preview // Deskripsi Preview
if (note.content.isNotEmpty()) { if (note.description.isNotEmpty()) {
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))
Text( Text(
note.content, note.description,
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
maxLines = 4, maxLines = 3,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
color = Constants.AppColors.OnSurfaceVariant, color = Constants.AppColors.OnSurfaceVariant,
lineHeight = 20.sp, lineHeight = 20.sp,
fontSize = 14.sp fontSize = 14.sp
) )
} else {
// Tampilkan placeholder jika deskripsi kosong
Spacer(modifier = Modifier.height(12.dp))
Text(
"Tidak ada deskripsi",
style = MaterialTheme.typography.bodyMedium,
color = Constants.AppColors.OnSurfaceVariant.copy(alpha = 0.5f),
fontStyle = androidx.compose.ui.text.font.FontStyle.Italic,
fontSize = 14.sp
)
} }
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))