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: Minecon724
GPG key ID: A02E6E67AB961189
5 changed files with 41 additions and 20 deletions

View file

@ -30,17 +30,24 @@ android {
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
buildFeatures {
compose = true
buildConfig = true
}
androidResources {
generateLocaleConfig = true
}
}
dependencies {

View file

@ -18,7 +18,6 @@
<activity
android:name=".activity.chat.ChatActivity"
android:exported="true"
android:label="@string/title_activity_chat"
android:theme="@style/Theme.ChatApp"
android:windowSoftInputMode="adjustNothing">
<intent-filter>
@ -30,7 +29,6 @@
<activity
android:name=".activity.select.SelectModelActivity"
android:exported="true"
android:label="@string/title_activity_chat"
android:theme="@style/Theme.ChatApp" />
</application>

View file

@ -39,7 +39,9 @@ import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarResult
import androidx.compose.material3.Text
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
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.platform.LocalContext
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
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.composable.AnimatedChangingText
import eu.m724.chatapp.activity.chat.composable.LanguageModelMistakeWarning
@ -92,6 +96,7 @@ class ChatActivity : ComponentActivity() {
val coroutineScope = rememberCoroutineScope()
val chatState = rememberChatState()
val threadViewLazyListState = rememberLazyListState()
val snackbarHostState = remember { SnackbarHostState() }
val onSend = {
if (chatState.composerValue.isNotBlank() && !uiState.requestInProgress) {
@ -104,6 +109,7 @@ class ChatActivity : ComponentActivity() {
uiState = uiState,
chatState = chatState,
threadViewLazyListState = threadViewLazyListState,
snackbarHostState = snackbarHostState,
onSend = onSend,
onRequestFocus = {
if (uiState.requestInProgress) return@ChatScreen
@ -128,9 +134,11 @@ class ChatActivity : ComponentActivity() {
// scroll to the last user message
threadViewLazyListState.animateScrollToItem(uiState.messages.size - 2)
} else if (uiState.messages.isNotEmpty()) {
// scroll to the last user message too
threadViewLazyListState.animateScrollToItem(uiState.messages.size - 2)
} else {
if (uiState.messages.isNotEmpty()) {
// 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 message is long, we let the user read it
@ -147,16 +155,12 @@ class ChatActivity : ComponentActivity() {
viewModel.uiEvents.collect { event ->
when (event) {
is ChatActivityUiEvent.Error -> {
Toast.makeText(context, event.error, Toast.LENGTH_SHORT)
.show() // TODO better way of showing this. snackbar?
// TODO add a smart action, for example check api key if unauthorized etc
// the user might have scrolled so this is good
threadViewLazyListState.layoutInfo.visibleItemsInfo.firstOrNull {
it.key == "composer"
}?.let {
chatState.requestFocus()
softwareKeyboardController?.show() // TODO perhaps it's pointless to focus since we can click on the toolbar? maybe make it configurable
}
snackbarHostState.showSnackbar(
message = event.error, // TODO consider a generic message
withDismissAction = true
)
}
}
}
@ -171,6 +175,7 @@ fun ChatScreen(
uiState: ChatActivityUiState,
chatState: ChatState,
threadViewLazyListState: LazyListState,
snackbarHostState: SnackbarHostState,
onSend: () -> Unit,
onRequestFocus: () -> Unit
) {
@ -180,7 +185,14 @@ fun ChatScreen(
Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = {
ChatTopAppBar(uiState.chatTitle ?: "Start a new conversation")
ChatTopAppBar(
title = uiState.chatTitle ?: stringResource(R.string.title_new_conversation)
)
},
snackbarHost = {
SnackbarHost(
hostState = snackbarHostState
)
}
) { innerPadding ->
ChatScreenContent(
@ -370,7 +382,9 @@ fun ChatMessageComposer(
value = value,
onValueChange = onValueChange,
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),
textStyle = LocalTextStyle.current.copy(
@ -417,7 +431,7 @@ fun ChatToolBar(
) {
Icon(
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>
<string name="app_name">Chat App</string>
<string name="title_activity_main">MainActivity</string>
<string name="title_activity_chat">ChatActivity</string>
<string name="app_name">Chat</string>
<string name="title_new_conversation">Start a new conversation</string>
<string name="button_send_icon_description">Send message</string>
<string name="composer_placeholder_type">Type your message…</string>
</resources>