Skip to content

Commit 4ec6703

Browse files
committed
file-preview
1 parent 15243de commit 4ec6703

File tree

3 files changed

+127
-234
lines changed

3 files changed

+127
-234
lines changed

composeApp/src/wasmJsMain/kotlin/love/forte/simbot/codegen/gen/view/preview/FileContentComponents.kt

Lines changed: 23 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import androidx.compose.foundation.background
44
import androidx.compose.foundation.horizontalScroll
55
import androidx.compose.foundation.layout.*
66
import androidx.compose.foundation.rememberScrollState
7+
import androidx.compose.foundation.rememberScrollbarAdapter
78
import androidx.compose.foundation.text.selection.SelectionContainer
89
import androidx.compose.foundation.verticalScroll
910
import androidx.compose.material.icons.Icons
@@ -16,9 +17,6 @@ import androidx.compose.ui.Modifier
1617
import androidx.compose.ui.graphics.Color
1718
import androidx.compose.ui.platform.ClipEntry
1819
import androidx.compose.ui.platform.LocalClipboard
19-
import androidx.compose.ui.text.AnnotatedString
20-
import androidx.compose.ui.text.SpanStyle
21-
import androidx.compose.ui.text.buildAnnotatedString
2220
import androidx.compose.ui.text.font.FontFamily
2321
import androidx.compose.ui.text.font.FontWeight
2422
import androidx.compose.ui.text.style.TextAlign
@@ -209,24 +207,26 @@ private fun FileHeader(content: FileContent) {
209207
*/
210208
@Composable
211209
private fun FileContentBody(content: FileContent) {
212-
val horizontalScrollState = rememberScrollState()
213210
val verticalScrollState = rememberScrollState()
211+
val horizontalScrollState = rememberScrollState()
214212

215213
Box(
216214
modifier = Modifier
217215
.fillMaxSize()
218216
.background(MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.1f))
219217
) {
220-
// 内容区域
221218
Row(
222219
modifier = Modifier
223220
.fillMaxSize()
224-
.horizontalScroll(horizontalScrollState)
225-
.verticalScroll(verticalScrollState)
226221
.padding(8.dp)
227222
) {
228-
// 行号列
229-
LineNumbers(content = content.content)
223+
// 行号列 - 不参与横向滚动,只跟随纵向滚动
224+
Box(
225+
modifier = Modifier
226+
.verticalScroll(verticalScrollState)
227+
) {
228+
LineNumbers(content = content.content)
229+
}
230230

231231
// 分隔线
232232
VerticalDivider(
@@ -236,12 +236,20 @@ private fun FileContentBody(content: FileContent) {
236236
color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.3f)
237237
)
238238

239-
// 代码内容
240-
CodeContent(
241-
content = content.content,
242-
mimeType = content.mimeType
243-
)
239+
// 代码内容区域 - 支持独立的横向和纵向滚动
240+
Box(
241+
modifier = Modifier
242+
.fillMaxSize()
243+
.horizontalScroll(horizontalScrollState)
244+
.verticalScroll(verticalScrollState)
245+
) {
246+
CodeContent(
247+
content = content.content,
248+
mimeType = content.mimeType
249+
)
250+
}
244251
}
252+
245253
}
246254
}
247255

@@ -286,13 +294,9 @@ private fun CodeContent(content: String, mimeType: String) {
286294
Font(Res.font.JetBrainsMono_Medium, FontWeight.Medium)
287295
)
288296

289-
val highlightedText = remember(content, mimeType) {
290-
highlightCode(content, mimeType)
291-
}
292-
293297
SelectionContainer {
294298
Text(
295-
text = highlightedText,
299+
text = content,
296300
style = MaterialTheme.typography.bodySmall.copy(
297301
fontFamily = jetBrainsMonoFontFamily,
298302
fontSize = 16.sp,
@@ -303,163 +307,6 @@ private fun CodeContent(content: String, mimeType: String) {
303307
}
304308
}
305309

306-
/**
307-
* 简单的代码高亮
308-
*/
309-
private fun highlightCode(content: String, mimeType: String): AnnotatedString {
310-
return buildAnnotatedString {
311-
append(content)
312-
313-
// 根据 MIME 类型应用不同的高亮规则
314-
when (mimeType) {
315-
"text/x-kotlin" -> applyKotlinHighlight(this, content)
316-
"text/x-java" -> applyJavaHighlight(this, content)
317-
"application/xml" -> applyXmlHighlight(this, content)
318-
"application/json" -> applyJsonHighlight(this, content)
319-
else -> applyGenericHighlight(this, content)
320-
}
321-
}
322-
}
323-
324-
/**
325-
* Kotlin 语法高亮
326-
*/
327-
private fun applyKotlinHighlight(builder: AnnotatedString.Builder, content: String) {
328-
val keywords = setOf(
329-
"class", "interface", "fun", "val", "var", "if", "else", "when", "for",
330-
"while", "do", "try", "catch", "finally", "return", "break", "continue",
331-
"object", "companion", "data", "sealed", "enum", "annotation", "suspend",
332-
"import", "package", "private", "public", "protected", "internal"
333-
)
334-
335-
highlightKeywords(builder, content, keywords, Color(0xFF0000FF)) // 蓝色关键字
336-
highlightStrings(builder, content, Color(0xFF008000)) // 绿色字符串
337-
highlightComments(builder, content, Color(0xFF808080)) // 灰色注释
338-
}
339-
340-
/**
341-
* Java 语法高亮
342-
*/
343-
private fun applyJavaHighlight(builder: AnnotatedString.Builder, content: String) {
344-
val keywords = setOf(
345-
"class", "interface", "public", "private", "protected", "static", "final",
346-
"abstract", "synchronized", "volatile", "transient", "native", "strictfp",
347-
"if", "else", "switch", "case", "default", "for", "while", "do", "try",
348-
"catch", "finally", "throw", "throws", "return", "break", "continue",
349-
"import", "package", "extends", "implements", "super", "this", "new"
350-
)
351-
352-
highlightKeywords(builder, content, keywords, Color(0xFF0000FF))
353-
highlightStrings(builder, content, Color(0xFF008000))
354-
highlightComments(builder, content, Color(0xFF808080))
355-
}
356-
357-
/**
358-
* XML 语法高亮
359-
*/
360-
private fun applyXmlHighlight(builder: AnnotatedString.Builder, content: String) {
361-
// 简单的 XML 标签高亮
362-
val tagRegex = Regex("<[^>]+>")
363-
tagRegex.findAll(content).forEach { match ->
364-
builder.addStyle(
365-
style = SpanStyle(color = Color(0xFF0000FF)),
366-
start = match.range.first,
367-
end = match.range.last + 1
368-
)
369-
}
370-
}
371-
372-
/**
373-
* JSON 语法高亮
374-
*/
375-
private fun applyJsonHighlight(builder: AnnotatedString.Builder, content: String) {
376-
// 字符串
377-
val stringRegex = Regex("\"[^\"]*\"")
378-
stringRegex.findAll(content).forEach { match ->
379-
builder.addStyle(
380-
style = SpanStyle(color = Color(0xFF008000)),
381-
start = match.range.first,
382-
end = match.range.last + 1
383-
)
384-
}
385-
386-
// 数字
387-
val numberRegex = Regex("\\b\\d+(\\.\\d+)?\\b")
388-
numberRegex.findAll(content).forEach { match ->
389-
builder.addStyle(
390-
style = SpanStyle(color = Color(0xFFFF0000)),
391-
start = match.range.first,
392-
end = match.range.last + 1
393-
)
394-
}
395-
}
396-
397-
/**
398-
* 通用高亮
399-
*/
400-
private fun applyGenericHighlight(builder: AnnotatedString.Builder, content: String) {
401-
// 只高亮字符串和注释
402-
highlightStrings(builder, content, Color(0xFF008000))
403-
highlightComments(builder, content, Color(0xFF808080))
404-
}
405-
406-
/**
407-
* 关键字高亮
408-
*/
409-
private fun highlightKeywords(
410-
builder: AnnotatedString.Builder,
411-
content: String,
412-
keywords: Set<String>,
413-
color: Color
414-
) {
415-
keywords.forEach { keyword ->
416-
val regex = Regex("\\b$keyword\\b")
417-
regex.findAll(content).forEach { match ->
418-
builder.addStyle(
419-
style = SpanStyle(color = color, fontWeight = FontWeight.Bold),
420-
start = match.range.first,
421-
end = match.range.last + 1
422-
)
423-
}
424-
}
425-
}
426-
427-
/**
428-
* 字符串高亮
429-
*/
430-
private fun highlightStrings(builder: AnnotatedString.Builder, content: String, color: Color) {
431-
val stringRegex = Regex("\"[^\"]*\"|'[^']*'")
432-
stringRegex.findAll(content).forEach { match ->
433-
builder.addStyle(
434-
style = SpanStyle(color = color),
435-
start = match.range.first,
436-
end = match.range.last + 1
437-
)
438-
}
439-
}
440-
441-
/**
442-
* 注释高亮
443-
*/
444-
private fun highlightComments(builder: AnnotatedString.Builder, content: String, color: Color) {
445-
val lineCommentRegex = Regex("//.*$", RegexOption.MULTILINE)
446-
lineCommentRegex.findAll(content).forEach { match ->
447-
builder.addStyle(
448-
style = SpanStyle(color = color),
449-
start = match.range.first,
450-
end = match.range.last + 1
451-
)
452-
}
453-
454-
val blockCommentRegex = Regex("/\\*.*?\\*/", RegexOption.DOT_MATCHES_ALL)
455-
blockCommentRegex.findAll(content).forEach { match ->
456-
builder.addStyle(
457-
style = SpanStyle(color = color),
458-
start = match.range.first,
459-
end = match.range.last + 1
460-
)
461-
}
462-
}
463310

464311
/**
465312
* 格式化文件大小

0 commit comments

Comments
 (0)