Browse Source

Redesign chat example (#3161)

* Redesign chat example

* Minor typography improvements

* Code cleanup

* Update examples/chat/iosApp/iosApp/iosApp.swift

Co-authored-by: Ivan Matkov <ivan.matkov@jetbrains.com>

* Use JPG instead of PNG

* Turn background in to a JPG
Add raw PXD file.

* Remove TEAM_ID

* Move to sp sizes

* Make Android text consistent with iOS variant

* Prefer light color scheme to prevent unwanted text color switch

* Remove PXD

---------

Co-authored-by: Ivan Matkov <ivan.matkov@jetbrains.com>
pull/3193/head
Sebastian Aigner 2 years ago committed by GitHub
parent
commit
dab4531fe4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 26
      examples/chat/iosApp/iosApp.xcodeproj/project.pbxproj
  2. 11
      examples/chat/iosApp/iosApp/ComposeInsideSwiftUIScreen.swift
  3. 1
      examples/chat/iosApp/iosApp/GradientTemplate.swift
  4. 12
      examples/chat/iosApp/iosApp/iosApp.swift
  5. 65
      examples/chat/shared/src/commonMain/kotlin/ChatApp.kt
  6. 143
      examples/chat/shared/src/commonMain/kotlin/ChatMessage.kt
  7. 5
      examples/chat/shared/src/commonMain/kotlin/Colors.kt
  8. 27
      examples/chat/shared/src/commonMain/kotlin/Data.kt
  9. 116
      examples/chat/shared/src/commonMain/kotlin/Messages.kt
  10. 9
      examples/chat/shared/src/commonMain/kotlin/SendMessage.kt
  11. BIN
      examples/chat/shared/src/commonMain/resources/background.jpg
  12. BIN
      examples/chat/shared/src/commonMain/resources/stock1.jpg
  13. BIN
      examples/chat/shared/src/commonMain/resources/stock2.jpg
  14. BIN
      examples/chat/shared/src/commonMain/resources/stock3.jpg
  15. BIN
      examples/chat/shared/src/commonMain/resources/stock4.jpg

26
examples/chat/iosApp/iosApp.xcodeproj/project.pbxproj

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
@ -25,7 +25,7 @@
1EB65E27D2C0F884D0A1A133 /* Pods-iosApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iosApp.debug.xcconfig"; path = "Target Support Files/Pods-iosApp/Pods-iosApp.debug.xcconfig"; sourceTree = "<group>"; };
2152FB032600AC8F00CF470E /* iosApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iosApp.swift; sourceTree = "<group>"; };
3D7A606AB0AD7636269BD9D0 /* Pods-iosApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iosApp.release.xcconfig"; path = "Target Support Files/Pods-iosApp/Pods-iosApp.release.xcconfig"; sourceTree = "<group>"; };
7555FF7B242A565900829871 /* iosApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iosApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
7555FF7B242A565900829871 /* Chat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Chat.app; sourceTree = BUILT_PRODUCTS_DIR; };
7555FF8C242A565B00829871 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8DE96E47030356CE6AD9794A /* Pods_iosApp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_iosApp.framework; sourceTree = BUILT_PRODUCTS_DIR; };
AB3632DC29227652001CCB65 /* Config.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; };
@ -57,7 +57,7 @@
7555FF7C242A565900829871 /* Products */ = {
isa = PBXGroup;
children = (
7555FF7B242A565900829871 /* iosApp.app */,
7555FF7B242A565900829871 /* Chat.app */,
);
name = Products;
sourceTree = "<group>";
@ -112,6 +112,7 @@
7555FF77242A565900829871 /* Sources */,
7555FF79242A565900829871 /* Resources */,
9964867F0862B4D9FB6ABFC7 /* Frameworks */,
BF14C3248E150D55CBFB145F /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@ -119,7 +120,7 @@
);
name = iosApp;
productName = iosApp;
productReference = 7555FF7B242A565900829871 /* iosApp.app */;
productReference = 7555FF7B242A565900829871 /* Chat.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
@ -166,6 +167,23 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
BF14C3248E150D55CBFB145F /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-resources.sh\"\n";
showEnvVarsInLog = 0;
};
E8D673591E7196AEA2EA10E2 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;

11
examples/chat/iosApp/iosApp/ComposeInsideSwiftUIScreen.swift

@ -14,7 +14,7 @@ struct ComposeInsideSwiftUIScreen: View {
struct ComposeLayer: View {
var body: some View {
GradientTemplate(title: "Compose inside SwiftUI") {
GradientTemplate(title: "The Composers Chat") {
ComposeViewControllerToSwiftUI()
.ignoresSafeArea(.keyboard) // Compose have own keyboard handler
}
@ -22,7 +22,7 @@ struct ComposeLayer: View {
}
struct TextInputLayer: View {
@State private var textState: String = "text message"
@State private var textState: String = ""
@FocusState private var textFieldFocused: Bool
var body: some View {
@ -39,12 +39,11 @@ struct TextInputLayer: View {
textState = ""
}) {
HStack {
Image(systemName: "play.fill")
Text("Send")
}.tint(.white)
Image(systemName: "arrow.up.circle.fill")
}.tint(Color(red: 0.671, green: 0.365, blue: 0.792))
}
}
}.padding(10).background(RoundedRectangle(cornerRadius: 10).fill(gradient).opacity(0.8)).padding(6)
}.padding(15).background(RoundedRectangle(cornerRadius: 200).fill(.white).opacity(0.95)).padding(15)
}
}
}

1
examples/chat/iosApp/iosApp/GradientTemplate.swift

@ -22,6 +22,5 @@ struct GradientTemplate<Content: View>: View {
.navigationBarTitleDisplayMode(.inline)
.statusBar(hidden: false)
}
.toolbar(.visible, for: .tabBar)
}
}

12
examples/chat/iosApp/iosApp/iosApp.swift

@ -1,7 +1,10 @@
import SwiftUI
let gradient = LinearGradient(
colors: gradient3Colors(),
colors: [
Color(red: 0.933, green: 0.937, blue: 0.953),
Color(red: 0.902, green: 0.941, blue: 0.949)
],
startPoint: .topLeading, endPoint: .bottomTrailing
)
@ -11,12 +14,13 @@ struct iOSApp: App {
WindowGroup {
TabView {
ComposeInsideSwiftUIScreen()
.tabItem { Label("Compose", systemImage: "square.and.pencil") }
.tabItem { Label("Group Chat", systemImage: "rectangle.3.group.bubble.left") }
YetAnotherSwiftUIScreen()
.tabItem { Label("SwiftUI", systemImage: "list.dash") }
.tabItem { Label("Settings", systemImage: "gear") }
}.accentColor(.white).preferredColorScheme(.dark)
}
.accentColor(Color(red: 0.671, green: 0.365, blue: 0.792)).preferredColorScheme(.light)
}
}
}

65
examples/chat/shared/src/commonMain/kotlin/ChatApp.kt

@ -1,19 +1,46 @@
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.LocalTextStyle
import androidx.compose.material.MaterialTheme
import androidx.compose.material.ProvideTextStyle
import androidx.compose.material.Scaffold
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.material.lightColors
import androidx.compose.runtime.Composable
import androidx.compose.runtime.*
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.delay
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource
val myUser = User("Me")
val friends = listOf(User("Alex"), User("Lily"), User("Sam"))
val myUser = User("Me", picture = null)
val friends = listOf(
User("Alex", picture = "stock1.jpg"),
User("Casey", picture = "stock2.jpg"),
User("Sam", picture = "stock3.jpg")
)
val friendMessages = listOf(
"Hi, have a nice day!",
"Nice to see you!",
"Multiline\ntext\nmessage"
"How's everybody doing today?",
"I've been meaning to chat!",
"When do we hang out next? 😋",
"We really need to catch up!",
"It's been too long!",
"I can't\nbelieve\nit! 😱",
"Did you see that ludicrous\ndisplay last night?",
"We should meet up in person!",
"How about a round of pinball?",
"I'd love to:\n🍔 Eat something\n🎥 Watch a movie, maybe?\nWDYT?"
)
val store = CoroutineScope(SupervisorJob()).createStore()
@ -23,7 +50,7 @@ fun ChatAppWithScaffold(displayTextField: Boolean = true) {
Scaffold(
topBar = {
TopAppBar(
title = { Text("Chat sample") },
title = { Text("The Composers Chat") },
backgroundColor = MaterialTheme.colors.background,
)
}) {
@ -32,12 +59,14 @@ fun ChatAppWithScaffold(displayTextField: Boolean = true) {
}
}
@OptIn(ExperimentalResourceApi::class)
@Composable
fun ChatApp(displayTextField: Boolean = true) {
val state by store.stateFlow.collectAsState()
Theme {
Surface {
Box(modifier = Modifier.fillMaxSize()) {
Image(painterResource("background.jpg"), null, contentScale = ContentScale.Crop)
Column(
modifier = Modifier.fillMaxSize()
) {
@ -58,13 +87,21 @@ fun ChatApp(displayTextField: Boolean = true) {
}
}
LaunchedEffect(Unit) {
var lastFriend = friends.random()
var lastMessage = friendMessages.random()
while (true) {
val thisFriend = friends.random()
val thisMessage = friendMessages.random()
if(thisFriend == lastFriend) continue
if(thisMessage == lastMessage) continue
lastFriend = thisFriend
lastMessage = thisMessage
store.send(
Action.SendMessage(
message = Message(
user = friends.random(),
user = thisFriend,
timeMs = timestampMs(),
text = friendMessages.random()
text = thisMessage
)
)
)
@ -76,11 +113,13 @@ fun ChatApp(displayTextField: Boolean = true) {
@Composable
fun Theme(content: @Composable () -> Unit) {
MaterialTheme(
colors = darkColors(
colors = lightColors(
surface = Color(ChatColors.SURFACE),
background = Color(ChatColors.BACKGROUND),
background = Color(ChatColors.TOP_GRADIENT.last()),
),
) {
ProvideTextStyle(LocalTextStyle.current.copy(letterSpacing = 0.sp)) {
content()
}
}
}

143
examples/chat/shared/src/commonMain/kotlin/ChatMessage.kt

@ -0,0 +1,143 @@
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@Composable
fun Triangle(risingToTheRight: Boolean, background: Color) {
Box(
Modifier
.padding(bottom = 10.dp, start = 0.dp)
.clip(TriangleEdgeShape(risingToTheRight))
.background(background)
.size(6.dp)
)
}
@Composable
inline fun ChatMessage(isMyMessage: Boolean, message: Message) {
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = if (isMyMessage) Alignment.CenterEnd else Alignment.CenterStart
) {
Row(verticalAlignment = Alignment.Bottom) {
if (!isMyMessage) {
Column {
UserPic(message.user)
}
Spacer(Modifier.size(2.dp))
Column {
Triangle(true, ChatColors.OTHERS_MESSAGE)
}
}
Column {
Box(
Modifier.clip(
RoundedCornerShape(
10.dp,
10.dp,
if (!isMyMessage) 10.dp else 0.dp,
if (!isMyMessage) 0.dp else 10.dp
)
)
.background(color = if (!isMyMessage) ChatColors.OTHERS_MESSAGE else ChatColors.MY_MESSAGE)
.padding(start = 10.dp, top = 5.dp, end = 10.dp, bottom = 5.dp),
) {
Column {
if(!isMyMessage) {
Row(verticalAlignment = Alignment.Bottom) {
Text(
text = message.user.name,
style = MaterialTheme.typography.body1.copy(
fontWeight = FontWeight.SemiBold,
letterSpacing = 0.sp,
fontSize = 14.sp
),
color = message.user.color
)
}
}
Spacer(Modifier.size(3.dp))
Text(
text = message.text,
style = MaterialTheme.typography.body1.copy(
fontSize = 18.sp,
letterSpacing = 0.sp
)
)
Spacer(Modifier.size(4.dp))
Row(
horizontalArrangement = Arrangement.End,
modifier = Modifier.align(Alignment.End)
) {
Text(
text = timeToString(message.timeMs),
textAlign = TextAlign.End,
style = MaterialTheme.typography.subtitle1.copy(fontSize = 10.sp),
color = ChatColors.TIME_TEXT
)
}
}
}
Box(Modifier.size(10.dp))
}
if(isMyMessage) {
Column {
Triangle(false, ChatColors.MY_MESSAGE)
}
}
}
}
}
// Adapted from https://stackoverflow.com/questions/65965852/jetpack-compose-create-chat-bubble-with-arrow-and-border-elevation
class TriangleEdgeShape(val risingToTheRight: Boolean) : Shape {
override fun createOutline(
size: Size,
layoutDirection: LayoutDirection,
density: Density
): Outline {
val trianglePath = if(risingToTheRight) {
Path().apply {
moveTo(x = 0f, y = size.height)
lineTo(x = size.width, y = 0f)
lineTo(x = size.width, y = size.height)
}
} else {
Path().apply {
moveTo(x = 0f, y = 0f)
lineTo(x = size.width, y = size.height)
lineTo(x = 0f, y = size.height)
}
}
return Outline.Generic(path = trianglePath)
}
}

5
examples/chat/shared/src/commonMain/kotlin/Colors.kt

@ -1,3 +1,4 @@
import androidx.compose.ui.graphics.Color
object ChatColors {
val GRADIENT_3 = listOf(0xFF7F52FF, 0xFFC811E2, 0xFFE54857)
@ -5,4 +6,8 @@ object ChatColors {
val PRIMARY = 0xFFAA77EE
val SURFACE = 0xFFCC99FF
val BACKGROUND = 0xFF663388
val TOP_GRADIENT = listOf(0xFFEEEFF3, 0xFFE6F0F2)
val MY_MESSAGE = Color(0xFFE5FEFB)
val OTHERS_MESSAGE = Color.White
val TIME_TEXT = Color(0xFF979797)
}

27
examples/chat/shared/src/commonMain/kotlin/Data.kt

@ -1,5 +1,6 @@
import androidx.compose.ui.graphics.Color
import kotlin.random.Random
import kotlin.random.nextInt
data class Message private constructor(
val user: User,
@ -21,9 +22,25 @@ data class Message private constructor(
data class User(
val name: String,
val pictureColor: Color = Color(
red = Random.nextInt(0xff),
green = Random.nextInt(0xff),
blue = Random.nextInt(0xff)
),
val color: Color = ColorProvider.getColor(),
val picture: String?
)
object ColorProvider {
val colors = mutableListOf(
0xFFEA3468,
0xFFB634EA,
0xFF349BEA,
)
val allColors = colors.toList()
fun getColor(): Color {
if(colors.size == 0) {
colors.addAll(allColors)
}
println(colors.lastIndex)
val idx = Random.nextInt(colors.indices)
val color = colors[idx]
colors.removeAt(idx)
return Color(color)
}
}

116
examples/chat/shared/src/commonMain/kotlin/Messages.kt

@ -1,30 +1,26 @@
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyItemScope
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.outlined.Favorite
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource
@Composable
internal inline fun Messages(messages: List<Message>) {
@ -35,97 +31,39 @@ internal inline fun Messages(messages: List<Message>) {
}
}
LazyColumn(
modifier = Modifier.fillMaxSize(),
modifier = Modifier.fillMaxSize().padding(start = 4.dp, end = 4.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
state = listState,
) {
messages.forEach { message ->
item(key = message.id) {
ChatMessage(isMyMessage = message.user == myUser, message)
}
item { Spacer(Modifier.size(20.dp)) }
items(messages, key = { it.id }) {
ChatMessage(isMyMessage = it.user == myUser, it)
}
item {
Box(Modifier.height(50.dp))
Box(Modifier.height(70.dp))
}
}
}
@OptIn(ExperimentalResourceApi::class)
@Composable
private inline fun ChatMessage(isMyMessage: Boolean, message: Message) {
val focusManager = LocalFocusManager.current
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = if (isMyMessage) Alignment.CenterEnd else Alignment.CenterStart
) {
Surface(
modifier = Modifier.padding(4.dp),
shape = RoundedCornerShape(size = 20.dp),
elevation = 8.dp
) {
Box(
Modifier.background(brush = Brush.horizontalGradient(
ChatColors.GRADIENT_2.map { Color(it) })
).padding(10.dp),
) {
Row(verticalAlignment = Alignment.Top) {
if (!isMyMessage) {
UserPic(message.user)
Spacer(Modifier.size(8.dp))
}
Column {
Row(verticalAlignment = Alignment.Bottom) {
Text(
text = message.user.name,
style = MaterialTheme.typography.h5
)
Spacer(Modifier.size(10.dp))
Text(
text = timeToString(message.timeMs),
style = MaterialTheme.typography.h6
)
}
Text(
text = message.text
)
}
if (isMyMessage) {
Spacer(Modifier.size(8.dp))
UserPic(message.user)
}
}
}
if (!isMyMessage) {
var liked by remember { mutableStateOf(false) }
Icon(
modifier = Modifier.align(Alignment.BottomEnd)
.clickable {
liked = !liked
focusManager.clearFocus(true)
}
.padding(3.dp),
imageVector = if (liked) Icons.Filled.Favorite else Icons.Outlined.Favorite,
contentDescription = "Like",
tint = if (liked) Color.Red else Color.Gray
)
}
}
fun UserPic(user: User) {
val imageSize = 48f
val painter = user.picture?.let {
painterResource(it)
} ?: object : Painter() {
override val intrinsicSize: Size = Size(imageSize, imageSize)
override fun DrawScope.onDraw() {
drawRect(user.color, size = Size(imageSize * 4, imageSize * 4))
}
}
@Composable
private fun UserPic(user: User) {
val imageSize = 64f
Image(
modifier = Modifier
.size(imageSize.dp)
.clip(CircleShape),
contentScale = ContentScale.Crop,
painter = object : Painter() {
override val intrinsicSize: Size = Size(imageSize, imageSize)
override fun DrawScope.onDraw() {
drawRect(user.pictureColor, size = Size(imageSize * 4, imageSize * 4))
}
},
painter = painter,
contentDescription = "User picture"
)
}

9
examples/chat/shared/src/commonMain/kotlin/SendMessage.kt

@ -7,13 +7,17 @@ import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.material.TextFieldDefaults
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Send
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.*
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
@Composable
@ -23,9 +27,10 @@ fun SendMessage(sendMessage: (String) -> Unit) {
modifier = Modifier.fillMaxWidth()
.background(MaterialTheme.colors.background)
.padding(10.dp),
colors = TextFieldDefaults.textFieldColors(backgroundColor = Color.White),
value = inputText,
placeholder = {
Text("type message here")
Text("Type message...")
},
onValueChange = {
inputText = it

BIN
examples/chat/shared/src/commonMain/resources/background.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 KiB

BIN
examples/chat/shared/src/commonMain/resources/stock1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
examples/chat/shared/src/commonMain/resources/stock2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
examples/chat/shared/src/commonMain/resources/stock3.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
examples/chat/shared/src/commonMain/resources/stock4.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Loading…
Cancel
Save