From 04892401d31b5376382ef0fab305423518526ef8 Mon Sep 17 00:00:00 2001 From: hoangchungk53qx1 Date: Sun, 14 Jan 2024 13:13:55 +0700 Subject: [PATCH 01/12] update chat --- .../ai/sample/feature/chat/ChatMessage.kt | 3 +- .../ai/sample/feature/chat/ChatScreen.kt | 28 ++++--- .../ai/sample/feature/chat/ChatUiState.kt | 25 +----- .../ai/sample/feature/chat/ChatViewModel.kt | 80 +++++++++++-------- 4 files changed, 68 insertions(+), 68 deletions(-) diff --git a/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/feature/chat/ChatMessage.kt b/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/feature/chat/ChatMessage.kt index ce76394b..118987c1 100644 --- a/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/feature/chat/ChatMessage.kt +++ b/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/feature/chat/ChatMessage.kt @@ -24,7 +24,6 @@ enum class Participant { data class ChatMessage( val id: String = UUID.randomUUID().toString(), - var text: String = "", + val text: String = "", val participant: Participant = Participant.USER, - var isPending: Boolean = false ) diff --git a/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/feature/chat/ChatScreen.kt b/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/feature/chat/ChatScreen.kt index d18846c3..6a40fe54 100644 --- a/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/feature/chat/ChatScreen.kt +++ b/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/feature/chat/ChatScreen.kt @@ -72,6 +72,7 @@ internal fun ChatRoute( Scaffold( bottomBar = { MessageInput( + isLoading = chatUiState.isLoading, onSendMessage = { inputText -> chatViewModel.sendMessage(inputText) }, @@ -146,13 +147,6 @@ fun ChatBubbleItem( modifier = Modifier.padding(bottom = 4.dp) ) Row { - if (chatMessage.isPending) { - CircularProgressIndicator( - modifier = Modifier - .align(Alignment.CenterVertically) - .padding(all = 8.dp) - ) - } BoxWithConstraints { Card( colors = CardDefaults.cardColors(containerColor = backgroundColor), @@ -171,6 +165,7 @@ fun ChatBubbleItem( @Composable fun MessageInput( + isLoading: Boolean, onSendMessage: (String) -> Unit, resetScroll: () -> Unit = {} ) { @@ -198,6 +193,7 @@ fun MessageInput( .weight(0.85f) ) IconButton( + enabled = !isLoading, onClick = { if (userMessage.isNotBlank()) { onSendMessage(userMessage) @@ -211,11 +207,19 @@ fun MessageInput( .fillMaxWidth() .weight(0.15f) ) { - Icon( - Icons.Default.Send, - contentDescription = stringResource(R.string.action_send), - modifier = Modifier - ) + if (isLoading) { + CircularProgressIndicator( + modifier = Modifier + .align(Alignment.CenterVertically) + .padding(all = 8.dp) + ) + } else { + Icon( + Icons.Default.Send, + contentDescription = stringResource(R.string.action_send), + modifier = Modifier + ) + } } } } diff --git a/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/feature/chat/ChatUiState.kt b/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/feature/chat/ChatUiState.kt index 48dea90e..fccc8c08 100644 --- a/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/feature/chat/ChatUiState.kt +++ b/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/feature/chat/ChatUiState.kt @@ -16,24 +16,7 @@ package com.google.ai.sample.feature.chat -import androidx.compose.runtime.toMutableStateList - -class ChatUiState( - messages: List = emptyList() -) { - private val _messages: MutableList = messages.toMutableStateList() - val messages: List = _messages - - fun addMessage(msg: ChatMessage) { - _messages.add(msg) - } - - fun replaceLastPendingMessage() { - val lastMessage = _messages.lastOrNull() - lastMessage?.let { - val newMessage = lastMessage.apply { isPending = false } - _messages.removeLast() - _messages.add(newMessage) - } - } -} +data class ChatUiState( + val isLoading : Boolean, + val messages: List +) \ No newline at end of file diff --git a/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/feature/chat/ChatViewModel.kt b/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/feature/chat/ChatViewModel.kt index f102678d..d1c8543b 100644 --- a/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/feature/chat/ChatViewModel.kt +++ b/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/feature/chat/ChatViewModel.kt @@ -21,10 +21,14 @@ import androidx.lifecycle.viewModelScope import com.google.ai.client.generativeai.GenerativeModel import com.google.ai.client.generativeai.type.asTextOrNull import com.google.ai.client.generativeai.type.content +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import kotlin.coroutines.cancellation.CancellationException class ChatViewModel( generativeModel: GenerativeModel @@ -36,52 +40,62 @@ class ChatViewModel( ) ) - private val _uiState: MutableStateFlow = - MutableStateFlow(ChatUiState(chat.history.map { content -> - // Map the initial messages - ChatMessage( - text = content.parts.first().asTextOrNull() ?: "", - participant = if (content.role == "user") Participant.USER else Participant.MODEL, - isPending = false - ) - })) - val uiState: StateFlow = - _uiState.asStateFlow() + private val _uiState: MutableStateFlow = MutableStateFlow( + ChatUiState( + isLoading = false, + messages = initMessage(), + ) + ) + val uiState: StateFlow = _uiState.asStateFlow() + + private fun initMessage(): List = chat.history.map { content -> + // Map the initial messages + ChatMessage( + text = content.parts.first().asTextOrNull() ?: "", + participant = if (content.role == "user") Participant.USER else Participant.MODEL, + ) + } fun sendMessage(userMessage: String) { - // Add a pending message - _uiState.value.addMessage( - ChatMessage( - text = userMessage, - participant = Participant.USER, - isPending = true + // Loading state, update user message + _uiState.update { currentState -> + currentState.copy( + isLoading = true, + messages = currentState.messages + ChatMessage( + text = userMessage, + participant = Participant.USER, + ) ) - ) + } viewModelScope.launch { try { - val response = chat.sendMessage(userMessage) - - _uiState.value.replaceLastPendingMessage() - - response.text?.let { modelResponse -> - _uiState.value.addMessage( - ChatMessage( + val response = withContext(Dispatchers.IO) { + chat.sendMessage(userMessage) + } + val modelResponse = response.text ?: return@launch + _uiState.update { + it.copy( + isLoading = false, + messages = it.messages + ChatMessage( text = modelResponse, participant = Participant.MODEL, - isPending = false ) ) } - } catch (e: Exception) { - _uiState.value.replaceLastPendingMessage() - _uiState.value.addMessage( - ChatMessage( - text = e.localizedMessage, - participant = Participant.ERROR + } catch (cancel: CancellationException) { + throw cancel + } catch (throwable: Throwable) { + _uiState.update { + it.copy( + isLoading = false, + messages = it.messages + ChatMessage( + text = throwable.localizedMessage ?: "Error", + participant = Participant.ERROR, + ) ) - ) + } } } } From f1b6acbf46d82dc090a8f71530d28efa1ed27b44 Mon Sep 17 00:00:00 2001 From: hoangchungk53qx1 Date: Sun, 14 Jan 2024 13:16:45 +0700 Subject: [PATCH 02/12] update deps --- generativeai-android-sample/app/build.gradle.kts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/generativeai-android-sample/app/build.gradle.kts b/generativeai-android-sample/app/build.gradle.kts index 93190d89..b68d18d6 100644 --- a/generativeai-android-sample/app/build.gradle.kts +++ b/generativeai-android-sample/app/build.gradle.kts @@ -53,11 +53,11 @@ android { } dependencies { - implementation("androidx.core:core-ktx:1.9.0") - implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") - implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2") - implementation("androidx.activity:activity-compose:1.8.1") - implementation("androidx.navigation:navigation-compose:2.7.5") + implementation("androidx.core:core-ktx:1.12.0") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0") + implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0") + implementation("androidx.activity:activity-compose:1.8.2") + implementation("androidx.navigation:navigation-compose:2.7.6") implementation(platform("androidx.compose:compose-bom:2023.10.01")) implementation("androidx.compose.ui:ui") From a7a3d8ce68719845f0669f83209f7b3680a45ffc Mon Sep 17 00:00:00 2001 From: hoangchungk53qx1 Date: Sun, 14 Jan 2024 13:17:43 +0700 Subject: [PATCH 03/12] rename param match overriding method --- .../com/google/ai/sample/GenerativeAiViewModelFactory.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/GenerativeAiViewModelFactory.kt b/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/GenerativeAiViewModelFactory.kt index 007606bc..3314d859 100644 --- a/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/GenerativeAiViewModelFactory.kt +++ b/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/GenerativeAiViewModelFactory.kt @@ -27,14 +27,14 @@ import com.google.ai.sample.feature.text.SummarizeViewModel val GenerativeViewModelFactory = object : ViewModelProvider.Factory { override fun create( - viewModelClass: Class, + modelClass: Class, extras: CreationExtras ): T { val config = generationConfig { temperature = 0.7f } - return with(viewModelClass) { + return with(modelClass) { when { isAssignableFrom(SummarizeViewModel::class.java) -> { // Initialize a GenerativeModel with the `gemini-pro` AI model @@ -69,7 +69,7 @@ val GenerativeViewModelFactory = object : ViewModelProvider.Factory { } else -> - throw IllegalArgumentException("Unknown ViewModel class: ${viewModelClass.name}") + throw IllegalArgumentException("Unknown ViewModel class: ${modelClass.name}") } } as T } From 28a07a0a1ba8427e4edf2d256cd2131ecbd5ea4d Mon Sep 17 00:00:00 2001 From: hoangchungk53qx1 Date: Sun, 14 Jan 2024 13:36:40 +0700 Subject: [PATCH 04/12] enable ComposeCompilerMetric --- .../app/build.gradle.kts | 21 +++++++++++++++++++ .../ai/sample/GenerativeAiViewModelFactory.kt | 2 ++ 2 files changed, 23 insertions(+) diff --git a/generativeai-android-sample/app/build.gradle.kts b/generativeai-android-sample/app/build.gradle.kts index b68d18d6..d4dc7aed 100644 --- a/generativeai-android-sample/app/build.gradle.kts +++ b/generativeai-android-sample/app/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + /* * Copyright 2023 Google LLC * @@ -50,6 +52,25 @@ android { composeOptions { kotlinCompilerExtensionVersion = "1.5.4" } + afterEvaluate { + val projectPath = rootProject.file(".").absolutePath + tasks.withType { + kotlinOptions { + freeCompilerArgs = freeCompilerArgs + listOf( + "-opt-in=kotlin.OptIn", + "-opt-in=kotlin.RequiresOptIn", + ) + freeCompilerArgs = freeCompilerArgs + listOf( + "-P", + "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=$projectPath/report/compose-metrics", + ) + freeCompilerArgs = freeCompilerArgs + listOf( + "-P", + "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=$projectPath/report/compose-reports", + ) + } + } + } } dependencies { diff --git a/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/GenerativeAiViewModelFactory.kt b/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/GenerativeAiViewModelFactory.kt index 3314d859..88f92207 100644 --- a/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/GenerativeAiViewModelFactory.kt +++ b/generativeai-android-sample/app/src/main/kotlin/com/google/ai/sample/GenerativeAiViewModelFactory.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:Suppress("UNCHECKED_CAST") + package com.google.ai.sample import androidx.lifecycle.ViewModel From 1cf1870c01619d21777d51f8dc304b7cd303f432 Mon Sep 17 00:00:00 2001 From: hoangchungk53qx1 Date: Sun, 14 Jan 2024 23:29:38 +0700 Subject: [PATCH 05/12] update input mode --- generativeai-android-sample/app/src/main/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generativeai-android-sample/app/src/main/AndroidManifest.xml b/generativeai-android-sample/app/src/main/AndroidManifest.xml index 0d795b20..0e5414a8 100644 --- a/generativeai-android-sample/app/src/main/AndroidManifest.xml +++ b/generativeai-android-sample/app/src/main/AndroidManifest.xml @@ -28,7 +28,7 @@ + android:windowSoftInputMode="adjustResize"> From d8ab47f23ef641e6203216a5c0c3eb1b0a722d72 Mon Sep 17 00:00:00 2001 From: hoangchung <52132635+hoangchungk53qx1@users.noreply.github.com> Date: Wed, 31 Jan 2024 15:18:46 +0700 Subject: [PATCH 06/12] Update build_release.yml --- .github/workflows/build_release.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_release.yml b/.github/workflows/build_release.yml index 1d3a3170..e791ff1d 100644 --- a/.github/workflows/build_release.yml +++ b/.github/workflows/build_release.yml @@ -20,8 +20,8 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '17' @@ -29,7 +29,7 @@ jobs: - name: Perform a Gradle build run: ./gradlew generativeai:publishAllPublicationsToMavenRepository - name: Upload generated artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: generative-ai-android path: generativeai/m2 From 781855a825121fa7bbe90ad4b7c699e8759dff9c Mon Sep 17 00:00:00 2001 From: hoangchung <52132635+hoangchungk53qx1@users.noreply.github.com> Date: Wed, 31 Jan 2024 15:19:03 +0700 Subject: [PATCH 07/12] Update check-code-format.yml --- .github/workflows/check-code-format.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-code-format.yml b/.github/workflows/check-code-format.yml index c96607eb..906f3265 100644 --- a/.github/workflows/check-code-format.yml +++ b/.github/workflows/check-code-format.yml @@ -7,9 +7,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout branch - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4 - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: 17 distribution: temurin From 63574000f17698280ae61bd636dd0fa3d7511f40 Mon Sep 17 00:00:00 2001 From: hoangchung <52132635+hoangchungk53qx1@users.noreply.github.com> Date: Wed, 31 Jan 2024 15:19:18 +0700 Subject: [PATCH 08/12] Update check-licensing.yml --- .github/workflows/check-licensing.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-licensing.yml b/.github/workflows/check-licensing.yml index 19f2c270..d1e3e555 100644 --- a/.github/workflows/check-licensing.yml +++ b/.github/workflows/check-licensing.yml @@ -7,9 +7,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout branch - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4 - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: 17 distribution: temurin From 3fa89cb38a2c11f744bd9df032d0450a4834595d Mon Sep 17 00:00:00 2001 From: hoangchung <52132635+hoangchungk53qx1@users.noreply.github.com> Date: Wed, 31 Jan 2024 15:19:46 +0700 Subject: [PATCH 09/12] Update check_for_api_changes.yml --- .github/workflows/check_for_api_changes.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check_for_api_changes.yml b/.github/workflows/check_for_api_changes.yml index d27fd2d9..79ce803e 100644 --- a/.github/workflows/check_for_api_changes.yml +++ b/.github/workflows/check_for_api_changes.yml @@ -7,12 +7,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout master - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4 with: ref: ${{ github.base_ref }} - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: 17 distribution: temurin @@ -26,10 +26,10 @@ jobs: run: mv generativeai/public.api ~/public.api - name: Checkout branch - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4 - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: 17 distribution: temurin From d62cb0fcf3100b846f46423459713c9bee4604ff Mon Sep 17 00:00:00 2001 From: hoangchung <52132635+hoangchungk53qx1@users.noreply.github.com> Date: Wed, 31 Jan 2024 15:20:04 +0700 Subject: [PATCH 10/12] Update generate_docs.yml --- .github/workflows/generate_docs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/generate_docs.yml b/.github/workflows/generate_docs.yml index a5525910..efec4c4c 100644 --- a/.github/workflows/generate_docs.yml +++ b/.github/workflows/generate_docs.yml @@ -20,8 +20,8 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '17' From 6eb273128dd68ec35b67fe917a42b16621cbb059 Mon Sep 17 00:00:00 2001 From: hoangchung <52132635+hoangchungk53qx1@users.noreply.github.com> Date: Wed, 31 Jan 2024 15:20:17 +0700 Subject: [PATCH 11/12] Update generate_docs.yml --- .github/workflows/generate_docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/generate_docs.yml b/.github/workflows/generate_docs.yml index efec4c4c..2bda60d0 100644 --- a/.github/workflows/generate_docs.yml +++ b/.github/workflows/generate_docs.yml @@ -29,7 +29,7 @@ jobs: - name: Run dokka run: ./gradlew generativeai:dokkaHtml - name: Upload generated docs - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: google-ai-android path: generativeai/build/dokka/html From a5ba0422a16d9fe54a20bcae0f215a5137bd04a6 Mon Sep 17 00:00:00 2001 From: hoangchung <52132635+hoangchungk53qx1@users.noreply.github.com> Date: Wed, 31 Jan 2024 15:20:30 +0700 Subject: [PATCH 12/12] Update unit-tests.yml --- .github/workflows/unit-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 2ddafab8..f20f3f7e 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -7,9 +7,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout branch - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4 - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: 17 distribution: temurin