1package soy.iko.opencode.ui.chat
3import androidx.compose.foundation.clickable
4import androidx.compose.foundation.layout.Column
5import androidx.compose.foundation.layout.Row
6import androidx.compose.foundation.layout.fillMaxWidth
7import androidx.compose.foundation.layout.heightIn
8import androidx.compose.foundation.layout.padding
9import androidx.compose.foundation.layout.size
10import androidx.compose.foundation.lazy.LazyColumn
11import androidx.compose.foundation.lazy.items
12import androidx.compose.material.icons.Icons
13import androidx.compose.material.icons.filled.Check
14import androidx.compose.material3.ExperimentalMaterial3Api
15import androidx.compose.material3.Icon
16import androidx.compose.material3.MaterialTheme
17import androidx.compose.material3.ModalBottomSheet
18import androidx.compose.material3.Text
19import androidx.compose.runtime.Composable
20import androidx.compose.ui.Alignment
21import androidx.compose.ui.Modifier
22import androidx.compose.ui.res.stringResource
23import androidx.compose.ui.semantics.Role
24import androidx.compose.ui.semantics.role
25import androidx.compose.ui.semantics.selected
26import androidx.compose.ui.semantics.semantics
27import androidx.compose.ui.unit.dp
28import soy.iko.opencode.data.model.ModelOption
29import soy.iko.opencode.R
31/** Bottom sheet that lists every provider/model and lets the user pick one. */
32@OptIn(ExperimentalMaterial3Api::class)
35 options: List<ModelOption>,
36 selected: ModelOption?,
37 onSelect: (ModelOption) -> Unit,
38 onDismiss: () -> Unit,
40 ModalBottomSheet(onDismissRequest = onDismiss) {
42 stringResource(R.string.model),
43 style = MaterialTheme.typography.titleMedium,
44 modifier = Modifier.padding(start = 24.dp, end = 24.dp, bottom = 8.dp),
46 if (options.isEmpty()) {
48 stringResource(R.string.no_models),
49 style = MaterialTheme.typography.bodyMedium,
50 color = MaterialTheme.colorScheme.onSurfaceVariant,
51 modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp),
54 LazyColumn(modifier = Modifier.fillMaxWidth().heightIn(max = 420.dp)) {
55 items(options, key = { it.providerID + "/" + it.modelID }) { option ->
56 val isSelected = option.providerID == selected?.providerID &&
57 option.modelID == selected.modelID
61 .semantics(mergeDescendants = true) {
62 role = Role.RadioButton
63 if (isSelected) this.selected = true
69 .padding(horizontal = 24.dp, vertical = 12.dp),
71 Row(verticalAlignment = Alignment.CenterVertically) {
74 style = MaterialTheme.typography.bodyLarge,
75 color = if (isSelected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurface,
76 modifier = Modifier.weight(1f),
81 contentDescription = null,
82 tint = MaterialTheme.colorScheme.primary,
83 modifier = Modifier.size(18.dp),
89 style = MaterialTheme.typography.bodySmall,
90 color = MaterialTheme.colorScheme.onSurfaceVariant,
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list