Centered songKey & take Included Source & filename on QR Content
This commit is contained in:
parent
997f5e87b4
commit
76f99cadce
4 changed files with 135 additions and 39 deletions
|
|
@ -15,7 +15,8 @@
|
|||
android:theme="@android:style/Theme.Material.Light.NoActionBar">
|
||||
<activity
|
||||
android:exported="true"
|
||||
android:name=".MainActivity">
|
||||
android:name=".MainActivity"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
|
|
|
|||
|
|
@ -89,12 +89,10 @@ class MainActivity : ComponentActivity() {
|
|||
|
||||
println("DeepLink: rawContent = $rawContent")
|
||||
|
||||
val fileName = rawContent
|
||||
.split("|")
|
||||
.firstOrNull { it.startsWith("t:") }
|
||||
?.removePrefix("t:")
|
||||
?.trim()
|
||||
|
||||
val fileName = data.getQueryParameter("name") ?: run {
|
||||
println("DeepLink: paramètre 'name' introuvable")
|
||||
return
|
||||
}
|
||||
println("DeepLink: fileName extrait = $fileName")
|
||||
|
||||
if (fileName.isNullOrBlank()) {
|
||||
|
|
@ -111,7 +109,7 @@ class MainActivity : ComponentActivity() {
|
|||
appDir.mkdirs()
|
||||
// docsDir.mkdirs()
|
||||
|
||||
val file = File(appDir, "$fileName.txt")
|
||||
val file = File(appDir, fileName)
|
||||
|
||||
try {
|
||||
file.writeText(rawContent)
|
||||
|
|
|
|||
|
|
@ -145,9 +145,10 @@ LaunchedEffect(isPlay, isPos) {
|
|||
)
|
||||
}
|
||||
val favoritePaths by sharedScreenModel.playlistItems.collectAsState()
|
||||
Scaffold(contentWindowInsets = WindowInsets(0, 0, 0, 0), topBar = {
|
||||
Scaffold(contentWindowInsets = WindowInsets.safeDrawing, topBar = {
|
||||
TopAppBar(
|
||||
modifier = Modifier.height(55.dp).windowInsetsPadding(WindowInsets.statusBars), title = {
|
||||
modifier = Modifier.height(55.dp).windowInsetsPadding(WindowInsets.safeDrawing),
|
||||
title = {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize().verticalScroll(scrollState),
|
||||
verticalArrangement = Arrangement.Center
|
||||
|
|
@ -169,13 +170,17 @@ LaunchedEffect(isPlay, isPos) {
|
|||
Icon(Icons.Filled.Menu, contentDescription = "Ouvrir Menu")
|
||||
}
|
||||
}, actions = {
|
||||
Text(
|
||||
text = songKey,
|
||||
fontSize = 25.sp,
|
||||
fontWeight = FontWeight.Black,
|
||||
)
|
||||
Spacer(Modifier.width(8.dp))
|
||||
|
||||
Box(
|
||||
modifier = Modifier.fillMaxHeight(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = songKey,
|
||||
fontSize = 25.sp,
|
||||
fontWeight = FontWeight.Black,
|
||||
modifier = Modifier.padding(end = 16.dp)
|
||||
)
|
||||
}
|
||||
}, colors = TopAppBarColors(
|
||||
containerColor = MaterialTheme.colorScheme.primary,
|
||||
titleContentColor = MaterialTheme.colorScheme.onPrimary,
|
||||
|
|
@ -228,6 +233,24 @@ LaunchedEffect(isPlay, isPos) {
|
|||
|
||||
|
||||
}
|
||||
/*AnimatedVisibility(
|
||||
visible = isExpanded and !showMidiCtrl,
|
||||
enter = fadeIn() + scaleIn() + slideInVertically { it / 2 },
|
||||
exit = fadeOut() + scaleOut() + slideOutVertically { it / 2 }
|
||||
) {
|
||||
FloatingActionButton(
|
||||
onClick = {
|
||||
sharedScreenModel.toggleEditMode()
|
||||
sharedScreenModel.setExpandedFAB(false)
|
||||
}, modifier = Modifier.alpha(0.45f)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Edit,
|
||||
contentDescription = "null",
|
||||
tint = Color.Blue
|
||||
)
|
||||
}
|
||||
}*/
|
||||
AnimatedVisibility(
|
||||
visible = isExpanded and !showMidiCtrl,
|
||||
enter = fadeIn() + scaleIn() + slideInVertically { it / 2 },
|
||||
|
|
@ -345,11 +368,14 @@ LaunchedEffect(isPlay, isPos) {
|
|||
}) { paddingValues ->
|
||||
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize().padding(paddingValues).windowInsetsPadding(WindowInsets.ime)
|
||||
modifier = Modifier.fillMaxSize().padding(paddingValues).consumeWindowInsets(paddingValues).windowInsetsPadding(WindowInsets.ime)
|
||||
) {
|
||||
content(PaddingValues(0.dp))
|
||||
if (sharedScreenModel.isQRCodeVisible.value) {
|
||||
QRDisplay(sharedScreenModel = sharedScreenModel)
|
||||
QRDisplay(
|
||||
sharedScreenModel = sharedScreenModel,
|
||||
fileRepository = solfaScreenModel.fileRepository
|
||||
)
|
||||
} else {
|
||||
if (filteredSongs.isNotEmpty()) {
|
||||
Column(
|
||||
|
|
|
|||
|
|
@ -6,42 +6,48 @@ import androidx.compose.foundation.background
|
|||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.produceState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import mg.dot.feufaro.FileRepository
|
||||
import mg.dot.feufaro.solfa.ColorPrefixA
|
||||
import mg.dot.feufaro.solfa.ColorPrefixB
|
||||
import mg.dot.feufaro.solfa.ColorValue
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.net.URLEncoder
|
||||
import java.util.zip.GZIPOutputStream
|
||||
import kotlin.io.encoding.Base64
|
||||
|
||||
@Composable
|
||||
fun QRDisplay(sharedScreenModel: SharedScreenModel) {
|
||||
fun QRDisplay(sharedScreenModel: SharedScreenModel, fileRepository: FileRepository) {
|
||||
|
||||
val content by sharedScreenModel.fileContent
|
||||
val path by sharedScreenModel.activeFilePath
|
||||
val fileName = path.substringAfterLast('/').substringAfterLast(':')
|
||||
|
||||
fun compressAndEncode(content: String?): String {
|
||||
val bos = ByteArrayOutputStream()
|
||||
GZIPOutputStream(bos).use { it.write(content?.toByteArray(Charsets.UTF_8)) }
|
||||
val compressedBytes = bos.toByteArray()
|
||||
return Base64.UrlSafe.encode(compressedBytes).trim('=')
|
||||
}
|
||||
val qrCodeImage by produceState<ImageBitmap?>(initialValue = null, content, path) {
|
||||
val expandedSource = expandInclusions(
|
||||
content = content,
|
||||
currentFilePath = path,
|
||||
fileRepository = fileRepository
|
||||
)
|
||||
if(expandedSource.isNotEmpty()) {
|
||||
val bos = ByteArrayOutputStream()
|
||||
GZIPOutputStream(bos).use { it.write(expandedSource.toByteArray(Charsets.UTF_8)) }
|
||||
val compressedBytes = bos.toByteArray()
|
||||
|
||||
val compressedData = compressAndEncode(content)
|
||||
val uri = "feufaro://song?file=$compressedData"
|
||||
// val encodedContent = URLEncoder.encode(content, "UTF-8")
|
||||
// val uri = "feufaro://song?file=$encodedContent"
|
||||
val compressedData = Base64.UrlSafe.encode(compressedBytes).trim('=')
|
||||
|
||||
val qrCodeImage = remember(content) {
|
||||
if (content != null) {
|
||||
generateQRCode(uri, size = 800)
|
||||
} else {
|
||||
null
|
||||
val uri = "feufaro://song?file=${compressedData}&name=$fileName"
|
||||
value = generateQRCode(uri, size = 800)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -64,14 +70,79 @@ fun QRDisplay(sharedScreenModel: SharedScreenModel) {
|
|||
Text("Scanner pour ouvrir ce partition")
|
||||
if (qrCodeImage != null) {
|
||||
Image(
|
||||
bitmap = qrCodeImage,
|
||||
bitmap = qrCodeImage!!,
|
||||
contentDescription = "Code QR du fichier actif",
|
||||
modifier = Modifier.size(400.dp)
|
||||
)
|
||||
} else {
|
||||
Text("Chargement du Code QR ou contenu vide...", modifier = Modifier.padding(16.dp))
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(400.dp)
|
||||
.padding(16.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.size(48.dp),
|
||||
color = ColorPrefixA,
|
||||
strokeWidth = 4.dp,
|
||||
trackColor = ColorPrefixB.copy(alpha = 0.2f)
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
Text(
|
||||
text = "Génération du QR Code...",
|
||||
style = MaterialTheme.typography.bodyMedium.copy(
|
||||
color = ColorValue,
|
||||
fontWeight = FontWeight.Medium
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun expandInclusions(
|
||||
content: String?,
|
||||
currentFilePath: String,
|
||||
fileRepository: FileRepository
|
||||
): String {
|
||||
if(content.isNullOrEmpty()) return ""
|
||||
val lines = content.split("\n")
|
||||
val result = StringBuilder()
|
||||
val lastSlash = currentFilePath.lastIndexOf('/')
|
||||
val directory = if (lastSlash != -1) currentFilePath.substring(0, lastSlash + 1) else ""
|
||||
|
||||
lines.forEach { line ->
|
||||
if (line.startsWith("I0:")) {
|
||||
try {
|
||||
val parts = line.substring(3).split(":")
|
||||
val fileName = parts[0]
|
||||
val ignorePattern = if (parts.size > 1) parts[1] else ""
|
||||
|
||||
val fullPath = directory + fileName
|
||||
val includedLines = fileRepository.readFileLines(fullPath)
|
||||
|
||||
val regexIgnore = if (ignorePattern.isNotEmpty()) Regex(ignorePattern) else null
|
||||
|
||||
includedLines.forEach { incLine ->
|
||||
if (regexIgnore == null || !regexIgnore.containsMatchIn(incLine)) {
|
||||
result.append(incLine).append("\n")
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
result.append("// Erreur inclusion: ${e.message}\n")
|
||||
}
|
||||
} else {
|
||||
result.append(line).append("\n")
|
||||
}
|
||||
}
|
||||
return result.toString().trimEnd()
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue