Skip to content

feature: implements edits screen on android sample #62

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 1 commit into from
Apr 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import co.yml.ychat.YChat
import co.yml.ychat.android.BuildConfig
import co.yml.ychat.android.presentation.chatcompletions.viewmodel.ChatCompletionsViewModel
import co.yml.ychat.android.presentation.completions.CompletionsViewModel
import co.yml.ychat.android.presentation.edits.EditsViewModel
import co.yml.ychat.android.presentation.home.viewmodel.HomeViewModel
import co.yml.ychat.android.presentation.models.viewmodel.ModelsViewModel
import org.koin.androidx.viewmodel.dsl.viewModelOf
Expand All @@ -15,4 +16,5 @@ val appModule = module {
viewModelOf(::ChatCompletionsViewModel)
viewModelOf(::ModelsViewModel)
viewModelOf(::CompletionsViewModel)
viewModelOf(::EditsViewModel)
}
Original file line number Diff line number Diff line change
@@ -1,32 +1,75 @@
package co.yml.ychat.android.presentation.edits

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import co.yml.ychat.android.ui.components.feedback.Feedback
import co.yml.ychat.android.ui.components.feedback.model.FeedbackState
import androidx.compose.ui.unit.dp
import co.yml.ychat.YChat
import co.yml.ychat.android.BuildConfig
import co.yml.ychat.android.R
import co.yml.ychat.android.ui.components.button.ButtonContained
import co.yml.ychat.android.ui.components.output.OutputBox
import co.yml.ychat.android.ui.components.textfield.StandardTextField
import co.yml.ychat.android.ui.theme.Dimens
import co.yml.ychat.android.ui.theme.TypographyStyle
import co.yml.ychat.android.ui.theme.YChatTheme
import org.koin.androidx.compose.getViewModel

@Composable
internal fun EditsScreen() {
internal fun EditsScreen(viewModel: EditsViewModel = getViewModel()) {
Column(
modifier = Modifier
.background(YChatTheme.colors.background)
.fillMaxHeight(),
verticalArrangement = Arrangement.Center,
.padding(Dimens.MD)
.fillMaxSize(),
) {
Feedback(feedbackState = FeedbackState.CONSTRUCTION)
TypographyStyle.MediumBody.Text(text = stringResource(id = R.string.edits_input_title))
StandardTextField(
value = viewModel.inputMessage.value,
hint = stringResource(id = R.string.edits_input_hint),
modifier = Modifier
.height(100.dp)
.fillMaxWidth()
.padding(top = Dimens.SM, bottom = Dimens.MD),
onTextChanged = { viewModel.onInputMessage(it) },
enabled = viewModel.onEnableTextField.value,
)
TypographyStyle.MediumBody.Text(text = stringResource(id = R.string.edits_instruction_title))
StandardTextField(
value = viewModel.instructionMessage.value,
hint = stringResource(id = R.string.edits_instruction_hint),
modifier = Modifier
.fillMaxWidth()
.padding(top = Dimens.SM, bottom = Dimens.XM)
,
onTextChanged = { viewModel.onInstructionMessage(it) },
enabled = viewModel.onEnableTextField.value,
)
ButtonContained(
text = stringResource(id = R.string.edits_action),
modifier = Modifier
.fillMaxWidth()
.padding(vertical = Dimens.XM),
enabled = viewModel.onEnableButton.value,
onClick = { viewModel.requestEdits() }
)
OutputBox(outputBoxStates = viewModel.outputBoxStates)
}
}

@Preview
@Composable
private fun EditsScreenPreview() {
YChatTheme {
EditsScreen()
val yChat = YChat.create(BuildConfig.API_KEY)
val viewModel = EditsViewModel(yChat)
EditsScreen(viewModel)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package co.yml.ychat.android.presentation.edits

import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import co.yml.ychat.YChat
import co.yml.ychat.android.ui.components.output.OutputBoxState
import kotlinx.coroutines.launch

internal class EditsViewModel(private val yChat: YChat) : ViewModel() {

val inputMessage = mutableStateOf("")

val instructionMessage = mutableStateOf("")

val outputBoxStates = mutableStateListOf<OutputBoxState>()

val onEnableButton = mutableStateOf(false)

val onEnableTextField = mutableStateOf(true)

fun requestEdits() = viewModelScope.launch {
outputBoxStates.clear()
onLoading(true)
val edits = yChat.edits()
.setInput(inputMessage.value)
.setResults(1)
runCatching { edits.execute(instructionMessage.value) }
.also { onLoading(false) }
.onSuccess { outputBoxStates.add(OutputBoxState.Text(it.first())) }
.onFailure { onError(true) }
}

fun onInputMessage(message: String) {
this.inputMessage.value = message
onEnableButton()
}

fun onInstructionMessage(message: String) {
this.instructionMessage.value = message
onEnableButton()
}

private fun onEnableButton() {
onEnableButton.value = inputMessage.value.isNotEmpty() &&
instructionMessage.value.isNotEmpty()
}

private fun onLoading(isLoading: Boolean) {
if (isLoading) {
onError(false)
onEnableButton.value = false
onEnableTextField.value = false
outputBoxStates.add(OutputBoxState.Loading)
} else {
onEnableTextField.value = true
outputBoxStates.remove(OutputBoxState.Loading)
onEnableButton()
}
}

private fun onError(isError: Boolean) {
if (isError) {
outputBoxStates.add(OutputBoxState.Error)
} else {
outputBoxStates.remove(OutputBoxState.Error)
}
}
}
7 changes: 7 additions & 0 deletions sample/android/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@
<string name="completions_hint">Write a tagline for an ice cream shop.</string>
<string name="completions_action">Submit</string>

<!-- EditsScreen -->
<string name="edits_input_title">Input</string>
<string name="edits_instruction_title">Instruction</string>
<string name="edits_input_hint">We is going to the market.</string>
<string name="edits_instruction_hint">Fix the grammar.</string>
<string name="edits_action">Submit</string>

<!-- FeedbackState.ERROR -->
<string name="feedback_state_error_title">Something went wrong</string>
<string name="feedback_state_error_message">There was a problem with the request. Please try again in a few moments.</string>
Expand Down