Support share button on FAB : export pdf|mid - desktop&android
This commit is contained in:
parent
92a3a0344d
commit
41fbb204bb
5 changed files with 98 additions and 42 deletions
|
|
@ -80,12 +80,6 @@ class AndroidFileRepository(private val context: Context) : FileRepository {
|
|||
val folder = context.getExternalFilesDir(null)
|
||||
return "$folder/$shortName"
|
||||
}
|
||||
/*override suspend fun readFileBytes(filePath: String): ByteArray = withContext(Dispatchers.IO) {
|
||||
val folder = context.getExternalFilesDir(null)
|
||||
val file = File(folder, filePath)
|
||||
if (!file.exists()) throw IOException("File not found: ${file.absolutePath}")
|
||||
file.readBytes()
|
||||
}*/
|
||||
|
||||
private fun String.parseSafToRelativePath(): String {
|
||||
if (!this.startsWith("content://")) return this
|
||||
|
|
@ -129,10 +123,12 @@ class AndroidFileRepository(private val context: Context) : FileRepository {
|
|||
if (filePath.endsWith(".pdf", ignoreCase = true)) {
|
||||
openPdfFile(context = context, filePath = filePath)
|
||||
} else {
|
||||
val shortDisplayPath = longPathToShort(displayPath)
|
||||
|
||||
Toast.makeText(
|
||||
context.applicationContext,
|
||||
"Sauvegarde réussie : ${displayPath.substringAfterLast('/')}",
|
||||
Toast.LENGTH_LONG
|
||||
"Sauvegarde réussie dans : $shortDisplayPath",
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
|
@ -144,6 +140,15 @@ class AndroidFileRepository(private val context: Context) : FileRepository {
|
|||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
private fun longPathToShort(displayPath: String): String {
|
||||
return if (displayPath.contains("Documents/")) {
|
||||
"Documents/" + displayPath.substringAfter("Documents/")
|
||||
} else {
|
||||
displayPath.substringAfterLast('/')
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getAppPublicFolder(): File {
|
||||
val publicDocsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)
|
||||
val appDir = File(publicDocsDir, "Feufaro")
|
||||
|
|
@ -162,7 +167,8 @@ class AndroidFileRepository(private val context: Context) : FileRepository {
|
|||
}
|
||||
|
||||
override fun pickSavePath(defaultName: String, title: String): String? {
|
||||
val file = File(context.filesDir, defaultName)
|
||||
val publicFolder = getPAppPublicFolder()
|
||||
val file = File(publicFolder, defaultName)
|
||||
return file?.absolutePath
|
||||
}
|
||||
suspend fun openPdfFile(context: Context, filePath: String) {
|
||||
|
|
@ -182,9 +188,10 @@ class AndroidFileRepository(private val context: Context) : FileRepository {
|
|||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
|
||||
val sPath = longPathToShort(filePath)
|
||||
try {
|
||||
withContext(Dispatchers.Main) {
|
||||
Toast.makeText(context.applicationContext, "Fichier sauvegardé avec succès", Toast.LENGTH_LONG).show()
|
||||
Toast.makeText(context.applicationContext, "Fichier sauvegardé avec succès dans $sPath", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
context.startActivity(intent)
|
||||
} catch (e: Exception) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package mg.dot.feufaro.midi
|
|||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import mg.dot.feufaro.FileRepository
|
||||
import mg.dot.feufaro.solfa.Transpose
|
||||
import mg.dot.feufaro.viewmodel.MidiMarkers
|
||||
|
|
@ -37,16 +38,12 @@ class MidiWriterforEXport constructor(private val fileRepository: FileRepositor
|
|||
}
|
||||
lastPitch[voiceNumber] = midiNote
|
||||
}
|
||||
fun save(filePath: String) {
|
||||
val parseScope = CoroutineScope(Dispatchers.Default)
|
||||
parseScope.launch {
|
||||
sequence.write()
|
||||
fileRepository.saveFile(filePath, sequence.out.toByteArray())
|
||||
//val fout = fileRepository.getOutputStream(filePath)
|
||||
}
|
||||
suspend fun save(filePath: String) = withContext(Dispatchers.Default) {
|
||||
sequence.write()
|
||||
fileRepository.saveLocalFile(filePath, sequence.out.toByteArray())
|
||||
}
|
||||
fun addMetaMessage(type: Int, tick: Int, nbData: Int, metaBytes: ByteArray) {
|
||||
sequence.addMeta(type, tick, nbData, metaBytes.toString())
|
||||
sequence.addMetaFe(type, tick, nbData, metaBytes)
|
||||
}
|
||||
|
||||
fun setTempoMeta(bpm: Float, tickPosition: Int = 0) {
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
|
||||
private val prefs: Settings = provideSettings()
|
||||
|
||||
fun generateMidiFile(bpm: Float) {
|
||||
fun generateMidiFile(bpm: Float, outputPath: String = "whawyd3.mid") {
|
||||
val parseScope = CoroutineScope(Dispatchers.Default)
|
||||
parseScope.launch {
|
||||
val pitchesSorted = pitches.sortedWith(compareBy({ it.tick }, { it.voiceNumber }))
|
||||
|
|
@ -273,8 +273,14 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
3 to prefs.getInt("voice_instrument", 0),
|
||||
4 to prefs.getInt("voice_instrument", 0),
|
||||
)
|
||||
midiWriter.process(pitchesSorted, sharedScreenModel.getFullMarkers(), initialBpm = bpm, instruments, initialKey = sharedScreenModel.songKey.value)
|
||||
midiWriter.save("whawyd3.mid")
|
||||
midiWriter.process(
|
||||
pitchesSorted,
|
||||
sharedScreenModel.getFullMarkers(),
|
||||
initialBpm = bpm,
|
||||
instruments,
|
||||
initialKey = sharedScreenModel.songKey.value
|
||||
)
|
||||
midiWriter.save(outputPath)
|
||||
}
|
||||
}
|
||||
fun justBuild(sourceFile: String, sourceContent: String) {
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ fun MainScreenWithDrawer(
|
|||
|
||||
val isExpanded by sharedScreenModel.expandedFAB.collectAsState()
|
||||
val showMidiCtrl by sharedScreenModel.showMidiCtrl.collectAsState()
|
||||
var isShareExpanded by remember { mutableStateOf(false) }
|
||||
|
||||
val isPlay by sharedScreenModel.isPlay.collectAsState()
|
||||
val isPos by sharedScreenModel.isPos.collectAsState()
|
||||
|
|
@ -732,27 +733,72 @@ fun MainScreenWithDrawer(
|
|||
enter = fadeIn() + scaleIn() + slideInVertically { it / 2 },
|
||||
exit = fadeOut() + scaleOut() + slideOutVertically { it / 2 }
|
||||
) {
|
||||
MyFAB(
|
||||
onClick = {
|
||||
sharedScreenModel.toggleQRCodeVisibility()
|
||||
sharedScreenModel.setExpandedFAB(false)
|
||||
},
|
||||
icon = Icons.Filled.QrCode
|
||||
)
|
||||
}
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = isShareExpanded,
|
||||
enter = fadeIn() + expandHorizontally(),
|
||||
exit = fadeOut() + shrinkHorizontally()
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
MyFAB(
|
||||
onClick = {
|
||||
sharedScreenModel.toggleQRCodeVisibility()
|
||||
sharedScreenModel.setExpandedFAB(false)
|
||||
isShareExpanded = false
|
||||
},
|
||||
icon = Icons.Filled.QrCode2
|
||||
)
|
||||
|
||||
MyFAB(
|
||||
onClick = {
|
||||
showPrintSettings = !showPrintSettings
|
||||
isShareExpanded = false
|
||||
},
|
||||
icon = Icons.Filled.Print
|
||||
)
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = isExpanded and !showMidiCtrl,
|
||||
enter = fadeIn() + scaleIn() + slideInVertically { it / 2 },
|
||||
exit = fadeOut() + scaleOut() + slideOutVertically { it / 2 }
|
||||
) {
|
||||
MyFAB(
|
||||
onClick = {
|
||||
showPrintSettings = !showPrintSettings
|
||||
},
|
||||
icon = Icons.Filled.Print
|
||||
)
|
||||
MyFAB(
|
||||
onClick = {
|
||||
isShareExpanded = false
|
||||
scope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
try {
|
||||
val cleanS = songTitle.replace(' ','_')
|
||||
val exportName = "${cleanS.ifEmpty { "partition" }}.mid"
|
||||
|
||||
val savedPath = solfaScreenModel.fileRepository.pickSavePath(
|
||||
defaultName = exportName,
|
||||
title = "Enregistrer le fichier MIDI"
|
||||
)
|
||||
|
||||
if (!savedPath.isNullOrEmpty()) {
|
||||
val bpm = sharedScreenModel.getBpmFlow().value ?: 120f
|
||||
|
||||
solfaScreenModel.generateMidiFile(bpm, savedPath)
|
||||
println("Fichier MIDI enregistré avec succès sous : $savedPath")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
icon = Icons.Filled.AudioFile
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
MyFAB(
|
||||
onClick = { isShareExpanded = !isShareExpanded },
|
||||
icon = Icons.Filled.Share
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class SolfaScreenModel(
|
|||
solfa.createNewSolfa(metadata)
|
||||
}
|
||||
}
|
||||
fun regenMidi(bpm: Float) {
|
||||
solfa.generateMidiFile(bpm)
|
||||
fun generateMidiFile(bpm: Float, path: String) {
|
||||
solfa.generateMidiFile(bpm, path)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue