Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/src/main/java/at/techbee/jtx/ui/list/ListCard.kt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import at.techbee.jtx.ui.reusable.elements.DragHandle
import at.techbee.jtx.ui.reusable.elements.ProgressElement
import at.techbee.jtx.ui.reusable.elements.VerticalDateBlock
import at.techbee.jtx.ui.reusable.components.filterCheckedCheckboxes
import at.techbee.jtx.ui.reusable.components.rtlAwareMarkdownComponents
import at.techbee.jtx.ui.settings.DropdownSettingOption
import at.techbee.jtx.ui.theme.Typography
import at.techbee.jtx.ui.theme.jtxCardBorderStrokeWidth
Expand Down Expand Up @@ -159,6 +160,7 @@ fun ListCard(
Markdown(
content = filteredContent.ellipsize(300),
imageTransformer = Coil3ImageTransformerImpl,
components = rtlAwareMarkdownComponents,
modifier = modifier
)
else
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/at/techbee/jtx/ui/list/ListCardGrid.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import at.techbee.jtx.database.locals.StoredCategory
import at.techbee.jtx.database.views.ICal4List
import at.techbee.jtx.flavored.BillingManager
import at.techbee.jtx.ui.reusable.components.filterCheckedCheckboxes
import at.techbee.jtx.ui.reusable.components.rtlAwareMarkdownComponents
import at.techbee.jtx.ui.reusable.elements.AudioPlaybackElement
import at.techbee.jtx.ui.theme.jtxCardBorderStrokeWidth
import at.techbee.jtx.util.UiUtil.ellipsize
Expand Down Expand Up @@ -150,6 +151,7 @@ fun ListCardGrid(
if(markdownEnabled && iCalObject.status != Status.CANCELLED.status)
Markdown(
content = filteredContent.ellipsize(150),
components = rtlAwareMarkdownComponents,
modifier = Modifier
.fillMaxWidth()
.padding(end = 8.dp)
Expand Down
6 changes: 5 additions & 1 deletion app/src/main/java/at/techbee/jtx/ui/list/ListCardKanban.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import at.techbee.jtx.database.locals.StoredCategory
import at.techbee.jtx.database.views.ICal4List
import at.techbee.jtx.flavored.BillingManager
import at.techbee.jtx.ui.reusable.components.filterCheckedCheckboxes
import at.techbee.jtx.ui.reusable.components.rtlAwareMarkdownComponents
import at.techbee.jtx.ui.reusable.elements.AudioPlaybackElement
import at.techbee.jtx.ui.theme.jtxCardBorderStrokeWidth
import at.techbee.jtx.util.UiUtil.ellipsize
Expand Down Expand Up @@ -118,7 +119,10 @@ fun ListCardKanban(
val filteredContent = if (hideDoneCheckboxes) filterCheckedCheckboxes(descriptionContent) else descriptionContent

if(markdownEnabled && iCalObject.status != Status.CANCELLED.status)
Markdown(content = filteredContent.ellipsize(100))
Markdown(
content = filteredContent.ellipsize(100),
components = rtlAwareMarkdownComponents
)
else
Text(
text = filteredContent.ellipsize(100),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ fun InteractiveMarkdown(
Markdown(
content = segment.content,
imageTransformer = Coil3ImageTransformerImpl,
components = rtlAwareMarkdownComponents,
modifier = Modifier.fillMaxWidth()
)
}
Expand Down Expand Up @@ -208,7 +209,8 @@ fun InteractiveCheckboxItem(
text = text,
style = MaterialTheme.typography.bodyMedium.copy(
color = MaterialTheme.colorScheme.onSurface
)
).withContentDirection(),
modifier = Modifier.weight(1f)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package at.techbee.jtx.ui.reusable.components

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.heading
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextDirection
import com.mikepenz.markdown.compose.components.MarkdownComponentModel
import com.mikepenz.markdown.compose.components.MarkdownComponents
import com.mikepenz.markdown.compose.components.markdownComponents
import com.mikepenz.markdown.compose.elements.MarkdownParagraph
import com.mikepenz.markdown.compose.elements.MarkdownText
import org.intellij.markdown.IElementType
import org.intellij.markdown.MarkdownTokenTypes

/**
* The default Markdown components render paragraphs and headings with a wrap-content width,
* so the text box is always placed at the start of the parent (left in an LTR app) and
* right-to-left paragraphs (e.g. Hebrew, Arabic) end up left-aligned.
* These components let paragraphs and headings fill the available width and resolve the
* text direction from their content, so each block is aligned according to its own language.
*/
val rtlAwareMarkdownComponents: MarkdownComponents = markdownComponents(
paragraph = { model ->
MarkdownParagraph(
content = model.content,
node = model.node,
modifier = Modifier.fillMaxWidth(),
style = model.typography.paragraph.withContentDirection()
)
},
heading1 = { RtlAwareHeader(it, it.typography.h1) },
heading2 = { RtlAwareHeader(it, it.typography.h2) },
heading3 = { RtlAwareHeader(it, it.typography.h3) },
heading4 = { RtlAwareHeader(it, it.typography.h4) },
heading5 = { RtlAwareHeader(it, it.typography.h5) },
heading6 = { RtlAwareHeader(it, it.typography.h6) },
setextHeading1 = { RtlAwareHeader(it, it.typography.h1, MarkdownTokenTypes.SETEXT_CONTENT) },
setextHeading2 = { RtlAwareHeader(it, it.typography.h2, MarkdownTokenTypes.SETEXT_CONTENT) },
)

/**
* Lets the text direction be determined by the first strong directional character of each paragraph.
*/
fun TextStyle.withContentDirection(): TextStyle = copy(textDirection = TextDirection.Content)

@Composable
private fun RtlAwareHeader(
model: MarkdownComponentModel,
style: TextStyle,
contentChildType: IElementType = MarkdownTokenTypes.ATX_CONTENT
) {
MarkdownText(
content = model.content,
node = model.node,
style = style.withContentDirection(),
modifier = Modifier
.fillMaxWidth()
.semantics { heading() },
contentChildType = contentChildType,
)
}
Loading