package com.example.aiapp import androidx.compose.foundation.lazy.LazyItemScope import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.items import androidx.compose.runtime.Composable /** * Keyed [items], with anything repeating a key already used left out. * * A lazy list throws when two of its items claim the same key, and the throw happens during measure * on the main thread -- so it is not an error the screen can show, it closes the app. That is a * disproportionate answer to a list with a repeat in it, and it lands on the reader rather than on * whoever produced the repeat: on 2026-08-31 the import list crashed on a Claude Code session id * recorded under two project directories, which is an ordinary state of a machine and not something * the phone did. * * Every list in this app keyed on an id keyed it on an id *the server chose*, so all of them shared * the hazard and none of them could rule it out locally. Hence one function they all go through * rather than a `distinctBy` remembered at each call site. * * Dropping the repeat is the right answer here because the key is the whole identity: two rows with * one id are two rows every action would treat as the same thing, so there is nothing to show about * the second that the first is not already showing. Where the duplicate means something -- the * import list's did -- the fix belongs at the source, and this is only what stops a data problem * from being a crash. It is counted so the render report says it happened rather than leaving a * silently shorter list. * * The transcript's own list is deliberately not on this: its keys are made here rather than * received, and it is the one list where an extra pass over the items is measurable. */ inline fun LazyListScope.uniqueItems( items: List, crossinline key: (T) -> Any, noinline contentType: (T) -> Any? = { null }, crossinline itemContent: @Composable LazyItemScope.(T) -> Unit, ) { val seen = HashSet(items.size) val unique = items.filter { seen.add(key(it)) } if (unique.size != items.size) { DebugStats.count("list items dropped for a repeated key") } items(unique, key = { key(it) }, contentType = contentType) { itemContent(it) } }