@@ -43,11 +43,14 @@ import androidx.compose.ui.graphics.toArgb
4343import androidx.compose.ui.input.pointer.pointerInput
4444import androidx.compose.ui.platform.LocalContext
4545import androidx.compose.ui.res.painterResource
46+ import androidx.compose.ui.text.AnnotatedString
4647import androidx.compose.ui.text.ExperimentalTextApi
4748import androidx.compose.ui.text.SpanStyle
4849import androidx.compose.ui.text.TextLayoutResult
4950import androidx.compose.ui.text.TextStyle
5051import androidx.compose.ui.text.buildAnnotatedString
52+ import androidx.compose.ui.text.font.Font
53+ import androidx.compose.ui.text.font.FontFamily
5154import androidx.compose.ui.text.font.FontWeight
5255import androidx.compose.ui.text.style.TextAlign
5356import androidx.compose.ui.text.style.TextDecoration
@@ -57,9 +60,12 @@ import androidx.compose.ui.unit.dp
5760import androidx.compose.ui.unit.sp
5861import androidx.compose.ui.viewinterop.AndroidView
5962import androidx.core.net.toUri
60- import com.github.creativecodecat.components.views.FontAppCompatTextView
63+ import com.github.codeworkscreativehub.mlauncher.R
64+ import com.github.codeworkscreativehub.mlauncher.data.Constants
65+ import com.github.codeworkscreativehub.mlauncher.data.Prefs
6166import com.github.codeworkscreativehub.mlauncher.services.HapticFeedbackService
6267import com.github.codeworkscreativehub.mlauncher.style.SettingsTheme
68+ import com.github.creativecodecat.components.views.FontAppCompatTextView
6369import kotlinx.coroutines.Job
6470import kotlinx.coroutines.delay
6571import kotlinx.coroutines.launch
@@ -94,7 +100,7 @@ object SettingsComposable {
94100 Spacer (modifier = Modifier .width(12 .dp)) // small spacing between icon and title
95101
96102 // Title text
97- Text (
103+ FontText (
98104 text = title,
99105 fontSize = titleFontSize,
100106 color = fontColor,
@@ -131,7 +137,7 @@ object SettingsComposable {
131137 .let { if (onIconClick != null ) it.clickable { onIconClick() } else it }
132138 )
133139
134- Text (
140+ FontText (
135141 text = title,
136142 fontSize = if (titleFontSize != TextUnit .Unspecified ) titleFontSize else 18 .sp,
137143 color = fontColor,
@@ -221,7 +227,7 @@ object SettingsComposable {
221227 Spacer (modifier = Modifier .width(12 .dp))
222228
223229 Column {
224- Text (
230+ FontText (
225231 text = title,
226232 color = headerColor,
227233 fontSize = if (titleFontSize != TextUnit .Unspecified ) titleFontSize else 18 .sp,
@@ -231,7 +237,7 @@ object SettingsComposable {
231237
232238 description?.let {
233239 Spacer (modifier = Modifier .height(1 .dp))
234- Text (
240+ FontText (
235241 text = it,
236242 color = optionColor,
237243 fontSize = if (descriptionFontSize != TextUnit .Unspecified ) descriptionFontSize else 12 .sp,
@@ -259,7 +265,7 @@ object SettingsComposable {
259265 horizontalAlignment = Alignment .CenterHorizontally
260266 ) {
261267 // Title
262- Text (
268+ FontText (
263269 text = title,
264270 color = titleColor,
265271 fontSize = titleFontSize,
@@ -337,7 +343,7 @@ object SettingsComposable {
337343
338344 val layoutResult = remember { mutableStateOf<TextLayoutResult ?>(null ) }
339345
340- Text (
346+ FontText (
341347 text = annotatedString,
342348 style = TextStyle (color = color, fontSize = fontSize),
343349 modifier = modifier.pointerInput(Unit ) {
@@ -379,7 +385,7 @@ object SettingsComposable {
379385 // Optional: touch ripple effect
380386 val typedValue = TypedValue ()
381387 context.theme.resolveAttribute(
382- android. R .attr.selectableItemBackground, typedValue, true
388+ R .attr.selectableItemBackground, typedValue, true
383389 )
384390 setBackgroundResource(typedValue.resourceId)
385391 }
@@ -514,20 +520,94 @@ object SettingsComposable {
514520 horizontalAlignment = Alignment .Start
515521 ) {
516522 // Title
517- Text (
523+ FontText (
518524 text = title,
519525 fontSize = fontSizeSp.sp,
520526 color = titleColor,
521527 modifier = Modifier .wrapContentHeight()
522528 )
523529
524530 // Option / secondary text
525- Text (
531+ FontText (
526532 text = option,
527533 fontSize = (fontSizeSp / 1.3f ).sp,
528534 color = optionColor,
529535 modifier = Modifier .wrapContentHeight()
530536 )
531537 }
532538 }
539+
540+ @Composable
541+ fun FontText (
542+ text : Any , // String or AnnotatedString
543+ modifier : Modifier = Modifier ,
544+ fontSize : TextUnit = 16.sp,
545+ color : Color = SettingsTheme .typography.title.color,
546+ fontWeight : FontWeight ? = null,
547+ style : TextStyle ? = null, // Optional additional style
548+ onClick : (() -> Unit )? = null,
549+ onTextLayout : ((TextLayoutResult ) -> Unit )? = null
550+ ) {
551+ val context = LocalContext .current
552+ val prefs = Prefs (context)
553+
554+ // Map saved preference to Compose FontFamily
555+ val fontFamily: FontFamily = remember(prefs.fontFamily) {
556+ when (prefs.fontFamily) {
557+ Constants .FontFamily .System -> FontFamily .Default
558+ Constants .FontFamily .Roboto -> FontFamily (Font (R .font.roboto))
559+ Constants .FontFamily .Bitter -> FontFamily (Font (R .font.bitter))
560+ Constants .FontFamily .Doto -> FontFamily (Font (R .font.doto))
561+ Constants .FontFamily .FiraCode -> FontFamily (Font (R .font.fira_code))
562+ Constants .FontFamily .Hack -> FontFamily (Font (R .font.hack))
563+ Constants .FontFamily .Lato -> FontFamily (Font (R .font.lato))
564+ Constants .FontFamily .Merriweather -> FontFamily (Font (R .font.merriweather))
565+ Constants .FontFamily .Montserrat -> FontFamily (Font (R .font.montserrat))
566+ Constants .FontFamily .Quicksand -> FontFamily (Font (R .font.quicksand))
567+ Constants .FontFamily .Raleway -> FontFamily (Font (R .font.raleway))
568+ Constants .FontFamily .SourceCodePro -> FontFamily (Font (R .font.source_code_pro))
569+ Constants .FontFamily .Custom -> FontFamily .Default
570+ }
571+ }
572+
573+ // Merge optional style with defaults
574+ val finalStyle = (style ? : TextStyle ()).copy(
575+ fontFamily = fontFamily,
576+ fontSize = fontSize,
577+ fontWeight = fontWeight,
578+ color = color
579+ )
580+
581+ // Clickable modifier with ripple
582+ val clickableModifier = if (onClick != null ) {
583+ Modifier .clickable(
584+ onClick = onClick,
585+ )
586+ } else Modifier
587+
588+ when (text) {
589+ is String -> {
590+ Text (
591+ text = text,
592+ modifier = modifier.then(clickableModifier),
593+ style = finalStyle,
594+ onTextLayout = onTextLayout
595+ )
596+ }
597+
598+ is AnnotatedString -> {
599+ if (onTextLayout != null ) {
600+ Text (
601+ text = text,
602+ modifier = modifier.then(clickableModifier),
603+ style = finalStyle,
604+ onTextLayout = onTextLayout
605+ )
606+ }
607+ }
608+
609+ else -> throw IllegalArgumentException (" FontText supports only String or AnnotatedString" )
610+ }
611+ }
612+
533613}
0 commit comments