diff --git a/app/src/main/java/com/example/cahier/core/data/SerializedInkDataClasses.kt b/app/src/main/java/com/example/cahier/core/data/SerializedInkDataClasses.kt index 9bd89177..596ff063 100644 --- a/app/src/main/java/com/example/cahier/core/data/SerializedInkDataClasses.kt +++ b/app/src/main/java/com/example/cahier/core/data/SerializedInkDataClasses.kt @@ -63,4 +63,7 @@ enum class SerializedStockBrush { PressurePenLatest, HighlighterLatest, DashedLineLatest, + EmojiHighlighterHeartLatest, + EmojiHighlighterStarLatest, + EmojiHighlighterPoopLatest, } \ No newline at end of file diff --git a/app/src/main/java/com/example/cahier/core/ui/CahierTextureBitmapStore.kt b/app/src/main/java/com/example/cahier/core/ui/CahierTextureBitmapStore.kt index 998fc362..2712b9b9 100644 --- a/app/src/main/java/com/example/cahier/core/ui/CahierTextureBitmapStore.kt +++ b/app/src/main/java/com/example/cahier/core/ui/CahierTextureBitmapStore.kt @@ -31,7 +31,10 @@ class CahierTextureBitmapStore(context: Context) : TextureBitmapStore { private val textureResources: Map = mapOf( "music-clef-g" to R.drawable.music_clef_g, - "music-note-sixteenth" to R.drawable.music_note_sixteenth + "music-note-sixteenth" to R.drawable.music_note_sixteenth, + "emoji-heart" to R.drawable.emoji_heart, + "emoji-star" to R.drawable.emoji_star, + "emoji-poop" to R.drawable.emoji_poop, ) private val loadedBitmaps = mutableMapOf() diff --git a/app/src/main/java/com/example/cahier/core/ui/Converters.kt b/app/src/main/java/com/example/cahier/core/ui/Converters.kt index d15b2a8e..0f014325 100644 --- a/app/src/main/java/com/example/cahier/core/ui/Converters.kt +++ b/app/src/main/java/com/example/cahier/core/ui/Converters.kt @@ -49,6 +49,9 @@ class Converters { StockBrushes.pressurePen() to SerializedStockBrush.PressurePenLatest, StockBrushes.highlighter() to SerializedStockBrush.HighlighterLatest, StockBrushes.dashedLine() to SerializedStockBrush.DashedLineLatest, + StockBrushes.emojiHighlighter("emoji-heart", showMiniEmojiTrail = true) to SerializedStockBrush.EmojiHighlighterHeartLatest, + StockBrushes.emojiHighlighter("emoji-star", showMiniEmojiTrail = true) to SerializedStockBrush.EmojiHighlighterStarLatest, + StockBrushes.emojiHighlighter("emoji-poop", showMiniEmojiTrail = true) to SerializedStockBrush.EmojiHighlighterPoopLatest, ) private val enumToStockBrush = diff --git a/app/src/main/java/com/example/cahier/developer/brushdesigner/ui/BrushDesignerTopBar.kt b/app/src/main/java/com/example/cahier/developer/brushdesigner/ui/BrushDesignerTopBar.kt index 2136e5eb..72b4c3fb 100644 --- a/app/src/main/java/com/example/cahier/developer/brushdesigner/ui/BrushDesignerTopBar.kt +++ b/app/src/main/java/com/example/cahier/developer/brushdesigner/ui/BrushDesignerTopBar.kt @@ -44,11 +44,15 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.PopupProperties import androidx.ink.brush.BrushFamily import androidx.ink.brush.StockBrushes import com.example.cahier.R @@ -140,6 +144,7 @@ private fun BrushLibraryMenu( R.string.marker to StockBrushes.marker(), R.string.pressure_pen to StockBrushes.pressurePen(), R.string.dashed_line to StockBrushes.dashedLine(), + R.string.emoji_highlighter to StockBrushes.emojiHighlighter("emoji-heart", showMiniEmojiTrail = true), ) } @@ -159,7 +164,7 @@ private fun BrushLibraryMenu( onClick = {}, enabled = false ) - stockBrushes.forEach { (nameResId, brushFamily) -> + stockBrushes.filter { it.first != R.string.emoji_highlighter }.forEach { (nameResId, brushFamily) -> DropdownMenuItem( text = { Text(stringResource(nameResId)) }, onClick = { @@ -168,6 +173,55 @@ private fun BrushLibraryMenu( } ) } + + var showEmojiSubMenu by remember { mutableStateOf(false) } + var itemWidth by remember { mutableStateOf(0) } + var itemHeight by remember { mutableStateOf(0) } + val density = LocalDensity.current + + Box(modifier = Modifier.onSizeChanged { + itemWidth = it.width + itemHeight = it.height + }) { + DropdownMenuItem( + text = { Text(stringResource(R.string.emoji_highlighter)) }, + trailingIcon = { + Text(text = if (showEmojiSubMenu) "▶" else "▼") + }, + onClick = { showEmojiSubMenu = true } + ) + DropdownMenu( + expanded = showEmojiSubMenu, + onDismissRequest = { showEmojiSubMenu = false }, + offset = DpOffset(x = density.run { itemWidth.toDp() }, y = density.run { -itemHeight.toDp() }), + properties = PopupProperties(focusable = true) + ) { + DropdownMenuItem( + text = { Text(stringResource(R.string.emoji_heart)) }, + onClick = { + onLoadBrush(StockBrushes.emojiHighlighter("emoji-heart", showMiniEmojiTrail = true)) + showEmojiSubMenu = false + expanded = false + } + ) + DropdownMenuItem( + text = { Text(stringResource(R.string.emoji_star)) }, + onClick = { + onLoadBrush(StockBrushes.emojiHighlighter("emoji-star", showMiniEmojiTrail = true)) + showEmojiSubMenu = false + expanded = false + } + ) + DropdownMenuItem( + text = { Text(stringResource(R.string.emoji_poop)) }, + onClick = { + onLoadBrush(StockBrushes.emojiHighlighter("emoji-poop", showMiniEmojiTrail = true)) + showEmojiSubMenu = false + expanded = false + } + ) + } + } if (cahierBrushes.isNotEmpty()) { DropdownMenuItem( diff --git a/app/src/main/java/com/example/cahier/features/drawing/DrawingToolbox.kt b/app/src/main/java/com/example/cahier/features/drawing/DrawingToolbox.kt index ef82901b..a433d36b 100644 --- a/app/src/main/java/com/example/cahier/features/drawing/DrawingToolbox.kt +++ b/app/src/main/java/com/example/cahier/features/drawing/DrawingToolbox.kt @@ -42,13 +42,17 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.window.PopupProperties import androidx.ink.brush.BrushFamily @@ -431,9 +435,14 @@ fun BrushesDropdownMenu( customBrushes: List, modifier: Modifier = Modifier ) { + var showEmojiSubMenu by remember { mutableStateOf(false) } + DropdownMenu( expanded = expanded, - onDismissRequest = onDismissRequest, + onDismissRequest = { + onDismissRequest() + showEmojiSubMenu = false + }, properties = PopupProperties(focusable = true), modifier = modifier ) { @@ -477,6 +486,77 @@ fun BrushesDropdownMenu( }, onClick = { onBrushChange(StockBrushes.dashedLine()) } ) + var itemWidth by remember { mutableStateOf(0) } + var itemHeight by remember { mutableStateOf(0) } + val density = LocalDensity.current + + Box(modifier = Modifier.onSizeChanged { + itemWidth = it.width + itemHeight = it.height + }) { + DropdownMenuItem( + text = { Text(text = stringResource(R.string.emoji_highlighter)) }, + leadingIcon = { + Icon( + painter = painterResource(R.drawable.ic_emoji_highlighter), + contentDescription = stringResource(R.string.emoji_highlighter) + ) + }, + trailingIcon = { + Text(text = if (showEmojiSubMenu) "▶" else "▼") + }, + onClick = { showEmojiSubMenu = true } + ) + DropdownMenu( + expanded = showEmojiSubMenu, + onDismissRequest = { showEmojiSubMenu = false }, + offset = DpOffset(x = density.run { itemWidth.toDp() }, y = density.run { -itemHeight.toDp() }), + properties = PopupProperties(focusable = true) + ) { + DropdownMenuItem( + text = { Text(text = stringResource(R.string.emoji_heart)) }, + leadingIcon = { + Icon( + painter = painterResource(R.drawable.ic_emoji_heart), + contentDescription = stringResource(R.string.emoji_heart) + ) + }, + onClick = { + onBrushChange(StockBrushes.emojiHighlighter("emoji-heart", showMiniEmojiTrail = true)) + showEmojiSubMenu = false + onDismissRequest() + } + ) + DropdownMenuItem( + text = { Text(text = stringResource(R.string.emoji_star)) }, + leadingIcon = { + Icon( + painter = painterResource(R.drawable.ic_emoji_star), + contentDescription = stringResource(R.string.emoji_star) + ) + }, + onClick = { + onBrushChange(StockBrushes.emojiHighlighter("emoji-star", showMiniEmojiTrail = true)) + showEmojiSubMenu = false + onDismissRequest() + } + ) + DropdownMenuItem( + text = { Text(text = stringResource(R.string.emoji_poop)) }, + leadingIcon = { + Icon( + painter = painterResource(R.drawable.ic_emoji_poop), + contentDescription = stringResource(R.string.emoji_poop) + ) + }, + onClick = { + onBrushChange(StockBrushes.emojiHighlighter("emoji-poop", showMiniEmojiTrail = true)) + showEmojiSubMenu = false + onDismissRequest() + } + ) + } + } if (customBrushes.isNotEmpty()) { HorizontalDivider() Text( diff --git a/app/src/main/java/com/example/cahier/features/drawing/viewmodel/DrawingCanvasViewModel.kt b/app/src/main/java/com/example/cahier/features/drawing/viewmodel/DrawingCanvasViewModel.kt index f8c87393..8104b241 100644 --- a/app/src/main/java/com/example/cahier/features/drawing/viewmodel/DrawingCanvasViewModel.kt +++ b/app/src/main/java/com/example/cahier/features/drawing/viewmodel/DrawingCanvasViewModel.kt @@ -88,6 +88,11 @@ class DrawingCanvasViewModel @Inject constructor( private val currentNightMode = AppCompatDelegate.getDefaultNightMode() + private val heartHighlighter = StockBrushes.emojiHighlighter("emoji-heart", showMiniEmojiTrail = true) + private val poopHighlighter = StockBrushes.emojiHighlighter("emoji-poop", showMiniEmojiTrail = true) + private val starHighlighter = StockBrushes.emojiHighlighter("emoji-star", showMiniEmojiTrail = true) + private val highlighter = StockBrushes.highlighter() + private val _defaultBrush = MutableStateFlow( Brush.createWithComposeColor( family = StockBrushes.pressurePen(), @@ -375,10 +380,12 @@ class DrawingCanvasViewModel @Inject constructor( isBrushSelectedInSession = true _selectedBrush.update { currentBrush -> val newBrush = currentBrush.copy(family = brushFamily) - val colorToApply = if (newBrush.family == StockBrushes.highlighter()) { - newBrush.composeColor.copy(alpha = HIGHLIGHTER_ALPHA) - } else { - newBrush.composeColor.copy(alpha = 1f) + val colorToApply = when(newBrush.family) { + highlighter -> newBrush.composeColor.copy(alpha = HIGHLIGHTER_ALPHA) + heartHighlighter -> Color(0xFFFF45CA).copy(alpha = HIGHLIGHTER_ALPHA) + poopHighlighter -> Color(0xFF783013).copy(alpha = HIGHLIGHTER_ALPHA) + starHighlighter -> Color(0xFFFFE100).copy(alpha = HIGHLIGHTER_ALPHA) + else -> newBrush.composeColor.copy(alpha = 1f) } newBrush.copyWithComposeColor(colorToApply) } @@ -388,10 +395,12 @@ class DrawingCanvasViewModel @Inject constructor( isBrushSelectedInSession = true _selectedBrush.update { currentBrush -> val newBrush = currentBrush.copy(family = brushFamily, size = size) - val colorToApply = if (newBrush.family == StockBrushes.highlighter()) { - newBrush.composeColor.copy(alpha = HIGHLIGHTER_ALPHA) - } else { - newBrush.composeColor.copy(alpha = 1f) + val colorToApply = when(newBrush.family) { + highlighter -> newBrush.composeColor.copy(alpha = HIGHLIGHTER_ALPHA) + heartHighlighter -> Color(0xFFFF45CA).copy(alpha = HIGHLIGHTER_ALPHA) + poopHighlighter -> Color(0xFF783013).copy(alpha = HIGHLIGHTER_ALPHA) + starHighlighter -> Color(0xFFFFE100).copy(alpha = HIGHLIGHTER_ALPHA) + else -> newBrush.composeColor.copy(alpha = 1f) } newBrush.copyWithComposeColor(colorToApply) } @@ -400,10 +409,12 @@ class DrawingCanvasViewModel @Inject constructor( fun changeBrushColor(color: Color) { isBrushSelectedInSession = true _selectedBrush.update { currentBrush -> - val colorToApply = if (currentBrush.family == StockBrushes.highlighter()) { - color.copy(alpha = HIGHLIGHTER_ALPHA) - } else { - color.copy(alpha = 1f) + val colorToApply = when(currentBrush.family) { + heartHighlighter, + poopHighlighter, + starHighlighter, + highlighter -> color.copy(alpha = HIGHLIGHTER_ALPHA) + else -> color.copy(alpha = 1f) } currentBrush.copyWithComposeColor(color = colorToApply) } diff --git a/app/src/main/res/drawable/emoji_heart.png b/app/src/main/res/drawable/emoji_heart.png new file mode 100644 index 00000000..d2d96d2e Binary files /dev/null and b/app/src/main/res/drawable/emoji_heart.png differ diff --git a/app/src/main/res/drawable/emoji_poop.png b/app/src/main/res/drawable/emoji_poop.png new file mode 100644 index 00000000..6ee9a4b8 Binary files /dev/null and b/app/src/main/res/drawable/emoji_poop.png differ diff --git a/app/src/main/res/drawable/emoji_star.png b/app/src/main/res/drawable/emoji_star.png new file mode 100644 index 00000000..04196162 Binary files /dev/null and b/app/src/main/res/drawable/emoji_star.png differ diff --git a/app/src/main/res/drawable/ic_emoji_heart.xml b/app/src/main/res/drawable/ic_emoji_heart.xml new file mode 100644 index 00000000..c9de8483 --- /dev/null +++ b/app/src/main/res/drawable/ic_emoji_heart.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_emoji_highlighter.xml b/app/src/main/res/drawable/ic_emoji_highlighter.xml new file mode 100644 index 00000000..684e2565 --- /dev/null +++ b/app/src/main/res/drawable/ic_emoji_highlighter.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_emoji_poop.xml b/app/src/main/res/drawable/ic_emoji_poop.xml new file mode 100644 index 00000000..b7bbb262 --- /dev/null +++ b/app/src/main/res/drawable/ic_emoji_poop.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_emoji_star.xml b/app/src/main/res/drawable/ic_emoji_star.xml new file mode 100644 index 00000000..be0426d5 --- /dev/null +++ b/app/src/main/res/drawable/ic_emoji_star.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7c9403b4..009423f0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -49,6 +49,10 @@ Marker Highlighter Dashed line + Emoji Highlighter + Heart Emoji + Star Emoji + Poop Emoji Note image preview Drawing note indicator