package cc.unitmesh.devins.ui.compose.agent import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.unit.dp import cc.unitmesh.devins.ui.compose.icons.AutoDevComposeIcons import cc.unitmesh.viewer.LanguageDetector import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File @Composable actual fun FileViewerPanelWrapper( filePath: String, onClose: () -> Unit, modifier: Modifier ) { var errorMessage by remember { mutableStateOf(null) } var fileName by remember { mutableStateOf("") } var isLoading by remember { mutableStateOf(true) } var fileContent by remember { mutableStateOf(null) } // Load file content LaunchedEffect(filePath) { isLoading = true errorMessage = null fileContent = null withContext(Dispatchers.IO) { try { val file = File(filePath) if (!file.exists()) { errorMessage = "File not found: $filePath" fileName = filePath return@withContext } fileName = file.name // Check if binary if (LanguageDetector.isBinaryFile(filePath)) { errorMessage = "Cannot open binary file: ${file.name}" return@withContext } // Check file size (10MB limit) val maxSize = 10 * 1024 * 1024 if (file.length() > maxSize) { errorMessage = "File too large (${file.length() / 1024 / 1024}MB). Maximum size is 10MB." return@withContext } fileContent = file.readText() } catch (e: Exception) { errorMessage = "Error loading file: ${e.message}" fileName = filePath } finally { isLoading = false } } } Column( modifier = modifier .fillMaxHeight() .background(MaterialTheme.colorScheme.surface) ) { // Header Surface( modifier = Modifier.fillMaxWidth(), color = MaterialTheme.colorScheme.surfaceVariant, shadowElevation = 2.dp ) { Row( modifier = Modifier .fillMaxWidth() .padding(8.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Column(modifier = Modifier.weight(1f)) { Text( text = fileName, style = MaterialTheme.typography.titleSmall, color = MaterialTheme.colorScheme.onSurfaceVariant ) Text( text = filePath, style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f) ) } IconButton(onClick = onClose) { Icon( imageVector = AutoDevComposeIcons.Close, contentDescription = "Close", tint = MaterialTheme.colorScheme.onSurfaceVariant ) } } } // Content Box(modifier = Modifier.fillMaxSize()) { when { isLoading -> { Column( modifier = Modifier .fillMaxSize() .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { CircularProgressIndicator(modifier = Modifier.size(48.dp)) Spacer(modifier = Modifier.height(16.dp)) Text( text = "Loading file...", style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurface ) } } errorMessage != null -> { Column( modifier = Modifier .fillMaxSize() .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text( text = "Error", style = MaterialTheme.typography.titleMedium, color = MaterialTheme.colorScheme.error ) Spacer(modifier = Modifier.height(8.dp)) Text( text = errorMessage!!, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurface ) } } fileContent != null -> { // Simple text display for Android LazyColumn( modifier = Modifier .fillMaxSize() .padding(16.dp) ) { item { Text( text = fileContent!!, style = MaterialTheme.typography.bodySmall.copy( fontFamily = FontFamily.Monospace ), color = MaterialTheme.colorScheme.onSurface ) } } } } } } }