Make translatable

Much to translate huh
Also added snackbar
This commit is contained in:
Minecon724 2025-06-21 20:15:51 +02:00
commit 109fe8898c
Signed by untrusted user who does not match committer: m724
GPG key ID: A02E6E67AB961189
5 changed files with 41 additions and 20 deletions

View file

@ -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 {

View file

@ -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>

View file

@ -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)
) )
} }
} }

View file

@ -0,0 +1 @@
unqualifiedResLocale=en-US

View file

@ -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>