Skip to content

Commit 7c10c10

Browse files
committed
feature: Add showcase of list models on Android Sample
1 parent 08ac62f commit 7c10c10

File tree

5 files changed

+147
-9
lines changed

5 files changed

+147
-9
lines changed

sample/android/src/main/java/co/yml/ychat/android/di/AppModule.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ import co.yml.ychat.YChat
44
import co.yml.ychat.android.BuildConfig
55
import co.yml.ychat.android.presentation.chatcompletions.viewmodel.ChatCompletionsViewModel
66
import co.yml.ychat.android.presentation.home.viewmodel.HomeViewModel
7+
import co.yml.ychat.android.presentation.models.viewmodel.ModelsViewModel
78
import org.koin.androidx.viewmodel.dsl.viewModelOf
89
import org.koin.dsl.module
910

1011
val appModule = module {
1112
single { YChat.create(BuildConfig.API_KEY) }
1213
viewModelOf(::HomeViewModel)
1314
viewModelOf(::ChatCompletionsViewModel)
15+
viewModelOf(::ModelsViewModel)
1416
}
Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,78 @@
11
package co.yml.ychat.android.presentation.models
22

33
import androidx.compose.foundation.background
4-
import androidx.compose.foundation.layout.Arrangement
5-
import androidx.compose.foundation.layout.Column
4+
import androidx.compose.foundation.layout.Box
5+
import androidx.compose.foundation.layout.Spacer
66
import androidx.compose.foundation.layout.fillMaxHeight
7+
import androidx.compose.foundation.layout.fillMaxWidth
8+
import androidx.compose.foundation.layout.padding
9+
import androidx.compose.foundation.lazy.LazyColumn
10+
import androidx.compose.foundation.lazy.items
11+
import androidx.compose.material.CircularProgressIndicator
712
import androidx.compose.runtime.Composable
13+
import androidx.compose.runtime.collectAsState
14+
import androidx.compose.ui.Alignment
815
import androidx.compose.ui.Modifier
916
import androidx.compose.ui.tooling.preview.Preview
17+
import co.yml.ychat.YChat
18+
import co.yml.ychat.android.BuildConfig
19+
import co.yml.ychat.android.presentation.models.viewmodel.ModelsViewModel
20+
import co.yml.ychat.android.presentation.models.viewmodel.ModelsViewModel.State
1021
import co.yml.ychat.android.ui.components.feedback.Feedback
1122
import co.yml.ychat.android.ui.components.feedback.model.FeedbackState
23+
import co.yml.ychat.android.ui.components.itemmenu.ItemMenu
24+
import co.yml.ychat.android.ui.theme.Dimens
1225
import co.yml.ychat.android.ui.theme.YChatTheme
26+
import co.yml.ychat.domain.model.AIModel
27+
import org.koin.androidx.compose.getViewModel
1328

1429
@Composable
15-
internal fun ModelsScreen() {
16-
Column(
30+
internal fun ModelsScreen(viewModel: ModelsViewModel = getViewModel()) {
31+
val state = viewModel.state.collectAsState().value
32+
Box(
1733
modifier = Modifier
1834
.background(YChatTheme.colors.background)
19-
.fillMaxHeight(),
20-
verticalArrangement = Arrangement.Center,
35+
.fillMaxHeight()
36+
.fillMaxWidth()
2137
) {
22-
Feedback(feedbackState = FeedbackState.CONSTRUCTION)
38+
when (state) {
39+
is State.Loading ->
40+
CircularProgressIndicator(
41+
modifier = Modifier.align(Alignment.Center)
42+
)
43+
is State.Error ->
44+
Feedback(
45+
modifier = Modifier.align(Alignment.Center),
46+
feedbackState = FeedbackState.ERROR,
47+
onButtonClick = { viewModel.fetchModels() }
48+
)
49+
is State.Success ->
50+
ModelListContent(state.models)
51+
}
52+
}
53+
}
54+
55+
@Composable
56+
private fun ModelListContent(models: List<AIModel>) {
57+
LazyColumn {
58+
item { Spacer(modifier = Modifier.padding(top = Dimens.MD)) }
59+
items(models) {
60+
val enableDivider = models.last() != it
61+
ItemMenu(
62+
startText = it.id,
63+
caption = it.ownedBy,
64+
isDividerVisible = enableDivider,
65+
)
66+
}
2367
}
2468
}
2569

2670
@Preview
2771
@Composable
2872
private fun ModelsScreenPreview() {
2973
YChatTheme {
30-
ModelsScreen()
74+
val yChat = YChat.create(BuildConfig.API_KEY)
75+
val viewModel = ModelsViewModel(yChat)
76+
ModelsScreen(viewModel)
3177
}
3278
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package co.yml.ychat.android.presentation.models.viewmodel
2+
3+
import androidx.lifecycle.ViewModel
4+
import androidx.lifecycle.viewModelScope
5+
import co.yml.ychat.YChat
6+
import co.yml.ychat.domain.model.AIModel
7+
import kotlinx.coroutines.flow.MutableStateFlow
8+
import kotlinx.coroutines.flow.StateFlow
9+
import kotlinx.coroutines.flow.asStateFlow
10+
import kotlinx.coroutines.launch
11+
12+
internal class ModelsViewModel(private val yChat: YChat) : ViewModel() {
13+
14+
private val yChatListModels by lazy { yChat.listModels() }
15+
16+
private val _state = MutableStateFlow<State>(State.Loading)
17+
val state: StateFlow<State> = _state.asStateFlow()
18+
19+
init {
20+
fetchModels()
21+
}
22+
23+
fun fetchModels() = viewModelScope.launch {
24+
_state.value = State.Loading
25+
runCatching { yChatListModels.execute() }
26+
.onSuccess { _state.value = State.Success(it) }
27+
.onFailure { _state.value = State.Error }
28+
}
29+
30+
sealed class State {
31+
object Loading : State()
32+
data class Success(val models: List<AIModel>) : State()
33+
object Error : State()
34+
}
35+
}

sample/android/src/main/java/co/yml/ychat/android/ui/components/feedback/Feedback.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ private const val ICON_SIZE = 128
2424
@Composable
2525
fun Feedback(
2626
feedbackState: FeedbackState,
27+
modifier: Modifier = Modifier,
2728
onButtonClick: (() -> Unit)? = null,
2829
) {
2930
Feedback(
31+
modifier = modifier,
3032
icons = feedbackState.icon,
3133
title = stringResource(id = feedbackState.title),
3234
message = stringResource(id = feedbackState.message),
@@ -37,6 +39,7 @@ fun Feedback(
3739

3840
@Composable
3941
fun Feedback(
42+
modifier: Modifier,
4043
icons: Icons,
4144
title: String,
4245
message: String,
@@ -45,7 +48,7 @@ fun Feedback(
4548
) {
4649
Column(
4750
horizontalAlignment = Alignment.CenterHorizontally,
48-
modifier = Modifier.padding(horizontal = Dimens.XXXL)
51+
modifier = modifier.padding(horizontal = Dimens.XXXL)
4952
) {
5053
icons.Icon(
5154
modifier = Modifier
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package co.yml.ychat.android.ui.components.itemmenu
2+
3+
import androidx.compose.foundation.background
4+
import androidx.compose.foundation.layout.Arrangement
5+
import androidx.compose.foundation.layout.Column
6+
import androidx.compose.foundation.layout.fillMaxHeight
7+
import androidx.compose.foundation.layout.fillMaxWidth
8+
import androidx.compose.foundation.layout.padding
9+
import androidx.compose.runtime.Composable
10+
import androidx.compose.ui.Modifier
11+
import androidx.compose.ui.tooling.preview.Preview
12+
import androidx.compose.ui.unit.dp
13+
import co.yml.ychat.android.ui.components.divider.HorizontalDivider
14+
import co.yml.ychat.android.ui.theme.Dimens
15+
import co.yml.ychat.android.ui.theme.TypographyStyle
16+
import co.yml.ychat.android.ui.theme.YChatTheme
17+
18+
@Composable
19+
fun ItemMenu(
20+
startText: String,
21+
caption: String,
22+
isDividerVisible: Boolean = true,
23+
) {
24+
Column {
25+
Column(
26+
modifier = Modifier
27+
.fillMaxWidth()
28+
.padding(horizontal = Dimens.MD, vertical = 14.dp),
29+
verticalArrangement = Arrangement.spacedBy(Dimens.XXS)
30+
) {
31+
TypographyStyle.MediumBody.Text(text = startText)
32+
TypographyStyle.SmallBody.Text(text = caption, color = YChatTheme.colors.text2)
33+
}
34+
if (isDividerVisible) {
35+
HorizontalDivider(modifier = Modifier.padding(horizontal = Dimens.MD))
36+
}
37+
}
38+
}
39+
40+
@Preview
41+
@Composable
42+
private fun ItemMenuPreview() {
43+
YChatTheme {
44+
Column(
45+
modifier = Modifier
46+
.background(YChatTheme.colors.background)
47+
.fillMaxHeight()
48+
) {
49+
ItemMenu(startText = "Label one line", caption = "Caption one line")
50+
}
51+
}
52+
}

0 commit comments

Comments
 (0)