diff --git a/app/schemas/cloud.pablos.overload.data.OverloadDatabase/2.json b/app/schemas/cloud.pablos.overload.data.OverloadDatabase/2.json index 9083aef..f2f3dac 100644 --- a/app/schemas/cloud.pablos.overload.data.OverloadDatabase/2.json +++ b/app/schemas/cloud.pablos.overload.data.OverloadDatabase/2.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 2, - "identityHash": "5786d9fcd0545b1af0077201c347aca5", + "identityHash": "eec8bb3483c07bec27c31bf05a9b56e7", "entities": [ { "tableName": "categories", @@ -50,7 +50,7 @@ }, { "tableName": "items", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `startTime` TEXT NOT NULL, `endTime` TEXT NOT NULL, `ongoing` INTEGER NOT NULL, `pause` INTEGER NOT NULL, `categoryId` INTEGER NOT NULL DEFAULT 0)", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `startTime` TEXT NOT NULL, `endTime` TEXT NOT NULL, `ongoing` INTEGER NOT NULL, `pause` INTEGER NOT NULL, `categoryId` INTEGER NOT NULL DEFAULT 1)", "fields": [ { "fieldPath": "id", @@ -87,7 +87,7 @@ "columnName": "categoryId", "affinity": "INTEGER", "notNull": true, - "defaultValue": "0" + "defaultValue": "1" } ], "primaryKey": { @@ -103,7 +103,7 @@ "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '5786d9fcd0545b1af0077201c347aca5')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'eec8bb3483c07bec27c31bf05a9b56e7')" ] } } \ No newline at end of file diff --git a/app/src/main/java/cloud/pablos/overload/data/category/CategoryEvent.kt b/app/src/main/java/cloud/pablos/overload/data/category/CategoryEvent.kt index 22ccda8..e5419d8 100644 --- a/app/src/main/java/cloud/pablos/overload/data/category/CategoryEvent.kt +++ b/app/src/main/java/cloud/pablos/overload/data/category/CategoryEvent.kt @@ -18,4 +18,6 @@ sealed interface CategoryEvent { data class SetSelectedCategoryConfigurations(val selectedCategoryConfigurations: Int) : CategoryEvent data class SetSelectedCategory(val selectedCategory: Int) : CategoryEvent + + data class SetIsCreateCategoryDialogOpenHome(val isCreateCategoryDialogOpenHome: Boolean) : CategoryEvent } diff --git a/app/src/main/java/cloud/pablos/overload/data/category/CategoryState.kt b/app/src/main/java/cloud/pablos/overload/data/category/CategoryState.kt index e5ad60f..1155296 100644 --- a/app/src/main/java/cloud/pablos/overload/data/category/CategoryState.kt +++ b/app/src/main/java/cloud/pablos/overload/data/category/CategoryState.kt @@ -15,4 +15,5 @@ data class CategoryState( // -- val selectedCategoryConfigurations: Int = 1, val selectedCategory: Int = 1, + val isCreateCategoryDialogOpenHome: Boolean = false, ) diff --git a/app/src/main/java/cloud/pablos/overload/data/category/CategoryViewModel.kt b/app/src/main/java/cloud/pablos/overload/data/category/CategoryViewModel.kt index 63509d2..d2e75f7 100644 --- a/app/src/main/java/cloud/pablos/overload/data/category/CategoryViewModel.kt +++ b/app/src/main/java/cloud/pablos/overload/data/category/CategoryViewModel.kt @@ -124,6 +124,14 @@ class CategoryViewModel( ) } } + + is CategoryEvent.SetIsCreateCategoryDialogOpenHome -> { + _state.update { + it.copy( + isCreateCategoryDialogOpenHome = event.isCreateCategoryDialogOpenHome, + ) + } + } } } } diff --git a/app/src/main/java/cloud/pablos/overload/data/item/Item.kt b/app/src/main/java/cloud/pablos/overload/data/item/Item.kt index 0f22883..7391bb7 100644 --- a/app/src/main/java/cloud/pablos/overload/data/item/Item.kt +++ b/app/src/main/java/cloud/pablos/overload/data/item/Item.kt @@ -11,6 +11,6 @@ data class Item( val endTime: String, val ongoing: Boolean, val pause: Boolean, - @ColumnInfo(defaultValue = "0") + @ColumnInfo(defaultValue = "1") val categoryId: Int, ) diff --git a/app/src/main/java/cloud/pablos/overload/data/item/ItemDao.kt b/app/src/main/java/cloud/pablos/overload/data/item/ItemDao.kt index 4da5440..3d27c9a 100644 --- a/app/src/main/java/cloud/pablos/overload/data/item/ItemDao.kt +++ b/app/src/main/java/cloud/pablos/overload/data/item/ItemDao.kt @@ -1,9 +1,12 @@ package cloud.pablos.overload.data.item +import androidx.compose.ui.graphics.Color import androidx.room.Dao import androidx.room.Delete import androidx.room.Query import androidx.room.Upsert +import cloud.pablos.overload.data.Converters.Companion.convertColorToLong +import cloud.pablos.overload.data.category.CategoryEvent import cloud.pablos.overload.data.category.CategoryState import cloud.pablos.overload.ui.tabs.home.getItemsOfDay import cloud.pablos.overload.ui.views.extractDate @@ -30,7 +33,31 @@ interface ItemDao { fun getAllItems(): Flow> } -fun startOrStopPause( +fun fabPress( + categoryState: CategoryState, + categoryEvent: (CategoryEvent) -> Unit, + itemState: ItemState, + itemEvent: (ItemEvent) -> Unit, +) { + val categories = categoryState.categories + + if (categories.isNotEmpty()) { + startOrStop(categoryState, itemState, itemEvent) + } else if (itemState.items.isNotEmpty()) { + categoryEvent(CategoryEvent.SetId(1)) + categoryEvent(CategoryEvent.SetName("Default")) + categoryEvent(CategoryEvent.SetColor(convertColorToLong(Color(204, 230, 255)))) + categoryEvent(CategoryEvent.SetEmoji("๐Ÿ•ฃ")) + categoryEvent(CategoryEvent.SetIsDefault(true)) + categoryEvent(CategoryEvent.SaveCategory) + + startOrStop(categoryState, itemState, itemEvent) + } else { + categoryEvent(CategoryEvent.SetIsCreateCategoryDialogOpenHome(true)) + } +} + +fun startOrStop( categoryState: CategoryState, itemState: ItemState, itemEvent: (ItemEvent) -> Unit, diff --git a/app/src/main/java/cloud/pablos/overload/ui/navigation/OverloadNavigationFab.kt b/app/src/main/java/cloud/pablos/overload/ui/navigation/OverloadNavigationFab.kt index 0dc7932..34f577e 100644 --- a/app/src/main/java/cloud/pablos/overload/ui/navigation/OverloadNavigationFab.kt +++ b/app/src/main/java/cloud/pablos/overload/ui/navigation/OverloadNavigationFab.kt @@ -35,7 +35,7 @@ import cloud.pablos.overload.data.category.CategoryEvent import cloud.pablos.overload.data.category.CategoryState import cloud.pablos.overload.data.item.ItemEvent import cloud.pablos.overload.data.item.ItemState -import cloud.pablos.overload.data.item.startOrStopPause +import cloud.pablos.overload.data.item.fabPress import cloud.pablos.overload.ui.tabs.home.HomeTabManualDialog import cloud.pablos.overload.ui.tabs.home.getItemsOfDay import cloud.pablos.overload.ui.views.TextView @@ -237,7 +237,7 @@ fun OverloadNavigationFab( FloatingActionButton( onClick = { if (isLongClick.not()) { - startOrStopPause(categoryState, itemState, itemEvent) + fabPress(categoryState, categoryEvent, itemState, itemEvent) } }, interactionSource = interactionSource, diff --git a/app/src/main/java/cloud/pablos/overload/ui/navigation/OverloadNavigationFabSmall.kt b/app/src/main/java/cloud/pablos/overload/ui/navigation/OverloadNavigationFabSmall.kt index 9a0cfcd..ac3950b 100644 --- a/app/src/main/java/cloud/pablos/overload/ui/navigation/OverloadNavigationFabSmall.kt +++ b/app/src/main/java/cloud/pablos/overload/ui/navigation/OverloadNavigationFabSmall.kt @@ -29,7 +29,7 @@ import cloud.pablos.overload.data.category.CategoryEvent import cloud.pablos.overload.data.category.CategoryState import cloud.pablos.overload.data.item.ItemEvent import cloud.pablos.overload.data.item.ItemState -import cloud.pablos.overload.data.item.startOrStopPause +import cloud.pablos.overload.data.item.fabPress import cloud.pablos.overload.ui.tabs.home.HomeTabDeleteFAB import cloud.pablos.overload.ui.tabs.home.HomeTabManualDialog import cloud.pablos.overload.ui.tabs.home.getItemsOfDay @@ -141,7 +141,7 @@ fun OverloadNavigationFabSmall( FloatingActionButton( onClick = { if (isLongClick.not()) { - startOrStopPause(categoryState, itemState, itemEvent) + fabPress(categoryState, categoryEvent, itemState, itemEvent) } }, interactionSource = interactionSource, diff --git a/app/src/main/java/cloud/pablos/overload/ui/screens/category/CategoryScreen.kt b/app/src/main/java/cloud/pablos/overload/ui/screens/category/CategoryScreen.kt index fe9fafa..7856d73 100644 --- a/app/src/main/java/cloud/pablos/overload/ui/screens/category/CategoryScreen.kt +++ b/app/src/main/java/cloud/pablos/overload/ui/screens/category/CategoryScreen.kt @@ -1,23 +1,60 @@ package cloud.pablos.overload.ui.screens.day +import android.graphics.drawable.Icon import android.os.Build import androidx.annotation.RequiresApi -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.clickable +import androidx.compose.foundation.horizontalScroll +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.DarkMode +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.clearAndSetSemantics +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.unit.dp +import cloud.pablos.overload.R +import cloud.pablos.overload.data.Converters.Companion.convertColorToLong +import cloud.pablos.overload.data.Converters.Companion.convertLongToColor import cloud.pablos.overload.data.category.CategoryEvent import cloud.pablos.overload.data.category.CategoryState import cloud.pablos.overload.data.item.ItemEvent import cloud.pablos.overload.data.item.ItemState import cloud.pablos.overload.ui.navigation.OverloadRoute import cloud.pablos.overload.ui.navigation.OverloadTopAppBar -import cloud.pablos.overload.ui.views.TextView +import cloud.pablos.overload.ui.tabs.configurations.ConfigurationDescription +import cloud.pablos.overload.ui.tabs.configurations.ConfigurationTitle +import cloud.pablos.overload.ui.tabs.configurations.ConfigurationsTabItem +import cloud.pablos.overload.ui.tabs.configurations.SelectableColor +import cloud.pablos.overload.ui.tabs.configurations.SelectableEmoji +import cloud.pablos.overload.ui.tabs.configurations.colorOptions +import cloud.pablos.overload.ui.tabs.configurations.emojiOptions +import cloud.pablos.overload.ui.tabs.configurations.hDivider -@OptIn(ExperimentalFoundationApi::class) @RequiresApi(Build.VERSION_CODES.S) @Composable fun CategoryScreen( @@ -27,6 +64,17 @@ fun CategoryScreen( itemEvent: (ItemEvent) -> Unit, ) { val selectedCategory = categoryState.categories.find { it.id == categoryState.selectedCategoryConfigurations } + var name by remember { mutableStateOf(TextFieldValue(selectedCategory?.name ?: "")) } + var color by remember { mutableStateOf(selectedCategory?.color?.let { convertLongToColor(it) } ?: Color.Unspecified) } + var emoji by remember { mutableStateOf(selectedCategory?.emoji ?: "") } + + var nameError by remember { mutableStateOf(false) } + + LaunchedEffect(color, emoji) { + if (selectedCategory != null) { + save(categoryEvent, selectedCategory.id, name.text, convertColorToLong(color), emoji, selectedCategory.isDefault) + } + } Scaffold( topBar = { @@ -38,8 +86,217 @@ fun CategoryScreen( ) }, ) { paddingValues -> - Box(modifier = Modifier.fillMaxSize().padding(paddingValues)) { - TextView(text = "lmao") + LazyColumn( + modifier = + Modifier + .fillMaxSize() + .padding(paddingValues) + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(6.dp), + ) { + if (selectedCategory != null) { + item { + ConfigurationsTabItem(title = "Name") + } + + item { + Column( + verticalArrangement = Arrangement.spacedBy(10.dp), + ) { + OutlinedTextField( + value = name, + onValueChange = { + name = it + + if (it.text.isNotEmpty()) { + nameError = false + } + }, + singleLine = true, + placeholder = { Text(text = "Name") }, + isError = nameError, + keyboardActions = + KeyboardActions( + onDone = { + if (name.text.isEmpty()) { + nameError = true + return@KeyboardActions + } else { + nameError = false + } + + save( + categoryEvent, + selectedCategory.id, + name.text, + convertColorToLong(color), + emoji, + selectedCategory.isDefault, + ) + }, + ), + modifier = Modifier.fillMaxWidth(), + ) + } + } + + if (selectedCategory.isDefault.not()) { + item { + hDivider() + } + + item { + ConfigurationsTabItem(title = "Color") + } + + item { + Column( + verticalArrangement = Arrangement.spacedBy(10.dp), + ) { + Row( + modifier = + Modifier + .horizontalScroll(rememberScrollState()), + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + colorOptions.forEach { colorOption -> + SelectableColor( + selected = colorOption == color, + onClick = { color = colorOption }, + color = colorOption, + surfaceColor = MaterialTheme.colorScheme.surfaceVariant, + ) + } + } + } + } + } + + item { + hDivider() + } + + item { + ConfigurationsTabItem(title = "Emoji") + } + + item { + Column( + verticalArrangement = Arrangement.spacedBy(10.dp), + ) { + Row( + modifier = + Modifier + .horizontalScroll(rememberScrollState()), + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + emojiOptions.forEach { emojiOption -> + SelectableEmoji( + selected = emojiOption == emoji, + onClick = { emoji = emojiOption }, + emoji = emojiOption, + color = color, + surfaceColor = MaterialTheme.colorScheme.surfaceVariant, + ) + } + } + } + } + + item { + hDivider() + } + + item { + ConfigurationsTabItem(title = stringResource(id = R.string.goals)) + } + + // Work Goal + item { + val itemLabel = + stringResource(id = R.string.work) + ": " + stringResource(id = R.string.work_goal_descr) + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = + Modifier + .clip(shape = RoundedCornerShape(15.dp)) + .clickable { + // workGoalDialogState.value = true + } + .clearAndSetSemantics { + contentDescription = itemLabel + }, + ) { + Text( + selectedCategory.emoji, + modifier = Modifier.padding(horizontal = 8.dp), + ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth(), + ) { + Column { + ConfigurationTitle(selectedCategory.name) + ConfigurationDescription("Set a goal for " + selectedCategory.name) + } + } + } + } + + // Pause Goal + item { + val itemLabel = + stringResource(id = R.string.pause) + ": " + stringResource(id = R.string.pause_goal_descr) + + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = + Modifier + .padding(bottom = 16.dp) + .clip(shape = RoundedCornerShape(15.dp)) + .clickable { + // pauseGoalDialogState.value = true + } + .clearAndSetSemantics { + contentDescription = itemLabel + }, + ) { + Icon( + imageVector = Icons.Filled.DarkMode, + contentDescription = stringResource(id = R.string.pause), + tint = MaterialTheme.colorScheme.primary, + modifier = Modifier.padding(horizontal = 8.dp), + ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth(), + ) { + Column { + ConfigurationTitle(stringResource(id = R.string.pause)) + ConfigurationDescription(stringResource(id = R.string.pause_goal_descr)) + } + } + } + } + } } } } + +fun save( + categoryEvent: (CategoryEvent) -> Unit, + id: Int, + name: String, + color: Long, + emoji: String, + isDefault: Boolean, +) { + categoryEvent(CategoryEvent.SetId(id)) + categoryEvent(CategoryEvent.SetName(name)) + categoryEvent(CategoryEvent.SetColor(color)) + categoryEvent(CategoryEvent.SetEmoji(emoji)) + categoryEvent(CategoryEvent.SetIsDefault(isDefault)) + categoryEvent(CategoryEvent.SaveCategory) +} diff --git a/app/src/main/java/cloud/pablos/overload/ui/screens/category/CategoryScreenTopAppBar.kt b/app/src/main/java/cloud/pablos/overload/ui/screens/category/CategoryScreenTopAppBar.kt index 69633ef..ca9bf10 100644 --- a/app/src/main/java/cloud/pablos/overload/ui/screens/category/CategoryScreenTopAppBar.kt +++ b/app/src/main/java/cloud/pablos/overload/ui/screens/category/CategoryScreenTopAppBar.kt @@ -21,7 +21,7 @@ fun CategoryScreenTopAppBar(categoryState: CategoryState) { TopAppBar( title = { TextView( - text = selectedCategory?.name ?: "Unknown Category", + text = "Category" + ": " + (selectedCategory?.name ?: "Unknown"), fontSize = MaterialTheme.typography.titleLarge.fontSize, ) }, diff --git a/app/src/main/java/cloud/pablos/overload/ui/tabs/configurations/ConfigurationsTab.kt b/app/src/main/java/cloud/pablos/overload/ui/tabs/configurations/ConfigurationsTab.kt index 60cc2b8..c425568 100644 --- a/app/src/main/java/cloud/pablos/overload/ui/tabs/configurations/ConfigurationsTab.kt +++ b/app/src/main/java/cloud/pablos/overload/ui/tabs/configurations/ConfigurationsTab.kt @@ -36,7 +36,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment @@ -53,7 +52,6 @@ import androidx.navigation.NavHostController import androidx.room.withTransaction import cloud.pablos.overload.R import cloud.pablos.overload.data.Backup -import cloud.pablos.overload.data.Converters.Companion.convertColorToLong import cloud.pablos.overload.data.OverloadDatabase import cloud.pablos.overload.data.category.Category import cloud.pablos.overload.data.category.CategoryEvent @@ -103,20 +101,6 @@ fun ConfigurationsTab( val workGoalDialogState = remember { mutableStateOf(false) } val pauseGoalDialogState = remember { mutableStateOf(false) } - val color = convertColorToLong(MaterialTheme.colorScheme.onSurfaceVariant) - - val categories = categoryState.categories - LaunchedEffect(categories) { - if (categories.isEmpty()) { - categoryEvent(CategoryEvent.SetId(1)) - categoryEvent(CategoryEvent.SetName("Default")) - categoryEvent(CategoryEvent.SetColor(color)) - categoryEvent(CategoryEvent.SetEmoji("๐Ÿ•ฃ")) - categoryEvent(CategoryEvent.SetIsDefault(true)) - categoryEvent(CategoryEvent.SaveCategory) - } - } - Scaffold( topBar = { OverloadTopAppBar( @@ -222,9 +206,7 @@ fun ConfigurationsTab( ConfigurationsTabItem(title = stringResource(id = R.string.categories)) } - categoryState.categories.filter { - categoryState.selectedCategory != it.id - }.forEach { category -> + categoryState.categories.forEach { category -> item { ConfigurationsTabItem( title = category.emoji + " " + category.name, @@ -245,16 +227,7 @@ fun ConfigurationsTab( .fillMaxWidth(), ) { FilledTonalButton(onClick = { - if (categoryState.categories.isEmpty()) { - categoryEvent(CategoryEvent.SetId(1)) - categoryEvent(CategoryEvent.SetName("Default")) - categoryEvent(CategoryEvent.SetColor(color)) - categoryEvent(CategoryEvent.SetEmoji("๐Ÿ•ฃ")) - categoryEvent(CategoryEvent.SetIsDefault(true)) - categoryEvent(CategoryEvent.SaveCategory) - } else { - createCategoryDialog.value = true - } + createCategoryDialog.value = true }) { Row( verticalAlignment = Alignment.CenterVertically, @@ -276,9 +249,7 @@ fun ConfigurationsTab( // Categories Divider item { - Row { - HorizontalDivider() - } + hDivider() } // Analytics Title @@ -316,9 +287,7 @@ fun ConfigurationsTab( // Analytics Divider item { - Row { - HorizontalDivider() - } + hDivider() } // Storage Title @@ -346,9 +315,7 @@ fun ConfigurationsTab( // Storage Divider item { - Row { - HorizontalDivider() - } + hDivider() } // About Title @@ -398,9 +365,7 @@ fun ConfigurationsTab( // About Divider item { - Row { - HorizontalDivider() - } + hDivider() } // Footer @@ -539,7 +504,6 @@ private fun importCsvData( val endTime = row[2].trim() val ongoing = row[3].trim() val pause = row[4].trim() - val categoryId = row[5].trim() val item = Item( @@ -547,7 +511,7 @@ private fun importCsvData( endTime = endTime, ongoing = ongoing.toBoolean(), pause = pause.toBoolean(), - categoryId = categoryId.toInt(), + categoryId = 1, ) val importResult = itemDao.upsertItem(item) @@ -742,6 +706,11 @@ fun ConfigurationDescription(text: String) { ) } +@Composable +fun hDivider() { + HorizontalDivider(modifier = Modifier.padding(top = 20.dp)) +} + class OlSharedPreferences(context: Context) { private val sharedPreferences = context.getSharedPreferences("ol_prefs", Context.MODE_PRIVATE) diff --git a/app/src/main/java/cloud/pablos/overload/ui/tabs/configurations/ConfigurationsTabCreateCategoryDialog.kt b/app/src/main/java/cloud/pablos/overload/ui/tabs/configurations/ConfigurationsTabCreateCategoryDialog.kt index 08ce945..c590ad9 100644 --- a/app/src/main/java/cloud/pablos/overload/ui/tabs/configurations/ConfigurationsTabCreateCategoryDialog.kt +++ b/app/src/main/java/cloud/pablos/overload/ui/tabs/configurations/ConfigurationsTabCreateCategoryDialog.kt @@ -21,6 +21,7 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Check import androidx.compose.material3.AlertDialog @@ -44,6 +45,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp @@ -52,75 +54,77 @@ import cloud.pablos.overload.data.Converters.Companion.convertColorToLong import cloud.pablos.overload.data.category.CategoryEvent import cloud.pablos.overload.ui.views.TextView +val colorOptions: List = + listOf( + Color(255, 209, 220), // Pastel Pink + Color(255, 204, 204), // Pastel Red + Color(250, 223, 173), // Pastel Yellow + Color(255, 230, 204), // Light Orange + Color(204, 255, 229), // Pastel Green + Color(230, 255, 204), // Light Lime + Color(221, 204, 255), // Pastel Purple + Color(230, 204, 255), // Light Indigo + Color(204, 230, 255), // Pastel Blue + Color(204, 255, 255), // Light Cyan + Color(255, 204, 230), // Light Magenta + Color(255, 230, 255), // Light Lavender + ) + +val emojiOptions: List = + listOf( + "๐Ÿ’ผ", + "๐Ÿ‘”", + "๐Ÿ’ป", + "๐Ÿ–‹๏ธ", + "๐Ÿ“š", + "๐ŸŽ“", + "๐Ÿ“", + "โœ๏ธ", + "๐Ÿ‹๏ธโ€โ™‚๏ธ", + "๐Ÿšด", + "๐Ÿƒ", + "โ›น๏ธโ€โ™€๏ธ", + "๐ŸŽ‰", + "๐Ÿป", + "๐ŸŽฎ", + "๐Ÿน", + "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ", + "๐Ÿ‘ช", + "๐Ÿก", + "๐ŸŽจ", + "๐ŸŽธ", + "๐ŸŽฎ", + "๐Ÿ“ท", + "๐Ÿณ", + "๐Ÿ”", + "๐Ÿ•", + "๐Ÿฅ—", + "โœˆ๏ธ", + "๐Ÿš—", + "๐Ÿšข", + "๐ŸŒ", + "๐Ÿ’Š", + "๐Ÿง˜", + "๐Ÿฅ", + "๐ŸŒฑ", + "๐Ÿ›€", + "๐ŸŒ…", + "๐Ÿ›‹๏ธ", + "๐Ÿ“บ", + ) + @OptIn(ExperimentalMaterial3Api::class) @Composable fun ConfigurationsTabCreateCategoryDialog( onClose: () -> Unit, categoryEvent: (CategoryEvent) -> Unit, ) { - val colorOptions: List = - listOf( - Color(255, 209, 220), // Pastel Pink - Color(255, 204, 204), // Pastel Red - Color(250, 223, 173), // Pastel Yellow - Color(255, 230, 204), // Light Orange - Color(204, 255, 229), // Pastel Green - Color(230, 255, 204), // Light Lime - Color(221, 204, 255), // Pastel Purple - Color(230, 204, 255), // Light Indigo - Color(204, 230, 255), // Pastel Blue - Color(204, 255, 255), // Light Cyan - Color(255, 204, 230), // Light Magenta - Color(255, 230, 255), // Light Lavender - ) - - val emojiOptions: List = - listOf( - "๐Ÿ’ผ", - "๐Ÿ‘”", - "๐Ÿ’ป", - "๐Ÿ–‹๏ธ", - "๐Ÿ“š", - "๐ŸŽ“", - "๐Ÿ“", - "โœ๏ธ", - "๐Ÿ‹๏ธโ€โ™‚๏ธ", - "๐Ÿšด", - "๐Ÿƒ", - "โ›น๏ธโ€โ™€๏ธ", - "๐ŸŽ‰", - "๐Ÿป", - "๐ŸŽฎ", - "๐Ÿน", - "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ", - "๐Ÿ‘ช", - "๐Ÿก", - "๐ŸŽจ", - "๐ŸŽธ", - "๐ŸŽฎ", - "๐Ÿ“ท", - "๐Ÿณ", - "๐Ÿ”", - "๐Ÿ•", - "๐Ÿฅ—", - "โœˆ๏ธ", - "๐Ÿš—", - "๐Ÿšข", - "๐ŸŒ", - "๐Ÿ’Š", - "๐Ÿง˜", - "๐Ÿฅ", - "๐ŸŒฑ", - "๐Ÿ›€", - "๐ŸŒ…", - "๐Ÿ›‹๏ธ", - "๐Ÿ“บ", - ) - var name by remember { mutableStateOf(TextFieldValue()) } var color by remember { mutableStateOf(colorOptions.first()) } var emoji by remember { mutableStateOf(emojiOptions.first()) } + var nameError by remember { mutableStateOf(false) } + AlertDialog( onDismissRequest = onClose, title = { @@ -140,10 +144,24 @@ fun ConfigurationsTabCreateCategoryDialog( Column( verticalArrangement = Arrangement.spacedBy(8.dp), ) { + TextView( + "Name", + fontWeight = FontWeight.Bold, + color = if (nameError) MaterialTheme.colorScheme.error else Color.Unspecified, + ) OutlinedTextField( value = name, - onValueChange = { name = it }, - label = { Text(text = "Name") }, + onValueChange = + { + name = it + if (it.text.isNotEmpty()) { + nameError = false + } + }, + singleLine = true, + placeholder = { Text(text = "Name") }, + isError = nameError, + keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Sentences), ) } @@ -198,6 +216,13 @@ fun ConfigurationsTabCreateCategoryDialog( confirmButton = { Button( onClick = { + if (name.text.isEmpty()) { + nameError = true + return@Button + } else { + nameError = false + } + categoryEvent(CategoryEvent.SetName(name.text.replaceFirstChar { it.uppercase() })) categoryEvent(CategoryEvent.SetEmoji(emoji)) categoryEvent(CategoryEvent.SetColor(convertColorToLong(color))) @@ -223,46 +248,25 @@ fun ConfigurationsTabCreateCategoryDialog( contentColor = MaterialTheme.colorScheme.onSecondaryContainer, ), ) { - Text(text = stringResource(R.string.cancel)) + TextView(text = stringResource(R.string.cancel)) } }, modifier = Modifier.padding(16.dp), ) } -private fun (() -> Unit).save( - sharedPreferences: OlSharedPreferences, - hours: Int?, - minutes: Int?, - valid: Boolean, - isPause: Boolean, -) { - if (valid) { - val hoursInMin = (hours ?: 0) * 60 - val minutesInMin = minutes ?: 0 - val goal = (hoursInMin + minutesInMin) * 60 * 1000 - - if (goal > 0) { - when (isPause) { - true -> sharedPreferences.savePauseGoal(goal) - false -> sharedPreferences.saveWorkGoal(goal) - } - this() - } - } -} - @Composable fun SelectableColor( modifier: Modifier = Modifier, selected: Boolean, onClick: () -> Unit, color: Color, + surfaceColor: Color = MaterialTheme.colorScheme.surfaceContainerLowest, ) { Surface( modifier = modifier, shape = RoundedCornerShape(16.dp), - color = MaterialTheme.colorScheme.inverseOnSurface, + color = surfaceColor, ) { Surface( modifier = @@ -306,13 +310,13 @@ fun SelectableEmoji( onClick: () -> Unit, emoji: String, color: Color, + surfaceColor: Color = MaterialTheme.colorScheme.surfaceContainerLowest, ) { - val surfaceColorUnselected = MaterialTheme.colorScheme.inverseOnSurface val surfaceColorSelected = MaterialTheme.colorScheme.primary - val surfaceColor = remember { Animatable(if (selected) surfaceColorSelected else surfaceColorUnselected) } + val surfaceColorBySelection = remember { Animatable(if (selected) surfaceColorSelected else surfaceColor) } LaunchedEffect(selected) { - surfaceColor.animateTo( - if (selected) surfaceColorSelected else surfaceColorUnselected, + surfaceColorBySelection.animateTo( + if (selected) surfaceColorSelected else surfaceColor, animationSpec = tween(250), ) } @@ -328,7 +332,7 @@ fun SelectableEmoji( Surface( modifier = modifier, shape = RoundedCornerShape(16.dp), - color = surfaceColor.value, + color = surfaceColorBySelection.value, ) { Surface( modifier = diff --git a/app/src/main/java/cloud/pablos/overload/ui/tabs/configurations/ConfigurationsTabItem.kt b/app/src/main/java/cloud/pablos/overload/ui/tabs/configurations/ConfigurationsTabItem.kt index 63c0ee2..551c77b 100644 --- a/app/src/main/java/cloud/pablos/overload/ui/tabs/configurations/ConfigurationsTabItem.kt +++ b/app/src/main/java/cloud/pablos/overload/ui/tabs/configurations/ConfigurationsTabItem.kt @@ -145,7 +145,7 @@ fun ConfigurationsTabItem( } } } else { - Row(Modifier.padding(top = 16.dp)) { + Row { ConfigurationLabel(title.replaceFirstChar { it.uppercase() }) } } diff --git a/app/src/main/java/cloud/pablos/overload/ui/tabs/home/HomeTab.kt b/app/src/main/java/cloud/pablos/overload/ui/tabs/home/HomeTab.kt index 2ffb759..b30c771 100644 --- a/app/src/main/java/cloud/pablos/overload/ui/tabs/home/HomeTab.kt +++ b/app/src/main/java/cloud/pablos/overload/ui/tabs/home/HomeTab.kt @@ -37,6 +37,7 @@ import cloud.pablos.overload.data.item.ItemEvent import cloud.pablos.overload.data.item.ItemState import cloud.pablos.overload.ui.navigation.OverloadRoute import cloud.pablos.overload.ui.navigation.OverloadTopAppBar +import cloud.pablos.overload.ui.tabs.configurations.ConfigurationsTabCreateCategoryDialog import cloud.pablos.overload.ui.utils.OverloadNavigationType import cloud.pablos.overload.ui.views.TextView import kotlinx.coroutines.launch @@ -142,6 +143,15 @@ fun HomeTab( } } } + + if (categoryState.isCreateCategoryDialogOpenHome) { + ConfigurationsTabCreateCategoryDialog( + onClose = { + categoryEvent(CategoryEvent.SetIsCreateCategoryDialogOpenHome(false)) + }, + categoryEvent, + ) + } } fun getFormattedDate( diff --git a/app/src/main/java/cloud/pablos/overload/ui/tabs/home/HomeTabFab.kt b/app/src/main/java/cloud/pablos/overload/ui/tabs/home/HomeTabFab.kt index da3435f..7b86cbd 100644 --- a/app/src/main/java/cloud/pablos/overload/ui/tabs/home/HomeTabFab.kt +++ b/app/src/main/java/cloud/pablos/overload/ui/tabs/home/HomeTabFab.kt @@ -39,7 +39,7 @@ import cloud.pablos.overload.data.category.CategoryEvent import cloud.pablos.overload.data.category.CategoryState import cloud.pablos.overload.data.item.ItemEvent import cloud.pablos.overload.data.item.ItemState -import cloud.pablos.overload.data.item.startOrStopPause +import cloud.pablos.overload.data.item.fabPress import cloud.pablos.overload.ui.views.TextView import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collectLatest @@ -179,7 +179,7 @@ fun HomeTabFab( FloatingActionButton( onClick = { if (isLongClick.not()) { - startOrStopPause(categoryState, itemState, itemEvent) + fabPress(categoryState, categoryEvent, itemState, itemEvent) } }, interactionSource = interactionSource, diff --git a/app/src/main/java/cloud/pablos/overload/ui/views/TextView.kt b/app/src/main/java/cloud/pablos/overload/ui/views/TextView.kt index d9be039..d0d60b5 100644 --- a/app/src/main/java/cloud/pablos/overload/ui/views/TextView.kt +++ b/app/src/main/java/cloud/pablos/overload/ui/views/TextView.kt @@ -15,7 +15,7 @@ fun TextView( text: String, modifier: Modifier = Modifier, fontSize: TextUnit = TextUnit.Unspecified, - fontWeight: FontWeight = FontWeight.Normal, + fontWeight: FontWeight? = null, color: Color = Color.Unspecified, align: TextAlign = TextAlign.Left, maxLines: Int = 1,