Remade the chat system based on the jetchat example app.
This commit is contained in:
parent
5ef0bf7160
commit
774adb608d
@ -38,6 +38,8 @@
|
|||||||
<entry key="../../../../../layout/compose-model-1641313051635.xml" value="0.3861111111111111" />
|
<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-1641313223231.xml" value="0.3861111111111111" />
|
||||||
<entry key="../../../../../layout/compose-model-1641313346209.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-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_arrow_back_24.xml" value="0.38981481481481484" />
|
||||||
<entry key="app/src/main/res/drawable/ic_baseline_keyboard_24.xml" value="0.38981481481481484" />
|
<entry key="app/src/main/res/drawable/ic_baseline_keyboard_24.xml" value="0.38981481481481484" />
|
||||||
|
@ -9,14 +9,10 @@ import androidx.compose.foundation.layout.fillMaxHeight
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.material.Surface
|
import androidx.compose.material.Surface
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.core.view.WindowInsetsControllerCompat
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
import androidx.navigation.compose.rememberNavController
|
|
||||||
import ch.mathieubroillet.jarvis.android.nav.Navigation
|
import ch.mathieubroillet.jarvis.android.nav.Navigation
|
||||||
import ch.mathieubroillet.jarvis.android.pages.DisplayMainPage
|
|
||||||
import ch.mathieubroillet.jarvis.android.ui.theme.JarvisComposeTheme
|
import ch.mathieubroillet.jarvis.android.ui.theme.JarvisComposeTheme
|
||||||
|
|
||||||
|
|
||||||
@ -51,13 +47,4 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Preview(showBackground = true)
|
|
||||||
@Composable
|
|
||||||
fun DefaultPreview() {
|
|
||||||
JarvisComposeTheme {
|
|
||||||
DisplayMainPage(rememberNavController())
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -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,
|
||||||
|
)
|
@ -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.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.material.Text
|
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.R
|
||||||
import ch.mathieubroillet.jarvis.android.ui.theme.productSansFont
|
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
|
@Composable
|
||||||
fun MessageFromJarvis(
|
fun MessageFromJarvis(
|
||||||
@ -95,7 +120,7 @@ fun MessageFromUser(text: String) {
|
|||||||
.fillMaxWidth(fraction = 0.8F)
|
.fillMaxWidth(fraction = 0.8F)
|
||||||
.clip(RoundedCornerShape(15.dp))
|
.clip(RoundedCornerShape(15.dp))
|
||||||
.background(color = MaterialTheme.colors.secondary)
|
.background(color = MaterialTheme.colors.secondary)
|
||||||
.padding(horizontal = 10.dp, vertical = 5.dp)
|
.padding(horizontal = 10.dp, vertical = 10.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = text,
|
text = text,
|
@ -1,10 +1,14 @@
|
|||||||
package ch.mathieubroillet.jarvis.android.nav
|
package ch.mathieubroillet.jarvis.android.nav
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
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.DisplayMainPage
|
||||||
import ch.mathieubroillet.jarvis.android.pages.DisplayPermissionsPage
|
import ch.mathieubroillet.jarvis.android.pages.DisplayPermissionsPage
|
||||||
import ch.mathieubroillet.jarvis.android.pages.DisplaySettingsPage
|
import ch.mathieubroillet.jarvis.android.pages.DisplaySettingsPage
|
||||||
@ -39,7 +43,17 @@ fun Navigation() {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MainScreen(navController: NavController) {
|
fun MainScreen(navController: NavController) {
|
||||||
DisplayMainPage(navController)
|
DisplayMainPage(
|
||||||
|
navController,
|
||||||
|
ConversationUiState(
|
||||||
|
listOf(
|
||||||
|
Message(
|
||||||
|
true,
|
||||||
|
stringResource(id = R.string.demo_message_1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package ch.mathieubroillet.jarvis.android.pages
|
package ch.mathieubroillet.jarvis.android.pages
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
|
||||||
import androidx.compose.material.*
|
import androidx.compose.material.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
@ -15,26 +14,35 @@ import androidx.compose.ui.unit.sp
|
|||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import ch.mathieubroillet.jarvis.android.R
|
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.nav.Screen
|
||||||
import ch.mathieubroillet.jarvis.android.ui.theme.JarvisComposeTheme
|
import ch.mathieubroillet.jarvis.android.ui.theme.JarvisComposeTheme
|
||||||
import ch.mathieubroillet.jarvis.android.ui.theme.productSansFont
|
import ch.mathieubroillet.jarvis.android.ui.theme.productSansFont
|
||||||
import ch.mathieubroillet.jarvis.android.utils.DefaultBox
|
import ch.mathieubroillet.jarvis.android.utils.DefaultBox
|
||||||
import ch.mathieubroillet.jarvis.android.utils.IconAlertDialogTextField
|
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".
|
//Draws the base of the main activity, that includes the 3-dots menu and the "hi text".
|
||||||
@Composable
|
@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)) {
|
Row(Modifier.align(Alignment.End)) {
|
||||||
|
var text by remember { mutableStateOf("") }
|
||||||
|
|
||||||
IconAlertDialogTextField(
|
IconAlertDialogTextField(
|
||||||
R.drawable.ic_baseline_keyboard_24,
|
buttonIcon = R.drawable.ic_baseline_keyboard_24,
|
||||||
stringResource(id = R.string.main_page_dialog_ask_me_anything),
|
title = stringResource(id = R.string.main_page_dialog_ask_me_anything),
|
||||||
stringResource(id = R.string.main_page_dialog_type_a_sentence)
|
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)
|
DropDownSettingsMenu(navController)
|
||||||
@ -98,24 +106,21 @@ fun StartRecordingFAB() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@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.
|
//We create a main box with basic padding to avoid having stuff too close to every side.
|
||||||
DefaultBox {
|
DefaultBox {
|
||||||
|
|
||||||
// This column regroup the base and all the conversations (everything except the footer)
|
// This column regroup the base and all the conversations (everything except the footer)
|
||||||
Column(Modifier.padding(bottom = 80.dp)) {
|
Column(Modifier.padding(bottom = 80.dp)) {
|
||||||
Base(navController)
|
|
||||||
|
|
||||||
// This column regroup only the conversations and make them scrollable
|
Base(navController, uiState)
|
||||||
LazyColumn(content = {
|
|
||||||
item {
|
Messages(
|
||||||
// Basic interaction stuff for demo
|
messages = uiState.messages,
|
||||||
MessageFromJarvis(text = stringResource(id = R.string.demo_message_1))
|
modifier = Modifier.weight(1f)
|
||||||
MessageFromUser(text = stringResource(id = R.string.demo_message_2))
|
)
|
||||||
MessageFromJarvis(text = stringResource(id = R.string.demo_message_3))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally we add the footer to the bottom center of the main box
|
// Finally we add the footer to the bottom center of the main box
|
||||||
@ -134,6 +139,10 @@ fun DisplayMainPage(navController: NavController) {
|
|||||||
@Composable
|
@Composable
|
||||||
fun MainPagePreview() {
|
fun MainPagePreview() {
|
||||||
JarvisComposeTheme {
|
JarvisComposeTheme {
|
||||||
DisplayMainPage(rememberNavController())
|
DisplayMainPage(
|
||||||
|
rememberNavController(), ConversationUiState(
|
||||||
|
listOf(Message(true, stringResource(id = R.string.demo_message_1)))
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,13 +4,14 @@ import androidx.compose.foundation.background
|
|||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.*
|
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.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.RectangleShape
|
import androidx.compose.ui.graphics.RectangleShape
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import ch.mathieubroillet.jarvis.android.R
|
import ch.mathieubroillet.jarvis.android.R
|
||||||
@ -21,7 +22,10 @@ import ch.mathieubroillet.jarvis.android.ui.theme.productSansFont
|
|||||||
fun IconAlertDialogTextField(
|
fun IconAlertDialogTextField(
|
||||||
buttonIcon: Int = R.drawable.ic_baseline_error_24,
|
buttonIcon: Int = R.drawable.ic_baseline_error_24,
|
||||||
title: String = "Title",
|
title: String = "Title",
|
||||||
label: String = "Label"
|
label: String = "Label",
|
||||||
|
text: String,
|
||||||
|
textFieldValue: (String) -> Unit,
|
||||||
|
onOKClick: () -> Unit
|
||||||
) {
|
) {
|
||||||
JarvisComposeTheme {
|
JarvisComposeTheme {
|
||||||
Column {
|
Column {
|
||||||
@ -68,12 +72,9 @@ fun IconAlertDialogTextField(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
Column {
|
Column {
|
||||||
var text by remember { mutableStateOf(TextFieldValue("")) }
|
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = text,
|
value = text,
|
||||||
onValueChange = { newText ->
|
onValueChange = textFieldValue,
|
||||||
text = newText
|
|
||||||
},
|
|
||||||
label = { Text(text = label) },
|
label = { Text(text = label) },
|
||||||
colors = TextFieldDefaults.outlinedTextFieldColors(
|
colors = TextFieldDefaults.outlinedTextFieldColors(
|
||||||
focusedBorderColor = MaterialTheme.colors.secondaryVariant,
|
focusedBorderColor = MaterialTheme.colors.secondaryVariant,
|
||||||
@ -93,7 +94,9 @@ fun IconAlertDialogTextField(
|
|||||||
color = MaterialTheme.colors.secondary
|
color = MaterialTheme.colors.secondary
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
TextButton(onClick = { /*TODO*/ }) {
|
TextButton(onClick = {
|
||||||
|
onOKClick(); openDialog.value = false
|
||||||
|
}) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(id = R.string.ok),
|
text = stringResource(id = R.string.ok),
|
||||||
color = MaterialTheme.colors.secondary
|
color = MaterialTheme.colors.secondary
|
||||||
@ -101,8 +104,6 @@ fun IconAlertDialogTextField(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user