Skip to content

Commit 811683a

Browse files
committed
file-preview, good~
1 parent 4ec6703 commit 811683a

File tree

3 files changed

+94
-74
lines changed

3 files changed

+94
-74
lines changed

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

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import androidx.compose.foundation.rememberScrollState
77
import androidx.compose.foundation.rememberScrollbarAdapter
88
import androidx.compose.foundation.text.selection.SelectionContainer
99
import androidx.compose.foundation.verticalScroll
10+
import androidx.compose.foundation.VerticalScrollbar
11+
import androidx.compose.foundation.HorizontalScrollbar
1012
import androidx.compose.material.icons.Icons
1113
import androidx.compose.material.icons.filled.ContentCopy
1214
import androidx.compose.material.icons.filled.Description
@@ -250,6 +252,17 @@ private fun FileContentBody(content: FileContent) {
250252
}
251253
}
252254

255+
// 垂直滚动条
256+
VerticalScrollbar(
257+
modifier = Modifier.align(Alignment.CenterEnd).fillMaxHeight(),
258+
adapter = rememberScrollbarAdapter(verticalScrollState)
259+
)
260+
261+
// 水平滚动条
262+
HorizontalScrollbar(
263+
modifier = Modifier.align(Alignment.BottomCenter).fillMaxWidth(),
264+
adapter = rememberScrollbarAdapter(horizontalScrollState)
265+
)
253266
}
254267
}
255268

@@ -266,21 +279,26 @@ private fun LineNumbers(content: String) {
266279
val maxLineNumber = lines.size
267280
val lineNumberWidth = maxLineNumber.toString().length
268281

282+
val textStyle = MaterialTheme.typography.bodySmall.copy(
283+
fontFamily = jetBrainsMonoFontFamily,
284+
fontSize = 16.sp,
285+
lineHeight = 24.sp // 增加行高以改善对齐
286+
)
287+
269288
Column(
270289
modifier = Modifier.padding(end = 8.dp)
271290
) {
272291
lines.forEachIndexed { index, _ ->
273-
Text(
274-
text = (index + 1).toString().padStart(lineNumberWidth),
275-
// fontFamily = jetBrainsMonoFontFamily,
276-
style = MaterialTheme.typography.bodySmall.copy(
277-
fontFamily = jetBrainsMonoFontFamily,
278-
fontSize = 16.sp,
279-
lineHeight = 16.sp
280-
),
281-
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f),
282-
modifier = Modifier.padding(vertical = 1.dp)
283-
)
292+
Box(
293+
modifier = Modifier.height(24.dp), // 固定高度确保对齐
294+
contentAlignment = Alignment.CenterStart
295+
) {
296+
Text(
297+
text = (index + 1).toString().padStart(lineNumberWidth),
298+
style = textStyle,
299+
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f),
300+
)
301+
}
284302
}
285303
}
286304
}
@@ -294,16 +312,26 @@ private fun CodeContent(content: String, mimeType: String) {
294312
Font(Res.font.JetBrainsMono_Medium, FontWeight.Medium)
295313
)
296314

315+
val textStyle = MaterialTheme.typography.bodySmall.copy(
316+
fontFamily = jetBrainsMonoFontFamily,
317+
fontSize = 16.sp,
318+
lineHeight = 24.sp // 与行号保持一致的行高
319+
)
320+
297321
SelectionContainer {
298-
Text(
299-
text = content,
300-
style = MaterialTheme.typography.bodySmall.copy(
301-
fontFamily = jetBrainsMonoFontFamily,
302-
fontSize = 16.sp,
303-
lineHeight = 16.sp
304-
),
305-
modifier = Modifier.padding(vertical = 1.dp),
306-
)
322+
Column {
323+
content.split('\n').forEach { line ->
324+
Box(
325+
modifier = Modifier.height(24.dp), // 固定高度确保对齐
326+
contentAlignment = Alignment.CenterStart
327+
) {
328+
Text(
329+
text = if (line.isEmpty()) " " else line, // 空行显示空格以保持高度
330+
style = textStyle,
331+
)
332+
}
333+
}
334+
}
307335
}
308336
}
309337

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

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -31,51 +31,24 @@ import androidx.compose.ui.unit.sp
3131

3232
/**
3333
* 计算应该自动展开的路径
34-
* 递归展开只有唯一子目录的目录
34+
* 只展开第一级目录
3535
*/
3636
private fun calculateAutoExpandPaths(nodes: List<ZipFileNode>): Set<String> {
3737
val autoExpandPaths = mutableSetOf<String>()
3838

39-
fun shouldAutoExpand(node: ZipFileNode): Boolean {
40-
if (!node.isDirectory) return false
41-
42-
// 统计子目录数量
43-
val childDirectories = node.children.filter { it.isDirectory }
44-
45-
// 如果只有一个子目录,则应该自动展开
46-
return childDirectories.size == 1
47-
}
48-
49-
fun collectAutoExpandPaths(nodeList: List<ZipFileNode>) {
50-
for (node in nodeList) {
51-
if (node.isDirectory) {
52-
// 如果是顶层目录,总是展开
53-
if (node.isTopLevel) {
54-
autoExpandPaths.add(node.path)
55-
}
56-
57-
// 如果应该自动展开,添加到集合中
58-
if (shouldAutoExpand(node)) {
59-
autoExpandPaths.add(node.path)
60-
61-
// 对唯一的子目录递归处理
62-
val childDir = node.children.first { it.isDirectory }
63-
collectAutoExpandPaths(listOf(childDir))
64-
}
65-
66-
// 递归处理所有子节点
67-
collectAutoExpandPaths(node.children)
68-
}
39+
// 只展开根级别的目录
40+
for (node in nodes) {
41+
if (node.isDirectory) {
42+
autoExpandPaths.add(node.path)
6943
}
7044
}
7145

72-
collectAutoExpandPaths(nodes)
7346
return autoExpandPaths
7447
}
7548

7649
/**
7750
* 文件树展示组件
78-
* 支持展开/折叠,默认展开第一层,自动展开只有唯一子目录的目录
51+
* 支持展开/折叠,默认只展开第一层目录
7952
*/
8053
@Composable
8154
fun FileTreeView(
@@ -220,11 +193,11 @@ private fun FileTreeNode(
220193
visible = isExpanded,
221194
enter = expandVertically(
222195
animationSpec = androidx.compose.animation.core.spring(
223-
dampingRatio = androidx.compose.animation.core.Spring.DampingRatioMediumBouncy,
224-
stiffness = androidx.compose.animation.core.Spring.StiffnessLow
196+
dampingRatio = androidx.compose.animation.core.Spring.DampingRatioNoBouncy,
197+
stiffness = androidx.compose.animation.core.Spring.StiffnessMedium
225198
)
226199
) + fadeIn(
227-
animationSpec = androidx.compose.animation.core.tween(300)
200+
animationSpec = androidx.compose.animation.core.tween(250)
228201
),
229202
exit = shrinkVertically(
230203
animationSpec = androidx.compose.animation.core.spring(

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

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@ import androidx.compose.animation.fadeIn
55
import androidx.compose.animation.fadeOut
66
import androidx.compose.foundation.background
77
import androidx.compose.foundation.layout.*
8+
import androidx.compose.foundation.rememberScrollState
9+
import androidx.compose.foundation.rememberScrollbarAdapter
810
import androidx.compose.foundation.shape.RoundedCornerShape
11+
import androidx.compose.foundation.verticalScroll
12+
import androidx.compose.foundation.VerticalScrollbar
913
import androidx.compose.material.icons.Icons
1014
import androidx.compose.material.icons.filled.Close
15+
import androidx.compose.material.icons.filled.Folder
1116
import androidx.compose.material.icons.filled.Visibility
1217
import androidx.compose.material3.*
1318
import androidx.compose.runtime.*
@@ -368,32 +373,46 @@ private fun DesktopLayout(
368373
colors = CardDefaults.cardColors(
369374
containerColor = MaterialTheme.colorScheme.surface
370375
),
371-
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
372-
shape = RoundedCornerShape(16.dp)
376+
elevation = CardDefaults.cardElevation(defaultElevation = 6.dp),
377+
shape = RoundedCornerShape(12.dp)
373378
) {
374379
Column(
375380
modifier = Modifier.fillMaxSize()
376381
) {
377382
// 标题区域
378-
Box(
379-
modifier = Modifier
380-
.fillMaxWidth()
381-
.background(
382-
MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.3f),
383-
RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)
384-
)
385-
.padding(horizontal = 16.dp, vertical = 12.dp)
383+
Surface(
384+
modifier = Modifier.fillMaxWidth(),
385+
color = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.4f),
386+
shape = RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp)
386387
) {
387-
Text(
388-
text = "📁 文件结构",
389-
style = MaterialTheme.typography.titleMedium.copy(
390-
fontWeight = FontWeight.SemiBold,
391-
fontSize = 16.sp
392-
),
393-
color = MaterialTheme.colorScheme.primary
394-
)
388+
Row(
389+
modifier = Modifier.padding(horizontal = 16.dp, vertical = 14.dp),
390+
verticalAlignment = Alignment.CenterVertically,
391+
horizontalArrangement = Arrangement.spacedBy(8.dp)
392+
) {
393+
Icon(
394+
imageVector = Icons.Default.Folder,
395+
contentDescription = null,
396+
modifier = Modifier.size(20.dp),
397+
tint = MaterialTheme.colorScheme.primary
398+
)
399+
Text(
400+
text = "文件结构",
401+
style = MaterialTheme.typography.titleMedium.copy(
402+
fontWeight = FontWeight.SemiBold,
403+
fontSize = 16.sp
404+
),
405+
color = MaterialTheme.colorScheme.primary
406+
)
407+
}
395408
}
396409

410+
// 分隔线
411+
HorizontalDivider(
412+
color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f),
413+
thickness = 1.dp
414+
)
415+
397416
// 文件树内容区域
398417
Box(
399418
modifier = Modifier

0 commit comments

Comments
 (0)