Thin the app's comments
The same pass the server had, on the Kotlin side: comments restating what the code says are gone, and the ones recording a measurement, a constraint or an incident are kept but cut to a few lines each. 6540 comment lines to 5674, and 920 lines off the app. Two doc comments had drifted onto the item above the one they describe -- `contextAfter`'s onto `sessionWorking` in Events.kt, and `UsageMonitor`'s equivalent on the server was fixed in the previous commit. Each is back on its own item, which is the only non-comment line this diff moves. The comments are reflowed to the column limit at their own indentation: several were written wide, and ktfmt re-wrapped them into lines holding a single orphan word. `/tmp` script, not kept -- ktfmt is idempotent over the result, which is the check. Left alone deliberately: this codebase's remaining comment density is high because the comments carry things the code cannot say -- what a null means, what a number was measured against, which bug a guard exists for. Of the 238 one-line doc comments in the app, five were pure restatement of the name and were removed; the rest each say something the signature does not. ktfmtFormat, compileDebugKotlin, lintDebug and testDebugUnitTest pass; cargo test (127), clippy --all-targets and fmt still clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
79682f03a7
commit
edc39c7371
68 files changed
+2077
-2997
No files matched your search
@@ -41,13 +41,12 @@ data class QuestionAnswer(val questionId: String, val answers: List<String>)
|
||||
* What the reader has settled on for one question, before any of it is sent.
|
||||
*
|
||||
* Held here rather than inferred from the transcript, which is what made picking an option feel
|
||||
* broken: the mark used to appear only when the answer had crossed the tunnel, been recorded and
|
||||
* come back as an event, so on a phone the card sat unchanged for most of a second after a tap and
|
||||
* the natural response was to tap again.
|
||||
* broken: the mark used to appear only when the answer had crossed the tunnel and come back as an
|
||||
* event, so the card sat unchanged for most of a second after a tap.
|
||||
*
|
||||
* Picked options and typed words are one field each because they are alternatives rather than
|
||||
* parts: answering in the reader's own words is the case no option covers, so typing puts the picks
|
||||
* away and picking puts the words away, and there is never a draft that means two things.
|
||||
* parts: typing puts the picks away and picking puts the words away, so there is never a draft that
|
||||
* means two things.
|
||||
*/
|
||||
data class Draft(val picked: Set<String> = emptySet(), val other: String = "") {
|
||||
val settled: Boolean
|
||||
@@ -65,29 +64,26 @@ data class Draft(val picked: Set<String> = emptySet(), val other: String = "") {
|
||||
/**
|
||||
* Every question one tool call is waiting on, one at a time.
|
||||
*
|
||||
* All of it comes from the question events themselves -- what each option means, what picking it
|
||||
* would produce, whether several may be picked at once. None of it is read out of the call's own
|
||||
* All of it comes from the question events themselves. None of it is read out of the call's own
|
||||
* input, which is one provider's JSON: parsing that here would put that provider's schema in the
|
||||
* app, where no other provider can reach it and where it drifts the first time the schema moves.
|
||||
*
|
||||
* One question on screen with arrows to the others, rather than all of them stacked. A card asking
|
||||
* three questions with four options and a description each is several screens tall, so the reader
|
||||
* scrolls past the question they are answering to reach the button that sends it, and never sees
|
||||
* the whole of any one of them. Paged, each question is a screen and the count says how many are
|
||||
* left -- which is also what makes "not all of them are answered" something the reader can act on
|
||||
* rather than something to go hunting for.
|
||||
* scrolls past the question they are answering to reach the button that sends it. Paged, each
|
||||
* question is a screen and the count says how many are left.
|
||||
*
|
||||
* Nothing is sent until Submit. Answering is one act even when it is several questions: the tool
|
||||
* asked them together and is waiting on all of them, and sending each as it was tapped meant the
|
||||
* reader could not change their mind about the first after reading the third.
|
||||
* asked them together, and sending each as it was tapped meant the reader could not change their
|
||||
* mind about the first after reading the third.
|
||||
*/
|
||||
@Composable
|
||||
fun AskUserQuestionBody(
|
||||
asks: List<TranscriptItem.QuestionCard>,
|
||||
onAnswer: (List<QuestionAnswer>, onSettled: () -> Unit) -> Unit,
|
||||
) {
|
||||
// Seeded from what was already answered, so a card the reader comes back to shows their
|
||||
// answers rather than an empty draft over them.
|
||||
// Seeded from what was already answered, so a card the reader comes back to shows their answers
|
||||
// rather than an empty draft over them.
|
||||
var drafts by
|
||||
remember(asks.map { it.id }) {
|
||||
mutableStateOf(
|
||||
@@ -125,7 +121,7 @@ fun AskUserQuestionBody(
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
// Disabled at the ends rather than absent, so the pair keeps its place and the
|
||||
// reader can see that there is nothing further that way.
|
||||
// reader can see there is nothing further that way.
|
||||
MarkButton("Previous question", { at-- }, enabled = at > 0) {
|
||||
Chevron(Pointing.Left, colour = LocalContentColor.current)
|
||||
}
|
||||
@@ -143,7 +139,7 @@ fun AskUserQuestionBody(
|
||||
if (outstanding.isNotEmpty()) {
|
||||
Spacer(Modifier.height(12.dp))
|
||||
// Greyed until every question has an answer, because the tool is waiting on all of
|
||||
// them: a submit that sent two of three would leave the third one asked and the card
|
||||
// them: a submit that sent two of three would leave the third asked and the card
|
||||
// looking dealt with.
|
||||
val ready = outstanding.all { drafts[it.id]?.settled == true }
|
||||
Button(
|
||||
@@ -155,8 +151,8 @@ fun AskUserQuestionBody(
|
||||
}
|
||||
) {
|
||||
// Back to a button whatever happened. A refusal is reported by the screen
|
||||
// around this, and the draft is still here to send again -- a spinner
|
||||
// that never stops would be the only sign of a failure this card cannot
|
||||
// around this, and the draft is still here to send again -- a spinner that
|
||||
// never stops would be the only sign of a failure this card cannot
|
||||
// describe.
|
||||
sending = false
|
||||
}
|
||||
@@ -165,8 +161,8 @@ fun AskUserQuestionBody(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
if (sending) {
|
||||
// In the button rather than beside it, so the row does not change height at
|
||||
// the moment it is pressed.
|
||||
// In the button rather than beside it, so the row does not change height at the
|
||||
// moment it is pressed.
|
||||
CircularProgressIndicator(
|
||||
Modifier.height(18.dp).width(18.dp),
|
||||
strokeWidth = 2.dp,
|
||||
@@ -186,8 +182,7 @@ fun AskUserQuestionBody(
|
||||
* One question: what is being asked, what can be answered, and what was.
|
||||
*
|
||||
* The same body wherever a question appears -- on the call that asked it, or as a card of its own
|
||||
* when nothing did. A question is the same thing either way, and two renderings of it would be two
|
||||
* places for an answer to go missing.
|
||||
* when nothing did. Two renderings of it would be two places for an answer to go missing.
|
||||
*
|
||||
* [draft] is what the reader has picked so far and [onDraft] is how they change it; nothing here
|
||||
* sends anything. An answered question ignores both and draws what was answered.
|
||||
@@ -214,10 +209,10 @@ fun AskedQuestion(
|
||||
// replacing them with a line repeating it. The options are what the question *was*, and
|
||||
// dropping them leaves an answer with nothing to have been an answer to -- "Sonnet" says
|
||||
// very little without the three it was chosen over. Marked in the same purple that says
|
||||
// "picked" while the question is still open, so it is one appearance learned once.
|
||||
// "picked" while the question is open, so it is one appearance learned once.
|
||||
val answered = ask.answers.isNotEmpty()
|
||||
// What is marked: what was answered once there is an answer, and what the finger has
|
||||
// chosen until then.
|
||||
// What is marked: what was answered once there is an answer, and what the finger has chosen
|
||||
// until then.
|
||||
val marked = if (answered) ask.answers.toSet() else draft.picked
|
||||
// Null once the question is answered: the options stay and stop being pressable.
|
||||
val onPick: ((String) -> Unit)? =
|
||||
@@ -233,9 +228,9 @@ fun AskedQuestion(
|
||||
}
|
||||
}
|
||||
}
|
||||
// What was answered in the reader's own words, which no option can mark -- see
|
||||
// [OtherAnswer]. Only ever the answers that match nothing offered, so a question answered
|
||||
// by picking says it by the mark alone.
|
||||
// What was answered in the reader's own words, which no option can mark. Only ever the
|
||||
// answers that match nothing offered, so a question answered by picking says it by the
|
||||
// mark.
|
||||
val inWords = ask.answers.filterNot { answer -> ask.options.any { it.label == answer } }
|
||||
if (inWords.isNotEmpty()) {
|
||||
Text(
|
||||
@@ -252,10 +247,8 @@ fun AskedQuestion(
|
||||
}
|
||||
|
||||
/**
|
||||
* [label] added to, or taken out of, what [draft] has picked.
|
||||
*
|
||||
* A single-answer question replaces rather than accumulates, and either way picking puts any typed
|
||||
* words away -- see [Draft].
|
||||
* [label] added to, or taken out of, what [draft] has picked. A single-answer question replaces
|
||||
* rather than accumulates, and either way picking puts any typed words away -- see [Draft].
|
||||
*/
|
||||
private fun pick(draft: Draft, label: String, multiSelect: Boolean): Draft =
|
||||
when {
|
||||
@@ -269,8 +262,7 @@ private fun pick(draft: Draft, label: String, multiSelect: Boolean): Draft =
|
||||
*
|
||||
* Outlined rather than tinted. Drawn first as a card one step up the surface ladder, it was
|
||||
* indistinguishable from the card behind it -- three paragraphs of text where three things to press
|
||||
* should have been, which is the failure a tint step routinely produces on a dark theme. A border
|
||||
* is one cue and it is unambiguous.
|
||||
* should have been. A border is one cue and it is unambiguous.
|
||||
*/
|
||||
@Composable
|
||||
private fun OptionCard(option: QuestionOption, selected: Boolean, onPick: () -> Unit) {
|
||||
@@ -324,8 +316,8 @@ private fun Preview(preview: String) {
|
||||
preview,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
fontFamily = FontFamily.Monospace,
|
||||
// Not wrapped: these are mockups and diffs, where a wrapped line reads as two lines
|
||||
// of the thing being previewed.
|
||||
// Not wrapped: these are mockups and diffs, where a wrapped line reads as two lines of
|
||||
// the thing being previewed.
|
||||
softWrap = false,
|
||||
modifier = Modifier.padding(8.dp).horizontalScroll(rememberScrollState()),
|
||||
)
|
||||
@@ -336,8 +328,7 @@ private fun Preview(preview: String) {
|
||||
* The choice the asker always leaves open, and the app has to as well.
|
||||
*
|
||||
* Every AskUserQuestion carries an implicit "Other" -- the reader may answer in their own words
|
||||
* rather than pick. Leaving it out narrows a question that was never that narrow, and the reader
|
||||
* cannot tell that it was ever open.
|
||||
* rather than pick. Leaving it out narrows a question that was never that narrow.
|
||||
*/
|
||||
@Composable
|
||||
private fun OtherAnswer(text: String, onText: (String) -> Unit) {
|
||||
@@ -358,8 +349,7 @@ private fun OtherAnswer(text: String, onText: (String) -> Unit) {
|
||||
*
|
||||
* A Row hands out intrinsic widths in order and clips whatever runs past the edge, so a question
|
||||
* with four options showed the first one or two and dropped the rest off the side of the screen.
|
||||
* That does not read as a bug: it reads as those having been the only choices, which is the worst
|
||||
* way for a list of choices to be wrong.
|
||||
* That reads as those having been the only choices.
|
||||
*/
|
||||
@Composable
|
||||
fun AnswerOptions(
|
||||
@@ -379,8 +369,8 @@ fun AnswerOptions(
|
||||
OutlinedButton(
|
||||
onClick = { onPick?.invoke(option.label) },
|
||||
// Disabled rather than removed, so an answered question still shows what it
|
||||
// offered. Material dims a disabled button's own border and label, which would
|
||||
// take the mark with it -- both are stated here instead.
|
||||
// offered. Material dims a disabled button's own border and label, which would take
|
||||
// the mark with it -- both are stated here instead.
|
||||
enabled = onPick != null,
|
||||
border =
|
||||
BorderStroke(
|
||||
|
||||
Reference in new issue
Block a user