From c740cc39edd34637a259ba246eba72b698c303a7 Mon Sep 17 00:00:00 2001
From: Gian <47775302+gpunto@users.noreply.github.com>
Date: Fri, 5 Jun 2026 15:37:17 +0200
Subject: [PATCH] Update tutorial code to use Chat v7
---
README.md | 17 +-
app/build.gradle | 16 +-
app/src/main/AndroidManifest.xml | 10 +-
.../example/chattutorial/ChannelActivity.kt | 62 +++++
.../example/chattutorial/ChannelActivity2.kt | 60 +++++
.../example/chattutorial/ChannelActivity3.kt | 165 ++++++++++++
.../example/chattutorial/ChannelActivity4.kt | 186 ++++++++++++++
.../com/example/chattutorial/MainActivity.kt | 65 +++--
.../example/chattutorial/MessagesActivity.kt | 49 ----
.../example/chattutorial/MessagesActivity2.kt | 63 -----
.../example/chattutorial/MessagesActivity3.kt | 194 --------------
.../example/chattutorial/MessagesActivity4.kt | 239 ------------------
.../example/chattutorial/ui/theme/Color.kt | 8 -
.../example/chattutorial/ui/theme/Shape.kt | 11 -
.../example/chattutorial/ui/theme/Theme.kt | 47 ----
.../com/example/chattutorial/ui/theme/Type.kt | 28 --
build.gradle | 6 +-
gradle/wrapper/gradle-wrapper.properties | 2 +-
18 files changed, 528 insertions(+), 700 deletions(-)
create mode 100644 app/src/main/java/com/example/chattutorial/ChannelActivity.kt
create mode 100644 app/src/main/java/com/example/chattutorial/ChannelActivity2.kt
create mode 100644 app/src/main/java/com/example/chattutorial/ChannelActivity3.kt
create mode 100644 app/src/main/java/com/example/chattutorial/ChannelActivity4.kt
delete mode 100644 app/src/main/java/com/example/chattutorial/MessagesActivity.kt
delete mode 100644 app/src/main/java/com/example/chattutorial/MessagesActivity2.kt
delete mode 100644 app/src/main/java/com/example/chattutorial/MessagesActivity3.kt
delete mode 100644 app/src/main/java/com/example/chattutorial/MessagesActivity4.kt
delete mode 100644 app/src/main/java/com/example/chattutorial/ui/theme/Color.kt
delete mode 100644 app/src/main/java/com/example/chattutorial/ui/theme/Shape.kt
delete mode 100644 app/src/main/java/com/example/chattutorial/ui/theme/Theme.kt
delete mode 100644 app/src/main/java/com/example/chattutorial/ui/theme/Type.kt
diff --git a/README.md b/README.md
index ec39b49..25a3667 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ The project is pre-configured with a shared [Stream](https://getstream.io) accou
## Quick start
1. Clone the repository
-2. Open the project in Android Studio (Arctic Fox or later)
+2. Open the project in the latest stable version of Android Studio
3. Run the _app_
4. Make sure to check the [Details](#details) section below for the different steps
@@ -18,19 +18,18 @@ The project is pre-configured with a shared [Stream](https://getstream.io) accou
The tutorial app consists of two screens:
* `MainActivity`: Shows the list of available channels.
-* `MessagesActivity`: Shows the selected channel view, which includes the header, message list, and message input view.
+* `ChannelActivity`: Shows the selected channel view, which includes the header, message list, and message input view.
-There are a handful of `MessagesActivity` implementations, which correspond to the steps of the tutorial. You can easily swap them by changing the `onChannelClick` handler located in `MainActivity`:
+`ChannelActivity` follows the published tutorial step-by-step and includes a colors customization on `ChatTheme`. Three additional `ChannelActivity*` implementations show alternative customization techniques and screen compositions. To try one, point `MainActivity`'s `onChannelClick` at it:
```kotlin
onChannelClick = { channel ->
- startActivity(MessagesActivity4.getIntent(this, channel.cid))
+ startActivity(ChannelActivity4.getIntent(this, channel.cid))
},
```
-You can choose from four different `MessagesActivity` implementations:
+You can choose from three alternative `ChannelActivity` implementations:
-* `MessagesActivity` - a basic _Message Screen_ implementation
-* `MessagesActivity2` - includes customization of the screen by using `ChatTheme`
-* `MessagesActivity3` - uses bound and stateless components to build the chat screen, with further customization
-* `MessagesActivity4` - uses a custom message composer component for extended customization
+* `ChannelActivity2` - customizes typography via `ChatTheme`
+* `ChannelActivity3` - uses bound and stateless components to build the chat screen
+* `ChannelActivity4` - uses a custom message composer component
diff --git a/app/build.gradle b/app/build.gradle
index b7a96c3..31d8705 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -5,13 +5,13 @@ plugins {
}
android {
- compileSdk 35
+ compileSdk 36
namespace "com.example.chattutorial"
defaultConfig {
applicationId "com.example.chattutorial"
- minSdk 21
- targetSdk 34
+ minSdk 24
+ targetSdk 36
versionCode 1
versionName "1.0"
@@ -45,15 +45,13 @@ android {
}
dependencies {
- implementation "io.getstream:stream-chat-android-compose:6.12.1"
- implementation "io.getstream:stream-chat-android-offline:6.12.1"
+ implementation "io.getstream:stream-chat-android-compose:7.3.0"
- implementation(platform("androidx.compose:compose-bom:2024.06.00"))
- implementation("androidx.activity:activity-compose:1.10.1")
+ implementation(platform("androidx.compose:compose-bom:2025.08.01"))
+ implementation("androidx.activity:activity-compose:1.9.3")
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-tooling")
implementation("androidx.compose.runtime:runtime")
implementation("androidx.compose.foundation:foundation")
- implementation("androidx.compose.material:material")
- implementation("androidx.compose.material:material-icons-extended")
+ implementation("androidx.compose.material3:material3")
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b940d2b..52b0985 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -14,19 +14,19 @@
android:supportsRtl="true"
android:theme="@style/Theme.ChatTutorial">
-
\ No newline at end of file
+
diff --git a/app/src/main/java/com/example/chattutorial/ChannelActivity.kt b/app/src/main/java/com/example/chattutorial/ChannelActivity.kt
new file mode 100644
index 0000000..139913e
--- /dev/null
+++ b/app/src/main/java/com/example/chattutorial/ChannelActivity.kt
@@ -0,0 +1,62 @@
+package com.example.chattutorial
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.ui.graphics.Color
+import io.getstream.chat.android.compose.ui.messages.ChannelScreen
+import io.getstream.chat.android.compose.ui.theme.ChatTheme
+import io.getstream.chat.android.compose.ui.theme.StreamDesign
+import io.getstream.chat.android.compose.viewmodel.messages.ChannelViewModelFactory
+import io.getstream.chat.android.compose.viewmodel.messages.MessageListOptions
+
+class ChannelActivity : ComponentActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // Load the ID of the selected channel from Intent Extras.
+ // If there is no channelId, then we finish the Activity and return.
+ val channelId = intent.getStringExtra(KEY_CHANNEL_ID)
+ if (channelId == null) {
+ finish()
+ return
+ }
+
+ // Set the UI
+ setContent {
+ val baseColors = if (isSystemInDarkTheme()) {
+ StreamDesign.Colors.defaultDark()
+ } else {
+ StreamDesign.Colors.default()
+ }
+ ChatTheme(
+ colors = baseColors.copy(
+ accentPrimary = Color(0xFF005FFF),
+ )
+ ) {
+ ChannelScreen(
+ viewModelFactory = ChannelViewModelFactory(
+ context = this,
+ channelId = channelId,
+ messageListOptions = MessageListOptions(messageLimit = 30),
+ ),
+ onBackPressed = { finish() }
+ )
+ }
+ }
+ }
+
+ // Define a helper function to build an Intent for this Activity.
+ companion object {
+ private const val KEY_CHANNEL_ID = "channelId"
+
+ fun getIntent(context: Context, channelId: String): Intent {
+ return Intent(context, ChannelActivity::class.java).apply {
+ putExtra(KEY_CHANNEL_ID, channelId)
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/chattutorial/ChannelActivity2.kt b/app/src/main/java/com/example/chattutorial/ChannelActivity2.kt
new file mode 100644
index 0000000..bf279ba
--- /dev/null
+++ b/app/src/main/java/com/example/chattutorial/ChannelActivity2.kt
@@ -0,0 +1,60 @@
+package com.example.chattutorial
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+import io.getstream.chat.android.compose.ui.messages.ChannelScreen
+import io.getstream.chat.android.compose.ui.theme.ChatTheme
+import io.getstream.chat.android.compose.ui.theme.StreamDesign
+import io.getstream.chat.android.compose.viewmodel.messages.ChannelViewModelFactory
+import io.getstream.chat.android.compose.viewmodel.messages.MessageListOptions
+
+/**
+ * Demonstrates customizing the [ChatTheme] typography. The same pattern works for any
+ * [StreamDesign.Typography] field; here we swap the font family and weights on a few text styles
+ * via [copy].
+ */
+class ChannelActivity2 : ComponentActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val channelId = intent.getStringExtra(KEY_CHANNEL_ID)
+ if (channelId == null) {
+ finish()
+ return
+ }
+
+ setContent {
+ val baseTypography = StreamDesign.Typography.default(fontFamily = FontFamily.Serif)
+ ChatTheme(
+ typography = baseTypography.copy(
+ bodyEmphasis = baseTypography.bodyEmphasis.copy(fontWeight = FontWeight.Bold),
+ headingMedium = baseTypography.headingMedium.copy(fontWeight = FontWeight.Black),
+ )
+ ) {
+ ChannelScreen(
+ viewModelFactory = ChannelViewModelFactory(
+ context = this,
+ channelId = channelId,
+ messageListOptions = MessageListOptions(messageLimit = 30),
+ ),
+ onBackPressed = { finish() }
+ )
+ }
+ }
+ }
+
+ companion object {
+ private const val KEY_CHANNEL_ID = "channelId"
+
+ fun getIntent(context: Context, channelId: String): Intent {
+ return Intent(context, ChannelActivity2::class.java).apply {
+ putExtra(KEY_CHANNEL_ID, channelId)
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/chattutorial/ChannelActivity3.kt b/app/src/main/java/com/example/chattutorial/ChannelActivity3.kt
new file mode 100644
index 0000000..616fc7a
--- /dev/null
+++ b/app/src/main/java/com/example/chattutorial/ChannelActivity3.kt
@@ -0,0 +1,165 @@
+package com.example.chattutorial
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.activity.viewModels
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.consumeWindowInsets
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.ime
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawingPadding
+import androidx.compose.material3.Scaffold
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Modifier
+import io.getstream.chat.android.compose.ui.components.messageactions.MessageActions
+import io.getstream.chat.android.compose.ui.components.messageactions.ReactionsMenu
+import io.getstream.chat.android.compose.ui.components.messageoptions.defaultMessageOptionsState
+import io.getstream.chat.android.compose.ui.messages.attachments.AttachmentPickerMenu
+import io.getstream.chat.android.compose.ui.messages.composer.MessageComposer
+import io.getstream.chat.android.compose.ui.messages.list.MessageList
+import io.getstream.chat.android.compose.ui.theme.ChatTheme
+import io.getstream.chat.android.compose.viewmodel.messages.AttachmentsPickerViewModel
+import io.getstream.chat.android.compose.viewmodel.messages.ChannelViewModelFactory
+import io.getstream.chat.android.compose.viewmodel.messages.MessageComposerViewModel
+import io.getstream.chat.android.compose.viewmodel.messages.MessageListViewModel
+import io.getstream.chat.android.compose.viewmodel.messages.MessageListOptions
+import io.getstream.chat.android.ui.common.state.messages.MessageMode
+import io.getstream.chat.android.ui.common.state.messages.list.SelectedMessageOptionsState
+import io.getstream.chat.android.ui.common.state.messages.list.SelectedMessageReactionsState
+
+/**
+ * Demonstrates building the chat screen from low-level, bound + stateless components instead of
+ * using [io.getstream.chat.android.compose.ui.messages.ChannelScreen]. The selected-message
+ * overlay is rendered with [MessageActions] / [ReactionsMenu].
+ */
+class ChannelActivity3 : ComponentActivity() {
+
+ private val factory by lazy {
+ ChannelViewModelFactory(
+ context = this,
+ channelId = intent.getStringExtra(KEY_CHANNEL_ID) ?: "",
+ messageListOptions = MessageListOptions(messageLimit = 30),
+ )
+ }
+
+ private val listViewModel: MessageListViewModel by viewModels { factory }
+ private val attachmentsPickerViewModel: AttachmentsPickerViewModel by viewModels { factory }
+ private val composerViewModel: MessageComposerViewModel by viewModels { factory }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val channelId = intent.getStringExtra(KEY_CHANNEL_ID)
+ if (channelId == null) {
+ finish()
+ return
+ }
+
+ setContent {
+ ChatTheme {
+ MyCustomUi()
+ }
+ }
+ }
+
+ @Composable
+ private fun MyCustomUi() {
+ val messagesState by listViewModel.currentMessagesState
+ val selectedMessageState = messagesState.selectedMessageState
+ val user by listViewModel.user.collectAsState()
+
+ Box(
+ modifier = Modifier
+ .fillMaxSize()
+ .safeDrawingPadding()
+ .consumeWindowInsets(WindowInsets.ime),
+ ) {
+ Scaffold(
+ modifier = Modifier.fillMaxSize(),
+ containerColor = ChatTheme.colors.backgroundCoreApp,
+ bottomBar = {
+ Column {
+ MessageComposer(
+ viewModel = composerViewModel,
+ onAttachmentsClick = {
+ attachmentsPickerViewModel.setPickerVisible(true)
+ }
+ )
+ AttachmentPickerMenu(
+ attachmentsPickerViewModel = attachmentsPickerViewModel,
+ composerViewModel = composerViewModel,
+ )
+ }
+ }
+ ) { contentPadding ->
+ MessageList(
+ modifier = Modifier
+ .background(ChatTheme.colors.backgroundCoreApp)
+ .padding(contentPadding)
+ .fillMaxSize(),
+ viewModel = listViewModel,
+ onThreadClick = { message ->
+ composerViewModel.setMessageMode(MessageMode.MessageThread(message))
+ listViewModel.openMessageThread(message)
+ }
+ )
+ }
+
+ if (selectedMessageState is SelectedMessageOptionsState) {
+ val selectedMessage = selectedMessageState.message
+ MessageActions(
+ message = selectedMessage,
+ messageOptions = defaultMessageOptionsState(
+ selectedMessage = selectedMessage,
+ currentUser = user,
+ isInThread = listViewModel.isInThread,
+ channel = selectedMessageState.channel,
+ ),
+ ownCapabilities = selectedMessageState.ownCapabilities,
+ onMessageAction = { action ->
+ composerViewModel.performMessageAction(action)
+ listViewModel.performMessageAction(action)
+ },
+ onShowMoreReactionsSelected = {
+ listViewModel.selectExtendedReactions(selectedMessage)
+ },
+ onDismiss = { listViewModel.removeOverlay() },
+ currentUser = user,
+ )
+ } else if (selectedMessageState is SelectedMessageReactionsState) {
+ val selectedMessage = selectedMessageState.message
+ ReactionsMenu(
+ message = selectedMessage,
+ currentUser = user,
+ ownCapabilities = selectedMessageState.ownCapabilities,
+ onMessageAction = { action ->
+ composerViewModel.performMessageAction(action)
+ listViewModel.performMessageAction(action)
+ },
+ onShowMoreReactionsSelected = {
+ listViewModel.selectExtendedReactions(selectedMessage)
+ },
+ onDismiss = { listViewModel.removeOverlay() },
+ )
+ }
+ }
+ }
+
+ companion object {
+ private const val KEY_CHANNEL_ID = "channelId"
+
+ fun getIntent(context: Context, channelId: String): Intent {
+ return Intent(context, ChannelActivity3::class.java).apply {
+ putExtra(KEY_CHANNEL_ID, channelId)
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/chattutorial/ChannelActivity4.kt b/app/src/main/java/com/example/chattutorial/ChannelActivity4.kt
new file mode 100644
index 0000000..1eefa79
--- /dev/null
+++ b/app/src/main/java/com/example/chattutorial/ChannelActivity4.kt
@@ -0,0 +1,186 @@
+package com.example.chattutorial
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.activity.viewModels
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.consumeWindowInsets
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.ime
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawingPadding
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.material3.Scaffold
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import io.getstream.chat.android.compose.ui.components.composer.MessageInput
+import io.getstream.chat.android.compose.ui.components.messageactions.MessageActions
+import io.getstream.chat.android.compose.ui.components.messageactions.ReactionsMenu
+import io.getstream.chat.android.compose.ui.components.messageoptions.defaultMessageOptionsState
+import io.getstream.chat.android.compose.ui.messages.attachments.AttachmentPickerMenu
+import io.getstream.chat.android.compose.ui.messages.composer.MessageComposer
+import io.getstream.chat.android.compose.ui.messages.list.MessageList
+import io.getstream.chat.android.compose.ui.theme.ChatTheme
+import io.getstream.chat.android.compose.viewmodel.messages.AttachmentsPickerViewModel
+import io.getstream.chat.android.compose.viewmodel.messages.ChannelViewModelFactory
+import io.getstream.chat.android.compose.viewmodel.messages.MessageComposerViewModel
+import io.getstream.chat.android.compose.viewmodel.messages.MessageListOptions
+import io.getstream.chat.android.compose.viewmodel.messages.MessageListViewModel
+import io.getstream.chat.android.ui.common.state.messages.MessageMode
+import io.getstream.chat.android.ui.common.state.messages.list.SelectedMessageOptionsState
+import io.getstream.chat.android.ui.common.state.messages.list.SelectedMessageReactionsState
+
+/**
+ * Same low-level screen as [ChannelActivity3], but supplies a custom `input` slot to
+ * [MessageComposer] wired to a hand-placed [MessageInput].
+ */
+class ChannelActivity4 : ComponentActivity() {
+
+ private val factory by lazy {
+ ChannelViewModelFactory(
+ context = this,
+ channelId = intent.getStringExtra(KEY_CHANNEL_ID) ?: "",
+ messageListOptions = MessageListOptions(messageLimit = 30),
+ )
+ }
+
+ private val listViewModel: MessageListViewModel by viewModels { factory }
+ private val attachmentsPickerViewModel: AttachmentsPickerViewModel by viewModels { factory }
+ private val composerViewModel: MessageComposerViewModel by viewModels { factory }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val channelId = intent.getStringExtra(KEY_CHANNEL_ID)
+ if (channelId == null) {
+ finish()
+ return
+ }
+
+ setContent {
+ ChatTheme {
+ MyCustomUi()
+ }
+ }
+ }
+
+ @Composable
+ private fun MyCustomUi() {
+ val messagesState by listViewModel.currentMessagesState
+ val selectedMessageState = messagesState.selectedMessageState
+ val user by listViewModel.user.collectAsState()
+
+ Box(
+ modifier = Modifier
+ .fillMaxSize()
+ .safeDrawingPadding()
+ .consumeWindowInsets(WindowInsets.ime),
+ ) {
+ Scaffold(
+ modifier = Modifier.fillMaxSize(),
+ containerColor = ChatTheme.colors.backgroundCoreApp,
+ bottomBar = {
+ Column {
+ MyCustomComposer()
+ AttachmentPickerMenu(
+ attachmentsPickerViewModel = attachmentsPickerViewModel,
+ composerViewModel = composerViewModel,
+ )
+ }
+ }
+ ) { contentPadding ->
+ MessageList(
+ modifier = Modifier
+ .background(ChatTheme.colors.backgroundCoreApp)
+ .padding(contentPadding)
+ .fillMaxSize(),
+ viewModel = listViewModel,
+ onThreadClick = { message ->
+ composerViewModel.setMessageMode(MessageMode.MessageThread(message))
+ listViewModel.openMessageThread(message)
+ }
+ )
+ }
+
+ if (selectedMessageState is SelectedMessageOptionsState) {
+ val selectedMessage = selectedMessageState.message
+ MessageActions(
+ message = selectedMessage,
+ messageOptions = defaultMessageOptionsState(
+ selectedMessage = selectedMessage,
+ currentUser = user,
+ isInThread = listViewModel.isInThread,
+ channel = selectedMessageState.channel,
+ ),
+ ownCapabilities = selectedMessageState.ownCapabilities,
+ onMessageAction = { action ->
+ composerViewModel.performMessageAction(action)
+ listViewModel.performMessageAction(action)
+ },
+ onShowMoreReactionsSelected = {
+ listViewModel.selectExtendedReactions(selectedMessage)
+ },
+ onDismiss = { listViewModel.removeOverlay() },
+ currentUser = user,
+ )
+ } else if (selectedMessageState is SelectedMessageReactionsState) {
+ val selectedMessage = selectedMessageState.message
+ ReactionsMenu(
+ message = selectedMessage,
+ currentUser = user,
+ ownCapabilities = selectedMessageState.ownCapabilities,
+ onMessageAction = { action ->
+ composerViewModel.performMessageAction(action)
+ listViewModel.performMessageAction(action)
+ },
+ onShowMoreReactionsSelected = {
+ listViewModel.selectExtendedReactions(selectedMessage)
+ },
+ onDismiss = { listViewModel.removeOverlay() },
+ )
+ }
+ }
+ }
+
+ @Composable
+ private fun MyCustomComposer() {
+ MessageComposer(
+ modifier = Modifier
+ .fillMaxWidth()
+ .wrapContentHeight(),
+ viewModel = composerViewModel,
+ onAttachmentsClick = { attachmentsPickerViewModel.setPickerVisible(true) },
+ input = { inputState ->
+ MessageInput(
+ modifier = Modifier
+ .weight(1f)
+ .padding(horizontal = 8.dp)
+ .align(Alignment.CenterVertically),
+ messageComposerState = inputState,
+ onValueChange = { composerViewModel.setMessageInput(it) },
+ onAttachmentRemoved = { composerViewModel.removeAttachment(it) },
+ )
+ }
+ )
+ }
+
+ companion object {
+ private const val KEY_CHANNEL_ID = "channelId"
+
+ fun getIntent(context: Context, channelId: String): Intent {
+ return Intent(context, ChannelActivity::class.java).apply {
+ putExtra(KEY_CHANNEL_ID, channelId)
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/chattutorial/MainActivity.kt b/app/src/main/java/com/example/chattutorial/MainActivity.kt
index e3de8ac..c9ce683 100644
--- a/app/src/main/java/com/example/chattutorial/MainActivity.kt
+++ b/app/src/main/java/com/example/chattutorial/MainActivity.kt
@@ -3,44 +3,33 @@ package com.example.chattutorial
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
-import androidx.compose.material.Text
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.safeDrawingPadding
+import androidx.compose.material3.Text
+import androidx.compose.ui.Modifier
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.res.stringResource
import io.getstream.chat.android.client.ChatClient
import io.getstream.chat.android.client.logger.ChatLogLevel
import io.getstream.chat.android.compose.ui.channels.ChannelsScreen
+import io.getstream.chat.android.compose.ui.channels.SearchMode
import io.getstream.chat.android.compose.ui.theme.ChatTheme
import io.getstream.chat.android.models.InitializationState
import io.getstream.chat.android.models.User
-import io.getstream.chat.android.offline.plugin.factory.StreamOfflinePluginFactory
-import io.getstream.chat.android.state.plugin.config.StatePluginConfig
-import io.getstream.chat.android.state.plugin.factory.StreamStatePluginFactory
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- // 1 - Set up the OfflinePlugin for offline storage
- val offlinePluginFactory = StreamOfflinePluginFactory(
- appContext = applicationContext,
- )
- val statePluginFactory = StreamStatePluginFactory(
- config = StatePluginConfig(
- backgroundSyncEnabled = true,
- userPresence = true,
- ),
- appContext = this,
- )
-
- // 2 - Set up the client for API calls and with the plugin for offline storage
+ // Set up the client for API calls with offline storage and state management
val client = ChatClient.Builder("uun7ywwamhs9", applicationContext)
- .withPlugins(offlinePluginFactory, statePluginFactory)
.logLevel(ChatLogLevel.ALL) // Set to NOTHING in prod
.build()
- // 3 - Authenticate and connect the user
+ // Authenticate and connect the user
val user = User(
id = "tutorial-droid",
name = "Tutorial Droid",
@@ -57,21 +46,29 @@ class MainActivity : ComponentActivity() {
val clientInitialisationState by client.clientState.initializationState.collectAsState()
ChatTheme {
- when (clientInitialisationState) {
- InitializationState.COMPLETE -> {
- ChannelsScreen(
- title = stringResource(id = R.string.app_name),
- onChannelClick = { channel ->
- startActivity(MessagesActivity4.getIntent(this@MainActivity, channel.cid))
- },
- onBackPressed = { finish() }
- )
- }
- InitializationState.INITIALIZING -> {
- Text(text = "Initialising...")
- }
- InitializationState.NOT_INITIALIZED -> {
- Text(text = "Not initialized...")
+ Box(
+ modifier = Modifier
+ .fillMaxSize()
+ .safeDrawingPadding(),
+ ) {
+ when (clientInitialisationState) {
+ InitializationState.COMPLETE -> {
+ ChannelsScreen(
+ title = stringResource(id = R.string.app_name),
+ isShowingHeader = true,
+ searchMode = SearchMode.Messages,
+ onChannelClick = { channel ->
+ startActivity(ChannelActivity.getIntent(this@MainActivity, channel.cid))
+ },
+ onBackPressed = { finish() }
+ )
+ }
+ InitializationState.INITIALIZING -> {
+ Text(text = "Initializing...")
+ }
+ InitializationState.NOT_INITIALIZED -> {
+ Text(text = "Not initialized...")
+ }
}
}
}
diff --git a/app/src/main/java/com/example/chattutorial/MessagesActivity.kt b/app/src/main/java/com/example/chattutorial/MessagesActivity.kt
deleted file mode 100644
index 0423ac9..0000000
--- a/app/src/main/java/com/example/chattutorial/MessagesActivity.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.example.chattutorial
-
-import android.content.Context
-import android.content.Intent
-import android.os.Bundle
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import io.getstream.chat.android.compose.ui.messages.MessagesScreen
-import io.getstream.chat.android.compose.ui.theme.ChatTheme
-import io.getstream.chat.android.compose.viewmodel.messages.MessagesViewModelFactory
-
-class MessagesActivity : ComponentActivity() {
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- // 1 - Load the ID of the selected channel
- val channelId = intent.getStringExtra(KEY_CHANNEL_ID)
-
- if (channelId == null) {
- finish()
- return
- }
-
- // 2 - Add the MessagesScreen to your UI
- setContent {
- ChatTheme {
- MessagesScreen(
- viewModelFactory = MessagesViewModelFactory(
- context = this,
- channelId = channelId,
- messageLimit = 30
- ),
- onBackPressed = { finish() }
- )
- }
- }
- }
-
- // 3 - Create an intent to start this Activity, with a given channelId
- companion object {
- private const val KEY_CHANNEL_ID = "channelId"
-
- fun getIntent(context: Context, channelId: String): Intent {
- return Intent(context, MessagesActivity::class.java).apply {
- putExtra(KEY_CHANNEL_ID, channelId)
- }
- }
- }
-}
diff --git a/app/src/main/java/com/example/chattutorial/MessagesActivity2.kt b/app/src/main/java/com/example/chattutorial/MessagesActivity2.kt
deleted file mode 100644
index a28f6db..0000000
--- a/app/src/main/java/com/example/chattutorial/MessagesActivity2.kt
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.example.chattutorial
-
-import android.content.Context
-import android.content.Intent
-import android.os.Bundle
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.ui.graphics.RectangleShape
-import androidx.compose.ui.unit.dp
-import io.getstream.chat.android.compose.ui.messages.MessagesScreen
-import io.getstream.chat.android.compose.ui.theme.ChatTheme
-import io.getstream.chat.android.compose.ui.theme.StreamShapes
-import io.getstream.chat.android.compose.viewmodel.messages.MessagesViewModelFactory
-
-class MessagesActivity2 : ComponentActivity() {
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- // 1 - Load the ID of the selected channel
- val channelId = intent.getStringExtra(KEY_CHANNEL_ID)
-
- if (channelId == null) {
- finish()
- return
- }
-
- // 2 - Add the MessagesScreen to your UI
- setContent {
- ChatTheme(
- shapes = StreamShapes
- .defaultShapes()
- .copy(
- avatar = RoundedCornerShape(8.dp),
- attachment = RoundedCornerShape(16.dp),
- myMessageBubble = RoundedCornerShape(16.dp),
- otherMessageBubble = RoundedCornerShape(16.dp),
- inputField = RectangleShape
- )
- ) {
- MessagesScreen(
- viewModelFactory = MessagesViewModelFactory(
- context = this,
- channelId = channelId,
- messageLimit = 30
- ),
- onBackPressed = { finish() }
- )
- }
- }
- }
-
- // 3 - Create an intent to start this Activity, with a given channelId
- companion object {
- private const val KEY_CHANNEL_ID = "channelId"
-
- fun getIntent(context: Context, channelId: String): Intent {
- return Intent(context, MessagesActivity2::class.java).apply {
- putExtra(KEY_CHANNEL_ID, channelId)
- }
- }
- }
-}
diff --git a/app/src/main/java/com/example/chattutorial/MessagesActivity3.kt b/app/src/main/java/com/example/chattutorial/MessagesActivity3.kt
deleted file mode 100644
index e971768..0000000
--- a/app/src/main/java/com/example/chattutorial/MessagesActivity3.kt
+++ /dev/null
@@ -1,194 +0,0 @@
-package com.example.chattutorial
-
-import android.content.Context
-import android.content.Intent
-import android.os.Bundle
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.activity.viewModels
-import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.wrapContentSize
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material.Scaffold
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.collectAsState
-import androidx.compose.runtime.getValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.RectangleShape
-import androidx.compose.ui.unit.dp
-import io.getstream.chat.android.compose.ui.components.messageoptions.defaultMessageOptionsState
-import io.getstream.chat.android.compose.ui.components.selectedmessage.SelectedMessageMenu
-import io.getstream.chat.android.compose.ui.components.selectedmessage.SelectedReactionsMenu
-import io.getstream.chat.android.compose.ui.messages.attachments.AttachmentsPicker
-import io.getstream.chat.android.compose.ui.messages.composer.MessageComposer
-import io.getstream.chat.android.compose.ui.messages.list.MessageList
-import io.getstream.chat.android.compose.ui.theme.ChatTheme
-import io.getstream.chat.android.compose.ui.theme.StreamShapes
-import io.getstream.chat.android.compose.viewmodel.messages.AttachmentsPickerViewModel
-import io.getstream.chat.android.compose.viewmodel.messages.MessageComposerViewModel
-import io.getstream.chat.android.compose.viewmodel.messages.MessageListViewModel
-import io.getstream.chat.android.compose.viewmodel.messages.MessagesViewModelFactory
-import io.getstream.chat.android.ui.common.state.messages.MessageMode
-import io.getstream.chat.android.ui.common.state.messages.list.SelectedMessageOptionsState
-import io.getstream.chat.android.ui.common.state.messages.list.SelectedMessageReactionsState
-
-class MessagesActivity3 : ComponentActivity() {
-
- // Build the ViewModel factory
- private val factory by lazy {
- MessagesViewModelFactory(
- context = this,
- channelId = intent.getStringExtra(KEY_CHANNEL_ID) ?: "",
- )
- }
-
- // Build the required ViewModels, using the 'factory'
- private val listViewModel: MessageListViewModel by viewModels { factory }
- private val attachmentsPickerViewModel: AttachmentsPickerViewModel by viewModels { factory }
- private val composerViewModel: MessageComposerViewModel by viewModels { factory }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- // 1 - Load the ID of the selected channel
- val channelId = intent.getStringExtra(KEY_CHANNEL_ID)
-
- if (channelId == null) {
- finish()
- return
- }
-
- // 2 - Add the MessagesScreen to your UI
- setContent {
- ChatTheme(
- shapes = StreamShapes
- .defaultShapes()
- .copy(
- avatar = RoundedCornerShape(8.dp),
- attachment = RoundedCornerShape(16.dp),
- myMessageBubble = RoundedCornerShape(16.dp),
- otherMessageBubble = RoundedCornerShape(16.dp),
- inputField = RectangleShape
- )
- ) {
- MyCustomUi()
- }
- }
- }
-
- @Composable
- fun MyCustomUi() {
- // 1 - Load the data
- val isShowingAttachments = attachmentsPickerViewModel.isShowingAttachments
- val selectedMessageState = listViewModel.currentMessagesState.selectedMessageState
- val user by listViewModel.user.collectAsState()
-
- Box(modifier = Modifier.fillMaxSize()) { // 2 - Define the root
- Scaffold(
- modifier = Modifier.fillMaxSize(),
- bottomBar = {
- MessageComposer( // 3 - Add a composer
- composerViewModel,
- onAttachmentsClick = {
- attachmentsPickerViewModel.changeAttachmentState(true)
- }
- )
- }
- ) {
- MessageList( // 4 - Build the MessageList and connect the actions
- modifier = Modifier
- .background(ChatTheme.colors.appBackground)
- .padding(it)
- .fillMaxSize(),
- viewModel = listViewModel,
- onThreadClick = { message ->
- composerViewModel.setMessageMode(MessageMode.MessageThread(message))
- listViewModel.openMessageThread(message)
- }
- )
- }
-
- // 5 - Show attachments when necessary
- if (isShowingAttachments) {
- AttachmentsPicker(
- attachmentsPickerViewModel = attachmentsPickerViewModel,
- modifier = Modifier
- .align(Alignment.BottomCenter)
- .height(350.dp),
- onAttachmentsSelected = { attachments ->
- attachmentsPickerViewModel.changeAttachmentState(false)
- composerViewModel.addSelectedAttachments(attachments)
- },
- onDismiss = {
- attachmentsPickerViewModel.changeAttachmentState(false)
- attachmentsPickerViewModel.dismissAttachments()
- },
- onTabClick = { _, _ -> /* Not needed for this example */ }
- )
- }
-
- // 6 - Show the overlay if we've selected a message
- if (selectedMessageState != null) {
- val selectedMessage = selectedMessageState.message
- if (selectedMessageState is SelectedMessageOptionsState) {
- SelectedMessageMenu(
- modifier = Modifier
- .align(Alignment.Center)
- .padding(horizontal = 20.dp)
- .wrapContentSize(),
- shape = ChatTheme.shapes.attachment,
- messageOptions = defaultMessageOptionsState(
- selectedMessage,
- user,
- selectedMessageState.ownCapabilities
- ),
- message = selectedMessage,
- onMessageAction = { action ->
- composerViewModel.performMessageAction(action)
- listViewModel.performMessageAction(action)
- },
- onShowMoreReactionsSelected = {
- listViewModel.selectExtendedReactions(selectedMessage)
- },
- onDismiss = { listViewModel.removeOverlay() },
- ownCapabilities = selectedMessageState.ownCapabilities
- )
- } else if (selectedMessageState is SelectedMessageReactionsState) {
- SelectedReactionsMenu(
- modifier = Modifier
- .align(Alignment.Center)
- .padding(horizontal = 20.dp)
- .wrapContentSize(),
- shape = ChatTheme.shapes.attachment,
- message = selectedMessage,
- currentUser = user,
- onMessageAction = { action ->
- composerViewModel.performMessageAction(action)
- listViewModel.performMessageAction(action)
- },
- onShowMoreReactionsSelected = {
- listViewModel.selectExtendedReactions(selectedMessage)
- },
- onDismiss = { listViewModel.removeOverlay() },
- ownCapabilities = selectedMessageState.ownCapabilities
- )
- }
- }
- }
- }
-
- // 3 - Create an intent to start this Activity, with a given channelId
- companion object {
- private const val KEY_CHANNEL_ID = "channelId"
-
- fun getIntent(context: Context, channelId: String): Intent {
- return Intent(context, MessagesActivity3::class.java).apply {
- putExtra(KEY_CHANNEL_ID, channelId)
- }
- }
- }
-}
diff --git a/app/src/main/java/com/example/chattutorial/MessagesActivity4.kt b/app/src/main/java/com/example/chattutorial/MessagesActivity4.kt
deleted file mode 100644
index f302067..0000000
--- a/app/src/main/java/com/example/chattutorial/MessagesActivity4.kt
+++ /dev/null
@@ -1,239 +0,0 @@
-package com.example.chattutorial
-
-import android.content.Context
-import android.content.Intent
-import android.os.Bundle
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.activity.viewModels
-import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Row
-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.foundation.layout.wrapContentHeight
-import androidx.compose.foundation.layout.wrapContentSize
-import androidx.compose.foundation.layout.wrapContentWidth
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material.Icon
-import androidx.compose.material.Scaffold
-import androidx.compose.material.Text
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Keyboard
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.collectAsState
-import androidx.compose.runtime.getValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.RectangleShape
-import androidx.compose.ui.unit.dp
-import io.getstream.chat.android.compose.ui.components.composer.MessageInput
-import io.getstream.chat.android.compose.ui.components.messageoptions.defaultMessageOptionsState
-import io.getstream.chat.android.compose.ui.components.selectedmessage.SelectedMessageMenu
-import io.getstream.chat.android.compose.ui.components.selectedmessage.SelectedReactionsMenu
-import io.getstream.chat.android.compose.ui.messages.attachments.AttachmentsPicker
-import io.getstream.chat.android.compose.ui.messages.composer.MessageComposer
-import io.getstream.chat.android.compose.ui.messages.list.MessageList
-import io.getstream.chat.android.compose.ui.theme.ChatTheme
-import io.getstream.chat.android.compose.ui.theme.StreamShapes
-import io.getstream.chat.android.compose.viewmodel.messages.AttachmentsPickerViewModel
-import io.getstream.chat.android.compose.viewmodel.messages.MessageComposerViewModel
-import io.getstream.chat.android.compose.viewmodel.messages.MessageListViewModel
-import io.getstream.chat.android.compose.viewmodel.messages.MessagesViewModelFactory
-import io.getstream.chat.android.ui.common.state.messages.MessageMode
-import io.getstream.chat.android.ui.common.state.messages.list.SelectedMessageOptionsState
-import io.getstream.chat.android.ui.common.state.messages.list.SelectedMessageReactionsState
-
-class MessagesActivity4 : ComponentActivity() {
-
- // Build the ViewModel factory
- private val factory by lazy {
- MessagesViewModelFactory(
- context = this,
- channelId = intent.getStringExtra(KEY_CHANNEL_ID) ?: "",
- )
- }
-
- // Build the required ViewModels, using the 'factory'
- private val listViewModel: MessageListViewModel by viewModels { factory }
- private val attachmentsPickerViewModel: AttachmentsPickerViewModel by viewModels { factory }
- private val composerViewModel: MessageComposerViewModel by viewModels { factory }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- // 1 - Load the ID of the selected channel
- val channelId = intent.getStringExtra(KEY_CHANNEL_ID)
-
- if (channelId == null) {
- finish()
- return
- }
-
- // 2 - Add the MessagesScreen to your UI
- setContent {
- ChatTheme(
- shapes = StreamShapes
- .defaultShapes()
- .copy(
- avatar = RoundedCornerShape(8.dp),
- attachment = RoundedCornerShape(16.dp),
- myMessageBubble = RoundedCornerShape(16.dp),
- otherMessageBubble = RoundedCornerShape(16.dp),
- inputField = RectangleShape
- )
- ) {
- MyCustomUi()
- }
- }
- }
-
- @Composable
- fun MyCustomUi() {
- // 1 - Load the data
- val isShowingAttachments = attachmentsPickerViewModel.isShowingAttachments
- val selectedMessageState = listViewModel.currentMessagesState.selectedMessageState
- val user by listViewModel.user.collectAsState()
-
- Box(modifier = Modifier.fillMaxSize()) { // 2 - Define the root
- Scaffold(
- modifier = Modifier.fillMaxSize(),
- bottomBar = {
- MyCustomComposer() // <--
- }
- ) {
- MessageList( // 4 - Build the MessageList and connect the actions
- modifier = Modifier
- .background(ChatTheme.colors.appBackground)
- .padding(it)
- .fillMaxSize(),
- viewModel = listViewModel,
- onThreadClick = { message ->
- composerViewModel.setMessageMode(MessageMode.MessageThread(message))
- listViewModel.openMessageThread(message)
- }
- )
- }
-
- // 5 - Show attachments when necessary
- if (isShowingAttachments) {
- AttachmentsPicker(
- attachmentsPickerViewModel = attachmentsPickerViewModel,
- modifier = Modifier
- .align(Alignment.BottomCenter)
- .height(350.dp),
- onAttachmentsSelected = { attachments ->
- attachmentsPickerViewModel.changeAttachmentState(false)
- composerViewModel.addSelectedAttachments(attachments)
- },
- onDismiss = {
- attachmentsPickerViewModel.changeAttachmentState(false)
- attachmentsPickerViewModel.dismissAttachments()
- },
- onTabClick = { _, _ -> /* Not needed for this example */ }
- )
- }
-
- // 6 - Show the overlay if we've selected a message
- if (selectedMessageState != null) {
- val selectedMessage = selectedMessageState.message
- if (selectedMessageState is SelectedMessageOptionsState) {
- SelectedMessageMenu(
- modifier = Modifier
- .align(Alignment.Center)
- .padding(horizontal = 20.dp)
- .wrapContentSize(),
- shape = ChatTheme.shapes.attachment,
- messageOptions = defaultMessageOptionsState(
- selectedMessage,
- user,
- selectedMessageState.ownCapabilities
- ),
- message = selectedMessage,
- onMessageAction = { action ->
- composerViewModel.performMessageAction(action)
- listViewModel.performMessageAction(action)
- },
- onShowMoreReactionsSelected = {
- listViewModel.selectExtendedReactions(selectedMessage)
- },
- onDismiss = { listViewModel.removeOverlay() },
- ownCapabilities = selectedMessageState.ownCapabilities
- )
- } else if (selectedMessageState is SelectedMessageReactionsState) {
- SelectedReactionsMenu(
- modifier = Modifier
- .align(Alignment.Center)
- .padding(horizontal = 20.dp)
- .wrapContentSize(),
- shape = ChatTheme.shapes.attachment,
- message = selectedMessage,
- currentUser = user,
- onMessageAction = { action ->
- composerViewModel.performMessageAction(action)
- listViewModel.performMessageAction(action)
- },
- onShowMoreReactionsSelected = {
- listViewModel.selectExtendedReactions(selectedMessage)
- },
- onDismiss = { listViewModel.removeOverlay() },
- ownCapabilities = selectedMessageState.ownCapabilities
- )
- }
- }
- }
- }
-
- @Composable
- fun MyCustomComposer() {
- MessageComposer( // 1 - Use our MessageComposer as the base component
- modifier = Modifier
- .fillMaxWidth()
- .wrapContentHeight(),
- viewModel = composerViewModel,
- integrations = {}, // 2 - Remove integrations from the composer
- input = { inputState ->// 3 - Add a custom message input
- MessageInput(
- modifier = Modifier
- .fillMaxWidth()
- .weight(7f)
- .padding(start = 8.dp)
- .align(Alignment.CenterVertically),
- messageComposerState = inputState,
- onValueChange = { composerViewModel.setMessageInput(it) },
- onAttachmentRemoved = { composerViewModel.removeSelectedAttachment(it) },
- label = { // 4 - Override the label to show a custom icon and a text
- Row(
- Modifier.wrapContentWidth(),
- verticalAlignment = Alignment.CenterVertically
- ) {
- Icon(
- imageVector = Icons.Default.Keyboard,
- contentDescription = null,
- tint = ChatTheme.colors.textLowEmphasis
- )
-
- Text(
- modifier = Modifier.padding(start = 4.dp),
- text = "Type something",
- color = ChatTheme.colors.textLowEmphasis
- )
- }
- }
- )
- }
- )
- }
-
- // 3 - Create an intent to start this Activity, with a given channelId
- companion object {
- private const val KEY_CHANNEL_ID = "channelId"
-
- fun getIntent(context: Context, channelId: String): Intent {
- return Intent(context, MessagesActivity4::class.java).apply {
- putExtra(KEY_CHANNEL_ID, channelId)
- }
- }
- }
-}
diff --git a/app/src/main/java/com/example/chattutorial/ui/theme/Color.kt b/app/src/main/java/com/example/chattutorial/ui/theme/Color.kt
deleted file mode 100644
index 173234a..0000000
--- a/app/src/main/java/com/example/chattutorial/ui/theme/Color.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.example.chattutorial.ui.theme
-
-import androidx.compose.ui.graphics.Color
-
-val Purple200 = Color(0xFFBB86FC)
-val Purple500 = Color(0xFF6200EE)
-val Purple700 = Color(0xFF3700B3)
-val Teal200 = Color(0xFF03DAC5)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/chattutorial/ui/theme/Shape.kt b/app/src/main/java/com/example/chattutorial/ui/theme/Shape.kt
deleted file mode 100644
index 5d7ef3b..0000000
--- a/app/src/main/java/com/example/chattutorial/ui/theme/Shape.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.example.chattutorial.ui.theme
-
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material.Shapes
-import androidx.compose.ui.unit.dp
-
-val Shapes = Shapes(
- small = RoundedCornerShape(4.dp),
- medium = RoundedCornerShape(4.dp),
- large = RoundedCornerShape(0.dp)
-)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/chattutorial/ui/theme/Theme.kt b/app/src/main/java/com/example/chattutorial/ui/theme/Theme.kt
deleted file mode 100644
index 30a9d4c..0000000
--- a/app/src/main/java/com/example/chattutorial/ui/theme/Theme.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.example.chattutorial.ui.theme
-
-import androidx.compose.foundation.isSystemInDarkTheme
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.darkColors
-import androidx.compose.material.lightColors
-import androidx.compose.runtime.Composable
-
-private val DarkColorPalette = darkColors(
- primary = Purple200,
- primaryVariant = Purple700,
- secondary = Teal200
-)
-
-private val LightColorPalette = lightColors(
- primary = Purple500,
- primaryVariant = Purple700,
- secondary = Teal200
-
- /* Other default colors to override
- background = Color.White,
- surface = Color.White,
- onPrimary = Color.White,
- onSecondary = Color.Black,
- onBackground = Color.Black,
- onSurface = Color.Black,
- */
-)
-
-@Composable
-fun ChatTutorialTheme(
- darkTheme: Boolean = isSystemInDarkTheme(),
- content: @Composable() () -> Unit
-) {
- val colors = if (darkTheme) {
- DarkColorPalette
- } else {
- LightColorPalette
- }
-
- MaterialTheme(
- colors = colors,
- typography = Typography,
- shapes = Shapes,
- content = content
- )
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/chattutorial/ui/theme/Type.kt b/app/src/main/java/com/example/chattutorial/ui/theme/Type.kt
deleted file mode 100644
index 7eb9a22..0000000
--- a/app/src/main/java/com/example/chattutorial/ui/theme/Type.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.example.chattutorial.ui.theme
-
-import androidx.compose.material.Typography
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.font.FontFamily
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.unit.sp
-
-// Set of Material typography styles to start with
-val Typography = Typography(
- body1 = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Normal,
- fontSize = 16.sp
- )
- /* Other default text styles to override
- button = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.W500,
- fontSize = 14.sp
- ),
- caption = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Normal,
- fontSize = 12.sp
- )
- */
-)
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index ace9a6b..e7cd049 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,9 +4,9 @@ buildscript {
mavenCentral()
}
dependencies {
- classpath "com.android.tools.build:gradle:8.8.2"
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.21"
- classpath "org.jetbrains.kotlin:compose-compiler-gradle-plugin:2.0.21"
+ classpath "com.android.tools.build:gradle:8.10.1"
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:2.2.0"
+ classpath "org.jetbrains.kotlin:compose-compiler-gradle-plugin:2.2.0"
}
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index fbf6762..6591053 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
#Fri Sep 15 12:53:53 KST 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists