|
|
@@ -15,12 +15,37 @@ import androidx.compose.foundation.layout.padding
|
|
|
import androidx.compose.foundation.rememberScrollState
|
|
|
import androidx.compose.foundation.verticalScroll
|
|
|
import androidx.compose.material.icons.Icons
|
|
|
+import androidx.compose.material.icons.filled.AlignHorizontalCenter
|
|
|
+import androidx.compose.material.icons.filled.AlignHorizontalLeft
|
|
|
+import androidx.compose.material.icons.filled.AlignHorizontalRight
|
|
|
+import androidx.compose.material.icons.filled.AspectRatio
|
|
|
+import androidx.compose.material.icons.filled.CallSplit
|
|
|
import androidx.compose.material.icons.filled.CleanHands
|
|
|
+import androidx.compose.material.icons.filled.Code
|
|
|
+import androidx.compose.material.icons.filled.CopyAll
|
|
|
+import androidx.compose.material.icons.filled.FormatAlignJustify
|
|
|
+import androidx.compose.material.icons.filled.FormatColorText
|
|
|
+import androidx.compose.material.icons.filled.FormatIndentIncrease
|
|
|
import androidx.compose.material.icons.filled.FormatItalic
|
|
|
+import androidx.compose.material.icons.filled.FormatLineSpacing
|
|
|
+import androidx.compose.material.icons.filled.FormatSize
|
|
|
import androidx.compose.material.icons.filled.FormatUnderlined
|
|
|
+import androidx.compose.material.icons.filled.Height
|
|
|
+import androidx.compose.material.icons.filled.Image
|
|
|
import androidx.compose.material.icons.filled.Layers
|
|
|
+import androidx.compose.material.icons.filled.LineWeight
|
|
|
+import androidx.compose.material.icons.filled.Minimize
|
|
|
+import androidx.compose.material.icons.filled.Palette
|
|
|
+import androidx.compose.material.icons.filled.Segment
|
|
|
+import androidx.compose.material.icons.filled.SpaceBar
|
|
|
import androidx.compose.material.icons.filled.TextFields
|
|
|
+import androidx.compose.material.icons.filled.Title
|
|
|
+import androidx.compose.material.icons.filled.Translate
|
|
|
import androidx.compose.material.icons.filled.Tune
|
|
|
+import androidx.compose.material.icons.filled.VerticalAlignBottom
|
|
|
+import androidx.compose.material.icons.filled.VerticalAlignTop
|
|
|
+import androidx.compose.material.icons.filled.ViewAgenda
|
|
|
+import androidx.compose.material.icons.filled.ViewHeadline
|
|
|
import androidx.compose.runtime.Composable
|
|
|
import androidx.compose.runtime.getValue
|
|
|
import androidx.compose.runtime.mutableFloatStateOf
|
|
|
@@ -30,6 +55,7 @@ import androidx.compose.runtime.remember
|
|
|
import androidx.compose.runtime.setValue
|
|
|
import androidx.compose.ui.Alignment
|
|
|
import androidx.compose.ui.Modifier
|
|
|
+import androidx.compose.ui.graphics.vector.ImageVector
|
|
|
import androidx.compose.ui.platform.LocalContext
|
|
|
import androidx.compose.ui.res.stringArrayResource
|
|
|
import androidx.compose.ui.res.stringResource
|
|
|
@@ -114,6 +140,7 @@ private fun FontWeightSetting(
|
|
|
selectedValue = value.toString(),
|
|
|
displayEntries = arrayOf(weightEntries[2], weightEntries[0], weightEntries[1]),
|
|
|
entryValues = arrayOf("2", "0", "1"),
|
|
|
+ imageVector = Icons.Default.LineWeight,
|
|
|
onValueChange = { onValueChange(it.toInt()) },
|
|
|
)
|
|
|
}
|
|
|
@@ -174,6 +201,7 @@ private fun TipPositionDropdown(
|
|
|
value: Int,
|
|
|
tipNames: List<String>,
|
|
|
tipValues: Array<Int>,
|
|
|
+ imageVector: ImageVector? = null,
|
|
|
onValueChange: (Int) -> Unit,
|
|
|
) {
|
|
|
TinyDropdownSettingItem(
|
|
|
@@ -181,6 +209,7 @@ private fun TipPositionDropdown(
|
|
|
selectedValue = value.toString(),
|
|
|
displayEntries = tipNames.toTypedArray(),
|
|
|
entryValues = tipValues.map { it.toString() }.toTypedArray(),
|
|
|
+ imageVector = imageVector,
|
|
|
onValueChange = { onValueChange(it.toInt()) },
|
|
|
)
|
|
|
}
|
|
|
@@ -200,24 +229,28 @@ private fun PaddingSliders(
|
|
|
title = stringResource(R.string.padding_top),
|
|
|
value = top,
|
|
|
valueRange = 0f..200f,
|
|
|
+ imageVector = Icons.Default.VerticalAlignTop,
|
|
|
onValueChange = onTopChange,
|
|
|
)
|
|
|
TinySliderSettingItem(
|
|
|
title = stringResource(R.string.padding_bottom),
|
|
|
value = bottom,
|
|
|
valueRange = 0f..200f,
|
|
|
+ imageVector = Icons.Default.VerticalAlignBottom,
|
|
|
onValueChange = onBottomChange,
|
|
|
)
|
|
|
TinySliderSettingItem(
|
|
|
title = stringResource(R.string.padding_left),
|
|
|
value = left,
|
|
|
valueRange = 0f..200f,
|
|
|
+ imageVector = Icons.Default.AlignHorizontalLeft,
|
|
|
onValueChange = onLeftChange,
|
|
|
)
|
|
|
TinySliderSettingItem(
|
|
|
title = stringResource(R.string.padding_right),
|
|
|
value = right,
|
|
|
valueRange = 0f..200f,
|
|
|
+ imageVector = Icons.Default.AlignHorizontalRight,
|
|
|
onValueChange = onRightChange,
|
|
|
)
|
|
|
}
|
|
|
@@ -279,6 +312,7 @@ internal fun TypographyBodyTab(
|
|
|
selectedValue = config.chineseConverterType.toString(),
|
|
|
displayEntries = chineseConvertEntries,
|
|
|
entryValues = chineseConvertValues,
|
|
|
+ imageVector = Icons.Default.Translate,
|
|
|
onValueChange = {
|
|
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.ChineseConverterType(it.toInt())))
|
|
|
},
|
|
|
@@ -289,11 +323,13 @@ internal fun TypographyBodyTab(
|
|
|
TinyColorSettingItem(
|
|
|
title = stringResource(R.string.text_color),
|
|
|
colorValue = config.textColor,
|
|
|
+ imageVector = Icons.Default.FormatColorText,
|
|
|
onClick = { onOpenColorPicker(TypographyColorTarget.Text) },
|
|
|
)
|
|
|
TinyColorSettingItem(
|
|
|
title = stringResource(R.string.text_accent_color),
|
|
|
colorValue = config.textAccentColor,
|
|
|
+ imageVector = Icons.Default.Palette,
|
|
|
onClick = { onOpenColorPicker(TypographyColorTarget.TextAccent) },
|
|
|
)
|
|
|
|
|
|
@@ -325,6 +361,7 @@ internal fun TypographyBodyTab(
|
|
|
value = indentCount.toFloat(),
|
|
|
valueRange = 0f..4f,
|
|
|
steps = 3,
|
|
|
+ imageVector = Icons.Default.FormatIndentIncrease,
|
|
|
onValueChange = { value ->
|
|
|
indentCount = value.toInt()
|
|
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.ParagraphIndent(" ".repeat(indentCount))))
|
|
|
@@ -335,6 +372,7 @@ internal fun TypographyBodyTab(
|
|
|
value = (letterSpacing * 100) + 50,
|
|
|
valueRange = 0f..100f,
|
|
|
steps = 99,
|
|
|
+ imageVector = Icons.Default.SpaceBar,
|
|
|
valueFormat = { ((it - 50) / 100f).toString() },
|
|
|
onValueChange = { value ->
|
|
|
letterSpacing = (value - 50) / 100f
|
|
|
@@ -346,6 +384,7 @@ internal fun TypographyBodyTab(
|
|
|
value = lineSpacing,
|
|
|
valueRange = 0f..20f,
|
|
|
steps = 19,
|
|
|
+ imageVector = Icons.Default.FormatLineSpacing,
|
|
|
valueFormat = { ((it - 10) / 10f).toString() },
|
|
|
onValueChange = { value ->
|
|
|
lineSpacing = value
|
|
|
@@ -357,6 +396,7 @@ internal fun TypographyBodyTab(
|
|
|
value = paragraphSpacing,
|
|
|
valueRange = 0f..20f,
|
|
|
steps = 19,
|
|
|
+ imageVector = Icons.Default.Segment,
|
|
|
valueFormat = { (it / 10f).toString() },
|
|
|
onValueChange = { value ->
|
|
|
paragraphSpacing = value
|
|
|
@@ -369,6 +409,7 @@ internal fun TypographyBodyTab(
|
|
|
TinySwitchSettingItem(
|
|
|
title = stringResource(R.string.text_full_justify),
|
|
|
checked = config.textFullJustify,
|
|
|
+ imageVector = Icons.Default.FormatAlignJustify,
|
|
|
onCheckedChange = {
|
|
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TextFullJustify(it)))
|
|
|
},
|
|
|
@@ -376,6 +417,7 @@ internal fun TypographyBodyTab(
|
|
|
TinySwitchSettingItem(
|
|
|
title = stringResource(R.string.text_bottom_justify),
|
|
|
checked = config.textBottomJustify,
|
|
|
+ imageVector = Icons.Default.VerticalAlignBottom,
|
|
|
onCheckedChange = {
|
|
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TextBottomJustify(it)))
|
|
|
},
|
|
|
@@ -400,6 +442,7 @@ internal fun TypographyBodyTab(
|
|
|
selectedValue = ReadBook.book?.getImageStyle() ?: Book.imgStyleDefault,
|
|
|
displayEntries = imgStyleEntries,
|
|
|
entryValues = imgStyleValues,
|
|
|
+ imageVector = Icons.Default.Image,
|
|
|
onValueChange = { style ->
|
|
|
onIntent(ReadBookIntent.MenuImageStyle(style))
|
|
|
},
|
|
|
@@ -456,6 +499,7 @@ internal fun TypographyTitleTab(
|
|
|
stringResource(R.string.title_hide),
|
|
|
),
|
|
|
entryValues = arrayOf("0", "1", "2"),
|
|
|
+ imageVector = Icons.Default.Title,
|
|
|
onValueChange = {
|
|
|
titleMode = it.toInt()
|
|
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TitleMode(titleMode)))
|
|
|
@@ -477,9 +521,10 @@ internal fun TypographyTitleTab(
|
|
|
},
|
|
|
)
|
|
|
TinyColorModeSettingItem(
|
|
|
- title = stringResource(R.string.title_color),
|
|
|
+ title = stringResource(R.string.color),
|
|
|
dayColor = if (config.titleColor != 0) config.titleColor else config.textColorDay,
|
|
|
nightColor = if (config.titleColorNight != 0) config.titleColorNight else config.textColorNight,
|
|
|
+ imageVector = Icons.Default.Palette,
|
|
|
onClickColor = { isNight ->
|
|
|
if (isNight) {
|
|
|
onOpenColorPicker(TypographyColorTarget.TitleNight)
|
|
|
@@ -489,10 +534,11 @@ internal fun TypographyTitleTab(
|
|
|
},
|
|
|
)
|
|
|
TinySliderSettingItem(
|
|
|
- title = stringResource(R.string.title_font_size),
|
|
|
+ title = stringResource(R.string.font_size),
|
|
|
value = titleSize.toFloat(),
|
|
|
valueRange = 8f..60f,
|
|
|
steps = 51,
|
|
|
+ imageVector = Icons.Default.FormatSize,
|
|
|
valueFormat = { "${it.toInt()}sp" },
|
|
|
onValueChange = { value ->
|
|
|
titleSize = value.toInt()
|
|
|
@@ -512,6 +558,7 @@ internal fun TypographyTitleTab(
|
|
|
stringResource(R.string.split_title_by_regex),
|
|
|
),
|
|
|
entryValues = arrayOf("0", "1", "2", "3"),
|
|
|
+ imageVector = Icons.Default.CallSplit,
|
|
|
onValueChange = {
|
|
|
titleSegType = it.toInt()
|
|
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TitleSegType(titleSegType)))
|
|
|
@@ -523,6 +570,7 @@ internal fun TypographyTitleTab(
|
|
|
value = titleSegDistance.toFloat(),
|
|
|
valueRange = 1f..20f,
|
|
|
steps = 18,
|
|
|
+ imageVector = Icons.Default.SpaceBar,
|
|
|
onValueChange = { value ->
|
|
|
titleSegDistance = value.toInt()
|
|
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TitleSegDistance(titleSegDistance)))
|
|
|
@@ -533,6 +581,7 @@ internal fun TypographyTitleTab(
|
|
|
TinyClickableSettingItem(
|
|
|
title = stringResource(R.string.rule_segment),
|
|
|
description = titleSegFlag.ifBlank { stringResource(R.string.split_title_mode) },
|
|
|
+ imageVector = Icons.Default.Code,
|
|
|
onClick = { showFlagDialog = true },
|
|
|
)
|
|
|
}
|
|
|
@@ -542,6 +591,7 @@ internal fun TypographyTitleTab(
|
|
|
valueRange = 0f..2f,
|
|
|
steps = 19,
|
|
|
stepSize = 0.1f,
|
|
|
+ imageVector = Icons.Default.AspectRatio,
|
|
|
valueFormat = { "%.1f".format(it) },
|
|
|
onValueChange = { value ->
|
|
|
titleSegScaling = (value * 10).roundToInt() / 10f
|
|
|
@@ -555,6 +605,7 @@ internal fun TypographyTitleTab(
|
|
|
title = stringResource(R.string.heading_spacing),
|
|
|
value = titleLineSpacingExtra.toFloat(),
|
|
|
valueRange = 0f..20f,
|
|
|
+ imageVector = Icons.Default.LineWeight,
|
|
|
onValueChange = { value ->
|
|
|
titleLineSpacingExtra = value.toInt()
|
|
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TitleLineSpacingExtra(titleLineSpacingExtra)))
|
|
|
@@ -564,6 +615,7 @@ internal fun TypographyTitleTab(
|
|
|
title = stringResource(R.string.subtitle_margin),
|
|
|
value = titleLineSpacingSub.toFloat(),
|
|
|
valueRange = -30f..30f,
|
|
|
+ imageVector = Icons.Default.Height,
|
|
|
onValueChange = { value ->
|
|
|
titleLineSpacingSub = value.toInt()
|
|
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TitleLineSpacingSub(titleLineSpacingSub)))
|
|
|
@@ -642,6 +694,7 @@ internal fun TypographyHeaderTab(
|
|
|
selectedValue = headerMode.toString(),
|
|
|
displayEntries = headerModes.values.toTypedArray(),
|
|
|
entryValues = headerModes.keys.map { it.toString() }.toTypedArray(),
|
|
|
+ imageVector = Icons.Default.ViewHeadline,
|
|
|
onValueChange = { onHeaderModeChange(it.toInt()) },
|
|
|
)
|
|
|
TipPositionDropdown(
|
|
|
@@ -649,6 +702,7 @@ internal fun TypographyHeaderTab(
|
|
|
value = headerLeft,
|
|
|
tipNames = tipNames,
|
|
|
tipValues = tipValues,
|
|
|
+ imageVector = Icons.Default.AlignHorizontalLeft,
|
|
|
onValueChange = { onTipChange(CustomTipTarget.HEADER_LEFT, it) },
|
|
|
)
|
|
|
TipPositionDropdown(
|
|
|
@@ -656,6 +710,7 @@ internal fun TypographyHeaderTab(
|
|
|
value = headerMiddle,
|
|
|
tipNames = tipNames,
|
|
|
tipValues = tipValues,
|
|
|
+ imageVector = Icons.Default.AlignHorizontalCenter,
|
|
|
onValueChange = { onTipChange(CustomTipTarget.HEADER_MIDDLE, it) },
|
|
|
)
|
|
|
TipPositionDropdown(
|
|
|
@@ -663,6 +718,7 @@ internal fun TypographyHeaderTab(
|
|
|
value = headerRight,
|
|
|
tipNames = tipNames,
|
|
|
tipValues = tipValues,
|
|
|
+ imageVector = Icons.Default.AlignHorizontalRight,
|
|
|
onValueChange = { onTipChange(CustomTipTarget.HEADER_RIGHT, it) },
|
|
|
)
|
|
|
|
|
|
@@ -671,6 +727,7 @@ internal fun TypographyHeaderTab(
|
|
|
TinySwitchSettingItem(
|
|
|
title = stringResource(R.string.showLine),
|
|
|
checked = showHeaderLine,
|
|
|
+ imageVector = Icons.Default.Minimize,
|
|
|
onCheckedChange = { onShowHeaderLineChange(it) },
|
|
|
)
|
|
|
TinyColorSettingItem(
|
|
|
@@ -680,6 +737,7 @@ internal fun TypographyHeaderTab(
|
|
|
0 -> config.textColorDay
|
|
|
else -> config.tipDividerColor
|
|
|
},
|
|
|
+ imageVector = Icons.Default.Palette,
|
|
|
onClick = { onOpenColorPicker(TypographyColorTarget.Divider) },
|
|
|
)
|
|
|
|
|
|
@@ -691,18 +749,20 @@ internal fun TypographyHeaderTab(
|
|
|
onClick = onOpenHeaderFontSelect,
|
|
|
)
|
|
|
TinySliderSettingItem(
|
|
|
- title = stringResource(R.string.title_font_size),
|
|
|
+ title = stringResource(R.string.font_size),
|
|
|
value = config.headerFontSize.toFloat(),
|
|
|
valueRange = 0f..100f,
|
|
|
+ imageVector = Icons.Default.FormatSize,
|
|
|
onValueChange = { value ->
|
|
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.HeaderFontSize(value.toInt())))
|
|
|
onIntent(ReadBookIntent.SaveReadStyleConfig)
|
|
|
},
|
|
|
)
|
|
|
TinyColorModeSettingItem(
|
|
|
- title = stringResource(R.string.title_color),
|
|
|
+ title = stringResource(R.string.color),
|
|
|
dayColor = if (config.tipHeaderColor != 0) config.tipHeaderColor else config.textColorDay,
|
|
|
nightColor = if (config.tipHeaderColorNight != 0) config.tipHeaderColorNight else config.textColorNight,
|
|
|
+ imageVector = Icons.Default.FormatColorText,
|
|
|
onClickColor = { isNight ->
|
|
|
if (isNight) {
|
|
|
onOpenColorPicker(TypographyColorTarget.HeaderNight)
|
|
|
@@ -750,6 +810,7 @@ internal fun TypographyFooterTab(
|
|
|
selectedValue = footerMode.toString(),
|
|
|
displayEntries = footerModes.values.toTypedArray(),
|
|
|
entryValues = footerModes.keys.map { it.toString() }.toTypedArray(),
|
|
|
+ imageVector = Icons.Default.ViewAgenda,
|
|
|
onValueChange = { onFooterModeChange(it.toInt()) },
|
|
|
)
|
|
|
TipPositionDropdown(
|
|
|
@@ -757,6 +818,7 @@ internal fun TypographyFooterTab(
|
|
|
value = footerLeft,
|
|
|
tipNames = tipNames,
|
|
|
tipValues = tipValues,
|
|
|
+ imageVector = Icons.Default.AlignHorizontalLeft,
|
|
|
onValueChange = { onTipChange(CustomTipTarget.FOOTER_LEFT, it) },
|
|
|
)
|
|
|
TipPositionDropdown(
|
|
|
@@ -764,6 +826,7 @@ internal fun TypographyFooterTab(
|
|
|
value = footerMiddle,
|
|
|
tipNames = tipNames,
|
|
|
tipValues = tipValues,
|
|
|
+ imageVector = Icons.Default.AlignHorizontalCenter,
|
|
|
onValueChange = { onTipChange(CustomTipTarget.FOOTER_MIDDLE, it) },
|
|
|
)
|
|
|
TipPositionDropdown(
|
|
|
@@ -771,6 +834,7 @@ internal fun TypographyFooterTab(
|
|
|
value = footerRight,
|
|
|
tipNames = tipNames,
|
|
|
tipValues = tipValues,
|
|
|
+ imageVector = Icons.Default.AlignHorizontalRight,
|
|
|
onValueChange = { onTipChange(CustomTipTarget.FOOTER_RIGHT, it) },
|
|
|
)
|
|
|
|
|
|
@@ -779,6 +843,7 @@ internal fun TypographyFooterTab(
|
|
|
TinySwitchSettingItem(
|
|
|
title = stringResource(R.string.showLine),
|
|
|
checked = showFooterLine,
|
|
|
+ imageVector = Icons.Default.Minimize,
|
|
|
onCheckedChange = { onShowFooterLineChange(it) },
|
|
|
)
|
|
|
|
|
|
@@ -787,6 +852,7 @@ internal fun TypographyFooterTab(
|
|
|
TinySwitchSettingItem(
|
|
|
title = stringResource(R.string.apply_header_style),
|
|
|
checked = config.applyHeaderStyle,
|
|
|
+ imageVector = Icons.Default.CopyAll,
|
|
|
onCheckedChange = {
|
|
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.ApplyHeaderStyle(it)))
|
|
|
},
|
|
|
@@ -798,18 +864,20 @@ internal fun TypographyFooterTab(
|
|
|
onClick = onOpenFooterFontSelect,
|
|
|
)
|
|
|
TinySliderSettingItem(
|
|
|
- title = stringResource(R.string.title_font_size),
|
|
|
+ title = stringResource(R.string.font_size),
|
|
|
value = config.footerFontSize.toFloat(),
|
|
|
valueRange = 0f..100f,
|
|
|
+ imageVector = Icons.Default.FormatSize,
|
|
|
onValueChange = { value ->
|
|
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.FooterFontSize(value.toInt())))
|
|
|
onIntent(ReadBookIntent.SaveReadStyleConfig)
|
|
|
},
|
|
|
)
|
|
|
TinyColorModeSettingItem(
|
|
|
- title = stringResource(R.string.title_color),
|
|
|
+ title = stringResource(R.string.color),
|
|
|
dayColor = if (config.tipFooterColor != 0) config.tipFooterColor else config.textColorDay,
|
|
|
nightColor = if (config.tipFooterColorNight != 0) config.tipFooterColorNight else config.textColorNight,
|
|
|
+ imageVector = Icons.Default.FormatColorText,
|
|
|
onClickColor = { isNight ->
|
|
|
if (isNight) {
|
|
|
onOpenColorPicker(TypographyColorTarget.FooterNight)
|
|
|
@@ -886,6 +954,7 @@ internal fun TypographyMarginTab(
|
|
|
title = stringResource(R.string.title_margin_top),
|
|
|
value = titleTopSpacing.toFloat(),
|
|
|
valueRange = 0f..200f,
|
|
|
+ imageVector = Icons.Default.VerticalAlignTop,
|
|
|
onValueChange = { value ->
|
|
|
titleTopSpacing = value.toInt()
|
|
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TitleTopSpacing(titleTopSpacing)))
|
|
|
@@ -895,6 +964,7 @@ internal fun TypographyMarginTab(
|
|
|
title = stringResource(R.string.title_margin_bottom),
|
|
|
value = titleBottomSpacing.toFloat(),
|
|
|
valueRange = 0f..200f,
|
|
|
+ imageVector = Icons.Default.VerticalAlignBottom,
|
|
|
onValueChange = { value ->
|
|
|
titleBottomSpacing = value.toInt()
|
|
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TitleBottomSpacing(titleBottomSpacing)))
|