Voice chips directly under the summary (before the long sections): every position further down fell off-screen and read as 'missing'; saved-report path keeps them under the report; dedupe with the bottom block
This commit is contained in:
parent
104aaa4d66
commit
1f688e79bc
1 changed files with 60 additions and 22 deletions
|
|
@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.heightIn
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.layout.widthIn
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
|
@ -853,6 +854,43 @@ fun DetailScreen(state: DesktopState) {
|
||||||
Text(it, style = MaterialTheme.typography.labelMedium,
|
Text(it, style = MaterialTheme.typography.labelMedium,
|
||||||
color = MaterialTheme.colorScheme.primary)
|
color = MaterialTheme.colorScheme.primary)
|
||||||
}
|
}
|
||||||
|
// Voice controls FIRST under the summary — before the long
|
||||||
|
// sections. Every time they sat further down (page bottom,
|
||||||
|
// then below the bullets) they fell off-screen and read as
|
||||||
|
// "missing". They act on this summary; they live here.
|
||||||
|
run {
|
||||||
|
val report = detail.reportText
|
||||||
|
val hasTranscript = detail.transcript != null ||
|
||||||
|
(report != null && !report.contains("_No transcript available._"))
|
||||||
|
val remoteKnown = state.remoteIdFor(detail.file) != null
|
||||||
|
val sumBusy = detail.jobs.firstOrNull { it.jobType == "summarize" }
|
||||||
|
?.status in setOf("queued", "running")
|
||||||
|
val voicesEnabled = remoteKnown && hasTranscript && !sumBusy
|
||||||
|
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
|
||||||
|
Text("Re-summarize in the voice of",
|
||||||
|
style = MaterialTheme.typography.labelMedium,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant)
|
||||||
|
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
|
SUMMARIZE_PERSONAS.forEach { (label, tone) ->
|
||||||
|
FilterChip(
|
||||||
|
selected = sumTone == tone,
|
||||||
|
enabled = voicesEnabled,
|
||||||
|
onClick = {
|
||||||
|
sumTone = tone
|
||||||
|
state.summarize(tone)
|
||||||
|
},
|
||||||
|
label = { Text(label) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!voicesEnabled && !remoteKnown) {
|
||||||
|
Text("Summarize unlocks once this file is uploaded (press Transcribe).",
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Spacer(Modifier.height(4.dp))
|
||||||
// Full structured sections (key points, decisions, action
|
// Full structured sections (key points, decisions, action
|
||||||
// items, questions, details) right on screen — the saved
|
// items, questions, details) right on screen — the saved
|
||||||
// .md report had them but the live view showed only the
|
// .md report had them but the live view showed only the
|
||||||
|
|
@ -878,38 +916,38 @@ fun DetailScreen(state: DesktopState) {
|
||||||
Spacer(Modifier.height(4.dp))
|
Spacer(Modifier.height(4.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Voice controls sit directly under the summary — they act on it,
|
// Re-transcribe + summarize progress (the chips themselves live
|
||||||
// and at the page bottom (below a long transcript) they read as
|
// under the summary for the live path; this block also covers a
|
||||||
// gone. Hoisted above the transcript section; same conditions.
|
// file opened as a saved report with no live summary object).
|
||||||
if (detail.transcript != null || detail.reportText != null) {
|
if (detail.transcript != null || detail.reportText != null) {
|
||||||
// Honest labels: "Re-…" only when that output actually exists.
|
|
||||||
val report = detail.reportText
|
val report = detail.reportText
|
||||||
val hasTranscript = detail.transcript != null ||
|
val hasTranscript = detail.transcript != null ||
|
||||||
(report != null && !report.contains("_No transcript available._"))
|
(report != null && !report.contains("_No transcript available._"))
|
||||||
val hasSummary = detail.summary != null ||
|
val hasSummary = detail.summary != null ||
|
||||||
(report?.contains("## Summary") == true)
|
(report?.contains("## Summary") == true)
|
||||||
val remoteKnown = state.remoteIdFor(detail.file) != null
|
val remoteKnown = state.remoteIdFor(detail.file) != null
|
||||||
// A voice chip IS the action: clicking one re-summarizes in
|
|
||||||
// that voice immediately — no separate Re-summarize button.
|
|
||||||
val sumBusy = detail.jobs.firstOrNull { it.jobType == "summarize" }
|
val sumBusy = detail.jobs.firstOrNull { it.jobType == "summarize" }
|
||||||
?.status in setOf("queued", "running")
|
?.status in setOf("queued", "running")
|
||||||
val voicesEnabled = remoteKnown && hasTranscript && !sumBusy
|
val voicesEnabled = remoteKnown && hasTranscript && !sumBusy
|
||||||
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
|
if (detail.transcript == null) {
|
||||||
Text(if (hasSummary) "Re-summarize in the voice of"
|
// Saved-report path: chips here, same rules.
|
||||||
else "Summarize in the voice of",
|
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
|
||||||
style = MaterialTheme.typography.labelMedium,
|
Text(if (hasSummary) "Re-summarize in the voice of"
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant)
|
else "Summarize in the voice of",
|
||||||
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
style = MaterialTheme.typography.labelMedium,
|
||||||
SUMMARIZE_PERSONAS.forEach { (label, tone) ->
|
color = MaterialTheme.colorScheme.onSurfaceVariant)
|
||||||
FilterChip(
|
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
selected = sumTone == tone,
|
SUMMARIZE_PERSONAS.forEach { (label, tone) ->
|
||||||
enabled = voicesEnabled,
|
FilterChip(
|
||||||
onClick = {
|
selected = sumTone == tone,
|
||||||
sumTone = tone
|
enabled = voicesEnabled,
|
||||||
state.summarize(tone)
|
onClick = {
|
||||||
},
|
sumTone = tone
|
||||||
label = { Text(label) },
|
state.summarize(tone)
|
||||||
)
|
},
|
||||||
|
label = { Text(label) },
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue