Misc Changes
This commit is contained in:
@@ -16,9 +16,16 @@ import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
@@ -38,6 +45,29 @@ fun ManPageDialog(
|
||||
) {
|
||||
val horizontalScrollState = rememberScrollState()
|
||||
val verticalScrollState = rememberScrollState()
|
||||
var searchQuery by remember(state.content) { mutableStateOf("") }
|
||||
var selectedMatch by remember(state.content) { mutableStateOf(0) }
|
||||
val contentLines = remember(state.content) { state.content.lines() }
|
||||
val matches = remember(searchQuery, contentLines) {
|
||||
if (searchQuery.isBlank()) {
|
||||
emptyList()
|
||||
} else {
|
||||
contentLines.mapIndexedNotNull { index, line ->
|
||||
index.takeIf { line.contains(searchQuery, ignoreCase = true) }
|
||||
}
|
||||
}
|
||||
}
|
||||
val matchCount = matches.size
|
||||
val currentMatchNumber = if (matchCount == 0) 0 else selectedMatch + 1
|
||||
|
||||
LaunchedEffect(searchQuery, matchCount) {
|
||||
selectedMatch = selectedMatch.coerceIn(0, (matchCount - 1).coerceAtLeast(0))
|
||||
}
|
||||
|
||||
LaunchedEffect(selectedMatch, matches) {
|
||||
val lineIndex = matches.getOrNull(selectedMatch) ?: return@LaunchedEffect
|
||||
verticalScrollState.animateScrollTo((lineIndex * 18).coerceAtMost(verticalScrollState.maxValue))
|
||||
}
|
||||
|
||||
Dialog(onDismissRequest = onClose) {
|
||||
Surface(
|
||||
@@ -71,6 +101,59 @@ fun ManPageDialog(
|
||||
Text("Close")
|
||||
}
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
TextField(
|
||||
value = searchQuery,
|
||||
onValueChange = {
|
||||
searchQuery = it
|
||||
selectedMatch = 0
|
||||
},
|
||||
modifier = Modifier.weight(1f),
|
||||
singleLine = true,
|
||||
placeholder = { Text("Search") },
|
||||
colors = TextFieldDefaults.colors(
|
||||
focusedTextColor = TextPrimary,
|
||||
unfocusedTextColor = TextPrimary,
|
||||
focusedContainerColor = PanelSecondary,
|
||||
unfocusedContainerColor = PanelSecondary,
|
||||
focusedIndicatorColor = Accent,
|
||||
unfocusedIndicatorColor = TextMuted,
|
||||
cursorColor = Accent,
|
||||
),
|
||||
)
|
||||
Button(
|
||||
onClick = {
|
||||
if (matchCount > 0) selectedMatch = (selectedMatch - 1 + matchCount) % matchCount
|
||||
},
|
||||
enabled = matchCount > 0,
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = PanelSecondary,
|
||||
contentColor = TextPrimary,
|
||||
),
|
||||
) {
|
||||
Text("Prev")
|
||||
}
|
||||
Button(
|
||||
onClick = {
|
||||
if (matchCount > 0) selectedMatch = (selectedMatch + 1) % matchCount
|
||||
},
|
||||
enabled = matchCount > 0,
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = PanelSecondary,
|
||||
contentColor = TextPrimary,
|
||||
),
|
||||
) {
|
||||
Text("Next")
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = "$currentMatchNumber/$matchCount",
|
||||
color = TextSecondary,
|
||||
fontSize = 12.sp,
|
||||
)
|
||||
Text(
|
||||
text = "git ${state.topic}",
|
||||
color = TextPrimary,
|
||||
|
||||
Reference in New Issue
Block a user