Compare commits

..

2 Commits

8 changed files with 198 additions and 122 deletions

View File

@@ -126,6 +126,7 @@ dependencies {
implementation(libs.androidx.room.runtime) // ADDED: Explicitly add runtime implementation(libs.androidx.room.runtime) // ADDED: Explicitly add runtime
implementation(libs.androidx.room.ktx) implementation(libs.androidx.room.ktx)
implementation(libs.core.ktx) implementation(libs.core.ktx)
implementation(libs.androidx.compose.runtime)
ksp(libs.room.compiler) ksp(libs.room.compiler)
// Networking // Networking

View File

@@ -154,8 +154,22 @@ fun AppNavHost(
NewWordReviewScreen(navController = navController) NewWordReviewScreen(navController = navController)
} }
composable(NavigationRoutes.START_EXERCISE) { composable(
StartExerciseScreen(navController = navController) route = "${NavigationRoutes.START_EXERCISE}?categoryId={categoryId}",
arguments = listOf(
navArgument("categoryId") {
type = NavType.StringType
nullable = true
defaultValue = null
}
)
) { backStackEntry ->
val categoryIdString = backStackEntry.arguments?.getString("categoryId")
val categoryId = categoryIdString?.toIntOrNull()
StartExerciseScreen(
navController = navController,
preselectedCategoryId = categoryId
)
} }
// Define all other navigation graphs at the same top level. // Define all other navigation graphs at the same top level.

View File

@@ -35,6 +35,7 @@ import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableIntStateOf
@@ -56,7 +57,6 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import eu.gaudian.translator.R import eu.gaudian.translator.R
import eu.gaudian.translator.model.Language import eu.gaudian.translator.model.Language
import eu.gaudian.translator.model.TagCategory
import eu.gaudian.translator.model.VocabularyCategory import eu.gaudian.translator.model.VocabularyCategory
import eu.gaudian.translator.model.VocabularyStage import eu.gaudian.translator.model.VocabularyStage
import eu.gaudian.translator.utils.findActivity import eu.gaudian.translator.utils.findActivity
@@ -76,17 +76,30 @@ import kotlinx.coroutines.launch
@Composable @Composable
fun StartExerciseScreen( fun StartExerciseScreen(
navController: NavHostController, navController: NavHostController,
preselectedCategoryId: Int? = null,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
val activity = androidx.compose.ui.platform.LocalContext.current.findActivity() val activity = androidx.compose.ui.platform.LocalContext.current.findActivity()
val vocabularyViewModel: VocabularyViewModel = hiltViewModel(viewModelStoreOwner = activity) val vocabularyViewModel: VocabularyViewModel = hiltViewModel(viewModelStoreOwner = activity)
val categoryViewModel: CategoryViewModel = hiltViewModel(viewModelStoreOwner = activity)
val exerciseViewModel: VocabularyExerciseViewModel = hiltViewModel(viewModelStoreOwner = activity) val exerciseViewModel: VocabularyExerciseViewModel = hiltViewModel(viewModelStoreOwner = activity)
val exerciseConfig by exerciseViewModel.pendingExerciseConfig.collectAsState() val exerciseConfig by exerciseViewModel.pendingExerciseConfig.collectAsState()
val allCategories by categoryViewModel.categories.collectAsState(initial = emptyList())
var selectedLanguagePairs by remember { mutableStateOf<List<Pair<Language, Language>>>(emptyList()) } var selectedLanguagePairs by remember { mutableStateOf<List<Pair<Language, Language>>>(emptyList()) }
var selectedCategories by remember { mutableStateOf<List<VocabularyCategory>>(emptyList()) } var selectedCategories by remember { mutableStateOf<List<VocabularyCategory>>(emptyList()) }
var selectedStages by remember { mutableStateOf<List<VocabularyStage>>(emptyList()) } var selectedStages by remember { mutableStateOf<List<VocabularyStage>>(emptyList()) }
// Initialize preselected category
LaunchedEffect(allCategories, preselectedCategoryId) {
if (preselectedCategoryId != null) {
val category = allCategories.find { it.id == preselectedCategoryId }
if (category != null && category !in selectedCategories) {
selectedCategories = listOf(category)
}
}
}
var selectedOriginLanguage by remember { mutableStateOf<Language?>(null) } var selectedOriginLanguage by remember { mutableStateOf<Language?>(null) }
var selectedTargetLanguage by remember { mutableStateOf<Language?>(null) } var selectedTargetLanguage by remember { mutableStateOf<Language?>(null) }
val isDirectionPreferenceSet = selectedOriginLanguage != null || selectedTargetLanguage != null val isDirectionPreferenceSet = selectedOriginLanguage != null || selectedTargetLanguage != null
@@ -143,6 +156,13 @@ fun StartExerciseScreen(
.widthIn(max = 700.dp) // Keeps it from over-stretching on tablets .widthIn(max = 700.dp) // Keeps it from over-stretching on tablets
.fillMaxSize() .fillMaxSize()
) { ) {
val languageViewModel: LanguageViewModel = hiltViewModel(viewModelStoreOwner = activity)
val allLanguages by languageViewModel.allLanguages.collectAsState(initial = emptyList())
val availableLanguages = remember(availableLanguagesFromItems, allLanguages) {
allLanguages.filter { it.nameResId in availableLanguagesFromItems }
}
TopBarSection( TopBarSection(
onBackClick = { navController.popBackStack() }, onBackClick = { navController.popBackStack() },
shuffleCards = exerciseConfig.shuffleCards, shuffleCards = exerciseConfig.shuffleCards,
@@ -152,6 +172,36 @@ fun StartExerciseScreen(
shuffleLanguagesEnabled = !isDirectionPreferenceSet, shuffleLanguagesEnabled = !isDirectionPreferenceSet,
trainingMode = exerciseConfig.trainingMode, trainingMode = exerciseConfig.trainingMode,
onTrainingModeChanged = { updateConfig(exerciseConfig.copy(trainingMode = it)) }, onTrainingModeChanged = { updateConfig(exerciseConfig.copy(trainingMode = it)) },
selectedOriginLanguage = selectedOriginLanguage,
selectedTargetLanguage = selectedTargetLanguage,
languageSelectionEnabled = true,
availableLanguages = availableLanguages,
onOriginLanguageSelected = { language ->
if (language?.nameResId == selectedOriginLanguage?.nameResId) {
selectedOriginLanguage = null
updateConfig(exerciseConfig.copy(originLanguageId = null))
} else {
selectedOriginLanguage = language
if (selectedTargetLanguage?.nameResId == language?.nameResId) {
selectedTargetLanguage = null
updateConfig(exerciseConfig.copy(targetLanguageId = null))
}
updateConfig(exerciseConfig.copy(originLanguageId = language?.nameResId))
}
},
onTargetLanguageSelected = { language ->
if (language?.nameResId == selectedTargetLanguage?.nameResId) {
selectedTargetLanguage = null
updateConfig(exerciseConfig.copy(targetLanguageId = null))
} else {
selectedTargetLanguage = language
if (selectedOriginLanguage?.nameResId == language?.nameResId) {
selectedOriginLanguage = null
updateConfig(exerciseConfig.copy(originLanguageId = null))
}
updateConfig(exerciseConfig.copy(targetLanguageId = language?.nameResId))
}
}
) )
LazyColumn( LazyColumn(
@@ -176,36 +226,7 @@ fun StartExerciseScreen(
updateConfig(exerciseConfig.copy(originLanguageId = null, targetLanguageId = null)) updateConfig(exerciseConfig.copy(originLanguageId = null, targetLanguageId = null))
} }
}, },
onOriginLanguageSelected = { language -> selectedPairsCount = selectedLanguagePairs.size
if (language?.nameResId == selectedOriginLanguage?.nameResId) {
selectedOriginLanguage = null
updateConfig(exerciseConfig.copy(originLanguageId = null))
} else {
selectedOriginLanguage = language
if (selectedTargetLanguage?.nameResId == language?.nameResId) {
selectedTargetLanguage = null
updateConfig(exerciseConfig.copy(targetLanguageId = null))
}
updateConfig(exerciseConfig.copy(originLanguageId = language?.nameResId))
}
},
onTargetLanguageSelected = { language ->
if (language?.nameResId == selectedTargetLanguage?.nameResId) {
selectedTargetLanguage = null
updateConfig(exerciseConfig.copy(targetLanguageId = null))
} else {
selectedTargetLanguage = language
if (selectedOriginLanguage?.nameResId == language?.nameResId) {
selectedOriginLanguage = null
updateConfig(exerciseConfig.copy(originLanguageId = null))
}
updateConfig(exerciseConfig.copy(targetLanguageId = language?.nameResId))
}
},
languageSelectionEnabled = true,
selectedPairsCount = selectedLanguagePairs.size,
selectedOriginLanguage = selectedOriginLanguage,
selectedTargetLanguage = selectedTargetLanguage
) )
} }
item { item {
@@ -284,7 +305,13 @@ fun TopBarSection(
onShuffleLanguagesChanged: (Boolean) -> Unit, onShuffleLanguagesChanged: (Boolean) -> Unit,
shuffleLanguagesEnabled: Boolean, shuffleLanguagesEnabled: Boolean,
trainingMode: Boolean, trainingMode: Boolean,
onTrainingModeChanged: (Boolean) -> Unit onTrainingModeChanged: (Boolean) -> Unit,
selectedOriginLanguage: Language?,
selectedTargetLanguage: Language?,
languageSelectionEnabled: Boolean,
availableLanguages: List<Language>,
onOriginLanguageSelected: (Language?) -> Unit,
onTargetLanguageSelected: (Language?) -> Unit
) { ) {
var showSettings by remember { mutableStateOf(false) } var showSettings by remember { mutableStateOf(false) }
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
@@ -343,6 +370,12 @@ fun TopBarSection(
shuffleLanguagesEnabled = shuffleLanguagesEnabled, shuffleLanguagesEnabled = shuffleLanguagesEnabled,
trainingMode = trainingMode, trainingMode = trainingMode,
onTrainingModeChanged = onTrainingModeChanged, onTrainingModeChanged = onTrainingModeChanged,
selectedOriginLanguage = selectedOriginLanguage,
selectedTargetLanguage = selectedTargetLanguage,
languageSelectionEnabled = languageSelectionEnabled,
availableLanguages = availableLanguages,
onOriginLanguageSelected = onOriginLanguageSelected,
onTargetLanguageSelected = onTargetLanguageSelected,
onDismiss = { onDismiss = {
scope.launch { sheetState.hide() }.invokeOnCompletion { scope.launch { sheetState.hide() }.invokeOnCompletion {
if (!sheetState.isVisible) { if (!sheetState.isVisible) {
@@ -388,12 +421,7 @@ fun LanguagePairSection(
selectedPairs: List<Pair<Language, Language>>, selectedPairs: List<Pair<Language, Language>>,
availableLanguageIds: Set<Int>, availableLanguageIds: Set<Int>,
onPairsChanged: (List<Pair<Language, Language>>) -> Unit, onPairsChanged: (List<Pair<Language, Language>>) -> Unit,
onOriginLanguageSelected: (Language?) -> Unit, selectedPairsCount: Int
onTargetLanguageSelected: (Language?) -> Unit,
languageSelectionEnabled: Boolean,
selectedPairsCount: Int,
selectedOriginLanguage: Language?,
selectedTargetLanguage: Language?
) { ) {
val activity = androidx.compose.ui.platform.LocalContext.current.findActivity() val activity = androidx.compose.ui.platform.LocalContext.current.findActivity()
val vocabularyViewModel: VocabularyViewModel = hiltViewModel(viewModelStoreOwner = activity) val vocabularyViewModel: VocabularyViewModel = hiltViewModel(viewModelStoreOwner = activity)
@@ -428,8 +456,17 @@ fun LanguagePairSection(
} }
} }
var isExpanded by remember { mutableStateOf(false) }
val displayedPairs = if (isExpanded) availablePairs else availablePairs.take(3)
Column { Column {
SectionHeader(title = stringResource(R.string.language_pair)) SectionHeader(
title = stringResource(R.string.language_pair),
actionText = if (availablePairs.size > 3) {
if (isExpanded) stringResource(R.string.label_show_less) else stringResource(R.string.label_show_more)
} else null,
onActionClick = { isExpanded = !isExpanded }
)
if (availablePairs.isEmpty()) { if (availablePairs.isEmpty()) {
Text( Text(
@@ -442,7 +479,7 @@ fun LanguagePairSection(
horizontalArrangement = Arrangement.spacedBy(12.dp), horizontalArrangement = Arrangement.spacedBy(12.dp),
verticalArrangement = Arrangement.spacedBy(12.dp) verticalArrangement = Arrangement.spacedBy(12.dp)
) { ) {
availablePairs.forEach { pair -> displayedPairs.forEach { pair ->
val isSelected = selectedPairs.contains(pair) val isSelected = selectedPairs.contains(pair)
LanguageChip( LanguageChip(
text = "${pair.first.name}${pair.second.name}", text = "${pair.first.name}${pair.second.name}",
@@ -460,74 +497,6 @@ fun LanguagePairSection(
} }
} }
} }
Spacer(modifier = Modifier.height(16.dp))
Text(
text = stringResource(R.string.label_language_direction),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold
)
Text(
text = stringResource(R.string.text_language_direction_explanation),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
if (!languageSelectionEnabled && selectedPairsCount > 0) {
Spacer(modifier = Modifier.height(8.dp))
Text(
text = stringResource(R.string.text_language_direction_disabled_with_pairs),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Spacer(modifier = Modifier.height(12.dp))
Row(
horizontalArrangement = Arrangement.spacedBy(16.dp),
modifier = Modifier.fillMaxWidth()
) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = stringResource(R.string.label_origin_language),
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(bottom = 8.dp)
)
eu.gaudian.translator.view.composable.SingleLanguageDropDown(
modifier = Modifier.fillMaxWidth(),
languageViewModel = languageViewModel,
selectedLanguage = selectedOriginLanguage,
onLanguageSelected = { language ->
if (selectedTargetLanguage?.nameResId == language.nameResId) return@SingleLanguageDropDown
onOriginLanguageSelected(language)
},
showNoneOption = true,
onNoneSelected = { onOriginLanguageSelected(null) },
alternateLanguages = availableLanguages,
restrictToAlternateLanguages = true,
enabled = languageSelectionEnabled
)
}
Column(modifier = Modifier.weight(1f)) {
Text(
text = stringResource(R.string.label_target_language),
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(bottom = 8.dp)
)
eu.gaudian.translator.view.composable.SingleLanguageDropDown(
modifier = Modifier.fillMaxWidth(),
languageViewModel = languageViewModel,
selectedLanguage = selectedTargetLanguage,
onLanguageSelected = { language ->
if (selectedOriginLanguage?.nameResId == language.nameResId) return@SingleLanguageDropDown
onTargetLanguageSelected(language)
},
showNoneOption = true,
onNoneSelected = { onTargetLanguageSelected(null) },
alternateLanguages = availableLanguages,
restrictToAlternateLanguages = true,
enabled = languageSelectionEnabled
)
}
}
} }
} }
@@ -576,10 +545,25 @@ fun CategoriesSection(
val categories by categoryViewModel.categories.collectAsState(initial = emptyList()) val categories by categoryViewModel.categories.collectAsState(initial = emptyList())
Column { Column {
SectionHeader(title = stringResource(R.string.label_categories)) val tagCategories = categories
var isExpanded by remember { mutableStateOf(false) }
val displayedCategories = if (isExpanded) tagCategories else tagCategories.take(3)
val tagCategories = categories.filterIsInstance<TagCategory>() SectionHeader(
if (tagCategories.size > 15) { title = stringResource(R.string.label_categories),
actionText = if (tagCategories.size > 3) {
if (isExpanded) stringResource(R.string.label_show_less) else stringResource(R.string.label_show_more)
} else null,
onActionClick = { isExpanded = !isExpanded }
)
if (tagCategories.isEmpty()) {
Text(
text = stringResource(R.string.no_vocabulary_items_found_perhaps_try_changing_the_filters),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
} else if (tagCategories.size > 15) {
CategoryDropdown( CategoryDropdown(
onCategorySelected = { selections -> onCategorySelected = { selections ->
onCategoriesChanged(selections.filterNotNull()) onCategoriesChanged(selections.filterNotNull())
@@ -596,7 +580,7 @@ fun CategoriesSection(
verticalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
tagCategories.forEach { category -> displayedCategories.forEach { category ->
val isSelected = selectedCategories.contains(category) val isSelected = selectedCategories.contains(category)
Surface( Surface(
shape = RoundedCornerShape(20.dp), shape = RoundedCornerShape(20.dp),
@@ -879,8 +863,17 @@ private fun StartExerciseSettingsBottomSheet(
shuffleLanguagesEnabled: Boolean, shuffleLanguagesEnabled: Boolean,
trainingMode: Boolean, trainingMode: Boolean,
onTrainingModeChanged: (Boolean) -> Unit, onTrainingModeChanged: (Boolean) -> Unit,
selectedOriginLanguage: Language?,
selectedTargetLanguage: Language?,
languageSelectionEnabled: Boolean,
availableLanguages: List<Language>,
onOriginLanguageSelected: (Language?) -> Unit,
onTargetLanguageSelected: (Language?) -> Unit,
onDismiss: () -> Unit onDismiss: () -> Unit
) { ) {
val activity = androidx.compose.ui.platform.LocalContext.current.findActivity()
val languageViewModel: LanguageViewModel = hiltViewModel(viewModelStoreOwner = activity)
ModalBottomSheet( ModalBottomSheet(
onDismissRequest = onDismiss, onDismissRequest = onDismiss,
sheetState = sheetState sheetState = sheetState
@@ -889,7 +882,7 @@ private fun StartExerciseSettingsBottomSheet(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 20.dp, vertical = 16.dp), .padding(horizontal = 20.dp, vertical = 16.dp),
verticalArrangement = Arrangement.spacedBy(12.dp) verticalArrangement = Arrangement.spacedBy(16.dp)
) { ) {
Text( Text(
text = stringResource(R.string.options), text = stringResource(R.string.options),
@@ -927,6 +920,73 @@ private fun StartExerciseSettingsBottomSheet(
checked = trainingMode, checked = trainingMode,
onCheckedChange = onTrainingModeChanged onCheckedChange = onTrainingModeChanged
) )
// Language Direction Section
Text(
text = stringResource(R.string.label_language_direction),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold
)
Text(
text = stringResource(R.string.text_language_direction_explanation),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
if (!languageSelectionEnabled) {
Text(
text = stringResource(R.string.text_language_direction_disabled_with_pairs),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Spacer(modifier = Modifier.height(12.dp))
Row(
horizontalArrangement = Arrangement.spacedBy(16.dp),
modifier = Modifier.fillMaxWidth()
) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = stringResource(R.string.label_origin_language),
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(bottom = 8.dp)
)
eu.gaudian.translator.view.composable.SingleLanguageDropDown(
modifier = Modifier.fillMaxWidth(),
languageViewModel = languageViewModel,
selectedLanguage = selectedOriginLanguage,
onLanguageSelected = { language ->
if (selectedTargetLanguage?.nameResId == language.nameResId) return@SingleLanguageDropDown
onOriginLanguageSelected(language)
},
showNoneOption = true,
onNoneSelected = { onOriginLanguageSelected(null) },
alternateLanguages = availableLanguages,
restrictToAlternateLanguages = true,
enabled = languageSelectionEnabled
)
}
Column(modifier = Modifier.weight(1f)) {
Text(
text = stringResource(R.string.label_target_language),
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(bottom = 8.dp)
)
eu.gaudian.translator.view.composable.SingleLanguageDropDown(
modifier = Modifier.fillMaxWidth(),
languageViewModel = languageViewModel,
selectedLanguage = selectedTargetLanguage,
onLanguageSelected = { language ->
if (selectedOriginLanguage?.nameResId == language.nameResId) return@SingleLanguageDropDown
onTargetLanguageSelected(language)
},
showNoneOption = true,
onNoneSelected = { onTargetLanguageSelected(null) },
alternateLanguages = availableLanguages,
restrictToAlternateLanguages = true,
enabled = languageSelectionEnabled
)
}
}
} }
} }
} }

View File

@@ -255,9 +255,7 @@ fun CategoryDetailScreen(
subtitle = subtitle, subtitle = subtitle,
categoryProgress = categoryProgress, categoryProgress = categoryProgress,
onStartExerciseClick = { onStartExerciseClick = {
val categories = listOf(category) navController.navigate("start_exercise?categoryId=$categoryId")
val categoryIds = categories.joinToString(",") { it?.id.toString() }
navController.navigate("vocabulary_exercise/false?categories=$categoryIds")
}, },
onEditClick = { onEditClick = {
categoryViewModel.setShowEditCategoryDialog(true, categoryId) categoryViewModel.setShowEditCategoryDialog(true, categoryId)

View File

@@ -834,7 +834,7 @@
<string name="label_quit_app">App beenden</string> <string name="label_quit_app">App beenden</string>
<string name="label_target_correct_answers_per_day">Ziel für richtige Antworten pro Tag</string> <string name="label_target_correct_answers_per_day">Ziel für richtige Antworten pro Tag</string>
<string name="label_interval_settings_in_days">Intervall-Einstellungen</string> <string name="label_interval_settings_in_days">Intervall-Einstellungen</string>
<string name="label_vocabulary_settings">Fortschritts-Einstellungen</string> <string name="label_vocabulary_settings">Fortschritt</string>
<string name="label_no_category">Keine</string> <string name="label_no_category">Keine</string>
<string name="text_search">Suche</string> <string name="text_search">Suche</string>
<string name="text_language_settings_description">Stelle ein, welche Sprachen du in der App verwenden möchtest. Sprachen, die nicht aktiviert sind, werden in dieser App nicht angezeigt. Du kannst auch deine eigene Sprache zur Liste hinzufügen oder eine vorhandene Sprache (Region/Locale) ändern.</string> <string name="text_language_settings_description">Stelle ein, welche Sprachen du in der App verwenden möchtest. Sprachen, die nicht aktiviert sind, werden in dieser App nicht angezeigt. Du kannst auch deine eigene Sprache zur Liste hinzufügen oder eine vorhandene Sprache (Region/Locale) ändern.</string>
@@ -898,7 +898,7 @@
<string name="cd_go">Los</string> <string name="cd_go">Los</string>
<string name="label_sort_by">Sortieren nach</string> <string name="label_sort_by">Sortieren nach</string>
<string name="label_reset">Zurücksetzen</string> <string name="label_reset">Zurücksetzen</string>
<string name="label_filter_cards">Filter Cards</string> <string name="label_filter_cards">Karten Filtern</string>
<string name="text_desc_organize_vocabulary_groups">Organisiere deinen Wortschatz in Gruppen</string> <string name="text_desc_organize_vocabulary_groups">Organisiere deinen Wortschatz in Gruppen</string>
<string name="text_add_new_word_to_list">Extrahiere ein neues Wort in deine Liste</string> <string name="text_add_new_word_to_list">Extrahiere ein neues Wort in deine Liste</string>
<string name="cd_scroll_to_top">Nach oben scrollen</string> <string name="cd_scroll_to_top">Nach oben scrollen</string>

View File

@@ -832,7 +832,7 @@
<string name="label_home">Início</string> <string name="label_home">Início</string>
<string name="label_quit_app">Sair do App</string> <string name="label_quit_app">Sair do App</string>
<string name="label_interval_settings_in_days">Configurações de Intervalo</string> <string name="label_interval_settings_in_days">Configurações de Intervalo</string>
<string name="label_vocabulary_settings">Configurações de Progresso</string> <string name="label_vocabulary_settings">Progresso</string>
<string name="label_no_category">Nenhum</string> <string name="label_no_category">Nenhum</string>
<string name="text_search">Buscar</string> <string name="text_search">Buscar</string>
<string name="text_language_settings_description">1. Escolha quais idiomas você quer usar no app. Idiomas que não estiverem ativados não vão aparecer aqui. Você também pode adicionar o seu próprio idioma à lista ou mudar um idioma existente (região/localidade)</string> <string name="text_language_settings_description">1. Escolha quais idiomas você quer usar no app. Idiomas que não estiverem ativados não vão aparecer aqui. Você também pode adicionar o seu próprio idioma à lista ou mudar um idioma existente (região/localidade)</string>

View File

@@ -1114,4 +1114,5 @@
<string name="label_search_cards">Search cards</string> <string name="label_search_cards">Search cards</string>
<string name="label_learnedd">learned</string> <string name="label_learnedd">learned</string>
<string name="label_all_categoriess">All Categories</string> <string name="label_all_categoriess">All Categories</string>
<string name="label_show_more">Show More</string>
</resources> </resources>

View File

@@ -42,6 +42,7 @@ coreKtxVersion = "1.7.0"
truth = "1.4.5" truth = "1.4.5"
zstdJni = "1.5.7-7" zstdJni = "1.5.7-7"
composeMarkdown = "0.5.8" composeMarkdown = "0.5.8"
runtime = "1.10.3"
[libraries] [libraries]
@@ -102,6 +103,7 @@ hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", ve
hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version = "1.3.0" } hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version = "1.3.0" }
mockk = { module = "io.mockk:mockk", version = "1.14.9" } mockk = { module = "io.mockk:mockk", version = "1.14.9" }
compose-markdown = { module = "com.github.jeziellago:compose-markdown", version.ref = "composeMarkdown" } compose-markdown = { module = "com.github.jeziellago:compose-markdown", version.ref = "composeMarkdown" }
androidx-compose-runtime = { group = "androidx.compose.runtime", name = "runtime", version.ref = "runtime" }
[plugins] [plugins]
android-application = { id = "com.android.application", version.ref = "agp" } android-application = { id = "com.android.application", version.ref = "agp" }