Summarize voices: exactly the four personas, drop custom-voice chip

This commit is contained in:
avi 2026-09-15 15:40:19 -05:00
commit cd1b08fda0

View file

@ -518,16 +518,12 @@ fun LibraryScreen(state: DesktopState) {
/** Personalities offered beside Re-summarize: (label, tone sent to the /** Personalities offered beside Re-summarize: (label, tone sent to the
* engine). The tone string is interpolated into "in a <tone> tone of * engine). The tone string is interpolated into "in a <tone> tone of
* voice", so it must read naturally there. null = neutral house voice. * voice", so it must read naturally there. null = neutral house voice.
* CUSTOM_TONE opens a free-text box — the engine accepts any phrase. */ * Exactly the four the user asked for — do not grow this list. */
private const val CUSTOM_TONE = "custom"
private val SUMMARIZE_PERSONAS = listOf( private val SUMMARIZE_PERSONAS = listOf(
"Neutral" to null, "Neutral" to null,
"Sarcastic" to "sarcastic", "Sarcastic" to "sarcastic",
"Funny" to "funny", "Funny" to "funny",
"Dry wit" to "dry, witty", "Dry wit" to "dry, witty",
"Enthusiastic" to "enthusiastic",
"Storyteller" to "storyteller",
) )
@androidx.compose.runtime.Composable @androidx.compose.runtime.Composable
@ -543,10 +539,6 @@ fun DetailScreen(state: DesktopState) {
var recQuery by remember { mutableStateOf("") } var recQuery by remember { mutableStateOf("") }
// Voice for the next summarize: null = Neutral (server default). // Voice for the next summarize: null = Neutral (server default).
var sumTone by remember(detail.file.name) { mutableStateOf<String?>(null) } var sumTone by remember(detail.file.name) { mutableStateOf<String?>(null) }
var customTone by remember(detail.file.name) { mutableStateOf("") }
var showCustomDialog by remember(detail.file.name) { mutableStateOf(false) }
val effectiveTone = if (sumTone == CUSTOM_TONE)
customTone.trim().takeIf { it.isNotBlank() } else sumTone
val playingFile by state.playingFile.collectAsState() val playingFile by state.playingFile.collectAsState()
val playError by state.playError.collectAsState() val playError by state.playError.collectAsState()
val isPlaying = playingFile?.absolutePath == detail.file.absolutePath val isPlaying = playingFile?.absolutePath == detail.file.absolutePath
@ -793,62 +785,17 @@ fun DetailScreen(state: DesktopState) {
label = { Text(label) }, label = { Text(label) },
) )
} }
FilterChip(
selected = sumTone == CUSTOM_TONE,
onClick = {
sumTone = CUSTOM_TONE
showCustomDialog = true
},
label = {
Text(if (sumTone == CUSTOM_TONE &&
customTone.isNotBlank())
"“${customTone.trim()}”" else "Other…")
},
)
}
if (showCustomDialog) {
AlertDialog(
onDismissRequest = { showCustomDialog = false },
title = { Text("Any voice you like") },
text = {
Column {
OutlinedTextField(customTone, {
if (it.length <= 60) customTone = it },
label = { Text("e.g. pirate, philosopher, sports caster") },
singleLine = true,
modifier = Modifier.fillMaxWidth())
Text("Used as: “…in a <your words> tone of voice.”",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant)
}
},
confirmButton = {
TextButton({
if (customTone.isNotBlank())
showCustomDialog = false
}) { Text("Use this voice") }
},
dismissButton = {
TextButton({
sumTone = null
customTone = ""
showCustomDialog = false
}) { Text("Cancel") }
},
)
} }
} }
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
TextButton({ state.transcribe() }) { TextButton({ state.transcribe() }) {
Text(if (hasTranscript) "Re-transcribe" else "Transcribe") Text(if (hasTranscript) "Re-transcribe" else "Transcribe")
} }
TextButton({ state.summarize(effectiveTone) }, TextButton({ state.summarize(sumTone) },
enabled = remoteKnown && hasTranscript && enabled = remoteKnown && hasTranscript) {
!(sumTone == CUSTOM_TONE &&
customTone.isBlank())) {
Text(buildString { Text(buildString {
append(if (hasSummary) "Re-summarize" else "Summarize") append(if (hasSummary) "Re-summarize" else "Summarize")
effectiveTone?.let { append(" · $it") } sumTone?.let { append(" · $it") }
}) })
} }
} }
@ -874,7 +821,7 @@ fun DetailScreen(state: DesktopState) {
sProg != null && sProg > 0 -> "Summarizing… $sProg%" sProg != null && sProg > 0 -> "Summarizing… $sProg%"
else -> "Summarizing…" else -> "Summarizing…"
}) })
effectiveTone?.let { append(" · $it") } sumTone?.let { append(" · $it") }
if (sAttempt > 0) if (sAttempt > 0)
append(" (attempt $sAttempt/${sJob?.maxAttempts})") append(" (attempt $sAttempt/${sJob?.maxAttempts})")
}, style = MaterialTheme.typography.bodySmall, }, style = MaterialTheme.typography.bodySmall,