* Add performance and stylus debugging logs

* Refactor and decouple UI models from `MainViewModel`

* Refactor library state management and projection logic

* Implement desktop shell using Compose Multiplatform

* Implement desktop shell using Compose Multiplatform

* Implement desktop shell using Compose Multiplatform

* Introduce ReaderEngine and enhance EPUB reader features in windows app

* Move core paginated reader logic to a Kotlin Multiplatform `shared` module and introduce experimental desktop support.

* Implement PDF rendering and text extraction for desktop using Pdfium

* Add `NonReaderScreens.kt` and UI dependencies

* Refactor and centralize library state management and models to improve cross-platform consistency

* Implement JSON persistence for desktop library and enhance library management features including shelf CRUD, tagging, and metadata editing

* Implement PDF annotation system and enhanced zoom controls for the desktop viewer

* Implement WebView-based EPUB rendering for desktop using CEF and embedded resources

* Optimize UI state projection, navigation state handling, and main screen pager performance

* Implement Bring Your Own Key (BYOK) support for AI features in OSS version

* Support Gemini-based Cloud TTS with BYOK support for OSS builds

* Refactor table cell image sizing in `PaginatedReader` and improve `MobiParser` native library loading and error handling.

* crash fixes

* Enhance navigation stability with lifecycle-aware safety checks and update `navigation-compose` to 2.9.6

* Implement dynamic bottom padding for the page info bar to account for device rounded corners

* Implement bidirectional jump history navigation and replace the jump-back pill with a dedicated `PdfJumpHistoryBar`

* Optimize PDF tiling performance and refine pan-and-fling gesture handling

* Implement customizable toolbars with drag-and-drop reordering and placement for PDF and EPUB readers

* Updated UI for customize toolbar

* Refine drag-and-drop reordering and section assignment for PDF and EPUB reader controls

* restructure PDF viewer UI component hierarchy to fix verifier crash

* Implement separate text dimming factors for light and dark themes

* Synchronize Pdfium access and improve resource lifecycle safety across Kotlin and native layers

* Enhance image alignment in paginated and EPUB readers through anchor detection and style-based positioning

* Centralize file type resolution logic and implement HTML sanitization during import

* Introduce vertical margin customization and configurable progress bar positioning

* texture support in epub reader

* Enhance TTS session management, progress tracking, and diagnostic logging

* Optimize library state projection and folder synchronization performance by refactoring collection lookups and refining metadata extraction logic.

* Refine TTS page mapping for PDF and overhaul TTS control UI

* Implement natural session completion logic in `TtsPlaybackManager` for cloud tts

* Replace Snackbar with `CustomTopBanner` for notifications in `PdfViewerScreen`

* Refine TTS playback continuity across PDF pages and improve state management for session transitions

* Implement global texture transparency and enhance textured theme support across PDF and EPUB readers.

* Update reader themes and improve texture rendering in page animations, EPUB UI, and immersive mode

* Add Support Project screen

* Optimize library performance via projection caching, batch database updates, and scoped folder synchronization.

* Enhance folder synchronization with fallback query mechanisms and refactor annotation sidecar importing logic

* Bump version to 1.0.47 (51)
This commit is contained in:
Aryan 2026-05-04 21:55:38 +05:30 committed by GitHub
parent f42de6b462
commit d7a9cae9e1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
126 changed files with 15287 additions and 3154 deletions

View file

@ -21,6 +21,7 @@ import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
@ -147,7 +148,7 @@ import coil.compose.AsyncImage
import coil.imageLoader
import coil.request.ImageRequest.Builder
import com.aryan.reader.R
import com.aryan.reader.ReaderTexture
import com.aryan.reader.loadReaderTextureBitmap
import com.aryan.reader.countWords
import com.aryan.reader.epub.EpubBook
import com.aryan.reader.epubreader.HighlightColor
@ -251,6 +252,12 @@ private fun headerFontScale(level: Int): Float = when (level) {
else -> 1.0f
}
private const val WEB_VIEW_NORMAL_LINE_HEIGHT_MULTIPLIER = 1.2f
private fun paginationLineHeightMultiplierForWebViewSetting(multiplier: Float): Float {
return if (abs(multiplier - 1.0f) < 0.001f) WEB_VIEW_NORMAL_LINE_HEIGHT_MULTIPLIER else multiplier
}
private fun createHeaderTextStyle(
baseStyle: TextStyle,
level: Int,
@ -473,6 +480,51 @@ private fun computeImageRenderSizeDp(
return with(density) { widthPx.toDp() to heightPx.toDp() }
}
private fun imageBlockContentAlignment(style: BlockStyle): Alignment {
return when {
style.float == "right" || style.horizontalAlign == "right" || style.horizontalAlign == "end" -> Alignment.CenterEnd
style.float == "left" || style.horizontalAlign == "left" || style.horizontalAlign == "start" -> Alignment.CenterStart
else -> Alignment.Center
}
}
private fun tableCellImageModifier(
block: ImageBlock,
density: Density,
imageSizeMultiplier: Float
): Modifier {
val baseModifier = if (block.style.width.isSpecified && block.style.width > 0.dp) {
Modifier.width(block.style.width * imageSizeMultiplier)
} else {
Modifier.fillMaxWidth(imageSizeMultiplier.coerceIn(0f, 1f))
}
val intrinsicWidth = block.intrinsicWidth
val intrinsicHeight = block.intrinsicHeight
val sizedModifier = if (
intrinsicWidth != null &&
intrinsicHeight != null &&
intrinsicWidth > 0f &&
intrinsicHeight > 0f
) {
baseModifier.aspectRatio(intrinsicWidth / intrinsicHeight)
} else {
baseModifier.height(
if (block.expectedHeight > 0) {
with(density) { (block.expectedHeight * imageSizeMultiplier).toDp() }
} else {
250.dp
}
)
}
return if (block.style.maxWidth.isSpecified && block.style.maxWidth > 0.dp) {
sizedModifier.widthIn(max = block.style.maxWidth * imageSizeMultiplier)
} else {
sizedModifier
}
}
@Composable
private fun WrappingContentLayout(
block: WrappingContentBlock,
@ -682,6 +734,7 @@ fun PaginatedReaderScreen(
paragraphGapMultiplier: Float,
imageSizeMultiplier: Float,
horizontalMarginMultiplier: Float,
verticalMarginMultiplier: Float,
fontFamily: FontFamily,
textAlign: ReaderTextAlign,
ttsHighlightInfo: TtsHighlightInfo?,
@ -702,7 +755,8 @@ fun PaginatedReaderScreen(
onHighlightDeleted: (String) -> Unit,
activeHighlightPalette: List<HighlightColor>,
onUpdatePalette: (Int, HighlightColor) -> Unit,
activeTextureId: String? = null
activeTextureId: String? = null,
activeTextureAlpha: Float = 0.55f
) {
LaunchedEffect(userHighlights) {
Timber.d("PaginatedReaderScreen: Received ${userHighlights.size} highlights.")
@ -713,11 +767,7 @@ fun PaginatedReaderScreen(
val context = LocalContext.current
val textureBitmap = remember(activeTextureId) {
activeTextureId?.let { id ->
ReaderTexture.entries.find { it.id == id }?.resId?.let { resId ->
ImageBitmap.imageResource(context.resources, resId)
}
}
loadReaderTextureBitmap(context, activeTextureId)
}
val textureModifier = if (textureBitmap != null) {
@ -725,13 +775,13 @@ fun PaginatedReaderScreen(
val brush = ShaderBrush(
ImageShader(textureBitmap, TileMode.Repeated, TileMode.Repeated)
)
drawRect(brush = brush, blendMode = BlendMode.Multiply, alpha = 0.6f)
drawRect(brush = brush, blendMode = BlendMode.SrcOver, alpha = activeTextureAlpha.coerceIn(0f, 1f))
}
} else Modifier
var isNavigatingByLink by remember { mutableStateOf(false) }
BoxWithConstraints(modifier = modifier.fillMaxSize().background(effectiveBg).then(textureModifier)) {
BoxWithConstraints(modifier = modifier.fillMaxSize().background(effectiveBg)) {
val textMeasurer = rememberTextMeasurer()
val baseTextStyle = MaterialTheme.typography.bodyLarge
@ -740,6 +790,7 @@ fun PaginatedReaderScreen(
var debouncedParagraphGapMult by remember { mutableFloatStateOf(paragraphGapMultiplier) }
var debouncedImageSizeMult by remember { mutableFloatStateOf(imageSizeMultiplier) }
var debouncedHorizontalMarginMult by remember { mutableFloatStateOf(horizontalMarginMultiplier) }
var debouncedVerticalMarginMult by remember { mutableFloatStateOf(verticalMarginMultiplier) }
var debouncedFontFamily by remember { mutableStateOf(fontFamily) }
var debouncedTextAlign by remember { mutableStateOf(textAlign) }
@ -781,7 +832,7 @@ fun PaginatedReaderScreen(
debouncedFontFamily
) {
val adjustedFontSize = baseTextStyle.fontSize * debouncedFontSizeMult
val adjustedLineHeight = adjustedFontSize * debouncedLineHeightMult
val adjustedLineHeight = adjustedFontSize * paginationLineHeightMultiplierForWebViewSetting(debouncedLineHeightMult)
baseTextStyle.copy(
color = effectiveText,
@ -810,12 +861,13 @@ fun PaginatedReaderScreen(
}
}
LaunchedEffect(fontSizeMultiplier, lineHeightMultiplier, paragraphGapMultiplier, imageSizeMultiplier, horizontalMarginMultiplier, fontFamily, textAlign) {
LaunchedEffect(fontSizeMultiplier, lineHeightMultiplier, paragraphGapMultiplier, imageSizeMultiplier, horizontalMarginMultiplier, verticalMarginMultiplier, fontFamily, textAlign) {
if (fontSizeMultiplier != debouncedFontSizeMult ||
lineHeightMultiplier != debouncedLineHeightMult ||
paragraphGapMultiplier != debouncedParagraphGapMult ||
imageSizeMultiplier != debouncedImageSizeMult ||
horizontalMarginMultiplier != debouncedHorizontalMarginMult ||
verticalMarginMultiplier != debouncedVerticalMarginMult ||
fontFamily != debouncedFontFamily ||
textAlign != debouncedTextAlign
) {
@ -836,6 +888,7 @@ fun PaginatedReaderScreen(
debouncedParagraphGapMult = paragraphGapMultiplier
debouncedImageSizeMult = imageSizeMultiplier
debouncedHorizontalMarginMult = horizontalMarginMultiplier
debouncedVerticalMarginMult = verticalMarginMultiplier
debouncedFontFamily = fontFamily
debouncedTextAlign = textAlign
Timber.d("Debounce complete. Applying new format settings.")
@ -851,8 +904,28 @@ fun PaginatedReaderScreen(
}
val density = LocalDensity.current
val horizontalPadding = 16.dp * debouncedHorizontalMarginMult
val verticalPadding = 16.dp
val requestedHorizontalPadding = 16.dp * debouncedHorizontalMarginMult
val requestedVerticalPadding = 16.dp * debouncedVerticalMarginMult
val effectiveReaderPadding =
remember(this.constraints, density, requestedHorizontalPadding, requestedVerticalPadding) {
val requestedHorizontalPaddingPx = with(density) { requestedHorizontalPadding.roundToPx() }
val requestedVerticalPaddingPx = with(density) { requestedVerticalPadding.roundToPx() }
val minReadableWidthPx = with(density) { 96.dp.roundToPx() }
.coerceAtMost(this.constraints.maxWidth)
val minReadableHeightPx = with(density) { 160.dp.roundToPx() }
.coerceAtMost(this.constraints.maxHeight)
val horizontalPaddingPx = requestedHorizontalPaddingPx.coerceAtMost(
((this.constraints.maxWidth - minReadableWidthPx) / 2).coerceAtLeast(0)
)
val verticalPaddingPx = requestedVerticalPaddingPx.coerceAtMost(
((this.constraints.maxHeight - minReadableHeightPx) / 2).coerceAtLeast(0)
)
with(density) {
horizontalPaddingPx.toDp() to verticalPaddingPx.toDp()
}
}
val horizontalPadding = effectiveReaderPadding.first
val verticalPadding = effectiveReaderPadding.second
val textConstraints =
remember(this.constraints, density, horizontalPadding, verticalPadding) {
@ -860,9 +933,9 @@ fun PaginatedReaderScreen(
val verticalPaddingPx = with(density) { verticalPadding.roundToPx() }
val finalConstraints = this.constraints.copy(
minWidth = 0,
maxWidth = this.constraints.maxWidth - (2 * horizontalPaddingPx),
maxWidth = (this.constraints.maxWidth - (2 * horizontalPaddingPx)).coerceAtLeast(1),
minHeight = 0,
maxHeight = this.constraints.maxHeight - (2 * verticalPaddingPx)
maxHeight = (this.constraints.maxHeight - (2 * verticalPaddingPx)).coerceAtLeast(1)
)
finalConstraints
}
@ -950,7 +1023,8 @@ fun PaginatedReaderScreen(
mathMLRenderer = mathMLRenderer,
userTextAlign = userTextAlign,
paragraphGapMultiplier = debouncedParagraphGapMult,
imageSizeMultiplier = debouncedImageSizeMult
imageSizeMultiplier = debouncedImageSizeMult,
verticalMarginMultiplier = debouncedVerticalMarginMult
)
}
@ -1168,7 +1242,10 @@ fun PaginatedReaderScreen(
isDarkTheme = isDarkTheme,
activeHighlightPalette = activeHighlightPalette,
onUpdatePalette = onUpdatePalette,
effectiveText = effectiveText
effectiveText = effectiveText,
pageTextureModifier = if (isPageTurnAnimationEnabled) Modifier else textureModifier,
pageTextureBitmap = textureBitmap,
pageTextureAlpha = activeTextureAlpha.coerceIn(0f, 1f)
)
androidx.compose.animation.AnimatedVisibility(
@ -1989,7 +2066,10 @@ internal fun PaginatedReaderContent(
onHighlightDeleted: (String) -> Unit,
activeHighlightPalette: List<HighlightColor>,
onUpdatePalette: (Int, HighlightColor) -> Unit,
isDarkTheme: Boolean
isDarkTheme: Boolean,
pageTextureModifier: Modifier = Modifier,
pageTextureBitmap: ImageBitmap? = null,
pageTextureAlpha: Float = 0f
) {
val coroutineScope = rememberCoroutineScope()
val density = LocalDensity.current
@ -2130,7 +2210,9 @@ internal fun PaginatedReaderContent(
pageIndex,
effectiveBg,
isDarkTheme,
pageTurnTouchY
pageTurnTouchY,
pageTextureBitmap,
pageTextureAlpha
)
} else Modifier
@ -2284,7 +2366,7 @@ internal fun PaginatedReaderContent(
pendingCrossPageSelection = null
}
Box(modifier = Modifier.fillMaxSize().then(pageModifier)) {
Box(modifier = Modifier.fillMaxSize().background(effectiveBg).then(pageTextureModifier).then(pageModifier)) {
Box(modifier = Modifier.fillMaxSize()) {
Box(modifier = Modifier.fillMaxSize().pointerInput(Unit) {
detectTapGestures(
@ -2784,12 +2866,14 @@ internal fun PaginatedReaderContent(
val markerAreaModifier =
Modifier.width(32.dp)
.padding(end = 8.dp)
val itemMarkerImage = block.itemMarkerImage
val itemMarker = block.itemMarker
if (block.itemMarkerImage != null) {
if (itemMarkerImage != null) {
val imageRequest =
Builder(LocalContext.current).data(
File(
block.itemMarkerImage
itemMarkerImage
)
).crossfade(true).build()
val imageSize = with(density) {
@ -2805,9 +2889,9 @@ internal fun PaginatedReaderContent(
alignment = Alignment.CenterEnd,
contentScale = ContentScale.FillHeight
)
} else if (block.itemMarker != null) {
} else if (itemMarker != null) {
Text(
text = block.itemMarker,
text = itemMarker,
style = textStyle.copy(
textAlign = TextAlign.End
),
@ -3017,10 +3101,12 @@ internal fun PaginatedReaderContent(
}
is MathBlock -> {
val svgContent = block.svgContent?.takeIf { it.isNotBlank() }
Timber.d(
"PaginatedReader: Rendering MathBlock. Alt: '${block.altText}', Has SVG: ${!block.svgContent.isNullOrBlank()}"
"PaginatedReader: Rendering MathBlock. Alt: '${block.altText}', Has SVG: ${svgContent != null}"
)
if (!block.svgContent.isNullOrBlank()) {
if (svgContent != null) {
val nonBlankSvgContent = svgContent
BoxWithConstraints(
modifier = paddingModifier
) {
@ -3104,7 +3190,7 @@ internal fun PaginatedReaderContent(
val imageRequest =
Builder(LocalContext.current).data(
SvgData(
block.svgContent
nonBlankSvgContent
)
).listener(
onError = { _, result ->
@ -3189,7 +3275,10 @@ internal fun PaginatedReaderContent(
)
}).crossfade(true).build()
BoxWithConstraints(modifier = paddingModifier) {
BoxWithConstraints(
modifier = paddingModifier,
contentAlignment = imageBlockContentAlignment(style)
) {
val scaledSize = computeImageRenderSizeDp(
block = block,
density = density,
@ -3357,9 +3446,10 @@ internal fun PaginatedReaderContent(
Row(
verticalAlignment = Alignment.Top
) {
if (blockInCell.itemMarker != null) {
val itemMarker = blockInCell.itemMarker
if (itemMarker != null) {
Text(
text = blockInCell.itemMarker,
text = itemMarker,
style = cellTextStyle,
modifier = Modifier.padding(
end = 4.dp
@ -3390,40 +3480,23 @@ internal fun PaginatedReaderContent(
}
is ImageBlock -> {
BoxWithConstraints(modifier = Modifier.fillMaxWidth()) {
val scaledSize = computeImageRenderSizeDp(
AsyncImage(
model = Builder(
LocalContext.current
).data(
File(
blockInCell.path
)
)
.build(),
contentDescription = blockInCell.altText,
contentScale = ContentScale.Fit,
modifier = tableCellImageModifier(
block = blockInCell,
density = density,
maxWidthDp = maxWidth,
imageSizeMultiplier = imageSizeMultiplier
)
val imageModifier = Modifier.then(
if (scaledSize != null) {
Modifier.width(scaledSize.first).height(scaledSize.second)
} else {
Modifier.fillMaxWidth().then(
if (blockInCell.expectedHeight > 0) {
Modifier.height(with(density) { (blockInCell.expectedHeight * imageSizeMultiplier).toDp() })
} else {
Modifier.height(250.dp)
}
)
}
)
AsyncImage(
model = Builder(
LocalContext.current
).data(
File(
blockInCell.path
)
)
.build(),
contentDescription = blockInCell.altText,
contentScale = ContentScale.Fit,
modifier = imageModifier
)
}
)
}
is TextContentBlock -> {
@ -4101,10 +4174,12 @@ private fun RenderFlexChildBlock(
val markerAreaModifier = Modifier
.width(32.dp)
.padding(end = 8.dp)
val itemMarkerImage = childBlock.itemMarkerImage
val itemMarker = childBlock.itemMarker
if (childBlock.itemMarkerImage != null) {
if (itemMarkerImage != null) {
val imageRequest =
Builder(LocalContext.current).data(File(childBlock.itemMarkerImage))
Builder(LocalContext.current).data(File(itemMarkerImage))
.crossfade(true).build()
val imageSize = with(density) { (textStyle.fontSize.value * 0.8f).sp.toDp() }
@ -4115,9 +4190,9 @@ private fun RenderFlexChildBlock(
alignment = Alignment.CenterEnd,
contentScale = ContentScale.FillHeight
)
} else if (childBlock.itemMarker != null) {
} else if (itemMarker != null) {
Text(
text = childBlock.itemMarker,
text = itemMarker,
style = textStyle.copy(textAlign = TextAlign.End),
modifier = markerAreaModifier
)
@ -4160,7 +4235,7 @@ private fun RenderFlexChildBlock(
ColorFilter.colorMatrix(ColorMatrix(matrix))
} else null
BoxWithConstraints {
BoxWithConstraints(contentAlignment = imageBlockContentAlignment(style)) {
val scaledSize = computeImageRenderSizeDp(
block = childBlock,
density = density,
@ -4278,37 +4353,20 @@ private fun RenderFlexChildBlock(
modifier = Modifier.fillMaxWidth()
)
} else if (blockInCell is ImageBlock) {
BoxWithConstraints(modifier = Modifier.fillMaxWidth()) {
val scaledSize = computeImageRenderSizeDp(
AsyncImage(
model = Builder(LocalContext.current).data(
File(
blockInCell.path
)
).build(),
contentDescription = blockInCell.altText,
contentScale = ContentScale.Fit,
modifier = tableCellImageModifier(
block = blockInCell,
density = density,
maxWidthDp = maxWidth,
imageSizeMultiplier = imageSizeMultiplier
)
val imageModifier = Modifier.then(
if (scaledSize != null) {
Modifier.width(scaledSize.first).height(scaledSize.second)
} else {
Modifier.fillMaxWidth().then(
if (blockInCell.expectedHeight > 0) {
Modifier.height(with(density) { (blockInCell.expectedHeight * imageSizeMultiplier).toDp() })
} else {
Modifier.height(250.dp)
}
)
}
)
AsyncImage(
model = Builder(LocalContext.current).data(
File(
blockInCell.path
)
).build(),
contentDescription = blockInCell.altText,
contentScale = ContentScale.Fit,
modifier = imageModifier
)
}
)
}
}
}
@ -4332,7 +4390,9 @@ private fun Modifier.realisticBookPage(
pageIndex: Int,
paperColor: Color,
isDarkTheme: Boolean,
touchY: Float?
touchY: Float?,
textureBitmap: ImageBitmap? = null,
textureAlpha: Float = 0f
): Modifier = composed {
val frontPath = remember { Path() }
@ -4360,9 +4420,19 @@ private fun Modifier.realisticBookPage(
.drawWithContent {
val drawStart = System.nanoTime()
val pageOffset = (pageIndex - pagerState.currentPage) - pagerState.currentPageOffsetFraction
fun drawPaperBackground() {
drawRect(color = paperColor)
if (textureBitmap != null && textureAlpha > 0f) {
drawRect(
brush = ShaderBrush(ImageShader(textureBitmap, TileMode.Repeated, TileMode.Repeated)),
blendMode = BlendMode.SrcOver,
alpha = textureAlpha
)
}
}
if (abs(pageOffset) < 0.001f) {
drawRect(color = paperColor)
drawPaperBackground()
drawContent()
}
else if (pageOffset < 0f && pageOffset > -1f) {
@ -4423,7 +4493,7 @@ private fun Modifier.realisticBookPage(
frontPath.close()
clipPath(frontPath) {
drawRect(color = paperColor)
drawPaperBackground()
this@drawWithContent.drawContent()
}
@ -4466,6 +4536,15 @@ private fun Modifier.realisticBookPage(
clipRect(0f, 0f, w, h) {
clipPath(frontPath) {
drawPath(reflectedScreenPath, color = paperColor)
if (textureBitmap != null && textureAlpha > 0f) {
clipPath(reflectedScreenPath) {
drawRect(
brush = ShaderBrush(ImageShader(textureBitmap, TileMode.Repeated, TileMode.Repeated)),
blendMode = BlendMode.SrcOver,
alpha = textureAlpha
)
}
}
val flapTint = if (isDarkTheme) Color.White.copy(alpha = 0.08f) else Color.Black.copy(alpha = 0.06f)
drawPath(reflectedScreenPath, color = flapTint)
@ -4493,12 +4572,12 @@ private fun Modifier.realisticBookPage(
}
} else {
drawRect(color = paperColor)
drawPaperBackground()
drawContent()
}
}
else {
drawRect(color = paperColor)
drawPaperBackground()
drawContent()
}
@ -4515,10 +4594,14 @@ fun Modifier.drawCssBorders(
blockStyle: BlockStyle,
@Suppress("unused") density: Density
): Modifier = this.drawBehind {
val topWidth = blockStyle.borderTop?.width?.toPx() ?: 0f
val rightWidth = blockStyle.borderRight?.width?.toPx() ?: 0f
val bottomWidth = blockStyle.borderBottom?.width?.toPx() ?: 0f
val leftWidth = blockStyle.borderLeft?.width?.toPx() ?: 0f
val borderTop = blockStyle.borderTop
val borderRight = blockStyle.borderRight
val borderBottom = blockStyle.borderBottom
val borderLeft = blockStyle.borderLeft
val topWidth = borderTop?.width?.toPx() ?: 0f
val rightWidth = borderRight?.width?.toPx() ?: 0f
val bottomWidth = borderBottom?.width?.toPx() ?: 0f
val leftWidth = borderLeft?.width?.toPx() ?: 0f
val tlRadius = blockStyle.borderTopLeftRadius.toPx()
val trRadius = blockStyle.borderTopRightRadius.toPx()
@ -4550,9 +4633,9 @@ fun Modifier.drawCssBorders(
}
// TOP
if (topWidth > 0f && blockStyle.borderTop != null) {
val color = blockStyle.borderTop.color
val effect = getPathEffect(blockStyle.borderTop.style, topWidth)
if (topWidth > 0f && borderTop != null) {
val color = borderTop.color
val effect = getPathEffect(borderTop.style, topWidth)
val offset = topWidth / 2f
val startX = if (tlRadius > 0) tlRadius else 0f
@ -4568,9 +4651,9 @@ fun Modifier.drawCssBorders(
}
// BOTTOM
if (bottomWidth > 0f && blockStyle.borderBottom != null) {
val color = blockStyle.borderBottom.color
val effect = getPathEffect(blockStyle.borderBottom.style, bottomWidth)
if (bottomWidth > 0f && borderBottom != null) {
val color = borderBottom.color
val effect = getPathEffect(borderBottom.style, bottomWidth)
val offset = size.height - (bottomWidth / 2f)
val startX = if (blRadius > 0) blRadius else 0f
@ -4586,9 +4669,9 @@ fun Modifier.drawCssBorders(
}
// LEFT
if (leftWidth > 0f && blockStyle.borderLeft != null) {
val color = blockStyle.borderLeft.color
val effect = getPathEffect(blockStyle.borderLeft.style, leftWidth)
if (leftWidth > 0f && borderLeft != null) {
val color = borderLeft.color
val effect = getPathEffect(borderLeft.style, leftWidth)
val offset = leftWidth / 2f
val startY = if (tlRadius > 0) tlRadius else 0f
@ -4604,9 +4687,9 @@ fun Modifier.drawCssBorders(
}
// RIGHT
if (rightWidth > 0f && blockStyle.borderRight != null) {
val color = blockStyle.borderRight.color
val effect = getPathEffect(blockStyle.borderRight.style, rightWidth)
if (rightWidth > 0f && borderRight != null) {
val color = borderRight.color
val effect = getPathEffect(borderRight.style, rightWidth)
val offset = size.width - (rightWidth / 2f)
val startY = if (trRadius > 0) trRadius else 0f
@ -4621,9 +4704,9 @@ fun Modifier.drawCssBorders(
)
}
if (tlRadius > 0f && topWidth > 0f && leftWidth > 0f && blockStyle.borderTop != null) {
if (tlRadius > 0f && topWidth > 0f && leftWidth > 0f && borderTop != null) {
drawArc(
color = blockStyle.borderTop.color,
color = borderTop.color,
startAngle = 180f, sweepAngle = 90f,
useCenter = false,
topLeft = Offset(leftWidth/2f, topWidth/2f),
@ -4632,9 +4715,9 @@ fun Modifier.drawCssBorders(
)
}
if (trRadius > 0f && topWidth > 0f && rightWidth > 0f && blockStyle.borderTop != null) {
if (trRadius > 0f && topWidth > 0f && rightWidth > 0f && borderTop != null) {
drawArc(
color = blockStyle.borderTop.color,
color = borderTop.color,
startAngle = 270f, sweepAngle = 90f,
useCenter = false,
topLeft = Offset(size.width - (trRadius * 2) + (rightWidth/2f), topWidth/2f),
@ -4643,9 +4726,9 @@ fun Modifier.drawCssBorders(
)
}
if (brRadius > 0f && bottomWidth > 0f && rightWidth > 0f && blockStyle.borderBottom != null) {
if (brRadius > 0f && bottomWidth > 0f && rightWidth > 0f && borderBottom != null) {
drawArc(
color = blockStyle.borderBottom.color,
color = borderBottom.color,
startAngle = 0f, sweepAngle = 90f,
useCenter = false,
topLeft = Offset(size.width - (brRadius * 2) + (rightWidth/2f), size.height - (brRadius * 2) + (bottomWidth/2f)),
@ -4654,9 +4737,9 @@ fun Modifier.drawCssBorders(
)
}
if (blRadius > 0f && bottomWidth > 0f && leftWidth > 0f && blockStyle.borderBottom != null) {
if (blRadius > 0f && bottomWidth > 0f && leftWidth > 0f && borderBottom != null) {
drawArc(
color = blockStyle.borderBottom.color,
color = borderBottom.color,
startAngle = 90f, sweepAngle = 90f,
useCenter = false,
topLeft = Offset(leftWidth/2f, size.height - (blRadius * 2) + (bottomWidth/2f)),