Menambahkan Dark/Light theme toggle
This commit is contained in:
parent
0876c82abc
commit
1b5e79166c
4
.idea/deploymentTargetSelector.xml
generated
4
.idea/deploymentTargetSelector.xml
generated
@ -4,10 +4,10 @@
|
|||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DropdownSelection timestamp="2025-12-13T07:41:36.634314200Z">
|
<DropdownSelection timestamp="2025-12-18T02:27:11.898714800Z">
|
||||||
<Target type="DEFAULT_BOOT">
|
<Target type="DEFAULT_BOOT">
|
||||||
<handle>
|
<handle>
|
||||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=RR8T103A6JZ" />
|
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\Fazri Abdurrahman\.android\avd\Medium_Tablet.avd" />
|
||||||
</handle>
|
</handle>
|
||||||
</Target>
|
</Target>
|
||||||
</DropdownSelection>
|
</DropdownSelection>
|
||||||
|
|||||||
@ -39,11 +39,13 @@ import com.example.notesai.data.model.Note
|
|||||||
import com.example.notesai.data.model.Category
|
import com.example.notesai.data.model.Category
|
||||||
import com.example.notesai.util.updateWhere
|
import com.example.notesai.util.updateWhere
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
import com.example.notesai.util.AppColors
|
||||||
|
|
||||||
// File: MainActivity.kt (Bagian Theme Setup)
|
// File: MainActivity.kt (Bagian Theme Setup)
|
||||||
// Ganti MaterialTheme di setContent dengan ini:
|
// Ganti MaterialTheme di setContent dengan ini:
|
||||||
|
|
||||||
import com.example.notesai.util.Constants
|
import com.example.notesai.util.Constants
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@ -52,34 +54,34 @@ class MainActivity : ComponentActivity() {
|
|||||||
MaterialTheme(
|
MaterialTheme(
|
||||||
colorScheme = darkColorScheme(
|
colorScheme = darkColorScheme(
|
||||||
// Primary colors
|
// Primary colors
|
||||||
primary = Constants.AppColors.Primary,
|
primary = AppColors.Primary,
|
||||||
onPrimary = Color.White,
|
onPrimary = Color.White,
|
||||||
primaryContainer = Constants.AppColors.PrimaryContainer,
|
primaryContainer = AppColors.PrimaryContainer,
|
||||||
onPrimaryContainer = Color.White,
|
onPrimaryContainer = Color.White,
|
||||||
|
|
||||||
// Secondary colors
|
// Secondary colors
|
||||||
secondary = Constants.AppColors.Secondary,
|
secondary = AppColors.Secondary,
|
||||||
onSecondary = Color.White,
|
onSecondary = Color.White,
|
||||||
secondaryContainer = Constants.AppColors.SecondaryVariant,
|
secondaryContainer = AppColors.SecondaryVariant,
|
||||||
onSecondaryContainer = Color.White,
|
onSecondaryContainer = Color.White,
|
||||||
|
|
||||||
// Background colors
|
// Background colors
|
||||||
background = Constants.AppColors.Background,
|
background = AppColors.Background,
|
||||||
onBackground = Constants.AppColors.OnBackground,
|
onBackground = AppColors.OnBackground,
|
||||||
|
|
||||||
// Surface colors
|
// Surface colors
|
||||||
surface = Constants.AppColors.Surface,
|
surface = AppColors.Surface,
|
||||||
onSurface = Constants.AppColors.OnSurface,
|
onSurface = AppColors.OnSurface,
|
||||||
surfaceVariant = Constants.AppColors.SurfaceVariant,
|
surfaceVariant = AppColors.SurfaceVariant,
|
||||||
onSurfaceVariant = Constants.AppColors.OnSurfaceVariant,
|
onSurfaceVariant = AppColors.OnSurfaceVariant,
|
||||||
|
|
||||||
// Error colors
|
// Error colors
|
||||||
error = Constants.AppColors.Error,
|
error = AppColors.Error,
|
||||||
onError = Color.White,
|
onError = Color.White,
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
outline = Constants.AppColors.Border,
|
outline = AppColors.Border,
|
||||||
outlineVariant = Constants.AppColors.Divider
|
outlineVariant = AppColors.Divider
|
||||||
),
|
),
|
||||||
typography = Typography(
|
typography = Typography(
|
||||||
// Improve typography for better readability
|
// Improve typography for better readability
|
||||||
@ -131,6 +133,17 @@ fun NotesApp() {
|
|||||||
var showFullScreenNote by remember { mutableStateOf(false) }
|
var showFullScreenNote by remember { mutableStateOf(false) }
|
||||||
var fullScreenNote by remember { mutableStateOf<Note?>(null) }
|
var fullScreenNote by remember { mutableStateOf<Note?>(null) }
|
||||||
|
|
||||||
|
// Theme state
|
||||||
|
var isDarkTheme by remember { mutableStateOf(true) }
|
||||||
|
|
||||||
|
// Load theme preference - SET THEME HERE
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
dataStoreManager.themeFlow.collect { theme ->
|
||||||
|
isDarkTheme = theme == "dark"
|
||||||
|
AppColors.setTheme(isDarkTheme) // SET GLOBAL THEME
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Load data dari DataStore
|
// Load data dari DataStore
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
try {
|
try {
|
||||||
@ -176,12 +189,10 @@ fun NotesApp() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Provide theme colors
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
// Di MainActivity.kt, ubah bagian topBar menjadi:
|
|
||||||
|
|
||||||
topBar = {
|
topBar = {
|
||||||
// Hide TopBar untuk AI Helper screen dan FullScreen Note
|
|
||||||
if (!showFullScreenNote && currentScreen != "ai") {
|
if (!showFullScreenNote && currentScreen != "ai") {
|
||||||
ModernTopBar(
|
ModernTopBar(
|
||||||
title = when(currentScreen) {
|
title = when(currentScreen) {
|
||||||
@ -210,12 +221,7 @@ fun NotesApp() {
|
|||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = currentScreen == "main" && !showFullScreenNote,
|
visible = currentScreen == "main" && !showFullScreenNote,
|
||||||
enter = scaleIn(
|
enter = scaleIn() + fadeIn(),
|
||||||
animationSpec = spring(
|
|
||||||
dampingRatio = Spring.DampingRatioMediumBouncy,
|
|
||||||
stiffness = Spring.StiffnessLow
|
|
||||||
)
|
|
||||||
) + fadeIn(),
|
|
||||||
exit = scaleOut() + fadeOut()
|
exit = scaleOut() + fadeOut()
|
||||||
) {
|
) {
|
||||||
FloatingActionButton(
|
FloatingActionButton(
|
||||||
@ -227,19 +233,10 @@ fun NotesApp() {
|
|||||||
showCategoryDialog = true
|
showCategoryDialog = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
containerColor = Constants.AppColors.Primary,
|
containerColor = AppColors.Primary,
|
||||||
contentColor = Color.White,
|
contentColor = Color.White
|
||||||
elevation = FloatingActionButtonDefaults.elevation(
|
|
||||||
defaultElevation = 8.dp,
|
|
||||||
pressedElevation = 12.dp
|
|
||||||
),
|
|
||||||
modifier = Modifier.size(64.dp)
|
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(Icons.Default.Add, contentDescription = "Add")
|
||||||
Icons.Default.Add,
|
|
||||||
contentDescription = if (selectedCategory != null) "Tambah Catatan" else "Tambah Kategori",
|
|
||||||
modifier = Modifier.size(28.dp)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -254,7 +251,8 @@ fun NotesApp() {
|
|||||||
onAIClick = { currentScreen = "ai" }
|
onAIClick = { currentScreen = "ai" }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
containerColor = AppColors.Background // SET BACKGROUND HERE
|
||||||
) { padding ->
|
) { padding ->
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
if (showFullScreenNote && fullScreenNote != null) {
|
if (showFullScreenNote && fullScreenNote != null) {
|
||||||
@ -486,19 +484,15 @@ fun NotesApp() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drawer with Animation - DI LUAR SCAFFOLD agar di atas semua
|
// Drawer with theme toggle
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = drawerState,
|
visible = drawerState,
|
||||||
enter = fadeIn() + slideInHorizontally(
|
enter = fadeIn() + slideInHorizontally { -it },
|
||||||
initialOffsetX = { -it }
|
exit = fadeOut() + slideOutHorizontally { -it }
|
||||||
),
|
|
||||||
exit = fadeOut() + slideOutHorizontally(
|
|
||||||
targetOffsetX = { -it }
|
|
||||||
),
|
|
||||||
modifier = Modifier.zIndex(100f) // Z-index tinggi
|
|
||||||
) {
|
) {
|
||||||
DrawerMenu(
|
DrawerMenu(
|
||||||
currentScreen = currentScreen,
|
currentScreen = currentScreen,
|
||||||
|
isDarkTheme = isDarkTheme,
|
||||||
onDismiss = { drawerState = false },
|
onDismiss = { drawerState = false },
|
||||||
onItemClick = { screen ->
|
onItemClick = { screen ->
|
||||||
currentScreen = screen
|
currentScreen = screen
|
||||||
@ -506,9 +500,15 @@ fun NotesApp() {
|
|||||||
drawerState = false
|
drawerState = false
|
||||||
showSearch = false
|
showSearch = false
|
||||||
searchQuery = ""
|
searchQuery = ""
|
||||||
|
},
|
||||||
|
onThemeToggle = {
|
||||||
|
isDarkTheme = !isDarkTheme
|
||||||
|
AppColors.setTheme(isDarkTheme) // UPDATE THEME
|
||||||
|
scope.launch {
|
||||||
|
dataStoreManager.saveTheme(if (isDarkTheme) "dark" else "light")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -50,7 +50,8 @@ class DataStoreManager(private val context: Context) {
|
|||||||
companion object {
|
companion object {
|
||||||
val CATEGORIES_KEY = stringPreferencesKey("categories")
|
val CATEGORIES_KEY = stringPreferencesKey("categories")
|
||||||
val NOTES_KEY = stringPreferencesKey("notes")
|
val NOTES_KEY = stringPreferencesKey("notes")
|
||||||
val CHAT_HISTORY_KEY = stringPreferencesKey("chat_history") // NEW
|
val CHAT_HISTORY_KEY = stringPreferencesKey("chat_history")
|
||||||
|
val THEME_KEY = stringPreferencesKey("theme") // NEW: "dark" or "light"
|
||||||
}
|
}
|
||||||
|
|
||||||
private val json = Json {
|
private val json = Json {
|
||||||
@ -219,4 +220,28 @@ class DataStoreManager(private val context: Context) {
|
|||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NEW: Theme Preference Flow
|
||||||
|
val themeFlow: Flow<String> = context.dataStore.data
|
||||||
|
.catch { exception ->
|
||||||
|
if (exception is IOException) {
|
||||||
|
emit(emptyPreferences())
|
||||||
|
} else {
|
||||||
|
throw exception
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.map { preferences ->
|
||||||
|
preferences[THEME_KEY] ?: "dark" // Default dark theme
|
||||||
|
}
|
||||||
|
|
||||||
|
// NEW: Save Theme Preference
|
||||||
|
suspend fun saveTheme(theme: String) {
|
||||||
|
try {
|
||||||
|
context.dataStore.edit { preferences ->
|
||||||
|
preferences[THEME_KEY] = theme
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,8 +1,11 @@
|
|||||||
package com.example.notesai.data.model
|
package com.example.notesai.data.model
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
//noinspection UnsafeOptInUsageError
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
|
@SuppressLint("UnsafeOptInUsageError")
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Note(
|
data class Note(
|
||||||
val id: String = UUID.randomUUID().toString(),
|
val id: String = UUID.randomUUID().toString(),
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import androidx.compose.ui.unit.sp
|
|||||||
import com.example.notesai.data.model.ChatHistory
|
import com.example.notesai.data.model.ChatHistory
|
||||||
import com.example.notesai.data.model.Category
|
import com.example.notesai.data.model.Category
|
||||||
import com.example.notesai.data.model.Note
|
import com.example.notesai.data.model.Note
|
||||||
|
import com.example.notesai.util.AppColors
|
||||||
import com.example.notesai.util.Constants
|
import com.example.notesai.util.Constants
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -56,7 +57,7 @@ fun ChatHistoryDrawer(
|
|||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(Constants.AppColors.Overlay)
|
.background(AppColors.Overlay)
|
||||||
.clickable(
|
.clickable(
|
||||||
onClick = onDismiss,
|
onClick = onDismiss,
|
||||||
indication = null,
|
indication = null,
|
||||||
@ -74,7 +75,7 @@ fun ChatHistoryDrawer(
|
|||||||
indication = null,
|
indication = null,
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
),
|
),
|
||||||
color = Constants.AppColors.Surface,
|
color = AppColors.Surface,
|
||||||
shadowElevation = Constants.Elevation.ExtraLarge.dp
|
shadowElevation = Constants.Elevation.ExtraLarge.dp
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
@ -87,7 +88,7 @@ fun ChatHistoryDrawer(
|
|||||||
.background(
|
.background(
|
||||||
brush = Brush.verticalGradient(
|
brush = Brush.verticalGradient(
|
||||||
colors = listOf(
|
colors = listOf(
|
||||||
Constants.AppColors.Primary.copy(alpha = 0.15f),
|
AppColors.Primary.copy(alpha = 0.15f),
|
||||||
Color.Transparent
|
Color.Transparent
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -103,7 +104,7 @@ fun ChatHistoryDrawer(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(48.dp)
|
.size(48.dp)
|
||||||
.background(
|
.background(
|
||||||
color = Constants.AppColors.Primary.copy(alpha = 0.2f),
|
color = AppColors.Primary.copy(alpha = 0.2f),
|
||||||
shape = RoundedCornerShape(Constants.Radius.Medium.dp)
|
shape = RoundedCornerShape(Constants.Radius.Medium.dp)
|
||||||
),
|
),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
@ -111,7 +112,7 @@ fun ChatHistoryDrawer(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.History,
|
Icons.Default.History,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.Primary,
|
tint = AppColors.Primary,
|
||||||
modifier = Modifier.size(24.dp)
|
modifier = Modifier.size(24.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -119,7 +120,7 @@ fun ChatHistoryDrawer(
|
|||||||
Text(
|
Text(
|
||||||
"Riwayat Chat",
|
"Riwayat Chat",
|
||||||
style = MaterialTheme.typography.headlineSmall,
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
color = Constants.AppColors.OnBackground,
|
color = AppColors.OnBackground,
|
||||||
fontWeight = FontWeight.Bold
|
fontWeight = FontWeight.Bold
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -129,7 +130,7 @@ fun ChatHistoryDrawer(
|
|||||||
Text(
|
Text(
|
||||||
"${chatHistories.size} percakapan tersimpan",
|
"${chatHistories.size} percakapan tersimpan",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = Constants.AppColors.OnSurfaceVariant
|
color = AppColors.OnSurfaceVariant
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,7 +146,7 @@ fun ChatHistoryDrawer(
|
|||||||
Text(
|
Text(
|
||||||
"Filter Kategori",
|
"Filter Kategori",
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = MaterialTheme.typography.labelMedium,
|
||||||
color = Constants.AppColors.OnSurfaceTertiary,
|
color = AppColors.OnSurfaceTertiary,
|
||||||
fontSize = 12.sp
|
fontSize = 12.sp
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -156,7 +157,7 @@ fun ChatHistoryDrawer(
|
|||||||
onClick = { showCategoryDropdown = !showCategoryDropdown },
|
onClick = { showCategoryDropdown = !showCategoryDropdown },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
colors = CardDefaults.cardColors(
|
colors = CardDefaults.cardColors(
|
||||||
containerColor = Constants.AppColors.SurfaceVariant
|
containerColor = AppColors.SurfaceVariant
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(12.dp)
|
shape = RoundedCornerShape(12.dp)
|
||||||
) {
|
) {
|
||||||
@ -174,12 +175,12 @@ fun ChatHistoryDrawer(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Folder,
|
Icons.Default.Folder,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.Primary,
|
tint = AppColors.Primary,
|
||||||
modifier = Modifier.size(18.dp)
|
modifier = Modifier.size(18.dp)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
selectedCategory?.name ?: "Semua Kategori",
|
selectedCategory?.name ?: "Semua Kategori",
|
||||||
color = Constants.AppColors.OnSurface,
|
color = AppColors.OnSurface,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
fontSize = 14.sp
|
fontSize = 14.sp
|
||||||
@ -188,7 +189,7 @@ fun ChatHistoryDrawer(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.ArrowDropDown,
|
Icons.Default.ArrowDropDown,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.OnSurfaceVariant
|
tint = AppColors.OnSurfaceVariant
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -198,7 +199,7 @@ fun ChatHistoryDrawer(
|
|||||||
onDismissRequest = { showCategoryDropdown = false },
|
onDismissRequest = { showCategoryDropdown = false },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(280.dp)
|
.width(280.dp)
|
||||||
.background(Constants.AppColors.SurfaceElevated)
|
.background(AppColors.SurfaceElevated)
|
||||||
) {
|
) {
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = {
|
text = {
|
||||||
@ -209,12 +210,12 @@ fun ChatHistoryDrawer(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Folder,
|
Icons.Default.Folder,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.OnSurfaceVariant,
|
tint = AppColors.OnSurfaceVariant,
|
||||||
modifier = Modifier.size(18.dp)
|
modifier = Modifier.size(18.dp)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
"Semua Kategori",
|
"Semua Kategori",
|
||||||
color = Constants.AppColors.OnSurface
|
color = AppColors.OnSurface
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -228,7 +229,7 @@ fun ChatHistoryDrawer(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Check,
|
Icons.Default.Check,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.Primary,
|
tint = AppColors.Primary,
|
||||||
modifier = Modifier.size(20.dp)
|
modifier = Modifier.size(20.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -236,7 +237,7 @@ fun ChatHistoryDrawer(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (categoriesWithNotes.isNotEmpty()) {
|
if (categoriesWithNotes.isNotEmpty()) {
|
||||||
HorizontalDivider(color = Constants.AppColors.Divider)
|
HorizontalDivider(color = AppColors.Divider)
|
||||||
}
|
}
|
||||||
|
|
||||||
categoriesWithNotes.forEach { category ->
|
categoriesWithNotes.forEach { category ->
|
||||||
@ -263,12 +264,12 @@ fun ChatHistoryDrawer(
|
|||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
category.name,
|
category.name,
|
||||||
color = Constants.AppColors.OnSurface
|
color = AppColors.OnSurface
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Surface(
|
Surface(
|
||||||
color = Constants.AppColors.Primary.copy(alpha = 0.15f),
|
color = AppColors.Primary.copy(alpha = 0.15f),
|
||||||
shape = RoundedCornerShape(Constants.Radius.Small.dp)
|
shape = RoundedCornerShape(Constants.Radius.Small.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
@ -277,7 +278,7 @@ fun ChatHistoryDrawer(
|
|||||||
horizontal = 8.dp,
|
horizontal = 8.dp,
|
||||||
vertical = 2.dp
|
vertical = 2.dp
|
||||||
),
|
),
|
||||||
color = Constants.AppColors.Primary,
|
color = AppColors.Primary,
|
||||||
fontSize = 11.sp,
|
fontSize = 11.sp,
|
||||||
fontWeight = FontWeight.Bold
|
fontWeight = FontWeight.Bold
|
||||||
)
|
)
|
||||||
@ -294,7 +295,7 @@ fun ChatHistoryDrawer(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Check,
|
Icons.Default.Check,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.Primary,
|
tint = AppColors.Primary,
|
||||||
modifier = Modifier.size(20.dp)
|
modifier = Modifier.size(20.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -308,7 +309,7 @@ fun ChatHistoryDrawer(
|
|||||||
Spacer(modifier = Modifier.height(Constants.Spacing.Medium.dp))
|
Spacer(modifier = Modifier.height(Constants.Spacing.Medium.dp))
|
||||||
|
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
color = Constants.AppColors.Divider,
|
color = AppColors.Divider,
|
||||||
modifier = Modifier.padding(horizontal = Constants.Spacing.Large.dp)
|
modifier = Modifier.padding(horizontal = Constants.Spacing.Large.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -335,18 +336,18 @@ fun ChatHistoryDrawer(
|
|||||||
Icons.Default.ChatBubbleOutline,
|
Icons.Default.ChatBubbleOutline,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.size(48.dp),
|
modifier = Modifier.size(48.dp),
|
||||||
tint = Constants.AppColors.OnSurfaceVariant
|
tint = AppColors.OnSurfaceVariant
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
"Belum ada riwayat chat",
|
"Belum ada riwayat chat",
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color = Constants.AppColors.OnSurfaceVariant,
|
color = AppColors.OnSurfaceVariant,
|
||||||
fontWeight = FontWeight.Medium
|
fontWeight = FontWeight.Medium
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
"Mulai chat dengan AI",
|
"Mulai chat dengan AI",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = Constants.AppColors.OnSurfaceTertiary
|
color = AppColors.OnSurfaceTertiary
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -368,19 +369,19 @@ fun ChatHistoryDrawer(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Folder,
|
Icons.Default.Folder,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.Primary,
|
tint = AppColors.Primary,
|
||||||
modifier = Modifier.size(16.dp)
|
modifier = Modifier.size(16.dp)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
categoryInfo.second,
|
categoryInfo.second,
|
||||||
style = MaterialTheme.typography.labelLarge,
|
style = MaterialTheme.typography.labelLarge,
|
||||||
color = Constants.AppColors.OnSurfaceVariant,
|
color = AppColors.OnSurfaceVariant,
|
||||||
fontWeight = FontWeight.SemiBold,
|
fontWeight = FontWeight.SemiBold,
|
||||||
fontSize = 13.sp
|
fontSize = 13.sp
|
||||||
)
|
)
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
color = Constants.AppColors.Divider
|
color = AppColors.Divider
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -413,7 +414,7 @@ private fun ChatHistoryItem(
|
|||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
colors = CardDefaults.cardColors(
|
colors = CardDefaults.cardColors(
|
||||||
containerColor = Constants.AppColors.SurfaceVariant
|
containerColor = AppColors.SurfaceVariant
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(Constants.Radius.Medium.dp)
|
shape = RoundedCornerShape(Constants.Radius.Medium.dp)
|
||||||
) {
|
) {
|
||||||
@ -429,7 +430,7 @@ private fun ChatHistoryItem(
|
|||||||
) {
|
) {
|
||||||
// Message Count
|
// Message Count
|
||||||
Surface(
|
Surface(
|
||||||
color = Constants.AppColors.Primary.copy(alpha = 0.15f),
|
color = AppColors.Primary.copy(alpha = 0.15f),
|
||||||
shape = RoundedCornerShape(Constants.Radius.Small.dp)
|
shape = RoundedCornerShape(Constants.Radius.Small.dp)
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
@ -443,12 +444,12 @@ private fun ChatHistoryItem(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Chat,
|
Icons.Default.Chat,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.Primary,
|
tint = AppColors.Primary,
|
||||||
modifier = Modifier.size(12.dp)
|
modifier = Modifier.size(12.dp)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
"${history.messages.size}",
|
"${history.messages.size}",
|
||||||
color = Constants.AppColors.Primary,
|
color = AppColors.Primary,
|
||||||
fontSize = 11.sp,
|
fontSize = 11.sp,
|
||||||
fontWeight = FontWeight.Bold
|
fontWeight = FontWeight.Bold
|
||||||
)
|
)
|
||||||
@ -463,7 +464,7 @@ private fun ChatHistoryItem(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Delete,
|
Icons.Default.Delete,
|
||||||
contentDescription = "Delete",
|
contentDescription = "Delete",
|
||||||
tint = Constants.AppColors.Error,
|
tint = AppColors.Error,
|
||||||
modifier = Modifier.size(18.dp)
|
modifier = Modifier.size(18.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -475,7 +476,7 @@ private fun ChatHistoryItem(
|
|||||||
Text(
|
Text(
|
||||||
history.lastMessagePreview,
|
history.lastMessagePreview,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color = Constants.AppColors.OnSurface,
|
color = AppColors.OnSurface,
|
||||||
maxLines = 2,
|
maxLines = 2,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
fontSize = 14.sp
|
fontSize = 14.sp
|
||||||
@ -487,7 +488,7 @@ private fun ChatHistoryItem(
|
|||||||
Text(
|
Text(
|
||||||
dateFormat.format(Date(history.timestamp)),
|
dateFormat.format(Date(history.timestamp)),
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = Constants.AppColors.OnSurfaceTertiary,
|
color = AppColors.OnSurfaceTertiary,
|
||||||
fontSize = 12.sp
|
fontSize = 12.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -501,7 +502,7 @@ private fun ChatHistoryItem(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.DeleteForever,
|
Icons.Default.DeleteForever,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.Error
|
tint = AppColors.Error
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
title = {
|
title = {
|
||||||
@ -520,7 +521,7 @@ private fun ChatHistoryItem(
|
|||||||
showDeleteConfirm = false
|
showDeleteConfirm = false
|
||||||
},
|
},
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
containerColor = Constants.AppColors.Error
|
containerColor = AppColors.Error
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Text("Hapus")
|
Text("Hapus")
|
||||||
@ -531,7 +532,7 @@ private fun ChatHistoryItem(
|
|||||||
Text("Batal")
|
Text("Batal")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
containerColor = Constants.AppColors.SurfaceElevated
|
containerColor = AppColors.SurfaceElevated
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -24,18 +24,22 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.example.notesai.util.Constants
|
import com.example.notesai.util.Constants
|
||||||
|
import com.example.notesai.util.AppColors
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DrawerMenu(
|
fun DrawerMenu(
|
||||||
currentScreen: String,
|
currentScreen: String,
|
||||||
|
isDarkTheme: Boolean,
|
||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
onItemClick: (String) -> Unit
|
onItemClick: (String) -> Unit,
|
||||||
|
onThemeToggle: () -> Unit
|
||||||
) {
|
) {
|
||||||
// Backdrop with blur effect
|
// Backdrop with blur effect
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(Constants.AppColors.Overlay)
|
.background(AppColors.Overlay)
|
||||||
.clickable(
|
.clickable(
|
||||||
onClick = onDismiss,
|
onClick = onDismiss,
|
||||||
indication = null,
|
indication = null,
|
||||||
@ -53,7 +57,7 @@ fun DrawerMenu(
|
|||||||
indication = null,
|
indication = null,
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
),
|
),
|
||||||
color = Constants.AppColors.Surface,
|
color = AppColors.Surface,
|
||||||
shadowElevation = Constants.Elevation.ExtraLarge.dp
|
shadowElevation = Constants.Elevation.ExtraLarge.dp
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
@ -66,7 +70,7 @@ fun DrawerMenu(
|
|||||||
.background(
|
.background(
|
||||||
brush = Brush.verticalGradient(
|
brush = Brush.verticalGradient(
|
||||||
colors = listOf(
|
colors = listOf(
|
||||||
Constants.AppColors.Primary.copy(alpha = 0.15f),
|
AppColors.Primary.copy(alpha = 0.15f),
|
||||||
Color.Transparent
|
Color.Transparent
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -79,7 +83,7 @@ fun DrawerMenu(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(56.dp)
|
.size(56.dp)
|
||||||
.background(
|
.background(
|
||||||
color = Constants.AppColors.Primary.copy(alpha = 0.2f),
|
color = AppColors.Primary.copy(alpha = 0.2f),
|
||||||
shape = RoundedCornerShape(Constants.Radius.Medium.dp)
|
shape = RoundedCornerShape(Constants.Radius.Medium.dp)
|
||||||
),
|
),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
@ -87,7 +91,7 @@ fun DrawerMenu(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Create,
|
Icons.Default.Create,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.Primary,
|
tint = AppColors.Primary,
|
||||||
modifier = Modifier.size(32.dp)
|
modifier = Modifier.size(32.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -97,7 +101,7 @@ fun DrawerMenu(
|
|||||||
Text(
|
Text(
|
||||||
Constants.APP_NAME,
|
Constants.APP_NAME,
|
||||||
style = MaterialTheme.typography.headlineMedium,
|
style = MaterialTheme.typography.headlineMedium,
|
||||||
color = Constants.AppColors.OnBackground,
|
color = AppColors.OnBackground,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
fontSize = 24.sp
|
fontSize = 24.sp
|
||||||
)
|
)
|
||||||
@ -107,7 +111,7 @@ fun DrawerMenu(
|
|||||||
Text(
|
Text(
|
||||||
"Smart Note Taking",
|
"Smart Note Taking",
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color = Constants.AppColors.OnSurfaceVariant,
|
color = AppColors.OnSurfaceVariant,
|
||||||
fontSize = 14.sp
|
fontSize = 14.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -144,11 +148,26 @@ fun DrawerMenu(
|
|||||||
onClick = { onItemClick("trash") }
|
onClick = { onItemClick("trash") }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(Constants.Spacing.Medium.dp))
|
||||||
|
|
||||||
|
HorizontalDivider(
|
||||||
|
color = AppColors.Divider,
|
||||||
|
modifier = Modifier.padding(horizontal = Constants.Spacing.Medium.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(Constants.Spacing.Medium.dp))
|
||||||
|
|
||||||
|
// Theme Toggle
|
||||||
|
ThemeToggleItem(
|
||||||
|
isDarkTheme = isDarkTheme,
|
||||||
|
onToggle = onThemeToggle
|
||||||
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
|
||||||
// Footer - Version info
|
// Footer - Version info
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
color = Constants.AppColors.Divider,
|
color = AppColors.Divider,
|
||||||
modifier = Modifier.padding(horizontal = Constants.Spacing.Medium.dp)
|
modifier = Modifier.padding(horizontal = Constants.Spacing.Medium.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -162,13 +181,13 @@ fun DrawerMenu(
|
|||||||
Text(
|
Text(
|
||||||
"Version ${Constants.APP_VERSION}",
|
"Version ${Constants.APP_VERSION}",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = Constants.AppColors.OnSurfaceTertiary,
|
color = AppColors.OnSurfaceTertiary,
|
||||||
fontSize = 12.sp
|
fontSize = 12.sp
|
||||||
)
|
)
|
||||||
|
|
||||||
// Powered by badge
|
// Powered by badge
|
||||||
Surface(
|
Surface(
|
||||||
color = Constants.AppColors.Primary.copy(alpha = 0.1f),
|
color = AppColors.Primary.copy(alpha = 0.1f),
|
||||||
shape = RoundedCornerShape(Constants.Radius.Small.dp)
|
shape = RoundedCornerShape(Constants.Radius.Small.dp)
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
@ -179,12 +198,12 @@ fun DrawerMenu(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.AutoAwesome,
|
Icons.Default.AutoAwesome,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.Primary,
|
tint = AppColors.Primary,
|
||||||
modifier = Modifier.size(12.dp)
|
modifier = Modifier.size(12.dp)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
"AI",
|
"AI",
|
||||||
color = Constants.AppColors.Primary,
|
color = AppColors.Primary,
|
||||||
fontSize = 11.sp,
|
fontSize = 11.sp,
|
||||||
fontWeight = FontWeight.Bold
|
fontWeight = FontWeight.Bold
|
||||||
)
|
)
|
||||||
@ -196,6 +215,76 @@ fun DrawerMenu(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ThemeToggleItem(
|
||||||
|
isDarkTheme: Boolean,
|
||||||
|
onToggle: () -> Unit
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = Constants.Spacing.Medium.dp)
|
||||||
|
.clip(RoundedCornerShape(Constants.Radius.Medium.dp))
|
||||||
|
.clickable(onClick = onToggle)
|
||||||
|
.background(AppColors.SurfaceVariant)
|
||||||
|
.padding(horizontal = Constants.Spacing.Medium.dp, vertical = Constants.Spacing.Medium.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(Constants.Spacing.Medium.dp)
|
||||||
|
) {
|
||||||
|
// Icon with background
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(40.dp)
|
||||||
|
.background(
|
||||||
|
color = AppColors.Primary.copy(alpha = 0.2f),
|
||||||
|
shape = CircleShape
|
||||||
|
),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
if (isDarkTheme) Icons.Default.DarkMode else Icons.Default.LightMode,
|
||||||
|
contentDescription = null,
|
||||||
|
tint = AppColors.Primary,
|
||||||
|
modifier = Modifier.size(20.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text
|
||||||
|
Column {
|
||||||
|
Text(
|
||||||
|
"Tema Aplikasi",
|
||||||
|
style = MaterialTheme.typography.bodyLarge,
|
||||||
|
color = AppColors.OnSurface,
|
||||||
|
fontWeight = FontWeight.SemiBold,
|
||||||
|
fontSize = 15.sp
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
if (isDarkTheme) "Mode Gelap" else "Mode Terang",
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = AppColors.OnSurfaceTertiary,
|
||||||
|
fontSize = 12.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle Switch
|
||||||
|
Switch(
|
||||||
|
checked = isDarkTheme,
|
||||||
|
onCheckedChange = { onToggle() },
|
||||||
|
colors = SwitchDefaults.colors(
|
||||||
|
checkedThumbColor = Color.White,
|
||||||
|
checkedTrackColor = AppColors.Primary,
|
||||||
|
uncheckedThumbColor = Color.White,
|
||||||
|
uncheckedTrackColor = AppColors.Border
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun DrawerMenuItem(
|
private fun DrawerMenuItem(
|
||||||
icon: ImageVector,
|
icon: ImageVector,
|
||||||
@ -221,7 +310,7 @@ private fun DrawerMenuItem(
|
|||||||
.clickable(onClick = onClick)
|
.clickable(onClick = onClick)
|
||||||
.background(
|
.background(
|
||||||
color = if (isSelected)
|
color = if (isSelected)
|
||||||
Constants.AppColors.Primary.copy(alpha = 0.1f)
|
AppColors.Primary.copy(alpha = 0.1f)
|
||||||
else
|
else
|
||||||
Color.Transparent
|
Color.Transparent
|
||||||
)
|
)
|
||||||
@ -234,9 +323,9 @@ private fun DrawerMenuItem(
|
|||||||
.size(40.dp)
|
.size(40.dp)
|
||||||
.background(
|
.background(
|
||||||
color = if (isSelected)
|
color = if (isSelected)
|
||||||
Constants.AppColors.Primary.copy(alpha = 0.2f)
|
AppColors.Primary.copy(alpha = 0.2f)
|
||||||
else
|
else
|
||||||
Constants.AppColors.SurfaceVariant,
|
AppColors.SurfaceVariant,
|
||||||
shape = CircleShape
|
shape = CircleShape
|
||||||
),
|
),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
@ -244,7 +333,7 @@ private fun DrawerMenuItem(
|
|||||||
Icon(
|
Icon(
|
||||||
icon,
|
icon,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = if (isSelected) Constants.AppColors.Primary else Constants.AppColors.OnSurfaceVariant,
|
tint = if (isSelected) AppColors.Primary else AppColors.OnSurfaceVariant,
|
||||||
modifier = Modifier.size(20.dp)
|
modifier = Modifier.size(20.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -255,7 +344,7 @@ private fun DrawerMenuItem(
|
|||||||
Text(
|
Text(
|
||||||
text,
|
text,
|
||||||
style = MaterialTheme.typography.bodyLarge,
|
style = MaterialTheme.typography.bodyLarge,
|
||||||
color = if (isSelected) Constants.AppColors.Primary else Constants.AppColors.OnSurface,
|
color = if (isSelected) AppColors.Primary else AppColors.OnSurface,
|
||||||
fontWeight = if (isSelected) FontWeight.SemiBold else FontWeight.Normal,
|
fontWeight = if (isSelected) FontWeight.SemiBold else FontWeight.Normal,
|
||||||
fontSize = 15.sp
|
fontSize = 15.sp
|
||||||
)
|
)
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.example.notesai.util.AppColors
|
||||||
import com.example.notesai.util.Constants
|
import com.example.notesai.util.Constants
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -47,7 +48,7 @@ fun ModernBottomBar(
|
|||||||
elevation = Constants.Elevation.Large.dp,
|
elevation = Constants.Elevation.Large.dp,
|
||||||
shape = RoundedCornerShape(Constants.Radius.ExtraLarge.dp)
|
shape = RoundedCornerShape(Constants.Radius.ExtraLarge.dp)
|
||||||
),
|
),
|
||||||
color = Constants.AppColors.SurfaceElevated,
|
color = AppColors.SurfaceElevated,
|
||||||
shape = RoundedCornerShape(Constants.Radius.ExtraLarge.dp)
|
shape = RoundedCornerShape(Constants.Radius.ExtraLarge.dp)
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
@ -96,7 +97,7 @@ private fun BottomBarItem(
|
|||||||
|
|
||||||
// Color animation
|
// Color animation
|
||||||
val iconColor by animateColorAsState(
|
val iconColor by animateColorAsState(
|
||||||
targetValue = if (selected) Constants.AppColors.Primary else Constants.AppColors.OnSurfaceVariant,
|
targetValue = if (selected) AppColors.Primary else AppColors.OnSurfaceVariant,
|
||||||
animationSpec = tween(Constants.ANIMATION_DURATION_MEDIUM),
|
animationSpec = tween(Constants.ANIMATION_DURATION_MEDIUM),
|
||||||
label = "color"
|
label = "color"
|
||||||
)
|
)
|
||||||
@ -125,7 +126,7 @@ private fun BottomBarItem(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(40.dp)
|
.size(40.dp)
|
||||||
.background(
|
.background(
|
||||||
color = Constants.AppColors.Primary.copy(alpha = 0.15f),
|
color = AppColors.Primary.copy(alpha = 0.15f),
|
||||||
shape = CircleShape
|
shape = CircleShape
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -148,7 +149,7 @@ private fun BottomBarItem(
|
|||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
Text(
|
Text(
|
||||||
label,
|
label,
|
||||||
color = Constants.AppColors.Primary,
|
color = AppColors.Primary,
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
fontSize = 12.sp
|
fontSize = 12.sp
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.example.notesai.util.AppColors
|
||||||
import com.example.notesai.util.Constants
|
import com.example.notesai.util.Constants
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@ -48,7 +49,7 @@ fun ModernTopBar(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.shadow(Constants.Elevation.Small.dp),
|
.shadow(Constants.Elevation.Small.dp),
|
||||||
color = Constants.AppColors.Surface
|
color = AppColors.Surface
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@ -63,16 +64,16 @@ fun ModernTopBar(
|
|||||||
placeholder = {
|
placeholder = {
|
||||||
Text(
|
Text(
|
||||||
"Cari catatan atau kategori...",
|
"Cari catatan atau kategori...",
|
||||||
color = Constants.AppColors.OnSurfaceVariant,
|
color = AppColors.OnSurfaceVariant,
|
||||||
fontSize = 15.sp
|
fontSize = 15.sp
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
colors = TextFieldDefaults.colors(
|
colors = TextFieldDefaults.colors(
|
||||||
focusedContainerColor = Constants.AppColors.SurfaceVariant,
|
focusedContainerColor = AppColors.SurfaceVariant,
|
||||||
unfocusedContainerColor = Constants.AppColors.SurfaceVariant,
|
unfocusedContainerColor = AppColors.SurfaceVariant,
|
||||||
focusedTextColor = Constants.AppColors.OnBackground,
|
focusedTextColor = AppColors.OnBackground,
|
||||||
unfocusedTextColor = Constants.AppColors.OnSurface,
|
unfocusedTextColor = AppColors.OnSurface,
|
||||||
cursorColor = Constants.AppColors.Primary,
|
cursorColor = AppColors.Primary,
|
||||||
focusedIndicatorColor = Color.Transparent,
|
focusedIndicatorColor = Color.Transparent,
|
||||||
unfocusedIndicatorColor = Color.Transparent
|
unfocusedIndicatorColor = Color.Transparent
|
||||||
),
|
),
|
||||||
@ -96,7 +97,7 @@ fun ModernTopBar(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Close,
|
Icons.Default.Close,
|
||||||
contentDescription = "Close Search",
|
contentDescription = "Close Search",
|
||||||
tint = Constants.AppColors.OnSurfaceVariant
|
tint = AppColors.OnSurfaceVariant
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,7 +108,7 @@ fun ModernTopBar(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.shadow(Constants.Elevation.Small.dp),
|
.shadow(Constants.Elevation.Small.dp),
|
||||||
color = Constants.AppColors.Surface
|
color = AppColors.Surface
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@ -120,7 +121,7 @@ fun ModernTopBar(
|
|||||||
Icon(
|
Icon(
|
||||||
if (showBackButton) Icons.AutoMirrored.Filled.ArrowBack else Icons.Default.Menu,
|
if (showBackButton) Icons.AutoMirrored.Filled.ArrowBack else Icons.Default.Menu,
|
||||||
contentDescription = if (showBackButton) "Back" else "Menu",
|
contentDescription = if (showBackButton) "Back" else "Menu",
|
||||||
tint = Constants.AppColors.OnSurface
|
tint = AppColors.OnSurface
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +130,7 @@ fun ModernTopBar(
|
|||||||
title,
|
title,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
fontSize = 20.sp,
|
fontSize = 20.sp,
|
||||||
color = Constants.AppColors.OnBackground,
|
color = AppColors.OnBackground,
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -138,7 +139,7 @@ fun ModernTopBar(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Search,
|
Icons.Default.Search,
|
||||||
contentDescription = "Search",
|
contentDescription = "Search",
|
||||||
tint = Constants.AppColors.OnSurfaceVariant
|
tint = AppColors.OnSurfaceVariant
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.example.notesai.util.AppColors
|
||||||
import com.example.notesai.util.Constants
|
import com.example.notesai.util.Constants
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -31,12 +32,12 @@ fun CategoryDialog(
|
|||||||
|
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
containerColor = Constants.AppColors.Surface,
|
containerColor = AppColors.Surface,
|
||||||
shape = RoundedCornerShape(20.dp),
|
shape = RoundedCornerShape(20.dp),
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
"Buat Kategori Baru",
|
"Buat Kategori Baru",
|
||||||
color = Constants.AppColors.OnBackground,
|
color = AppColors.OnBackground,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
fontSize = 20.sp
|
fontSize = 20.sp
|
||||||
)
|
)
|
||||||
@ -52,24 +53,24 @@ fun CategoryDialog(
|
|||||||
label = {
|
label = {
|
||||||
Text(
|
Text(
|
||||||
"Nama Kategori",
|
"Nama Kategori",
|
||||||
color = Constants.AppColors.OnSurfaceVariant
|
color = AppColors.OnSurfaceVariant
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
placeholder = {
|
placeholder = {
|
||||||
Text(
|
Text(
|
||||||
"Contoh: Pekerjaan, Personal",
|
"Contoh: Pekerjaan, Personal",
|
||||||
color = Constants.AppColors.OnSurfaceTertiary,
|
color = AppColors.OnSurfaceTertiary,
|
||||||
fontSize = 14.sp
|
fontSize = 14.sp
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
colors = OutlinedTextFieldDefaults.colors(
|
colors = OutlinedTextFieldDefaults.colors(
|
||||||
focusedTextColor = Constants.AppColors.OnBackground,
|
focusedTextColor = AppColors.OnBackground,
|
||||||
unfocusedTextColor = Constants.AppColors.OnSurface,
|
unfocusedTextColor = AppColors.OnSurface,
|
||||||
focusedContainerColor = Constants.AppColors.SurfaceVariant,
|
focusedContainerColor = AppColors.SurfaceVariant,
|
||||||
unfocusedContainerColor = Constants.AppColors.SurfaceVariant,
|
unfocusedContainerColor = AppColors.SurfaceVariant,
|
||||||
cursorColor = Constants.AppColors.Primary,
|
cursorColor = AppColors.Primary,
|
||||||
focusedBorderColor = Constants.AppColors.Primary,
|
focusedBorderColor = AppColors.Primary,
|
||||||
unfocusedBorderColor = Color.Transparent
|
unfocusedBorderColor = Color.Transparent
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(12.dp),
|
shape = RoundedCornerShape(12.dp),
|
||||||
@ -83,18 +84,18 @@ fun CategoryDialog(
|
|||||||
Text(
|
Text(
|
||||||
"Pilih Warna:",
|
"Pilih Warna:",
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color = Constants.AppColors.OnSurface,
|
color = AppColors.OnSurface,
|
||||||
fontWeight = FontWeight.SemiBold,
|
fontWeight = FontWeight.SemiBold,
|
||||||
fontSize = 14.sp
|
fontSize = 14.sp
|
||||||
)
|
)
|
||||||
|
|
||||||
Constants.AppColors.CategoryColors.chunked(4).forEach { row ->
|
Constants.CategoryColors.chunked(4).forEach { row ->
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
row.forEach { gradient ->
|
row.forEach { gradient ->
|
||||||
val globalIndex = Constants.AppColors.CategoryColors.indexOf(gradient)
|
val globalIndex = Constants.CategoryColors.indexOf(gradient)
|
||||||
val isSelected = selectedGradient == globalIndex
|
val isSelected = selectedGradient == globalIndex
|
||||||
|
|
||||||
// Scale animation
|
// Scale animation
|
||||||
@ -120,11 +121,7 @@ fun CategoryDialog(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.clickable { selectedGradient = globalIndex }
|
.clickable { selectedGradient = globalIndex },
|
||||||
.then(
|
|
||||||
if (isSelected) Modifier
|
|
||||||
else Modifier
|
|
||||||
),
|
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
// Check icon dengan animation
|
// Check icon dengan animation
|
||||||
@ -158,14 +155,14 @@ fun CategoryDialog(
|
|||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (name.isNotBlank()) {
|
if (name.isNotBlank()) {
|
||||||
val gradient = Constants.AppColors.CategoryColors[selectedGradient]
|
val gradient = Constants.CategoryColors[selectedGradient]
|
||||||
onSave(name, gradient.first, gradient.second)
|
onSave(name, gradient.first, gradient.second)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
enabled = name.isNotBlank(),
|
enabled = name.isNotBlank(),
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
containerColor = Constants.AppColors.Primary,
|
containerColor = AppColors.Primary,
|
||||||
disabledContainerColor = Constants.AppColors.Primary.copy(alpha = 0.5f)
|
disabledContainerColor = AppColors.Primary.copy(alpha = 0.5f)
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(12.dp),
|
shape = RoundedCornerShape(12.dp),
|
||||||
modifier = Modifier.height(48.dp)
|
modifier = Modifier.height(48.dp)
|
||||||
@ -186,7 +183,7 @@ fun CategoryDialog(
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
"Batal",
|
"Batal",
|
||||||
color = Constants.AppColors.OnSurfaceVariant,
|
color = AppColors.OnSurfaceVariant,
|
||||||
fontSize = 15.sp
|
fontSize = 15.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.example.notesai.data.model.Note
|
import com.example.notesai.data.model.Note
|
||||||
|
import com.example.notesai.util.AppColors
|
||||||
import com.example.notesai.util.Constants
|
import com.example.notesai.util.Constants
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -29,19 +30,19 @@ fun NoteDialog(
|
|||||||
if (showDeleteConfirm) {
|
if (showDeleteConfirm) {
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { showDeleteConfirm = false },
|
onDismissRequest = { showDeleteConfirm = false },
|
||||||
containerColor = Constants.AppColors.Surface,
|
containerColor = AppColors.Surface,
|
||||||
shape = RoundedCornerShape(20.dp),
|
shape = RoundedCornerShape(20.dp),
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
"Hapus Catatan?",
|
"Hapus Catatan?",
|
||||||
color = Constants.AppColors.OnBackground,
|
color = AppColors.OnBackground,
|
||||||
fontWeight = FontWeight.Bold
|
fontWeight = FontWeight.Bold
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
text = {
|
text = {
|
||||||
Text(
|
Text(
|
||||||
"Catatan ini akan dipindahkan ke sampah.",
|
"Catatan ini akan dipindahkan ke sampah.",
|
||||||
color = Constants.AppColors.OnSurfaceVariant
|
color = AppColors.OnSurfaceVariant
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
@ -51,7 +52,7 @@ fun NoteDialog(
|
|||||||
showDeleteConfirm = false
|
showDeleteConfirm = false
|
||||||
},
|
},
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
containerColor = Constants.AppColors.Error
|
containerColor = AppColors.Error
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(12.dp)
|
shape = RoundedCornerShape(12.dp)
|
||||||
) {
|
) {
|
||||||
@ -63,7 +64,7 @@ fun NoteDialog(
|
|||||||
onClick = { showDeleteConfirm = false },
|
onClick = { showDeleteConfirm = false },
|
||||||
shape = RoundedCornerShape(12.dp)
|
shape = RoundedCornerShape(12.dp)
|
||||||
) {
|
) {
|
||||||
Text("Batal", color = Constants.AppColors.OnSurfaceVariant)
|
Text("Batal", color = AppColors.OnSurfaceVariant)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -71,12 +72,12 @@ fun NoteDialog(
|
|||||||
|
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
containerColor = Constants.AppColors.Surface,
|
containerColor = AppColors.Surface,
|
||||||
shape = RoundedCornerShape(20.dp),
|
shape = RoundedCornerShape(20.dp),
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
if (note == null) "Catatan Baru" else "Edit Catatan",
|
if (note == null) "Catatan Baru" else "Edit Catatan",
|
||||||
color = Constants.AppColors.OnBackground,
|
color = AppColors.OnBackground,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
fontSize = 20.sp
|
fontSize = 20.sp
|
||||||
)
|
)
|
||||||
@ -92,24 +93,24 @@ fun NoteDialog(
|
|||||||
label = {
|
label = {
|
||||||
Text(
|
Text(
|
||||||
"Judul",
|
"Judul",
|
||||||
color = Constants.AppColors.OnSurfaceVariant
|
color = AppColors.OnSurfaceVariant
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
placeholder = {
|
placeholder = {
|
||||||
Text(
|
Text(
|
||||||
"Masukkan judul catatan",
|
"Masukkan judul catatan",
|
||||||
color = Constants.AppColors.OnSurfaceTertiary,
|
color = AppColors.OnSurfaceTertiary,
|
||||||
fontSize = 14.sp
|
fontSize = 14.sp
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
colors = OutlinedTextFieldDefaults.colors(
|
colors = OutlinedTextFieldDefaults.colors(
|
||||||
focusedTextColor = Constants.AppColors.OnBackground,
|
focusedTextColor = AppColors.OnBackground,
|
||||||
unfocusedTextColor = Constants.AppColors.OnSurface,
|
unfocusedTextColor = AppColors.OnSurface,
|
||||||
focusedContainerColor = Constants.AppColors.SurfaceVariant,
|
focusedContainerColor = AppColors.SurfaceVariant,
|
||||||
unfocusedContainerColor = Constants.AppColors.SurfaceVariant,
|
unfocusedContainerColor = AppColors.SurfaceVariant,
|
||||||
cursorColor = Constants.AppColors.Primary,
|
cursorColor = AppColors.Primary,
|
||||||
focusedBorderColor = Constants.AppColors.Primary,
|
focusedBorderColor = AppColors.Primary,
|
||||||
unfocusedBorderColor = Color.Transparent
|
unfocusedBorderColor = Color.Transparent
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(12.dp),
|
shape = RoundedCornerShape(12.dp),
|
||||||
@ -123,13 +124,13 @@ fun NoteDialog(
|
|||||||
label = {
|
label = {
|
||||||
Text(
|
Text(
|
||||||
"Deskripsi",
|
"Deskripsi",
|
||||||
color = Constants.AppColors.OnSurfaceVariant
|
color = AppColors.OnSurfaceVariant
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
placeholder = {
|
placeholder = {
|
||||||
Text(
|
Text(
|
||||||
"Tambahkan deskripsi singkat...",
|
"Tambahkan deskripsi singkat...",
|
||||||
color = Constants.AppColors.OnSurfaceTertiary,
|
color = AppColors.OnSurfaceTertiary,
|
||||||
fontSize = 14.sp
|
fontSize = 14.sp
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -137,12 +138,12 @@ fun NoteDialog(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.heightIn(min = 120.dp, max = 200.dp),
|
.heightIn(min = 120.dp, max = 200.dp),
|
||||||
colors = OutlinedTextFieldDefaults.colors(
|
colors = OutlinedTextFieldDefaults.colors(
|
||||||
focusedTextColor = Constants.AppColors.OnBackground,
|
focusedTextColor = AppColors.OnBackground,
|
||||||
unfocusedTextColor = Constants.AppColors.OnSurface,
|
unfocusedTextColor = AppColors.OnSurface,
|
||||||
focusedContainerColor = Constants.AppColors.SurfaceVariant,
|
focusedContainerColor = AppColors.SurfaceVariant,
|
||||||
unfocusedContainerColor = Constants.AppColors.SurfaceVariant,
|
unfocusedContainerColor = AppColors.SurfaceVariant,
|
||||||
cursorColor = Constants.AppColors.Primary,
|
cursorColor = AppColors.Primary,
|
||||||
focusedBorderColor = Constants.AppColors.Primary,
|
focusedBorderColor = AppColors.Primary,
|
||||||
unfocusedBorderColor = Color.Transparent
|
unfocusedBorderColor = Color.Transparent
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(12.dp),
|
shape = RoundedCornerShape(12.dp),
|
||||||
@ -163,7 +164,7 @@ fun NoteDialog(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Delete,
|
Icons.Default.Delete,
|
||||||
contentDescription = "Hapus",
|
contentDescription = "Hapus",
|
||||||
tint = Constants.AppColors.Error
|
tint = AppColors.Error
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,7 +179,7 @@ fun NoteDialog(
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
"Batal",
|
"Batal",
|
||||||
color = Constants.AppColors.OnSurfaceVariant,
|
color = AppColors.OnSurfaceVariant,
|
||||||
fontSize = 15.sp
|
fontSize = 15.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -192,8 +193,8 @@ fun NoteDialog(
|
|||||||
},
|
},
|
||||||
enabled = title.isNotBlank(),
|
enabled = title.isNotBlank(),
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
containerColor = Constants.AppColors.Primary,
|
containerColor = AppColors.Primary,
|
||||||
disabledContainerColor = Constants.AppColors.Primary.copy(alpha = 0.5f)
|
disabledContainerColor = AppColors.Primary.copy(alpha = 0.5f)
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(12.dp),
|
shape = RoundedCornerShape(12.dp),
|
||||||
modifier = Modifier.height(48.dp)
|
modifier = Modifier.height(48.dp)
|
||||||
|
|||||||
@ -34,6 +34,7 @@ import com.example.notesai.presentation.screens.ai.components.ChatBubble
|
|||||||
import com.example.notesai.presentation.screens.ai.components.ChatHistoryDrawer
|
import com.example.notesai.presentation.screens.ai.components.ChatHistoryDrawer
|
||||||
import com.example.notesai.presentation.screens.ai.components.CompactStatItem
|
import com.example.notesai.presentation.screens.ai.components.CompactStatItem
|
||||||
import com.example.notesai.presentation.screens.ai.components.SuggestionChip
|
import com.example.notesai.presentation.screens.ai.components.SuggestionChip
|
||||||
|
import com.example.notesai.util.AppColors
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@ -128,11 +129,11 @@ fun AIHelperScreen(
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(Constants.AppColors.Background)
|
.background(AppColors.Background)
|
||||||
) {
|
) {
|
||||||
// Top Bar with History Button & Stats
|
// Top Bar with History Button & Stats
|
||||||
Surface(
|
Surface(
|
||||||
color = Constants.AppColors.Surface,
|
color = AppColors.Surface,
|
||||||
shadowElevation = 2.dp
|
shadowElevation = 2.dp
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
@ -152,21 +153,21 @@ fun AIHelperScreen(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(40.dp)
|
.size(40.dp)
|
||||||
.background(
|
.background(
|
||||||
Constants.AppColors.Primary.copy(alpha = 0.1f),
|
AppColors.Primary.copy(alpha = 0.1f),
|
||||||
CircleShape
|
CircleShape
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Menu,
|
Icons.Default.Menu,
|
||||||
contentDescription = "Menu",
|
contentDescription = "Menu",
|
||||||
tint = Constants.AppColors.Primary,
|
tint = AppColors.Primary,
|
||||||
modifier = Modifier.size(20.dp)
|
modifier = Modifier.size(20.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Category Badge
|
// Category Badge
|
||||||
Surface(
|
Surface(
|
||||||
color = Constants.AppColors.Primary.copy(alpha = 0.1f),
|
color = AppColors.Primary.copy(alpha = 0.1f),
|
||||||
shape = RoundedCornerShape(Constants.Radius.Medium.dp)
|
shape = RoundedCornerShape(Constants.Radius.Medium.dp)
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
@ -180,12 +181,12 @@ fun AIHelperScreen(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Folder,
|
Icons.Default.Folder,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.Primary,
|
tint = AppColors.Primary,
|
||||||
modifier = Modifier.size(16.dp)
|
modifier = Modifier.size(16.dp)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
selectedCategory?.name ?: "Semua Kategori",
|
selectedCategory?.name ?: "Semua Kategori",
|
||||||
color = Constants.AppColors.Primary,
|
color = AppColors.Primary,
|
||||||
fontSize = 13.sp,
|
fontSize = 13.sp,
|
||||||
fontWeight = FontWeight.SemiBold
|
fontWeight = FontWeight.SemiBold
|
||||||
)
|
)
|
||||||
@ -197,7 +198,7 @@ fun AIHelperScreen(
|
|||||||
Button(
|
Button(
|
||||||
onClick = { startNewChat() },
|
onClick = { startNewChat() },
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
containerColor = Constants.AppColors.Primary
|
containerColor = AppColors.Primary
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(Constants.Radius.Medium.dp),
|
shape = RoundedCornerShape(Constants.Radius.Medium.dp),
|
||||||
contentPadding = PaddingValues(
|
contentPadding = PaddingValues(
|
||||||
@ -252,7 +253,7 @@ fun AIHelperScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HorizontalDivider(color = Constants.AppColors.Divider)
|
HorizontalDivider(color = AppColors.Divider)
|
||||||
|
|
||||||
// Chat Area
|
// Chat Area
|
||||||
Box(
|
Box(
|
||||||
@ -273,7 +274,7 @@ fun AIHelperScreen(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(80.dp)
|
.size(80.dp)
|
||||||
.background(
|
.background(
|
||||||
color = Constants.AppColors.Primary.copy(alpha = 0.1f),
|
color = AppColors.Primary.copy(alpha = 0.1f),
|
||||||
shape = CircleShape
|
shape = CircleShape
|
||||||
),
|
),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
@ -282,7 +283,7 @@ fun AIHelperScreen(
|
|||||||
Icons.Default.AutoAwesome,
|
Icons.Default.AutoAwesome,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.size(40.dp),
|
modifier = Modifier.size(40.dp),
|
||||||
tint = Constants.AppColors.Primary
|
tint = AppColors.Primary
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,7 +292,7 @@ fun AIHelperScreen(
|
|||||||
Text(
|
Text(
|
||||||
"AI Assistant",
|
"AI Assistant",
|
||||||
style = MaterialTheme.typography.headlineMedium,
|
style = MaterialTheme.typography.headlineMedium,
|
||||||
color = Constants.AppColors.OnBackground,
|
color = AppColors.OnBackground,
|
||||||
fontWeight = FontWeight.Bold
|
fontWeight = FontWeight.Bold
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -300,7 +301,7 @@ fun AIHelperScreen(
|
|||||||
Text(
|
Text(
|
||||||
"Tanyakan apa saja tentang catatan Anda",
|
"Tanyakan apa saja tentang catatan Anda",
|
||||||
style = MaterialTheme.typography.bodyLarge,
|
style = MaterialTheme.typography.bodyLarge,
|
||||||
color = Constants.AppColors.OnSurfaceVariant,
|
color = AppColors.OnSurfaceVariant,
|
||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -315,7 +316,7 @@ fun AIHelperScreen(
|
|||||||
Text(
|
Text(
|
||||||
"Contoh pertanyaan:",
|
"Contoh pertanyaan:",
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = MaterialTheme.typography.labelMedium,
|
||||||
color = Constants.AppColors.OnSurfaceTertiary
|
color = AppColors.OnSurfaceTertiary
|
||||||
)
|
)
|
||||||
SuggestionChip("Analisis catatan saya") { prompt = it }
|
SuggestionChip("Analisis catatan saya") { prompt = it }
|
||||||
SuggestionChip("Buat ringkasan") { prompt = it }
|
SuggestionChip("Buat ringkasan") { prompt = it }
|
||||||
@ -356,7 +357,7 @@ fun AIHelperScreen(
|
|||||||
horizontalArrangement = Arrangement.Start
|
horizontalArrangement = Arrangement.Start
|
||||||
) {
|
) {
|
||||||
Surface(
|
Surface(
|
||||||
color = Constants.AppColors.SurfaceVariant,
|
color = AppColors.SurfaceVariant,
|
||||||
shape = RoundedCornerShape(16.dp)
|
shape = RoundedCornerShape(16.dp)
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
@ -366,12 +367,12 @@ fun AIHelperScreen(
|
|||||||
) {
|
) {
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
modifier = Modifier.size(20.dp),
|
modifier = Modifier.size(20.dp),
|
||||||
color = Constants.AppColors.Primary,
|
color = AppColors.Primary,
|
||||||
strokeWidth = 2.dp
|
strokeWidth = 2.dp
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
"AI sedang berpikir...",
|
"AI sedang berpikir...",
|
||||||
color = Constants.AppColors.OnSurfaceVariant,
|
color = AppColors.OnSurfaceVariant,
|
||||||
style = MaterialTheme.typography.bodyMedium
|
style = MaterialTheme.typography.bodyMedium
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -383,7 +384,7 @@ fun AIHelperScreen(
|
|||||||
if (errorMessage.isNotEmpty()) {
|
if (errorMessage.isNotEmpty()) {
|
||||||
Surface(
|
Surface(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
color = Constants.AppColors.Error.copy(alpha = 0.1f),
|
color = AppColors.Error.copy(alpha = 0.1f),
|
||||||
shape = RoundedCornerShape(12.dp)
|
shape = RoundedCornerShape(12.dp)
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
@ -394,12 +395,12 @@ fun AIHelperScreen(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Warning,
|
Icons.Default.Warning,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.Error,
|
tint = AppColors.Error,
|
||||||
modifier = Modifier.size(20.dp)
|
modifier = Modifier.size(20.dp)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
errorMessage,
|
errorMessage,
|
||||||
color = Constants.AppColors.Error,
|
color = AppColors.Error,
|
||||||
style = MaterialTheme.typography.bodySmall
|
style = MaterialTheme.typography.bodySmall
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -411,7 +412,7 @@ fun AIHelperScreen(
|
|||||||
|
|
||||||
// Input Area - Minimalist
|
// Input Area - Minimalist
|
||||||
Surface(
|
Surface(
|
||||||
color = Constants.AppColors.Surface,
|
color = AppColors.Surface,
|
||||||
shadowElevation = 8.dp,
|
shadowElevation = 8.dp,
|
||||||
shape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp)
|
shape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp)
|
||||||
) {
|
) {
|
||||||
@ -428,19 +429,19 @@ fun AIHelperScreen(
|
|||||||
placeholder = {
|
placeholder = {
|
||||||
Text(
|
Text(
|
||||||
"Ketik pesan...",
|
"Ketik pesan...",
|
||||||
color = Constants.AppColors.OnSurfaceTertiary
|
color = AppColors.OnSurfaceTertiary
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.heightIn(min = 48.dp, max = 120.dp),
|
.heightIn(min = 48.dp, max = 120.dp),
|
||||||
colors = OutlinedTextFieldDefaults.colors(
|
colors = OutlinedTextFieldDefaults.colors(
|
||||||
focusedTextColor = Constants.AppColors.OnBackground,
|
focusedTextColor = AppColors.OnBackground,
|
||||||
unfocusedTextColor = Constants.AppColors.OnSurface,
|
unfocusedTextColor = AppColors.OnSurface,
|
||||||
focusedContainerColor = Constants.AppColors.SurfaceVariant,
|
focusedContainerColor = AppColors.SurfaceVariant,
|
||||||
unfocusedContainerColor = Constants.AppColors.SurfaceVariant,
|
unfocusedContainerColor = AppColors.SurfaceVariant,
|
||||||
cursorColor = Constants.AppColors.Primary,
|
cursorColor = AppColors.Primary,
|
||||||
focusedBorderColor = Constants.AppColors.Primary,
|
focusedBorderColor = AppColors.Primary,
|
||||||
unfocusedBorderColor = Color.Transparent
|
unfocusedBorderColor = Color.Transparent
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(24.dp),
|
shape = RoundedCornerShape(24.dp),
|
||||||
@ -501,7 +502,7 @@ fun AIHelperScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
containerColor = Constants.AppColors.Primary,
|
containerColor = AppColors.Primary,
|
||||||
modifier = Modifier.size(48.dp)
|
modifier = Modifier.size(48.dp)
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
|
|||||||
@ -30,6 +30,7 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.example.notesai.data.model.ChatMessage
|
import com.example.notesai.data.model.ChatMessage
|
||||||
|
import com.example.notesai.util.AppColors
|
||||||
import com.example.notesai.util.Constants
|
import com.example.notesai.util.Constants
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
@ -52,7 +53,7 @@ fun ChatBubble(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(32.dp)
|
.size(32.dp)
|
||||||
.background(
|
.background(
|
||||||
color = Constants.AppColors.Primary.copy(alpha = 0.1f),
|
color = AppColors.Primary.copy(alpha = 0.1f),
|
||||||
shape = CircleShape
|
shape = CircleShape
|
||||||
),
|
),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
@ -60,7 +61,7 @@ fun ChatBubble(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.AutoAwesome,
|
Icons.Default.AutoAwesome,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.Primary,
|
tint = AppColors.Primary,
|
||||||
modifier = Modifier.size(16.dp)
|
modifier = Modifier.size(16.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -73,9 +74,9 @@ fun ChatBubble(
|
|||||||
) {
|
) {
|
||||||
Surface(
|
Surface(
|
||||||
color = if (message.isUser)
|
color = if (message.isUser)
|
||||||
Constants.AppColors.Primary
|
AppColors.Primary
|
||||||
else
|
else
|
||||||
Constants.AppColors.SurfaceVariant,
|
AppColors.SurfaceVariant,
|
||||||
shape = RoundedCornerShape(
|
shape = RoundedCornerShape(
|
||||||
topStart = 16.dp,
|
topStart = 16.dp,
|
||||||
topEnd = 16.dp,
|
topEnd = 16.dp,
|
||||||
@ -86,7 +87,7 @@ fun ChatBubble(
|
|||||||
Column(modifier = Modifier.padding(12.dp)) {
|
Column(modifier = Modifier.padding(12.dp)) {
|
||||||
Text(
|
Text(
|
||||||
message.message,
|
message.message,
|
||||||
color = if (message.isUser) Color.White else Constants.AppColors.OnSurface,
|
color = if (message.isUser) Color.White else AppColors.OnSurface,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
lineHeight = 20.sp
|
lineHeight = 20.sp
|
||||||
)
|
)
|
||||||
@ -101,7 +102,7 @@ fun ChatBubble(
|
|||||||
color = if (message.isUser)
|
color = if (message.isUser)
|
||||||
Color.White.copy(0.7f)
|
Color.White.copy(0.7f)
|
||||||
else
|
else
|
||||||
Constants.AppColors.OnSurfaceTertiary,
|
AppColors.OnSurfaceTertiary,
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
fontSize = 11.sp,
|
fontSize = 11.sp,
|
||||||
modifier = Modifier.padding(top = 4.dp)
|
modifier = Modifier.padding(top = 4.dp)
|
||||||
@ -115,7 +116,7 @@ fun ChatBubble(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.ContentCopy,
|
Icons.Default.ContentCopy,
|
||||||
contentDescription = "Copy",
|
contentDescription = "Copy",
|
||||||
tint = Constants.AppColors.OnSurfaceVariant,
|
tint = AppColors.OnSurfaceVariant,
|
||||||
modifier = Modifier.size(14.dp)
|
modifier = Modifier.size(14.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -127,7 +128,7 @@ fun ChatBubble(
|
|||||||
if (showCopied && !message.isUser) {
|
if (showCopied && !message.isUser) {
|
||||||
Text(
|
Text(
|
||||||
"✓ Disalin",
|
"✓ Disalin",
|
||||||
color = Constants.AppColors.Success,
|
color = AppColors.Success,
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
fontSize = 11.sp,
|
fontSize = 11.sp,
|
||||||
modifier = Modifier.padding(top = 4.dp, start = 8.dp)
|
modifier = Modifier.padding(top = 4.dp, start = 8.dp)
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.example.notesai.util.AppColors
|
||||||
import com.example.notesai.util.Constants
|
import com.example.notesai.util.Constants
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -32,7 +33,7 @@ fun CompactStatItem(
|
|||||||
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.background(
|
.background(
|
||||||
color = Constants.AppColors.SurfaceVariant,
|
color = AppColors.SurfaceVariant,
|
||||||
shape = RoundedCornerShape(8.dp)
|
shape = RoundedCornerShape(8.dp)
|
||||||
)
|
)
|
||||||
.padding(horizontal = 12.dp, vertical = 8.dp)
|
.padding(horizontal = 12.dp, vertical = 8.dp)
|
||||||
@ -40,21 +41,21 @@ fun CompactStatItem(
|
|||||||
Icon(
|
Icon(
|
||||||
icon,
|
icon,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.Primary,
|
tint = AppColors.Primary,
|
||||||
modifier = Modifier.size(16.dp)
|
modifier = Modifier.size(16.dp)
|
||||||
)
|
)
|
||||||
Column {
|
Column {
|
||||||
Text(
|
Text(
|
||||||
value,
|
value,
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = MaterialTheme.typography.titleMedium,
|
||||||
color = Constants.AppColors.OnBackground,
|
color = AppColors.OnBackground,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
fontSize = 16.sp
|
fontSize = 16.sp
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
label,
|
label,
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = Constants.AppColors.OnSurfaceTertiary,
|
color = AppColors.OnSurfaceTertiary,
|
||||||
fontSize = 11.sp
|
fontSize = 11.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.example.notesai.util.AppColors
|
||||||
import com.example.notesai.util.Constants
|
import com.example.notesai.util.Constants
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -32,7 +33,7 @@ fun SuggestionChip(
|
|||||||
) {
|
) {
|
||||||
Surface(
|
Surface(
|
||||||
onClick = { onSelect(text) },
|
onClick = { onSelect(text) },
|
||||||
color = Constants.AppColors.SurfaceVariant,
|
color = AppColors.SurfaceVariant,
|
||||||
shape = RoundedCornerShape(12.dp)
|
shape = RoundedCornerShape(12.dp)
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
@ -43,12 +44,12 @@ fun SuggestionChip(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Lightbulb,
|
Icons.Default.Lightbulb,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.Primary,
|
tint = AppColors.Primary,
|
||||||
modifier = Modifier.size(16.dp)
|
modifier = Modifier.size(16.dp)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text,
|
text,
|
||||||
color = Constants.AppColors.OnSurface,
|
color = AppColors.OnSurface,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
fontSize = 14.sp
|
fontSize = 14.sp
|
||||||
)
|
)
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.example.notesai.data.model.Category
|
import com.example.notesai.data.model.Category
|
||||||
|
import com.example.notesai.util.AppColors
|
||||||
import com.example.notesai.util.Constants
|
import com.example.notesai.util.Constants
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -54,14 +55,14 @@ fun CategoryCard(
|
|||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
"Pindahkan ke Sampah?",
|
"Pindahkan ke Sampah?",
|
||||||
color = Constants.AppColors.OnBackground,
|
color = AppColors.OnBackground,
|
||||||
fontWeight = FontWeight.Bold
|
fontWeight = FontWeight.Bold
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
text = {
|
text = {
|
||||||
Text(
|
Text(
|
||||||
"Kategori '${category.name}' dan $noteCount catatan di dalamnya akan dipindahkan ke sampah.",
|
"Kategori '${category.name}' dan $noteCount catatan di dalamnya akan dipindahkan ke sampah.",
|
||||||
color = Constants.AppColors.OnSurfaceVariant
|
color = AppColors.OnSurfaceVariant
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
@ -71,7 +72,7 @@ fun CategoryCard(
|
|||||||
showDeleteConfirm = false
|
showDeleteConfirm = false
|
||||||
},
|
},
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
containerColor = Constants.AppColors.Error
|
containerColor = AppColors.Error
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Text("Hapus", color = Color.White)
|
Text("Hapus", color = Color.White)
|
||||||
@ -79,10 +80,10 @@ fun CategoryCard(
|
|||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { showDeleteConfirm = false }) {
|
TextButton(onClick = { showDeleteConfirm = false }) {
|
||||||
Text("Batal", color = Constants.AppColors.OnSurfaceVariant)
|
Text("Batal", color = AppColors.OnSurfaceVariant)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
containerColor = Constants.AppColors.Surface,
|
containerColor = AppColors.Surface,
|
||||||
shape = RoundedCornerShape(Constants.Radius.Large.dp)
|
shape = RoundedCornerShape(Constants.Radius.Large.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -107,7 +108,7 @@ fun CategoryCard(
|
|||||||
.clickable(onClick = onClick),
|
.clickable(onClick = onClick),
|
||||||
shape = RoundedCornerShape(Constants.Radius.Large.dp),
|
shape = RoundedCornerShape(Constants.Radius.Large.dp),
|
||||||
colors = CardDefaults.cardColors(
|
colors = CardDefaults.cardColors(
|
||||||
containerColor = Constants.AppColors.Surface
|
containerColor = AppColors.Surface
|
||||||
),
|
),
|
||||||
elevation = CardDefaults.cardElevation(
|
elevation = CardDefaults.cardElevation(
|
||||||
defaultElevation = Constants.Elevation.Small.dp
|
defaultElevation = Constants.Elevation.Small.dp
|
||||||
@ -167,7 +168,7 @@ fun CategoryCard(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.MoreVert,
|
Icons.Default.MoreVert,
|
||||||
contentDescription = "Menu",
|
contentDescription = "Menu",
|
||||||
tint = Constants.AppColors.OnSurfaceVariant,
|
tint = AppColors.OnSurfaceVariant,
|
||||||
modifier = Modifier.size(20.dp)
|
modifier = Modifier.size(20.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -175,7 +176,7 @@ fun CategoryCard(
|
|||||||
DropdownMenu(
|
DropdownMenu(
|
||||||
expanded = showMenu,
|
expanded = showMenu,
|
||||||
onDismissRequest = { showMenu = false },
|
onDismissRequest = { showMenu = false },
|
||||||
modifier = Modifier.background(Constants.AppColors.SurfaceElevated)
|
modifier = Modifier.background(AppColors.SurfaceElevated)
|
||||||
) {
|
) {
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = {
|
text = {
|
||||||
@ -186,12 +187,12 @@ fun CategoryCard(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Edit,
|
Icons.Default.Edit,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.Primary,
|
tint = AppColors.Primary,
|
||||||
modifier = Modifier.size(18.dp)
|
modifier = Modifier.size(18.dp)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
"Edit Kategori",
|
"Edit Kategori",
|
||||||
color = Constants.AppColors.OnSurface,
|
color = AppColors.OnSurface,
|
||||||
fontSize = 14.sp
|
fontSize = 14.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -211,12 +212,12 @@ fun CategoryCard(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Delete,
|
Icons.Default.Delete,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.Error,
|
tint = AppColors.Error,
|
||||||
modifier = Modifier.size(18.dp)
|
modifier = Modifier.size(18.dp)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
"Pindah ke Sampah",
|
"Pindah ke Sampah",
|
||||||
color = Constants.AppColors.OnSurface,
|
color = AppColors.OnSurface,
|
||||||
fontSize = 14.sp
|
fontSize = 14.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -237,7 +238,7 @@ fun CategoryCard(
|
|||||||
category.name,
|
category.name,
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = MaterialTheme.typography.titleLarge,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
color = Constants.AppColors.OnBackground,
|
color = AppColors.OnBackground,
|
||||||
fontSize = 18.sp
|
fontSize = 18.sp
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -251,13 +252,13 @@ fun CategoryCard(
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Description,
|
Icons.Default.Description,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Constants.AppColors.OnSurfaceTertiary,
|
tint = AppColors.OnSurfaceTertiary,
|
||||||
modifier = Modifier.size(14.dp)
|
modifier = Modifier.size(14.dp)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
"$noteCount catatan",
|
"$noteCount catatan",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = Constants.AppColors.OnSurfaceTertiary,
|
color = AppColors.OnSurfaceTertiary,
|
||||||
fontSize = 13.sp
|
fontSize = 13.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -275,7 +276,7 @@ fun EditCategoryDialog(
|
|||||||
var name by remember { mutableStateOf(category.name) }
|
var name by remember { mutableStateOf(category.name) }
|
||||||
var selectedGradient by remember {
|
var selectedGradient by remember {
|
||||||
mutableStateOf(
|
mutableStateOf(
|
||||||
Constants.AppColors.CategoryColors.indexOfFirst {
|
Constants.CategoryColors.indexOfFirst {
|
||||||
it.first == category.gradientStart && it.second == category.gradientEnd
|
it.first == category.gradientStart && it.second == category.gradientEnd
|
||||||
}.takeIf { it >= 0 } ?: 0
|
}.takeIf { it >= 0 } ?: 0
|
||||||
)
|
)
|
||||||
@ -283,12 +284,12 @@ fun EditCategoryDialog(
|
|||||||
|
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
containerColor = Constants.AppColors.Surface,
|
containerColor = AppColors.Surface,
|
||||||
shape = RoundedCornerShape(Constants.Radius.Large.dp),
|
shape = RoundedCornerShape(Constants.Radius.Large.dp),
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
"Edit Kategori",
|
"Edit Kategori",
|
||||||
color = Constants.AppColors.OnBackground,
|
color = AppColors.OnBackground,
|
||||||
fontWeight = FontWeight.Bold
|
fontWeight = FontWeight.Bold
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -300,18 +301,18 @@ fun EditCategoryDialog(
|
|||||||
label = {
|
label = {
|
||||||
Text(
|
Text(
|
||||||
"Nama Kategori",
|
"Nama Kategori",
|
||||||
color = Constants.AppColors.OnSurfaceVariant
|
color = AppColors.OnSurfaceVariant
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
colors = OutlinedTextFieldDefaults.colors(
|
colors = OutlinedTextFieldDefaults.colors(
|
||||||
focusedTextColor = Constants.AppColors.OnBackground,
|
focusedTextColor = AppColors.OnBackground,
|
||||||
unfocusedTextColor = Constants.AppColors.OnSurface,
|
unfocusedTextColor = AppColors.OnSurface,
|
||||||
focusedContainerColor = Constants.AppColors.SurfaceVariant,
|
focusedContainerColor = AppColors.SurfaceVariant,
|
||||||
unfocusedContainerColor = Constants.AppColors.SurfaceVariant,
|
unfocusedContainerColor = AppColors.SurfaceVariant,
|
||||||
cursorColor = Constants.AppColors.Primary,
|
cursorColor = AppColors.Primary,
|
||||||
focusedBorderColor = Constants.AppColors.Primary,
|
focusedBorderColor = AppColors.Primary,
|
||||||
unfocusedBorderColor = Constants.AppColors.Border
|
unfocusedBorderColor = AppColors.Border
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(Constants.Radius.Medium.dp)
|
shape = RoundedCornerShape(Constants.Radius.Medium.dp)
|
||||||
)
|
)
|
||||||
@ -321,20 +322,20 @@ fun EditCategoryDialog(
|
|||||||
Text(
|
Text(
|
||||||
"Pilih Warna:",
|
"Pilih Warna:",
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color = Constants.AppColors.OnSurface,
|
color = AppColors.OnSurface,
|
||||||
fontWeight = FontWeight.SemiBold,
|
fontWeight = FontWeight.SemiBold,
|
||||||
fontSize = 14.sp
|
fontSize = 14.sp
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
|
||||||
Constants.AppColors.CategoryColors.chunked(4).forEach { row ->
|
Constants.CategoryColors.chunked(4).forEach { row ->
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
row.forEachIndexed { _, gradient ->
|
row.forEachIndexed { _, gradient ->
|
||||||
val globalIndex = Constants.AppColors.CategoryColors.indexOf(gradient)
|
val globalIndex = Constants.CategoryColors.indexOf(gradient)
|
||||||
val isSelected = selectedGradient == globalIndex
|
val isSelected = selectedGradient == globalIndex
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
@ -376,13 +377,13 @@ fun EditCategoryDialog(
|
|||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (name.isNotBlank()) {
|
if (name.isNotBlank()) {
|
||||||
val gradient = Constants.AppColors.CategoryColors[selectedGradient]
|
val gradient = Constants.CategoryColors[selectedGradient]
|
||||||
onSave(name, gradient.first, gradient.second)
|
onSave(name, gradient.first, gradient.second)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
enabled = name.isNotBlank(),
|
enabled = name.isNotBlank(),
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
containerColor = Constants.AppColors.Primary
|
containerColor = AppColors.Primary
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Text("Simpan", color = Color.White, fontWeight = FontWeight.Bold)
|
Text("Simpan", color = Color.White, fontWeight = FontWeight.Bold)
|
||||||
@ -390,7 +391,7 @@ fun EditCategoryDialog(
|
|||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = onDismiss) {
|
TextButton(onClick = onDismiss) {
|
||||||
Text("Batal", color = Constants.AppColors.OnSurfaceVariant)
|
Text("Batal", color = AppColors.OnSurfaceVariant)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.example.notesai.data.model.Note
|
import com.example.notesai.data.model.Note
|
||||||
|
import com.example.notesai.util.AppColors
|
||||||
import com.example.notesai.util.Constants
|
import com.example.notesai.util.Constants
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -51,7 +52,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
|
containerColor = AppColors.SurfaceVariant
|
||||||
),
|
),
|
||||||
elevation = CardDefaults.cardElevation(
|
elevation = CardDefaults.cardElevation(
|
||||||
defaultElevation = 2.dp
|
defaultElevation = 2.dp
|
||||||
@ -73,7 +74,7 @@ fun NoteCard(
|
|||||||
note.title,
|
note.title,
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = MaterialTheme.typography.titleLarge,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
color = Constants.AppColors.OnBackground,
|
color = AppColors.OnBackground,
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
maxLines = 2,
|
maxLines = 2,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
@ -88,7 +89,7 @@ fun NoteCard(
|
|||||||
Icon(
|
Icon(
|
||||||
if (note.isPinned) Icons.Filled.Star else Icons.Outlined.StarBorder,
|
if (note.isPinned) Icons.Filled.Star else Icons.Outlined.StarBorder,
|
||||||
contentDescription = "Pin",
|
contentDescription = "Pin",
|
||||||
tint = if (note.isPinned) Constants.AppColors.Warning else Constants.AppColors.OnSurfaceVariant,
|
tint = if (note.isPinned) AppColors.Warning else AppColors.OnSurfaceVariant,
|
||||||
modifier = Modifier.size(18.dp)
|
modifier = Modifier.size(18.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -103,7 +104,7 @@ fun NoteCard(
|
|||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
maxLines = 3,
|
maxLines = 3,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
color = Constants.AppColors.OnSurfaceVariant,
|
color = AppColors.OnSurfaceVariant,
|
||||||
lineHeight = 20.sp,
|
lineHeight = 20.sp,
|
||||||
fontSize = 14.sp
|
fontSize = 14.sp
|
||||||
)
|
)
|
||||||
@ -114,7 +115,7 @@ fun NoteCard(
|
|||||||
Text(
|
Text(
|
||||||
"Tidak ada deskripsi",
|
"Tidak ada deskripsi",
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color = Constants.AppColors.OnSurfaceVariant.copy(alpha = 0.5f),
|
color = AppColors.OnSurfaceVariant.copy(alpha = 0.5f),
|
||||||
fontStyle = androidx.compose.ui.text.font.FontStyle.Italic,
|
fontStyle = androidx.compose.ui.text.font.FontStyle.Italic,
|
||||||
fontSize = 14.sp
|
fontSize = 14.sp
|
||||||
)
|
)
|
||||||
@ -124,7 +125,7 @@ fun NoteCard(
|
|||||||
|
|
||||||
// Divider
|
// Divider
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
color = Constants.AppColors.Divider,
|
color = AppColors.Divider,
|
||||||
thickness = 1.dp
|
thickness = 1.dp
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -139,7 +140,7 @@ fun NoteCard(
|
|||||||
Text(
|
Text(
|
||||||
dateFormat.format(Date(note.timestamp)),
|
dateFormat.format(Date(note.timestamp)),
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = Constants.AppColors.OnSurfaceTertiary,
|
color = AppColors.OnSurfaceTertiary,
|
||||||
fontSize = 12.sp
|
fontSize = 12.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
package com.example.notesai.util
|
package com.example.notesai.util
|
||||||
|
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
|
||||||
object Constants {
|
object Constants {
|
||||||
@ -16,56 +19,68 @@ object Constants {
|
|||||||
const val MAX_CHAT_PREVIEW_LINES = 2
|
const val MAX_CHAT_PREVIEW_LINES = 2
|
||||||
const val GRID_COLUMNS = 2
|
const val GRID_COLUMNS = 2
|
||||||
|
|
||||||
// NEW MINIMALIST COLOR PALETTE
|
// DARK THEME COLORS
|
||||||
object AppColors {
|
object DarkColors {
|
||||||
// Backgrounds - Neutral Dark
|
val Background = Color(0xFF0A0A0A)
|
||||||
val Background = Color(0xFF0A0A0A) // Almost black
|
val Surface = Color(0xFF141414)
|
||||||
val Surface = Color(0xFF141414) // Dark gray
|
val SurfaceVariant = Color(0xFF1E1E1E)
|
||||||
val SurfaceVariant = Color(0xFF1E1E1E) // Lighter dark gray
|
val SurfaceElevated = Color(0xFF252525)
|
||||||
val SurfaceElevated = Color(0xFF252525) // Elevated surface
|
val Primary = Color(0xFF3B82F6)
|
||||||
|
val PrimaryVariant = Color(0xFF60A5FA)
|
||||||
// Primary Accent - Subtle Blue (minimalist)
|
val PrimaryContainer = Color(0xFF1E3A8A)
|
||||||
val Primary = Color(0xFF3B82F6) // Modern blue
|
val Secondary = Color(0xFF8B5CF6)
|
||||||
val PrimaryVariant = Color(0xFF60A5FA) // Light blue
|
val SecondaryVariant = Color(0xFFA78BFA)
|
||||||
val PrimaryContainer = Color(0xFF1E3A8A) // Dark blue container
|
val OnBackground = Color(0xFFFFFFFF)
|
||||||
|
val OnSurface = Color(0xFFE5E5E5)
|
||||||
// Secondary Accent - Minimal use
|
val OnSurfaceVariant = Color(0xFF9CA3AF)
|
||||||
val Secondary = Color(0xFF8B5CF6) // Subtle purple
|
val OnSurfaceTertiary = Color(0xFF6B7280)
|
||||||
val SecondaryVariant = Color(0xFFA78BFA) // Light purple
|
val Success = Color(0xFF10B981)
|
||||||
|
val Error = Color(0xFFEF4444)
|
||||||
// Text Colors - High contrast for readability
|
val Warning = Color(0xFFFBBF24)
|
||||||
val OnBackground = Color(0xFFFFFFFF) // Pure white
|
val Info = Color(0xFF3B82F6)
|
||||||
val OnSurface = Color(0xFFE5E5E5) // Off white
|
val Border = Color(0xFF2A2A2A)
|
||||||
val OnSurfaceVariant = Color(0xFF9CA3AF) // Gray text
|
val Divider = Color(0xFF1F1F1F)
|
||||||
val OnSurfaceTertiary = Color(0xFF6B7280) // Muted gray
|
|
||||||
|
|
||||||
// Functional Colors
|
|
||||||
val Success = Color(0xFF10B981) // Green
|
|
||||||
val Error = Color(0xFFEF4444) // Red
|
|
||||||
val Warning = Color(0xFFFBBF24) // Amber
|
|
||||||
val Info = Color(0xFF3B82F6) // Blue
|
|
||||||
|
|
||||||
// Border & Dividers - Subtle
|
|
||||||
val Border = Color(0xFF2A2A2A) // Subtle border
|
|
||||||
val Divider = Color(0xFF1F1F1F) // Very subtle divider
|
|
||||||
|
|
||||||
// Overlay & Shadows
|
|
||||||
val Overlay = Color(0xFF000000).copy(alpha = 0.5f)
|
val Overlay = Color(0xFF000000).copy(alpha = 0.5f)
|
||||||
val Shadow = Color(0xFF000000).copy(alpha = 0.3f)
|
val Shadow = Color(0xFF000000).copy(alpha = 0.3f)
|
||||||
|
|
||||||
// Category Colors - Minimalist Palette (subtle & muted)
|
|
||||||
val CategoryColors = listOf(
|
|
||||||
Pair(0xFF3B82F6L, 0xFF60A5FAL), // Blue gradient
|
|
||||||
Pair(0xFF8B5CF6L, 0xFFA78BFAL), // Purple gradient
|
|
||||||
Pair(0xFF10B981L, 0xFF34D399L), // Green gradient
|
|
||||||
Pair(0xFFF59E0BL, 0xFFFBBF24L), // Amber gradient
|
|
||||||
Pair(0xFFEF4444L, 0xFFF87171L), // Red gradient
|
|
||||||
Pair(0xFF06B6D4L, 0xFF22D3EEL), // Cyan gradient
|
|
||||||
Pair(0xFFEC4899L, 0xFFF472B6L), // Pink gradient
|
|
||||||
Pair(0xFF6366F1L, 0xFF818CF8L) // Indigo gradient
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LIGHT THEME COLORS
|
||||||
|
object LightColors {
|
||||||
|
val Background = Color(0xFFF8F9FA)
|
||||||
|
val Surface = Color(0xFFFFFFFF)
|
||||||
|
val SurfaceVariant = Color(0xFFF1F3F5)
|
||||||
|
val SurfaceElevated = Color(0xFFFFFFFF)
|
||||||
|
val Primary = Color(0xFF3B82F6)
|
||||||
|
val PrimaryVariant = Color(0xFF2563EB)
|
||||||
|
val PrimaryContainer = Color(0xFFDCEEFF)
|
||||||
|
val Secondary = Color(0xFF8B5CF6)
|
||||||
|
val SecondaryVariant = Color(0xFF7C3AED)
|
||||||
|
val OnBackground = Color(0xFF1F2937)
|
||||||
|
val OnSurface = Color(0xFF374151)
|
||||||
|
val OnSurfaceVariant = Color(0xFF6B7280)
|
||||||
|
val OnSurfaceTertiary = Color(0xFF9CA3AF)
|
||||||
|
val Success = Color(0xFF10B981)
|
||||||
|
val Error = Color(0xFFEF4444)
|
||||||
|
val Warning = Color(0xFFA16207)
|
||||||
|
val Info = Color(0xFF3B82F6)
|
||||||
|
val Border = Color(0xFFE5E7EB)
|
||||||
|
val Divider = Color(0xFFF3F4F6)
|
||||||
|
val Overlay = Color(0xFF000000).copy(alpha = 0.3f)
|
||||||
|
val Shadow = Color(0xFF000000).copy(alpha = 0.1f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Category Colors - Same for both themes
|
||||||
|
val CategoryColors = listOf(
|
||||||
|
Pair(0xFF3B82F6L, 0xFF60A5FAL), // Blue
|
||||||
|
Pair(0xFF8B5CF6L, 0xFFA78BFAL), // Purple
|
||||||
|
Pair(0xFF10B981L, 0xFF34D399L), // Green
|
||||||
|
Pair(0xFFF59E0BL, 0xFFFBBF24L), // Amber
|
||||||
|
Pair(0xFFEF4444L, 0xFFF87171L), // Red
|
||||||
|
Pair(0xFF06B6D4L, 0xFF22D3EEL), // Cyan
|
||||||
|
Pair(0xFFEC4899L, 0xFFF472B6L), // Pink
|
||||||
|
Pair(0xFF6366F1L, 0xFF818CF8L) // Indigo
|
||||||
|
)
|
||||||
|
|
||||||
// Animation Durations
|
// Animation Durations
|
||||||
const val ANIMATION_DURATION_SHORT = 150
|
const val ANIMATION_DURATION_SHORT = 150
|
||||||
const val ANIMATION_DURATION_MEDIUM = 300
|
const val ANIMATION_DURATION_MEDIUM = 300
|
||||||
@ -73,7 +88,7 @@ object Constants {
|
|||||||
const val FADE_IN_DURATION = 200
|
const val FADE_IN_DURATION = 200
|
||||||
const val FADE_OUT_DURATION = 200
|
const val FADE_OUT_DURATION = 200
|
||||||
|
|
||||||
// Spacing System (8dp grid)
|
// Spacing System
|
||||||
object Spacing {
|
object Spacing {
|
||||||
const val ExtraSmall = 4
|
const val ExtraSmall = 4
|
||||||
const val Small = 8
|
const val Small = 8
|
||||||
@ -101,3 +116,78 @@ object Constants {
|
|||||||
const val ExtraLarge = 16
|
const val ExtraLarge = 16
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// REACTIVE APP COLORS - Using Compose State
|
||||||
|
object AppColors {
|
||||||
|
// Internal state
|
||||||
|
private var _isDark by mutableStateOf(true)
|
||||||
|
|
||||||
|
// Public setter
|
||||||
|
fun setTheme(isDark: Boolean) {
|
||||||
|
_isDark = isDark
|
||||||
|
}
|
||||||
|
|
||||||
|
// All colors are now reactive via mutableStateOf
|
||||||
|
val Background: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.Background else Constants.LightColors.Background
|
||||||
|
|
||||||
|
val Surface: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.Surface else Constants.LightColors.Surface
|
||||||
|
|
||||||
|
val SurfaceVariant: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.SurfaceVariant else Constants.LightColors.SurfaceVariant
|
||||||
|
|
||||||
|
val SurfaceElevated: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.SurfaceElevated else Constants.LightColors.SurfaceElevated
|
||||||
|
|
||||||
|
val Primary: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.Primary else Constants.LightColors.Primary
|
||||||
|
|
||||||
|
val PrimaryVariant: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.PrimaryVariant else Constants.LightColors.PrimaryVariant
|
||||||
|
|
||||||
|
val PrimaryContainer: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.PrimaryContainer else Constants.LightColors.PrimaryContainer
|
||||||
|
|
||||||
|
val Secondary: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.Secondary else Constants.LightColors.Secondary
|
||||||
|
|
||||||
|
val SecondaryVariant: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.SecondaryVariant else Constants.LightColors.SecondaryVariant
|
||||||
|
|
||||||
|
val OnBackground: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.OnBackground else Constants.LightColors.OnBackground
|
||||||
|
|
||||||
|
val OnSurface: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.OnSurface else Constants.LightColors.OnSurface
|
||||||
|
|
||||||
|
val OnSurfaceVariant: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.OnSurfaceVariant else Constants.LightColors.OnSurfaceVariant
|
||||||
|
|
||||||
|
val OnSurfaceTertiary: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.OnSurfaceTertiary else Constants.LightColors.OnSurfaceTertiary
|
||||||
|
|
||||||
|
val Success: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.Success else Constants.LightColors.Success
|
||||||
|
|
||||||
|
val Error: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.Error else Constants.LightColors.Error
|
||||||
|
|
||||||
|
val Warning: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.Warning else Constants.LightColors.Warning
|
||||||
|
|
||||||
|
val Info: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.Info else Constants.LightColors.Info
|
||||||
|
|
||||||
|
val Border: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.Border else Constants.LightColors.Border
|
||||||
|
|
||||||
|
val Divider: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.Divider else Constants.LightColors.Divider
|
||||||
|
|
||||||
|
val Overlay: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.Overlay else Constants.LightColors.Overlay
|
||||||
|
|
||||||
|
val Shadow: Color
|
||||||
|
get() = if (_isDark) Constants.DarkColors.Shadow else Constants.LightColors.Shadow
|
||||||
|
}
|
||||||
@ -12,6 +12,10 @@ constraintlayout = "2.1.4"
|
|||||||
uiText = "1.10.0"
|
uiText = "1.10.0"
|
||||||
material3 = "1.4.0"
|
material3 = "1.4.0"
|
||||||
animationCore = "1.10.0"
|
animationCore = "1.10.0"
|
||||||
|
firebaseAnnotations = "17.0.0"
|
||||||
|
firebaseFirestoreKtx = "26.0.2"
|
||||||
|
uiGraphics = "1.10.0"
|
||||||
|
roomCompiler = "2.8.4"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
@ -25,6 +29,10 @@ androidx-constraintlayout = { group = "androidx.constraintlayout", name = "const
|
|||||||
androidx-ui-text = { group = "androidx.compose.ui", name = "ui-text", version.ref = "uiText" }
|
androidx-ui-text = { group = "androidx.compose.ui", name = "ui-text", version.ref = "uiText" }
|
||||||
androidx-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" }
|
androidx-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" }
|
||||||
androidx-animation-core = { group = "androidx.compose.animation", name = "animation-core", version.ref = "animationCore" }
|
androidx-animation-core = { group = "androidx.compose.animation", name = "animation-core", version.ref = "animationCore" }
|
||||||
|
firebase-annotations = { group = "com.google.firebase", name = "firebase-annotations", version.ref = "firebaseAnnotations" }
|
||||||
|
firebase-firestore-ktx = { group = "com.google.firebase", name = "firebase-firestore-ktx", version.ref = "firebaseFirestoreKtx" }
|
||||||
|
androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics", version.ref = "uiGraphics" }
|
||||||
|
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "roomCompiler" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user