Skip to content

Commit afeb818

Browse files
authored
Merge pull request #74 from HellBus1/richtext-editor-1.3.0
Merge richtext editor into 1.3.0
2 parents 048ee9e + fd771f1 commit afeb818

26 files changed

Lines changed: 1731 additions & 460 deletions
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package com.digiventure.ventnote.commons.richtext
2+
3+
import androidx.compose.animation.animateColorAsState
4+
import androidx.compose.animation.core.tween
5+
import androidx.compose.foundation.background
6+
import androidx.compose.foundation.clickable
7+
import androidx.compose.foundation.layout.Arrangement
8+
import androidx.compose.foundation.layout.Box
9+
import androidx.compose.foundation.layout.Row
10+
import androidx.compose.foundation.layout.fillMaxWidth
11+
import androidx.compose.foundation.layout.padding
12+
import androidx.compose.foundation.layout.size
13+
import androidx.compose.foundation.shape.RoundedCornerShape
14+
import androidx.compose.material3.MaterialTheme
15+
import androidx.compose.material3.Text
16+
import androidx.compose.runtime.Composable
17+
import androidx.compose.runtime.getValue
18+
import androidx.compose.ui.Alignment
19+
import androidx.compose.ui.Modifier
20+
import androidx.compose.ui.draw.clip
21+
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
22+
import androidx.compose.ui.platform.LocalHapticFeedback
23+
import androidx.compose.ui.text.font.FontStyle
24+
import androidx.compose.ui.text.font.FontWeight
25+
import androidx.compose.ui.text.style.TextDecoration
26+
import androidx.compose.ui.unit.dp
27+
import androidx.compose.ui.unit.sp
28+
29+
/**
30+
* Formatting toolbar with toggle buttons for bold, italic, underline, and bullet list.
31+
* Uses text-based buttons to avoid the Material Icons Extended dependency.
32+
*/
33+
@Composable
34+
fun FormattingToolbar(
35+
richTextState: RichTextState,
36+
modifier: Modifier = Modifier
37+
) {
38+
Row(
39+
modifier = modifier
40+
.fillMaxWidth()
41+
.background(
42+
MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f),
43+
RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)
44+
)
45+
.padding(horizontal = 16.dp, vertical = 8.dp),
46+
horizontalArrangement = Arrangement.SpaceEvenly,
47+
verticalAlignment = Alignment.CenterVertically
48+
) {
49+
FormatToggleButton(
50+
label = "B",
51+
fontWeight = FontWeight.ExtraBold,
52+
isActive = richTextState.isStyleActive(RichTextStyle.Bold),
53+
onClick = { richTextState.toggleStyle(RichTextStyle.Bold) }
54+
)
55+
56+
FormatToggleButton(
57+
label = "I",
58+
fontStyle = FontStyle.Italic,
59+
isActive = richTextState.isStyleActive(RichTextStyle.Italic),
60+
onClick = { richTextState.toggleStyle(RichTextStyle.Italic) }
61+
)
62+
63+
FormatToggleButton(
64+
label = "U",
65+
textDecoration = TextDecoration.Underline,
66+
isActive = richTextState.isStyleActive(RichTextStyle.Underline),
67+
onClick = { richTextState.toggleStyle(RichTextStyle.Underline) }
68+
)
69+
70+
FormatToggleButton(
71+
label = "",
72+
fontSize = 20,
73+
isActive = richTextState.isBulletListActive(),
74+
onClick = { richTextState.toggleBulletList() }
75+
)
76+
}
77+
}
78+
79+
@Composable
80+
private fun FormatToggleButton(
81+
label: String,
82+
isActive: Boolean,
83+
onClick: () -> Unit,
84+
fontWeight: FontWeight = FontWeight.SemiBold,
85+
fontStyle: FontStyle = FontStyle.Normal,
86+
textDecoration: TextDecoration = TextDecoration.None,
87+
fontSize: Int = 18
88+
) {
89+
val haptics = LocalHapticFeedback.current
90+
91+
val backgroundColor by animateColorAsState(
92+
targetValue = if (isActive) {
93+
MaterialTheme.colorScheme.primaryContainer
94+
} else {
95+
MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.01f)
96+
},
97+
animationSpec = tween(200),
98+
label = "format_button_bg"
99+
)
100+
101+
val textColor by animateColorAsState(
102+
targetValue = if (isActive) {
103+
MaterialTheme.colorScheme.onPrimaryContainer
104+
} else {
105+
MaterialTheme.colorScheme.onSurfaceVariant
106+
},
107+
animationSpec = tween(200),
108+
label = "format_button_text"
109+
)
110+
111+
Box(
112+
modifier = Modifier
113+
.size(40.dp)
114+
.clip(RoundedCornerShape(10.dp))
115+
.background(backgroundColor, RoundedCornerShape(10.dp))
116+
.clickable {
117+
haptics.performHapticFeedback(HapticFeedbackType.TextHandleMove)
118+
onClick()
119+
},
120+
contentAlignment = Alignment.Center
121+
) {
122+
Text(
123+
text = label,
124+
fontSize = fontSize.sp,
125+
fontWeight = fontWeight,
126+
fontStyle = fontStyle,
127+
textDecoration = textDecoration,
128+
color = textColor
129+
)
130+
}
131+
}

0 commit comments

Comments
 (0)