Make translatable
Much to translate huh Also added snackbar
This commit is contained in:
parent
597fecd908
commit
109fe8898c
5 changed files with 41 additions and 20 deletions
|
|
@ -30,17 +30,24 @@ android {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_11
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
targetCompatibility = JavaVersion.VERSION_11
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "11"
|
jvmTarget = "11"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
compose = true
|
compose = true
|
||||||
buildConfig = true
|
buildConfig = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
androidResources {
|
||||||
|
generateLocaleConfig = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.chat.ChatActivity"
|
android:name=".activity.chat.ChatActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/title_activity_chat"
|
|
||||||
android:theme="@style/Theme.ChatApp"
|
android:theme="@style/Theme.ChatApp"
|
||||||
android:windowSoftInputMode="adjustNothing">
|
android:windowSoftInputMode="adjustNothing">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|
@ -30,7 +29,6 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.select.SelectModelActivity"
|
android:name=".activity.select.SelectModelActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/title_activity_chat"
|
|
||||||
android:theme="@style/Theme.ChatApp" />
|
android:theme="@style/Theme.ChatApp" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,9 @@ import androidx.compose.material3.IconButtonDefaults
|
||||||
import androidx.compose.material3.LocalTextStyle
|
import androidx.compose.material3.LocalTextStyle
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.SnackbarHost
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
|
import androidx.compose.material3.SnackbarResult
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
|
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
|
||||||
import androidx.compose.material3.windowsizeclass.WindowSizeClass
|
import androidx.compose.material3.windowsizeclass.WindowSizeClass
|
||||||
|
|
@ -59,9 +61,11 @@ import androidx.compose.ui.focus.focusRequester
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import eu.m724.chatapp.R
|
||||||
import eu.m724.chatapp.activity.chat.ChatState.Companion.rememberChatState
|
import eu.m724.chatapp.activity.chat.ChatState.Companion.rememberChatState
|
||||||
import eu.m724.chatapp.activity.chat.composable.AnimatedChangingText
|
import eu.m724.chatapp.activity.chat.composable.AnimatedChangingText
|
||||||
import eu.m724.chatapp.activity.chat.composable.LanguageModelMistakeWarning
|
import eu.m724.chatapp.activity.chat.composable.LanguageModelMistakeWarning
|
||||||
|
|
@ -92,6 +96,7 @@ class ChatActivity : ComponentActivity() {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
val chatState = rememberChatState()
|
val chatState = rememberChatState()
|
||||||
val threadViewLazyListState = rememberLazyListState()
|
val threadViewLazyListState = rememberLazyListState()
|
||||||
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
|
|
||||||
val onSend = {
|
val onSend = {
|
||||||
if (chatState.composerValue.isNotBlank() && !uiState.requestInProgress) {
|
if (chatState.composerValue.isNotBlank() && !uiState.requestInProgress) {
|
||||||
|
|
@ -104,6 +109,7 @@ class ChatActivity : ComponentActivity() {
|
||||||
uiState = uiState,
|
uiState = uiState,
|
||||||
chatState = chatState,
|
chatState = chatState,
|
||||||
threadViewLazyListState = threadViewLazyListState,
|
threadViewLazyListState = threadViewLazyListState,
|
||||||
|
snackbarHostState = snackbarHostState,
|
||||||
onSend = onSend,
|
onSend = onSend,
|
||||||
onRequestFocus = {
|
onRequestFocus = {
|
||||||
if (uiState.requestInProgress) return@ChatScreen
|
if (uiState.requestInProgress) return@ChatScreen
|
||||||
|
|
@ -128,9 +134,11 @@ class ChatActivity : ComponentActivity() {
|
||||||
|
|
||||||
// scroll to the last user message
|
// scroll to the last user message
|
||||||
threadViewLazyListState.animateScrollToItem(uiState.messages.size - 2)
|
threadViewLazyListState.animateScrollToItem(uiState.messages.size - 2)
|
||||||
} else if (uiState.messages.isNotEmpty()) {
|
} else {
|
||||||
// scroll to the last user message too
|
if (uiState.messages.isNotEmpty()) {
|
||||||
threadViewLazyListState.animateScrollToItem(uiState.messages.size - 2)
|
// scroll to the last user message too
|
||||||
|
threadViewLazyListState.animateScrollToItem(uiState.messages.size - 2)
|
||||||
|
}
|
||||||
|
|
||||||
// if the composer is visible (message is short enough), focus on it
|
// if the composer is visible (message is short enough), focus on it
|
||||||
// if the message is long, we let the user read it
|
// if the message is long, we let the user read it
|
||||||
|
|
@ -147,16 +155,12 @@ class ChatActivity : ComponentActivity() {
|
||||||
viewModel.uiEvents.collect { event ->
|
viewModel.uiEvents.collect { event ->
|
||||||
when (event) {
|
when (event) {
|
||||||
is ChatActivityUiEvent.Error -> {
|
is ChatActivityUiEvent.Error -> {
|
||||||
Toast.makeText(context, event.error, Toast.LENGTH_SHORT)
|
// TODO add a smart action, for example check api key if unauthorized etc
|
||||||
.show() // TODO better way of showing this. snackbar?
|
|
||||||
|
|
||||||
// the user might have scrolled so this is good
|
snackbarHostState.showSnackbar(
|
||||||
threadViewLazyListState.layoutInfo.visibleItemsInfo.firstOrNull {
|
message = event.error, // TODO consider a generic message
|
||||||
it.key == "composer"
|
withDismissAction = true
|
||||||
}?.let {
|
)
|
||||||
chatState.requestFocus()
|
|
||||||
softwareKeyboardController?.show() // TODO perhaps it's pointless to focus since we can click on the toolbar? maybe make it configurable
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -171,6 +175,7 @@ fun ChatScreen(
|
||||||
uiState: ChatActivityUiState,
|
uiState: ChatActivityUiState,
|
||||||
chatState: ChatState,
|
chatState: ChatState,
|
||||||
threadViewLazyListState: LazyListState,
|
threadViewLazyListState: LazyListState,
|
||||||
|
snackbarHostState: SnackbarHostState,
|
||||||
onSend: () -> Unit,
|
onSend: () -> Unit,
|
||||||
onRequestFocus: () -> Unit
|
onRequestFocus: () -> Unit
|
||||||
) {
|
) {
|
||||||
|
|
@ -180,7 +185,14 @@ fun ChatScreen(
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
topBar = {
|
topBar = {
|
||||||
ChatTopAppBar(uiState.chatTitle ?: "Start a new conversation")
|
ChatTopAppBar(
|
||||||
|
title = uiState.chatTitle ?: stringResource(R.string.title_new_conversation)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
snackbarHost = {
|
||||||
|
SnackbarHost(
|
||||||
|
hostState = snackbarHostState
|
||||||
|
)
|
||||||
}
|
}
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
ChatScreenContent(
|
ChatScreenContent(
|
||||||
|
|
@ -370,7 +382,9 @@ fun ChatMessageComposer(
|
||||||
value = value,
|
value = value,
|
||||||
onValueChange = onValueChange,
|
onValueChange = onValueChange,
|
||||||
placeholder = {
|
placeholder = {
|
||||||
Text("Type your message...") // TODO hide when just browsing history?
|
Text(
|
||||||
|
text = stringResource(R.string.composer_placeholder_type)
|
||||||
|
) // TODO hide when just browsing history?
|
||||||
},
|
},
|
||||||
padding = PaddingValues(vertical = 10.dp),
|
padding = PaddingValues(vertical = 10.dp),
|
||||||
textStyle = LocalTextStyle.current.copy(
|
textStyle = LocalTextStyle.current.copy(
|
||||||
|
|
@ -417,7 +431,7 @@ fun ChatToolBar(
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.AutoMirrored.Filled.Send,
|
imageVector = Icons.AutoMirrored.Filled.Send,
|
||||||
contentDescription = "Send"
|
contentDescription = stringResource(R.string.button_send_icon_description)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
app/src/main/res/resources.properties
Normal file
1
app/src/main/res/resources.properties
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
unqualifiedResLocale=en-US
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Chat App</string>
|
<string name="app_name">Chat</string>
|
||||||
<string name="title_activity_main">MainActivity</string>
|
<string name="title_new_conversation">Start a new conversation</string>
|
||||||
<string name="title_activity_chat">ChatActivity</string>
|
<string name="button_send_icon_description">Send message</string>
|
||||||
|
<string name="composer_placeholder_type">Type your message…</string>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue