@@ -4,7 +4,7 @@ import androidx.compose.foundation.background
44import androidx.compose.foundation.horizontalScroll
55import androidx.compose.foundation.layout.*
66import androidx.compose.foundation.rememberScrollState
7- import androidx.compose.foundation.shape.RoundedCornerShape
7+ import androidx.compose.foundation.text.selection.SelectionContainer
88import androidx.compose.foundation.verticalScroll
99import androidx.compose.material.icons.Icons
1010import androidx.compose.material.icons.filled.ContentCopy
@@ -13,9 +13,9 @@ import androidx.compose.material3.*
1313import androidx.compose.runtime.*
1414import androidx.compose.ui.Alignment
1515import androidx.compose.ui.Modifier
16- import androidx.compose.ui.draw.clip
1716import androidx.compose.ui.graphics.Color
18- import androidx.compose.ui.platform.LocalClipboardManager
17+ import androidx.compose.ui.platform.ClipEntry
18+ import androidx.compose.ui.platform.LocalClipboard
1919import androidx.compose.ui.text.AnnotatedString
2020import androidx.compose.ui.text.SpanStyle
2121import androidx.compose.ui.text.buildAnnotatedString
@@ -25,7 +25,9 @@ import androidx.compose.ui.text.style.TextAlign
2525import androidx.compose.ui.unit.dp
2626import androidx.compose.ui.unit.sp
2727import kotlinx.coroutines.launch
28- import androidx.compose.foundation.text.selection.SelectionContainer
28+ import org.jetbrains.compose.resources.Font
29+ import simbot_codegen.composeapp.generated.resources.JetBrainsMono_Medium
30+ import simbot_codegen.composeapp.generated.resources.Res
2931
3032/* *
3133 * 文件内容预览组件
@@ -126,11 +128,11 @@ private fun FileContentDisplay(content: FileContent) {
126128 Column (modifier = Modifier .fillMaxSize()) {
127129 // 文件信息头部
128130 FileHeader (content = content)
129-
131+
130132 HorizontalDivider (
131133 color = MaterialTheme .colorScheme.outlineVariant.copy(alpha = 0.5f )
132134 )
133-
135+
134136 // 文件内容
135137 FileContentBody (content = content)
136138 }
@@ -141,7 +143,7 @@ private fun FileContentDisplay(content: FileContent) {
141143 */
142144@Composable
143145private fun FileHeader (content : FileContent ) {
144- val clipboardManager = LocalClipboardManager .current
146+ val clipboardManager = LocalClipboard .current
145147 val scope = rememberCoroutineScope()
146148 var showCopyFeedback by remember { mutableStateOf(false ) }
147149
@@ -180,11 +182,12 @@ private fun FileHeader(content: FileContent) {
180182 color = MaterialTheme .colorScheme.primary
181183 )
182184 }
183-
185+
184186 IconButton (
185187 onClick = {
186188 scope.launch {
187- clipboardManager.setText(AnnotatedString (content.content))
189+ clipboardManager.nativeClipboard
190+ clipboardManager.setClipEntry(ClipEntry .withPlainText(content.content))
188191 showCopyFeedback = true
189192 kotlinx.coroutines.delay(2000 )
190193 showCopyFeedback = false
@@ -224,15 +227,15 @@ private fun FileContentBody(content: FileContent) {
224227 ) {
225228 // 行号列
226229 LineNumbers (content = content.content)
227-
230+
228231 // 分隔线
229232 VerticalDivider (
230233 modifier = Modifier
231234 .fillMaxHeight()
232235 .padding(horizontal = 8 .dp),
233236 color = MaterialTheme .colorScheme.outlineVariant.copy(alpha = 0.3f )
234237 )
235-
238+
236239 // 代码内容
237240 CodeContent (
238241 content = content.content,
@@ -247,19 +250,25 @@ private fun FileContentBody(content: FileContent) {
247250 */
248251@Composable
249252private fun LineNumbers (content : String ) {
253+ val jetBrainsMonoFontFamily = FontFamily (
254+ Font (Res .font.JetBrainsMono_Medium , FontWeight .Medium )
255+ )
256+
250257 val lines = content.split(' \n ' )
251258 val maxLineNumber = lines.size
252259 val lineNumberWidth = maxLineNumber.toString().length
253-
260+
254261 Column (
255262 modifier = Modifier .padding(end = 8 .dp)
256263 ) {
257264 lines.forEachIndexed { index, _ ->
258265 Text (
259266 text = (index + 1 ).toString().padStart(lineNumberWidth),
267+ // fontFamily = jetBrainsMonoFontFamily,
260268 style = MaterialTheme .typography.bodySmall.copy(
261- fontFamily = FontFamily .Monospace ,
262- fontSize = 12 .sp
269+ fontFamily = jetBrainsMonoFontFamily,
270+ fontSize = 16 .sp,
271+ lineHeight = 16 .sp
263272 ),
264273 color = MaterialTheme .colorScheme.onSurfaceVariant.copy(alpha = 0.6f ),
265274 modifier = Modifier .padding(vertical = 1 .dp)
@@ -273,19 +282,23 @@ private fun LineNumbers(content: String) {
273282 */
274283@Composable
275284private fun CodeContent (content : String , mimeType : String ) {
285+ val jetBrainsMonoFontFamily = FontFamily (
286+ Font (Res .font.JetBrainsMono_Medium , FontWeight .Medium )
287+ )
288+
276289 val highlightedText = remember(content, mimeType) {
277290 highlightCode(content, mimeType)
278291 }
279-
292+
280293 SelectionContainer {
281294 Text (
282295 text = highlightedText,
283296 style = MaterialTheme .typography.bodySmall.copy(
284- fontFamily = FontFamily . Monospace ,
285- fontSize = 12 .sp,
297+ fontFamily = jetBrainsMonoFontFamily ,
298+ fontSize = 16 .sp,
286299 lineHeight = 16 .sp
287300 ),
288- modifier = Modifier .padding(vertical = 1 .dp)
301+ modifier = Modifier .padding(vertical = 1 .dp),
289302 )
290303 }
291304}
@@ -296,7 +309,7 @@ private fun CodeContent(content: String, mimeType: String) {
296309private fun highlightCode (content : String , mimeType : String ): AnnotatedString {
297310 return buildAnnotatedString {
298311 append(content)
299-
312+
300313 // 根据 MIME 类型应用不同的高亮规则
301314 when (mimeType) {
302315 " text/x-kotlin" -> applyKotlinHighlight(this , content)
@@ -313,12 +326,12 @@ private fun highlightCode(content: String, mimeType: String): AnnotatedString {
313326 */
314327private fun applyKotlinHighlight (builder : AnnotatedString .Builder , content : String ) {
315328 val keywords = setOf (
316- " class" , " interface" , " fun" , " val" , " var" , " if" , " else" , " when" , " for" ,
329+ " class" , " interface" , " fun" , " val" , " var" , " if" , " else" , " when" , " for" ,
317330 " while" , " do" , " try" , " catch" , " finally" , " return" , " break" , " continue" ,
318331 " object" , " companion" , " data" , " sealed" , " enum" , " annotation" , " suspend" ,
319332 " import" , " package" , " private" , " public" , " protected" , " internal"
320333 )
321-
334+
322335 highlightKeywords(builder, content, keywords, Color (0xFF0000FF )) // 蓝色关键字
323336 highlightStrings(builder, content, Color (0xFF008000 )) // 绿色字符串
324337 highlightComments(builder, content, Color (0xFF808080 )) // 灰色注释
@@ -335,7 +348,7 @@ private fun applyJavaHighlight(builder: AnnotatedString.Builder, content: String
335348 " catch" , " finally" , " throw" , " throws" , " return" , " break" , " continue" ,
336349 " import" , " package" , " extends" , " implements" , " super" , " this" , " new"
337350 )
338-
351+
339352 highlightKeywords(builder, content, keywords, Color (0xFF0000FF ))
340353 highlightStrings(builder, content, Color (0xFF008000 ))
341354 highlightComments(builder, content, Color (0xFF808080 ))
@@ -369,7 +382,7 @@ private fun applyJsonHighlight(builder: AnnotatedString.Builder, content: String
369382 end = match.range.last + 1
370383 )
371384 }
372-
385+
373386 // 数字
374387 val numberRegex = Regex (" \\ b\\ d+(\\ .\\ d+)?\\ b" )
375388 numberRegex.findAll(content).forEach { match ->
@@ -394,8 +407,8 @@ private fun applyGenericHighlight(builder: AnnotatedString.Builder, content: Str
394407 * 关键字高亮
395408 */
396409private fun highlightKeywords (
397- builder : AnnotatedString .Builder ,
398- content : String ,
410+ builder : AnnotatedString .Builder ,
411+ content : String ,
399412 keywords : Set <String >,
400413 color : Color
401414) {
@@ -437,7 +450,7 @@ private fun highlightComments(builder: AnnotatedString.Builder, content: String,
437450 end = match.range.last + 1
438451 )
439452 }
440-
453+
441454 val blockCommentRegex = Regex (" /\\ *.*?\\ */" , RegexOption .DOT_MATCHES_ALL )
442455 blockCommentRegex.findAll(content).forEach { match ->
443456 builder.addStyle(
0 commit comments