Remade the chat system based on the jetchat example app.

This commit is contained in:
Mathieu 2022-01-05 10:39:19 +01:00
parent 5ef0bf7160
commit 774adb608d
7 changed files with 106 additions and 46 deletions

View File

@ -38,6 +38,8 @@
<entry key="../../../../../layout/compose-model-1641313051635.xml" value="0.3861111111111111" />
<entry key="../../../../../layout/compose-model-1641313223231.xml" value="0.3861111111111111" />
<entry key="../../../../../layout/compose-model-1641313346209.xml" value="0.3861111111111111" />
<entry key="../../../../../layout/compose-model-1641371559019.xml" value="0.33" />
<entry key="../../../../../layout/compose-model-1641372970000.xml" value="0.3861111111111111" />
<entry key="app/src/main/res/drawable-v24/ic_launcher_foreground.xml" value="0.5307291666666667" />
<entry key="app/src/main/res/drawable/ic_baseline_arrow_back_24.xml" value="0.38981481481481484" />
<entry key="app/src/main/res/drawable/ic_baseline_keyboard_24.xml" value="0.38981481481481484" />

View File

@ -9,14 +9,10 @@ import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.navigation.compose.rememberNavController
import ch.mathieubroillet.jarvis.android.nav.Navigation
import ch.mathieubroillet.jarvis.android.pages.DisplayMainPage
import ch.mathieubroillet.jarvis.android.ui.theme.JarvisComposeTheme
@ -51,13 +47,4 @@ class MainActivity : ComponentActivity() {
}
}
}
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
JarvisComposeTheme {
DisplayMainPage(rememberNavController())
}
}

View File

@ -0,0 +1,22 @@
package ch.mathieubroillet.jarvis.android.chat
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.mutableStateListOf
class ConversationUiState(
initialMessages: List<Message>
) {
private val _messages: MutableList<Message> =
mutableStateListOf(*initialMessages.toTypedArray())
val messages: List<Message> = _messages
fun addMessage(msg: Message) {
_messages.add(0, msg) // Add to the beginning of the list
}
}
@Immutable
data class Message(
val isJarvis: Boolean,
val content: String,
)

View File

@ -1,9 +1,10 @@
package ch.mathieubroillet.jarvis.android.utils
package ch.mathieubroillet.jarvis.android.chat
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
@ -16,6 +17,30 @@ import androidx.compose.ui.unit.dp
import ch.mathieubroillet.jarvis.android.R
import ch.mathieubroillet.jarvis.android.ui.theme.productSansFont
@Composable
fun Messages(
messages: List<Message>,
modifier: Modifier = Modifier
) {
Box(modifier = modifier) {
LazyColumn(
modifier = Modifier
.fillMaxSize()
) {
val reverse: List<Message> = messages.reversed()
for (message in reverse) {
item {
if (message.isJarvis) {
MessageFromJarvis(text = message.content)
} else {
MessageFromUser(text = message.content)
}
}
}
}
}
}
@Composable
fun MessageFromJarvis(
@ -95,7 +120,7 @@ fun MessageFromUser(text: String) {
.fillMaxWidth(fraction = 0.8F)
.clip(RoundedCornerShape(15.dp))
.background(color = MaterialTheme.colors.secondary)
.padding(horizontal = 10.dp, vertical = 5.dp)
.padding(horizontal = 10.dp, vertical = 10.dp)
) {
Text(
text = text,

View File

@ -1,10 +1,14 @@
package ch.mathieubroillet.jarvis.android.nav
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import ch.mathieubroillet.jarvis.android.R
import ch.mathieubroillet.jarvis.android.chat.ConversationUiState
import ch.mathieubroillet.jarvis.android.chat.Message
import ch.mathieubroillet.jarvis.android.pages.DisplayMainPage
import ch.mathieubroillet.jarvis.android.pages.DisplayPermissionsPage
import ch.mathieubroillet.jarvis.android.pages.DisplaySettingsPage
@ -39,7 +43,17 @@ fun Navigation() {
@Composable
fun MainScreen(navController: NavController) {
DisplayMainPage(navController)
DisplayMainPage(
navController,
ConversationUiState(
listOf(
Message(
true,
stringResource(id = R.string.demo_message_1)
)
)
)
)
}
@Composable

View File

@ -1,7 +1,6 @@
package ch.mathieubroillet.jarvis.android.pages
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
@ -15,26 +14,35 @@ import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import androidx.navigation.compose.rememberNavController
import ch.mathieubroillet.jarvis.android.R
import ch.mathieubroillet.jarvis.android.chat.ConversationUiState
import ch.mathieubroillet.jarvis.android.chat.Message
import ch.mathieubroillet.jarvis.android.chat.Messages
import ch.mathieubroillet.jarvis.android.nav.Screen
import ch.mathieubroillet.jarvis.android.ui.theme.JarvisComposeTheme
import ch.mathieubroillet.jarvis.android.ui.theme.productSansFont
import ch.mathieubroillet.jarvis.android.utils.DefaultBox
import ch.mathieubroillet.jarvis.android.utils.IconAlertDialogTextField
import ch.mathieubroillet.jarvis.android.utils.MessageFromJarvis
import ch.mathieubroillet.jarvis.android.utils.MessageFromUser
//Draws the base of the main activity, that includes the 3-dots menu and the "hi text".
@Composable
fun Base(navController: NavController) {
fun Base(navController: NavController, uiState: ConversationUiState) {
Column(Modifier.padding(bottom = 25.dp).fillMaxWidth()) {
Column(
Modifier
.padding(bottom = 25.dp)
.fillMaxWidth()
) {
Row(Modifier.align(Alignment.End)) {
var text by remember { mutableStateOf("") }
IconAlertDialogTextField(
R.drawable.ic_baseline_keyboard_24,
stringResource(id = R.string.main_page_dialog_ask_me_anything),
stringResource(id = R.string.main_page_dialog_type_a_sentence)
buttonIcon = R.drawable.ic_baseline_keyboard_24,
title = stringResource(id = R.string.main_page_dialog_ask_me_anything),
label = stringResource(id = R.string.main_page_dialog_type_a_sentence),
text = text,
textFieldValue = { text = it },
onOKClick = { uiState.addMessage(Message(false, text)); text = "" }
)
DropDownSettingsMenu(navController)
@ -98,24 +106,21 @@ fun StartRecordingFAB() {
}
}
@Composable
fun DisplayMainPage(navController: NavController) {
fun DisplayMainPage(navController: NavController, uiState: ConversationUiState) {
//We create a main box with basic padding to avoid having stuff too close to every side.
DefaultBox {
// This column regroup the base and all the conversations (everything except the footer)
Column(Modifier.padding(bottom = 80.dp)) {
Base(navController)
// This column regroup only the conversations and make them scrollable
LazyColumn(content = {
item {
// Basic interaction stuff for demo
MessageFromJarvis(text = stringResource(id = R.string.demo_message_1))
MessageFromUser(text = stringResource(id = R.string.demo_message_2))
MessageFromJarvis(text = stringResource(id = R.string.demo_message_3))
}
})
Base(navController, uiState)
Messages(
messages = uiState.messages,
modifier = Modifier.weight(1f)
)
}
// Finally we add the footer to the bottom center of the main box
@ -134,6 +139,10 @@ fun DisplayMainPage(navController: NavController) {
@Composable
fun MainPagePreview() {
JarvisComposeTheme {
DisplayMainPage(rememberNavController())
DisplayMainPage(
rememberNavController(), ConversationUiState(
listOf(Message(true, stringResource(id = R.string.demo_message_1)))
)
)
}
}

View File

@ -4,13 +4,14 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import ch.mathieubroillet.jarvis.android.R
@ -21,7 +22,10 @@ import ch.mathieubroillet.jarvis.android.ui.theme.productSansFont
fun IconAlertDialogTextField(
buttonIcon: Int = R.drawable.ic_baseline_error_24,
title: String = "Title",
label: String = "Label"
label: String = "Label",
text: String,
textFieldValue: (String) -> Unit,
onOKClick: () -> Unit
) {
JarvisComposeTheme {
Column {
@ -68,12 +72,9 @@ fun IconAlertDialogTextField(
.fillMaxWidth()
) {
Column {
var text by remember { mutableStateOf(TextFieldValue("")) }
OutlinedTextField(
value = text,
onValueChange = { newText ->
text = newText
},
onValueChange = textFieldValue,
label = { Text(text = label) },
colors = TextFieldDefaults.outlinedTextFieldColors(
focusedBorderColor = MaterialTheme.colors.secondaryVariant,
@ -93,7 +94,9 @@ fun IconAlertDialogTextField(
color = MaterialTheme.colors.secondary
)
}
TextButton(onClick = { /*TODO*/ }) {
TextButton(onClick = {
onOKClick(); openDialog.value = false
}) {
Text(
text = stringResource(id = R.string.ok),
color = MaterialTheme.colors.secondary
@ -101,8 +104,6 @@ fun IconAlertDialogTextField(
}
}
}
}
}
},