Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd5cbaa3bc | ||
|
|
e65c699bcb |
@@ -535,23 +535,94 @@ class DrugDetailParser {
|
|||||||
* Converts block elements to newlines for better readability.
|
* Converts block elements to newlines for better readability.
|
||||||
*/
|
*/
|
||||||
private fun cleanText(element: Element): String {
|
private fun cleanText(element: Element): String {
|
||||||
// Clone to avoid affecting the original
|
|
||||||
val clone = element.clone()
|
val clone = element.clone()
|
||||||
|
val output = StringBuilder()
|
||||||
|
|
||||||
// Replace block-level elements with newlines for structure
|
// Process all nodes in order (both elements and text nodes)
|
||||||
clone.select("p, div, h2, h3, h4, li, br").before("\n")
|
processNode(clone, output)
|
||||||
|
|
||||||
// Get the text and clean it up
|
return output.toString()
|
||||||
var text = clone.text()
|
.replace(Regex("\\n{3,}"), "\n\n") // Collapse 3+ newlines to 2
|
||||||
.replace(Regex("\\n\\s*\\n+"), "\n\n") // Collapse multiple newlines
|
|
||||||
.replace(Regex("[ \\t]+"), " ") // Collapse spaces/tabs
|
|
||||||
.trim()
|
.trim()
|
||||||
|
|
||||||
// Ensure lists look decent
|
|
||||||
if (element.tagName() == "li") {
|
|
||||||
text = "• $text"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return text
|
/**
|
||||||
|
* Recursively process nodes to build formatted text
|
||||||
|
*/
|
||||||
|
private fun processNode(node: org.jsoup.nodes.Node, output: StringBuilder) {
|
||||||
|
when (node) {
|
||||||
|
is Element -> {
|
||||||
|
when (node.tagName()) {
|
||||||
|
"h2" -> {
|
||||||
|
val text = node.text().trim()
|
||||||
|
if (text.isNotEmpty()) {
|
||||||
|
output.append("\n\n📌 $text\n\n")
|
||||||
|
output.append("─".repeat(minOf(30, text.length))).append("\n\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"h3" -> {
|
||||||
|
val text = node.text().trim()
|
||||||
|
if (text.isNotEmpty()) {
|
||||||
|
output.append("\n\n🔹 $text\n\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"h4" -> {
|
||||||
|
val text = node.text().trim()
|
||||||
|
if (text.isNotEmpty()) {
|
||||||
|
output.append("\n▸ $text\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"p" -> {
|
||||||
|
val text = node.text().trim()
|
||||||
|
if (text.isNotEmpty()) {
|
||||||
|
output.append(text).append("\n\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"ul", "ol" -> {
|
||||||
|
for (li in node.select("li")) {
|
||||||
|
val liText = li.text().trim()
|
||||||
|
if (liText.isNotEmpty()) {
|
||||||
|
output.append(" • $liText\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output.append("\n")
|
||||||
|
}
|
||||||
|
"li" -> {
|
||||||
|
// Handled by ul/ol processing, but if standalone:
|
||||||
|
val text = node.text().trim()
|
||||||
|
if (text.isNotEmpty()) {
|
||||||
|
output.append(" • $text\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"br" -> {
|
||||||
|
output.append("\n")
|
||||||
|
}
|
||||||
|
"strong", "b" -> {
|
||||||
|
val text = node.text().trim()
|
||||||
|
if (text.isNotEmpty()) {
|
||||||
|
output.append("**$text**")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"div", "section", "article" -> {
|
||||||
|
// Process children of container elements
|
||||||
|
for (child in node.childNodes()) {
|
||||||
|
processNode(child, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
// For other elements, just process their children
|
||||||
|
for (child in node.childNodes()) {
|
||||||
|
processNode(child, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is org.jsoup.nodes.TextNode -> {
|
||||||
|
val text = node.text().trim()
|
||||||
|
if (text.isNotEmpty()) {
|
||||||
|
output.append(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,12 +25,14 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.SecondaryTabRow
|
||||||
import androidx.compose.material3.Tab
|
import androidx.compose.material3.Tab
|
||||||
import androidx.compose.material3.TabRow
|
import androidx.compose.material3.TabRow
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
@@ -39,8 +41,10 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.LayoutDirection
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
@@ -70,6 +74,7 @@ fun DrugDetailScreen(
|
|||||||
viewModel.loadDrugDetail(detailUrl)
|
viewModel.loadDrugDetail(detailUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
@@ -93,6 +98,7 @@ fun DrugDetailScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
Text("جزئیات دارو", fontSize = 16.sp)
|
Text("جزئیات دارو", fontSize = 16.sp)
|
||||||
}
|
}
|
||||||
@@ -148,7 +154,10 @@ fun DrugDetailScreen(
|
|||||||
ManufacturerInfoCard(
|
ManufacturerInfoCard(
|
||||||
manufacturer = drugDetail.manufacturer!!,
|
manufacturer = drugDetail.manufacturer!!,
|
||||||
genericInfo = drugDetail.genericInfo,
|
genericInfo = drugDetail.genericInfo,
|
||||||
modifier = Modifier.padding(horizontal = dime.md, vertical = dime.sm)
|
modifier = Modifier.padding(
|
||||||
|
horizontal = dime.md,
|
||||||
|
vertical = dime.sm
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,12 +195,15 @@ fun DrugDetailScreen(
|
|||||||
0 -> {
|
0 -> {
|
||||||
item { GeneralInfoTabContent(drugDetail) }
|
item { GeneralInfoTabContent(drugDetail) }
|
||||||
}
|
}
|
||||||
|
|
||||||
1 -> {
|
1 -> {
|
||||||
item { SpecializedInfoTabContent(drugDetail) }
|
item { SpecializedInfoTabContent(drugDetail) }
|
||||||
}
|
}
|
||||||
|
|
||||||
2 -> {
|
2 -> {
|
||||||
item { DosageFormsTabContent(drugDetail) }
|
item { DosageFormsTabContent(drugDetail) }
|
||||||
}
|
}
|
||||||
|
|
||||||
3 -> {
|
3 -> {
|
||||||
item { BrandNamesTabContent(drugDetail) }
|
item { BrandNamesTabContent(drugDetail) }
|
||||||
}
|
}
|
||||||
@@ -215,6 +227,7 @@ fun DrugDetailScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ManufacturerInfoCard(
|
fun ManufacturerInfoCard(
|
||||||
|
|||||||
Reference in New Issue
Block a user