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.CircularProgressIndicator
15import androidx.compose.material3.ExperimentalMaterial3Api
16import androidx.compose.material3.Icon
17import androidx.compose.material3.MaterialTheme
18import androidx.compose.material3.ModalBottomSheet
19import androidx.compose.material3.Text
20import androidx.compose.runtime.Composable
21import androidx.compose.ui.Alignment
22import androidx.compose.ui.Modifier
23import androidx.compose.ui.res.stringResource
24import androidx.compose.ui.semantics.Role
25import androidx.compose.ui.semantics.role
26import androidx.compose.ui.semantics.selected
27import androidx.compose.ui.semantics.semantics
28import androidx.compose.ui.unit.dp
29import androidx.compose.foundation.layout.Box
30import soy.iko.opencode.data.model.ModelOption
31import soy.iko.opencode.R
33/** Bottom sheet that lists every provider/model and lets the user pick one. */
34@OptIn(ExperimentalMaterial3Api::class)
37 options: List<ModelOption>,
38 selected: ModelOption?,
40 onSelect: (ModelOption) -> Unit,
41 onDismiss: () -> Unit,
43 ModalBottomSheet(onDismissRequest = onDismiss) {
45 stringResource(R.string.model),
46 style = MaterialTheme.typography.titleMedium,
47 modifier = Modifier.padding(start = 24.dp, end = 24.dp, bottom = 8.dp),
51 modifier = Modifier.fillMaxWidth().padding(vertical = 24.dp),
52 contentAlignment = Alignment.Center,
54 CircularProgressIndicator()
56 } else if (options.isEmpty()) {
58 stringResource(R.string.no_models),
59 style = MaterialTheme.typography.bodyMedium,
60 color = MaterialTheme.colorScheme.onSurfaceVariant,
61 modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp),
64 LazyColumn(modifier = Modifier.fillMaxWidth().heightIn(max = 420.dp)) {
65 items(options, key = { it.providerID + "/" + it.modelID }) { option ->
66 val isSelected = option.providerID == selected?.providerID &&
67 option.modelID == selected.modelID
71 .semantics(mergeDescendants = true) {
72 role = Role.RadioButton
73 if (isSelected) this.selected = true
79 .padding(horizontal = 24.dp, vertical = 12.dp),
81 Row(verticalAlignment = Alignment.CenterVertically) {
84 style = MaterialTheme.typography.bodyLarge,
85 color = if (isSelected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurface,
86 modifier = Modifier.weight(1f),
91 contentDescription = null,
92 tint = MaterialTheme.colorScheme.primary,
93 modifier = Modifier.size(18.dp),
99 style = MaterialTheme.typography.bodySmall,
100 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