Resolve crash in TUO by refactoring composables - Android
This commit is contained in:
parent
10eca05472
commit
1d7273a531
1 changed files with 279 additions and 282 deletions
|
|
@ -320,84 +320,6 @@ fun TimeUnitComposable(
|
|||
modifier = Modifier
|
||||
.background(animatedColor)
|
||||
) {
|
||||
if (TimeUnitObject._hasMarker) {
|
||||
val lineHeight = 20.sp
|
||||
val density = LocalDensity.current
|
||||
val lineHeightDp : Dp = with(density) {
|
||||
lineHeight.toDp()
|
||||
}
|
||||
var fontStyle = FontStyle.Normal
|
||||
var fontWeight = FontWeight.Normal
|
||||
val hairPinSymbol = tuo.hasHairPin()
|
||||
val yHeight = with(density) { lineHeightDp.toPx()}
|
||||
|
||||
/*if (tuo.isTriolet()) {
|
||||
Canvas(modifier = Modifier.fillMaxSize()) {
|
||||
val arcWidth = with(density) { size.width * 0.75f}
|
||||
drawArc(
|
||||
color = FEUFAROO_TRIOLET_COLOR,
|
||||
startAngle = 200f,
|
||||
sweepAngle = 140f,
|
||||
useCenter = false,
|
||||
topLeft = Offset(0f, yHeight / 2),
|
||||
size = Size(arcWidth, yHeight),
|
||||
style = Stroke(width = 2f)
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
if ((hairPinSymbol == '=') && (TimeUnitObject.lastHairPinSymbol != null)) {
|
||||
println("LastHairpin: ${TimeUnitObject.lastHairPinSymbol} ${TimeUnitObject.lastHairPinStart}")
|
||||
val hairPinStart = TimeUnitObject.lastHairPinStart
|
||||
val lastHairPinSymbol = TimeUnitObject.lastHairPinSymbol
|
||||
val hairPinStartLine: Int = (hairPinStart - 1) / gridColumnCount
|
||||
val hairPinEndLine: Int = (tuo.numBlock - 1) / gridColumnCount
|
||||
if (hairPinStartLine == hairPinEndLine) {
|
||||
Canvas(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
val xStart = if (lastHairPinSymbol == '>') -size.width * (tuo.numBlock - hairPinStart) else size.width/2
|
||||
val xEnd = if (lastHairPinSymbol == '>') size.width/2 else -size.width * (tuo.numBlock - hairPinStart)
|
||||
drawLine(
|
||||
Color.DarkGray,
|
||||
start = Offset(x=xStart, y=0f),
|
||||
end = Offset(xEnd, yHeight/2)
|
||||
)
|
||||
drawLine(
|
||||
Color.DarkGray,
|
||||
start = Offset(xStart, yHeight),
|
||||
end = Offset(xEnd, yHeight/2)
|
||||
)
|
||||
}
|
||||
TimeUnitObject.endHairPin()
|
||||
}
|
||||
|
||||
}
|
||||
if (hairPinSymbol != null && hairPinSymbol != '=') {
|
||||
TimeUnitObject.startHairPin(hairPinSymbol, tuo.numBlock)
|
||||
}
|
||||
// @todo pTemplate.markerToString retourne les marqueurs comme une seule chaîne
|
||||
// problème si template = $QD:,-$QD
|
||||
tuo.pTemplate.resetCalledMarker()
|
||||
val text = tuo.pTemplate.markerToString()
|
||||
if (text.contains(Regex("^([mfp]+|[rR]it.*)$"))) {
|
||||
fontStyle = FontStyle.Italic
|
||||
}
|
||||
if (text.contains("p")) {
|
||||
fontWeight = FontWeight.Bold
|
||||
}*/
|
||||
/*AutoResizingText(
|
||||
text = text,
|
||||
minFontSize = 18.sp,
|
||||
maxFontSize = 18.sp,
|
||||
maxLines = 2,
|
||||
fontStyle = fontStyle,
|
||||
fontWeight = fontWeight,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
.height(lineHeightDp))*/
|
||||
|
||||
|
||||
}
|
||||
Row (modifier = Modifier.height(IntrinsicSize.Min)){
|
||||
if (tuo.sep0 == "/" || tuo.sep0 == "|") {
|
||||
Box(
|
||||
|
|
@ -850,106 +772,20 @@ fun LazyVerticalGridTUO(
|
|||
}
|
||||
var fontStyle = FontStyle.Normal
|
||||
var fontWeight = FontWeight.Normal
|
||||
val hairPinSymbol = tuo.hasHairPin()
|
||||
val yHeight = with(density) { lineHeightDp.toPx() }
|
||||
|
||||
if (tuo.isTriolet()) {
|
||||
Canvas(modifier = Modifier.fillMaxSize()) {
|
||||
val arcWidth = size.width * 0.65f
|
||||
drawArc(
|
||||
color = colorUnderline,
|
||||
startAngle = 200f,
|
||||
sweepAngle = 140f,
|
||||
useCenter = false,
|
||||
//topLeft = Offset(0f, yHeight/* / 2*/),
|
||||
topLeft = Offset(size.width *0.05f, -yHeight * 0.1f),
|
||||
size = Size(arcWidth, yHeight),
|
||||
style = Stroke(width = 2f)
|
||||
|
||||
TuoHeaderDecorations(
|
||||
tuo,
|
||||
colorUnderline,
|
||||
yHeight,
|
||||
hairpinByEndBlock,
|
||||
ptSerifBoldItalic,
|
||||
emmentaler,
|
||||
ptSerif,
|
||||
fontStyle
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val hairpinRange = hairpinByEndBlock[tuo.numBlock]
|
||||
if (hairpinRange != null) {
|
||||
Canvas(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
val xStart = if (hairpinRange.symbol == '>') -size.width * (tuo.numBlock - hairpinRange.startBlock) else size.width / 2
|
||||
val xEnd = if (hairpinRange.symbol == '>') size.width / 2 else -size.width * (tuo.numBlock - hairpinRange.startBlock)
|
||||
val offsetUp = -yHeight * 0.30f
|
||||
val hairpinHeight = yHeight * 0.70f
|
||||
|
||||
val yTop = 0f + offsetUp
|
||||
val yCenter = (hairpinHeight / 2) + offsetUp
|
||||
val yBottom = hairpinHeight + offsetUp
|
||||
|
||||
drawLine(
|
||||
color = colorUnderline,
|
||||
start = Offset(x = xStart, y = yTop),
|
||||
end = Offset(xEnd, yCenter),
|
||||
strokeWidth = 0.5f
|
||||
)
|
||||
drawLine(
|
||||
color = colorUnderline,
|
||||
start = Offset(xStart, yBottom),
|
||||
end = Offset(xEnd, yCenter),
|
||||
strokeWidth = 0.5f
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// @todo pTemplate.markerToString retourne les marqueurs comme une seule chaîne
|
||||
// problème si template = $QD:,-$QD
|
||||
tuo.pTemplate.resetCalledMarker()
|
||||
|
||||
val markerList = tuo.pTemplate.markerToList()
|
||||
Row(
|
||||
modifier = Modifier.wrapContentSize(unbounded = true, align = Alignment.CenterStart),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
markerList.forEach { marker ->
|
||||
Column {
|
||||
var markerFontFamily: FontFamily = FontFamily.Default
|
||||
var markerFontSize: Float = MaterialTheme.typography.titleMedium.fontSize.value
|
||||
|
||||
when {
|
||||
musicForPtSerifBIRegex.matches(marker) -> {
|
||||
markerFontSize = MaterialTheme.typography.titleMedium.fontSize.value
|
||||
markerFontFamily = ptSerifBoldItalic
|
||||
}
|
||||
|
||||
musicForEmmentRegex.matches(marker) -> {
|
||||
markerFontSize = MaterialTheme.typography.titleMedium.fontSize.value + 11
|
||||
markerFontFamily = emmentaler
|
||||
}
|
||||
|
||||
else -> {
|
||||
markerFontFamily = ptSerif
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = marker,
|
||||
modifier = Modifier
|
||||
.wrapContentSize(unbounded = true, align = Alignment.CenterStart,),
|
||||
softWrap = false,
|
||||
maxLines = 1,
|
||||
fontStyle = fontStyle,
|
||||
fontWeight = FontWeight.Bold,
|
||||
style = MaterialTheme.typography.titleMedium.copy(
|
||||
color = MaterialTheme.colorScheme.onSecondary,
|
||||
fontSize = markerFontSize.sp,
|
||||
fontFamily = markerFontFamily
|
||||
)
|
||||
)
|
||||
if (marker != markerList.last()) {
|
||||
Spacer(modifier = Modifier.width(2.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(showFullChord) {
|
||||
|
|
@ -959,55 +795,17 @@ fun LazyVerticalGridTUO(
|
|||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
measureTUOs.forEachIndexed { indexInMeasure, tuo ->
|
||||
val chordMap = (1..4).mapNotNull { voice ->
|
||||
val noteStr = tuo.tuNotes.getOrNull(voice)?.toString()
|
||||
if (noteStr != null) voice to noteStr else null
|
||||
}.toMap()
|
||||
|
||||
val degreeName = remember(chordMap) {
|
||||
if (chordMap.isNotEmpty()) HarmonicAnalyzer.analyzeDegree(chordMap) else null
|
||||
}
|
||||
val appliedInterval by sharedScreenModel.transpositionInterval.collectAsState()
|
||||
val songKey = sharedScreenModel.songKey.value
|
||||
val chordName = remember(chordMap, songKey, appliedInterval) {
|
||||
if (chordMap.isNotEmpty()) HarmonicAnalyzer.analyzeChordName(chordMap, songKey, appliedInterval) else null
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.width(gridWidthDp / gridColumnCount)
|
||||
) {
|
||||
val maxFontSize = 12.sp
|
||||
val minFontSize = 10.sp
|
||||
var currentFontSize by remember { mutableStateOf(maxFontSize) }
|
||||
|
||||
TextButton(
|
||||
onClick = { toggleWithDegreeAndChord = !toggleWithDegreeAndChord },
|
||||
contentPadding = PaddingValues(0.dp),
|
||||
modifier = Modifier.height(24.dp).fillMaxWidth()
|
||||
) {
|
||||
BoxWithConstraints(modifier = Modifier.fillMaxWidth()) {
|
||||
val textToDisplay = if (toggleWithDegreeAndChord) (chordName ?: "") else (degreeName ?: "")
|
||||
|
||||
Text(
|
||||
text = textToDisplay,
|
||||
onTextLayout = { textLayoutResult ->
|
||||
if (textLayoutResult.hasVisualOverflow && currentFontSize > minFontSize) {
|
||||
currentFontSize = (currentFontSize.value * 0.9f).sp
|
||||
}
|
||||
TuoChordRowItem(
|
||||
tuo,
|
||||
sharedScreenModel,
|
||||
gridWidthDp,
|
||||
gridColumnCount,
|
||||
toggleWithDegreeAndChord,
|
||||
onToggleChange = {
|
||||
toggleWithDegreeAndChord = it
|
||||
},
|
||||
softWrap = false,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Visible,
|
||||
style = TextStyle(
|
||||
color = if (!toggleWithDegreeAndChord) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary.copy(red = MaterialTheme.colorScheme.secondary.red * 0.4f, green = MaterialTheme.colorScheme.secondary.green * 0.4f, blue = MaterialTheme.colorScheme.secondary.blue * 0.4f ),
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = currentFontSize
|
||||
modifier = Modifier.height(24.dp).fillMaxWidth()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1192,73 +990,21 @@ fun LazyVerticalGridTUO(
|
|||
|
||||
val currentSelected = selectedTUO
|
||||
if ((showEditDialog || showDetailDialog) && currentSelected != null && selectedIndex == globalIndex) {
|
||||
val canAdd = showAddDialog
|
||||
val canEdit = showEditDialog || canAdd
|
||||
|
||||
val template = oneTUO.pTemplate.template
|
||||
val expectedTemplate = template.count { it.isLetter() } == 2 && template.contains(".")
|
||||
|
||||
val fileC = sharedScreenModel.fileContent.value ?: ""
|
||||
val lines = fileC.split("\n").toMutableList()
|
||||
val u0Idx = lines.indexOfFirst { it.startsWith("U0:") }
|
||||
val t0Idx = lines.indexOfFirst { it.startsWith("T0:") }
|
||||
|
||||
val fullLine = when {
|
||||
t0Idx != -1 -> {
|
||||
lines[t0Idx]
|
||||
}
|
||||
u0Idx != -1 -> {
|
||||
lines[u0Idx]
|
||||
}
|
||||
else -> ""
|
||||
}
|
||||
val afterU0T0 = fullLine.substringAfter("0:")
|
||||
val match = blankPrefixRegex.find(afterU0T0)
|
||||
val blankPrefix = match?.groups?.get(1)?.value ?: ""
|
||||
|
||||
val anchorsByVoice = (0..3).associate { voiceIdx ->
|
||||
val linePrefix = "N${voiceIdx + 1}:"
|
||||
val fullLine = lines.firstOrNull { it.startsWith(linePrefix) } ?: ""
|
||||
voiceIdx to extractAnchorFromNoteLine(fullLine)
|
||||
}
|
||||
val editState = TUOEditState(
|
||||
tuoIndex = oneTUO.firstTuoIndex,
|
||||
notesByVoice = (0..3).associate { i ->
|
||||
val rawNote = oneTUO.tuNotes.getOrNull(i + 1)?.toString() ?: ""
|
||||
val fixedNote = autoFixNote(rawNote, template)
|
||||
i to fixedNote
|
||||
},
|
||||
lyricsByStanza = (1..currentStanza).associate { s ->
|
||||
s to oneTUO.lyricsAsMultiString(currentStanza)
|
||||
}.toMutableMap(),
|
||||
templateFragment = oneTUO.pTemplate.template,
|
||||
marker = listOfNotNull(
|
||||
oneTUO.pTemplate.markerToString().takeIf { it.isNotBlank() },
|
||||
oneTUO.hasHairPin()?.toString()?.takeIf { it.isNotBlank() }
|
||||
).joinToString(" "),
|
||||
silentDuration = blankPrefix,
|
||||
sep = oneTUO.sep0
|
||||
)
|
||||
TUODetailDialog(
|
||||
editState = editState,
|
||||
tuo = currentSelected,
|
||||
currentStanza = currentStanza,
|
||||
menuPosition = IntOffset(
|
||||
menuOffset.x.roundToInt(),
|
||||
menuOffset.y.roundToInt()
|
||||
),
|
||||
val lines = fileC.split("\n")
|
||||
TuoEditDialogWrapper(
|
||||
oneTUO = currentSelected,
|
||||
globalIndex = globalIndex,
|
||||
isEditable = canEdit,
|
||||
canAdd = canAdd,
|
||||
currentStanza = currentStanza,
|
||||
menuOffset = menuOffset,
|
||||
sharedScreenModel = sharedScreenModel,
|
||||
anchorsByVoice = anchorsByVoice,
|
||||
lines = lines,
|
||||
onDismiss = {
|
||||
showAddDialog = false
|
||||
showDetailDialog = false
|
||||
showEditDialog = false
|
||||
},
|
||||
onSave = { newState ->
|
||||
sharedScreenModel.openTUOEditor(newState)
|
||||
onSaveSuccess = {
|
||||
showAddDialog = false
|
||||
showEditDialog = false
|
||||
},
|
||||
|
|
@ -1378,6 +1124,257 @@ fun LazyVerticalGridTUO(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TuoChordRowItem(
|
||||
tuo: TimeUnitObject,
|
||||
sharedScreenModel: SharedScreenModel,
|
||||
gridWidthDp: Dp,
|
||||
gridColumnCount: Int,
|
||||
toggleWithDegreeAndChord: Boolean,
|
||||
onToggleChange: (Boolean) -> Unit,
|
||||
modifier: Modifier
|
||||
) {
|
||||
val chordMap = (1..4).mapNotNull { voice ->
|
||||
val noteStr = tuo.tuNotes.getOrNull(voice)?.toString()
|
||||
if (noteStr != null) voice to noteStr else null
|
||||
}.toMap()
|
||||
|
||||
val degreeName = remember(chordMap) {
|
||||
if (chordMap.isNotEmpty()) HarmonicAnalyzer.analyzeDegree(chordMap) else null
|
||||
}
|
||||
val appliedInterval by sharedScreenModel.transpositionInterval.collectAsState()
|
||||
val songKey = sharedScreenModel.songKey.value
|
||||
val chordName = remember(chordMap, songKey, appliedInterval) {
|
||||
if (chordMap.isNotEmpty()) HarmonicAnalyzer.analyzeChordName(chordMap, songKey, appliedInterval) else null
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.width(gridWidthDp / gridColumnCount)
|
||||
) {
|
||||
val maxFontSize = 12.sp
|
||||
val minFontSize = 10.sp
|
||||
var currentFontSize by remember { mutableStateOf(maxFontSize) }
|
||||
|
||||
TextButton(
|
||||
onClick = { onToggleChange(!toggleWithDegreeAndChord) },
|
||||
contentPadding = PaddingValues(0.dp),
|
||||
modifier = modifier
|
||||
) {
|
||||
BoxWithConstraints(modifier = Modifier.fillMaxWidth()) {
|
||||
val textToDisplay = if (toggleWithDegreeAndChord) (chordName ?: "") else (degreeName ?: "")
|
||||
|
||||
Text(
|
||||
text = textToDisplay,
|
||||
onTextLayout = { textLayoutResult ->
|
||||
if (textLayoutResult.hasVisualOverflow && currentFontSize > minFontSize) {
|
||||
currentFontSize = (currentFontSize.value * 0.9f).sp
|
||||
}
|
||||
},
|
||||
softWrap = false,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Visible,
|
||||
style = TextStyle(
|
||||
color = if (!toggleWithDegreeAndChord) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary.copy(
|
||||
red = MaterialTheme.colorScheme.secondary.red * 0.4f,
|
||||
green = MaterialTheme.colorScheme.secondary.green * 0.4f,
|
||||
blue = MaterialTheme.colorScheme.secondary.blue * 0.4f
|
||||
),
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = currentFontSize
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TuoHeaderDecorations(
|
||||
tuo: TimeUnitObject,
|
||||
colorUnderline: Color,
|
||||
yHeight: Float,
|
||||
hairpinByEndBlock: Map<Int, HairpinRange>,
|
||||
ptSerifBoldItalic: FontFamily,
|
||||
emmentaler: FontFamily,
|
||||
ptSerif: FontFamily,
|
||||
fontStyle: FontStyle
|
||||
) {
|
||||
if (tuo.isTriolet()) {
|
||||
Canvas(modifier = Modifier.fillMaxSize()) {
|
||||
val arcWidth = size.width * 0.65f
|
||||
drawArc(
|
||||
color = colorUnderline,
|
||||
startAngle = 200f,
|
||||
sweepAngle = 140f,
|
||||
useCenter = false,
|
||||
//topLeft = Offset(0f, yHeight/* / 2*/),
|
||||
topLeft = Offset(size.width * 0.05f, -yHeight * 0.1f),
|
||||
size = Size(arcWidth, yHeight),
|
||||
style = Stroke(width = 2f)
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val hairpinRange = hairpinByEndBlock[tuo.numBlock]
|
||||
if (hairpinRange != null) {
|
||||
Canvas(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
val xStart =
|
||||
if (hairpinRange.symbol == '>') -size.width * (tuo.numBlock - hairpinRange.startBlock) else size.width / 2
|
||||
val xEnd =
|
||||
if (hairpinRange.symbol == '>') size.width / 2 else -size.width * (tuo.numBlock - hairpinRange.startBlock)
|
||||
val offsetUp = -yHeight * 0.30f
|
||||
val hairpinHeight = yHeight * 0.70f
|
||||
|
||||
val yTop = 0f + offsetUp
|
||||
val yCenter = (hairpinHeight / 2) + offsetUp
|
||||
val yBottom = hairpinHeight + offsetUp
|
||||
|
||||
drawLine(
|
||||
color = colorUnderline,
|
||||
start = Offset(x = xStart, y = yTop),
|
||||
end = Offset(xEnd, yCenter),
|
||||
strokeWidth = 0.5f
|
||||
)
|
||||
drawLine(
|
||||
color = colorUnderline,
|
||||
start = Offset(xStart, yBottom),
|
||||
end = Offset(xEnd, yCenter),
|
||||
strokeWidth = 0.5f
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// problème si template = $QD:,-$QD
|
||||
tuo.pTemplate.resetCalledMarker()
|
||||
|
||||
val markerList = tuo.pTemplate.markerToList()
|
||||
Row(
|
||||
modifier = Modifier.wrapContentSize(unbounded = true, align = Alignment.CenterStart),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
markerList.forEach { marker ->
|
||||
Column {
|
||||
var markerFontFamily: FontFamily = FontFamily.Default
|
||||
var markerFontSize: Float = MaterialTheme.typography.titleMedium.fontSize.value
|
||||
|
||||
when {
|
||||
musicForPtSerifBIRegex.matches(marker) -> {
|
||||
markerFontSize = MaterialTheme.typography.titleMedium.fontSize.value
|
||||
markerFontFamily = ptSerifBoldItalic
|
||||
}
|
||||
|
||||
musicForEmmentRegex.matches(marker) -> {
|
||||
markerFontSize = MaterialTheme.typography.titleMedium.fontSize.value + 11
|
||||
markerFontFamily = emmentaler
|
||||
}
|
||||
|
||||
else -> {
|
||||
markerFontFamily = ptSerif
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = marker,
|
||||
modifier = Modifier
|
||||
.wrapContentSize(unbounded = true, align = Alignment.CenterStart),
|
||||
softWrap = false,
|
||||
maxLines = 1,
|
||||
fontStyle = fontStyle,
|
||||
fontWeight = FontWeight.Bold,
|
||||
style = MaterialTheme.typography.titleMedium.copy(
|
||||
color = MaterialTheme.colorScheme.onSecondary,
|
||||
fontSize = markerFontSize.sp,
|
||||
fontFamily = markerFontFamily
|
||||
)
|
||||
)
|
||||
if (marker != markerList.last()) {
|
||||
Spacer(modifier = Modifier.width(2.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TuoEditDialogWrapper(
|
||||
oneTUO: TimeUnitObject,
|
||||
globalIndex: Int,
|
||||
currentStanza: Int,
|
||||
menuOffset: Offset,
|
||||
sharedScreenModel: SharedScreenModel,
|
||||
lines: List<String>,
|
||||
onDismiss: () -> Unit,
|
||||
onSaveSuccess: () -> Unit,
|
||||
onIndexChanged: (Int) -> Unit
|
||||
) {
|
||||
val template = oneTUO.pTemplate.template
|
||||
|
||||
val u0Idx = lines.indexOfFirst { it.startsWith("U0:") }
|
||||
val t0Idx = lines.indexOfFirst { it.startsWith("T0:") }
|
||||
|
||||
val fullLine = when {
|
||||
t0Idx != -1 -> {
|
||||
lines[t0Idx]
|
||||
}
|
||||
|
||||
u0Idx != -1 -> {
|
||||
lines[u0Idx]
|
||||
}
|
||||
|
||||
else -> ""
|
||||
}
|
||||
val afterU0T0 = fullLine.substringAfter("0:")
|
||||
val match = blankPrefixRegex.find(afterU0T0)
|
||||
val blankPrefix = match?.groups?.get(1)?.value ?: ""
|
||||
|
||||
val anchorsByVoice = (0..3).associate { voiceIdx ->
|
||||
val linePrefix = "N${voiceIdx + 1}:"
|
||||
val fullLine = lines.firstOrNull { it.startsWith(linePrefix) } ?: ""
|
||||
voiceIdx to extractAnchorFromNoteLine(fullLine)
|
||||
}
|
||||
val editState = TUOEditState(
|
||||
tuoIndex = oneTUO.firstTuoIndex,
|
||||
notesByVoice = (0..3).associate { i ->
|
||||
val rawNote = oneTUO.tuNotes.getOrNull(i + 1)?.toString() ?: ""
|
||||
val fixedNote = autoFixNote(rawNote, template)
|
||||
i to fixedNote
|
||||
},
|
||||
lyricsByStanza = (1..currentStanza).associate { s ->
|
||||
s to oneTUO.lyricsAsMultiString(currentStanza)
|
||||
}.toMutableMap(),
|
||||
templateFragment = oneTUO.pTemplate.template,
|
||||
marker = listOfNotNull(
|
||||
oneTUO.pTemplate.markerToString().takeIf { it.isNotBlank() },
|
||||
oneTUO.hasHairPin()?.toString()?.takeIf { it.isNotBlank() }
|
||||
).joinToString(" "),
|
||||
silentDuration = blankPrefix,
|
||||
sep = oneTUO.sep0
|
||||
)
|
||||
TUODetailDialog(
|
||||
editState = editState,
|
||||
tuo = oneTUO,
|
||||
currentStanza = currentStanza,
|
||||
menuPosition = IntOffset(
|
||||
menuOffset.x.roundToInt(),
|
||||
menuOffset.y.roundToInt()
|
||||
),
|
||||
globalIndex = globalIndex,
|
||||
isEditable = true,
|
||||
canAdd = false,
|
||||
sharedScreenModel = sharedScreenModel,
|
||||
anchorsByVoice = anchorsByVoice,
|
||||
onDismiss = onDismiss,
|
||||
onSave = { newState ->
|
||||
sharedScreenModel.openTUOEditor(newState)
|
||||
onSaveSuccess()
|
||||
},
|
||||
onIndexChanged = onIndexChanged
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun makeSpaceBetweenSyllables(
|
||||
textMeasurer: TextMeasurer,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue