Update editor: build using temp files and save directly to source
This commit is contained in:
parent
d61ec9e1f2
commit
1223416923
5 changed files with 116 additions and 18 deletions
|
|
@ -0,0 +1,22 @@
|
|||
package mg.dot.feufaro
|
||||
|
||||
|
||||
class AndroidPathValidator : PathValidator {
|
||||
override fun isRestrictedPath(path: String): Boolean {
|
||||
if (path.isEmpty()) return true
|
||||
|
||||
val lowerPath = path.lowercase()
|
||||
|
||||
val isAndroidAsset = lowerPath.contains("android_asset") ||
|
||||
lowerPath.startsWith("assets/")
|
||||
|
||||
val isAndroidCacheOrTmp = lowerPath.contains("/cache/") ||
|
||||
lowerPath.contains("/code_cache/") ||
|
||||
lowerPath.contains("/tmp/") ||
|
||||
lowerPath.contains("_tmp")
|
||||
|
||||
return isAndroidAsset || isAndroidCacheOrTmp
|
||||
}
|
||||
}
|
||||
|
||||
actual fun getPathValidator(): PathValidator = AndroidPathValidator()
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package mg.dot.feufaro
|
||||
|
||||
interface PathValidator {
|
||||
fun isRestrictedPath(path: String): Boolean
|
||||
}
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
package mg.dot.feufaro
|
||||
|
||||
|
||||
interface Platform {
|
||||
val name: String
|
||||
}
|
||||
|
||||
expect fun getPlatform(): Platform
|
||||
expect fun getPlatform(): Platform
|
||||
|
||||
expect fun getPathValidator(): PathValidator
|
||||
|
|
@ -15,7 +15,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
|||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBackIos
|
||||
import androidx.compose.material.icons.automirrored.filled.Undo
|
||||
import androidx.compose.material.icons.filled.Build
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
|
|
@ -51,6 +50,7 @@ import mg.dot.feufaro.ContextualMenu
|
|||
import mg.dot.feufaro.FileRepository
|
||||
import mg.dot.feufaro.TUODetailDialog
|
||||
import mg.dot.feufaro.data.GridTUOData
|
||||
import mg.dot.feufaro.getPathValidator
|
||||
import mg.dot.feufaro.ui.rememberFileSaveLauncher
|
||||
import mg.dot.feufaro.viewmodel.MidiMarkers
|
||||
import mg.dot.feufaro.viewmodel.SolfaScreenModel
|
||||
|
|
@ -1039,10 +1039,15 @@ private suspend fun expandInclusions(
|
|||
val lastSlash = currentFilePath.lastIndexOf('/')
|
||||
val directory = if (lastSlash != -1) currentFilePath.substring(0, lastSlash + 1) else ""
|
||||
|
||||
val inclusionRegex = Regex("^I([0-9]):(.*)")
|
||||
|
||||
lines.forEach { line ->
|
||||
if (line.startsWith("I0:")) {
|
||||
val match = inclusionRegex.find(line)
|
||||
|
||||
if (match != null) {
|
||||
try {
|
||||
val parts = line.substring(3).split(":")
|
||||
val body = match.groupValues[2]
|
||||
val parts = body.split(":")
|
||||
val fileName = parts[0]
|
||||
val ignorePattern = if (parts.size > 1) parts[1] else ""
|
||||
|
||||
|
|
@ -1057,7 +1062,7 @@ private suspend fun expandInclusions(
|
|||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
result.append("// Erreur inclusion: ${e.message}\n")
|
||||
result.append("// Erreur inclusion sur ${line}: ${e.message}\n")
|
||||
}
|
||||
} else {
|
||||
result.append(line).append("\n")
|
||||
|
|
@ -1092,8 +1097,20 @@ fun EditSourceCompose(
|
|||
var currentTempFile by remember { mutableStateOf<File?>(null) }
|
||||
|
||||
var codeContent by remember { mutableStateOf(sourceContent?: "") }
|
||||
|
||||
val pathValidator = remember { getPathValidator() }
|
||||
// restricted path pour les fichiers interne de l'app
|
||||
val isRestrictedPath = remember(sourcePath) {
|
||||
pathValidator.isRestrictedPath(sourcePath)
|
||||
}
|
||||
|
||||
val isModified = remember(codeContent, sourceContent) { codeContent != sourceContent }
|
||||
|
||||
var previousCodeContentBeforeBuild by remember { mutableStateOf<String?>(null) }
|
||||
|
||||
LaunchedEffect(sourceContent) {
|
||||
codeContent = sourceContent
|
||||
previousCodeContentBeforeBuild = null
|
||||
}
|
||||
var textLayoutResult by remember { mutableStateOf<TextLayoutResult?>(null) }
|
||||
|
||||
|
|
@ -1140,6 +1157,8 @@ fun EditSourceCompose(
|
|||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
EditorActionButtons(
|
||||
isSaveVisible = isModified || isRestrictedPath,
|
||||
isUndoVisible = isModified,
|
||||
onUndo = {
|
||||
scope.launch {
|
||||
codeContent = sourceContent
|
||||
|
|
@ -1162,19 +1181,20 @@ fun EditSourceCompose(
|
|||
|
||||
if (currentTempFile == null || !currentTempFile!!.exists()) {
|
||||
val tempDir = System.getProperty("java.io.tmpdir")
|
||||
currentTempFile = File(tempDir, fileName)
|
||||
currentTempFile = File(tempDir, fileName.ifEmpty { "preview_solfa.txt" })
|
||||
currentTempFile?.deleteOnExit()
|
||||
}
|
||||
|
||||
currentTempFile?.writeText(expandedContent)
|
||||
|
||||
currentTempFile?.let { file ->
|
||||
withContext(Dispatchers.Main) {
|
||||
solfaScreenModel.justeCompile(file.absolutePath)
|
||||
}
|
||||
withContext(Dispatchers.IO) {
|
||||
currentTempFile?.writeText(expandedContent)
|
||||
}
|
||||
|
||||
println("Compilation sur le fichier : ${currentTempFile?.absolutePath}")
|
||||
withContext(Dispatchers.Main) {
|
||||
solfaScreenModel.justeCompile(currentTempFile!!.absolutePath)
|
||||
|
||||
println("Compilation temporaire réussie : ${currentTempFile?.absolutePath}")
|
||||
currentTempFile?.deleteOnExit()
|
||||
}
|
||||
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
|
|
@ -1184,8 +1204,23 @@ fun EditSourceCompose(
|
|||
onSave = {
|
||||
scope.launch {
|
||||
try {
|
||||
val initialDir = solfaScreenModel.fileRepository.getAppPublicFolder().absolutePath
|
||||
saveLauncher.launch(fileName, initialDir)
|
||||
if (!isRestrictedPath) {
|
||||
val externalFile = File(sourcePath)
|
||||
withContext(Dispatchers.IO) {
|
||||
externalFile.writeText(codeContent)
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
sharedScreenModel.setFileContent(codeContent, sourcePath)
|
||||
solfaScreenModel.loadExternalFile(sourcePath)
|
||||
}
|
||||
println("Vraie source écrasée avec succès : $sourcePath")
|
||||
} else {
|
||||
val initialDir = solfaScreenModel.fileRepository.getAppPublicFolder().absolutePath
|
||||
saveLauncher.launch(fileName, initialDir)
|
||||
}
|
||||
currentTempFile?.delete()
|
||||
currentTempFile = null
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
|
@ -1221,11 +1256,15 @@ fun EditSourceCompose(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun EditorActionButtons(onUndo: () -> Unit, onBuild: () -> Unit, onSave: () -> Unit, onClose: () -> Unit) {
|
||||
fun EditorActionButtons(isSaveVisible: Boolean, isUndoVisible: Boolean, onUndo: () -> Unit, onBuild: () -> Unit, onSave: () -> Unit, onClose: () -> Unit) {
|
||||
Row(horizontalArrangement = Arrangement.SpaceBetween) {
|
||||
IconButton(onClick = onUndo) { Icon(Icons.AutoMirrored.Filled.Undo, null, tint = Color.Gray) }
|
||||
if(isUndoVisible) {
|
||||
IconButton(onClick = onUndo) { Icon(Icons.AutoMirrored.Filled.Undo, null, tint = Color.Gray) }
|
||||
}
|
||||
IconButton(onClick = onBuild) { Icon(Icons.Default.Build, null, tint = Color(0xFF2196F3)) }
|
||||
IconButton(onClick = onSave) { Icon(Icons.Default.Save, null, tint = Color(0xFF4CAF50)) }
|
||||
if(isSaveVisible) {
|
||||
IconButton(onClick = onSave) { Icon(Icons.Default.Save, null, tint = Color(0xFF4CAF50)) }
|
||||
}
|
||||
IconButton(onClick = onClose) { Icon(Icons.Default.Close, null, tint = Color.Red) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
package mg.dot.feufaro
|
||||
|
||||
import java.io.File
|
||||
|
||||
class DesktopPathValidator : PathValidator {
|
||||
private val systemTmpDir: String by lazy {
|
||||
try {
|
||||
File(System.getProperty("java.io.tmpdir")).absolutePath.lowercase()
|
||||
} catch (e: Exception) {
|
||||
"/tmp"
|
||||
}
|
||||
}
|
||||
|
||||
override fun isRestrictedPath(path: String): Boolean {
|
||||
if (path.isEmpty()) return true
|
||||
|
||||
val lowerPath = path.lowercase()
|
||||
|
||||
val isInSystemTmp = lowerPath.contains(systemTmpDir)
|
||||
|
||||
val isOtherRestricted = lowerPath.contains("/tmp/") ||
|
||||
lowerPath.contains("_tmp") ||
|
||||
lowerPath.contains("assets")
|
||||
|
||||
return isInSystemTmp || isOtherRestricted
|
||||
}
|
||||
}
|
||||
|
||||
actual fun getPathValidator(): PathValidator = DesktopPathValidator()
|
||||
Loading…
Add table
Reference in a new issue