mirror of
https://github.com/pepaskopec-blip/Graduately.git
synced 2026-10-27 15:14:35 +00:00
Add four years of English from the gymnasium syllabus.
Each year mixes listening, reading, writing, gap-fill, quizzes, and a year test so the subject is usable through the maturita. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
c561c0acb5
commit
bb93ec76ec
32 changed files with 6607 additions and 14 deletions
|
|
@ -146,6 +146,11 @@ class AppViewModel(app: Application) : AndroidViewModel(app) {
|
|||
refresh()
|
||||
}
|
||||
|
||||
fun markEn(year: Int, id: Int) {
|
||||
progress.markEn(year, id)
|
||||
refresh()
|
||||
}
|
||||
|
||||
fun markLit(id: Int) {
|
||||
progress.markLit(id)
|
||||
refresh()
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ import org.maturita.maturita.ui.On3QuizScreen
|
|||
import org.maturita.maturita.ui.On4QuizScreen
|
||||
import org.maturita.maturita.ui.OnQuizScreen
|
||||
import org.maturita.maturita.ui.OnYearsScreen
|
||||
import org.maturita.maturita.ui.EnYearsScreen
|
||||
import org.maturita.maturita.ui.EngExScreen
|
||||
import org.maturita.maturita.ui.PlotScreen
|
||||
import org.maturita.maturita.ui.RoadmapScreen
|
||||
import org.maturita.maturita.ui.SearchScreen
|
||||
|
|
@ -238,6 +240,21 @@ private fun MaturitaAppBody(vm: AppViewModel) {
|
|||
}
|
||||
}
|
||||
is Route.HwEx -> HwQuizScreen(vm, r.id)
|
||||
Route.EnYears -> EnYearsScreen(vm)
|
||||
is Route.EnMap -> LessonListScreen(
|
||||
vm, vm.tr("en_year${r.year}"), vm.tr("en_y${r.year}_sub"),
|
||||
vm.content.enYear(r.year).map { l ->
|
||||
val id = l.int("id")
|
||||
LessonRow(vm.tr(l.str("titleKey")), vm.progress.enDone(r.year, id), Route.EnLesson(r.year, id))
|
||||
},
|
||||
)
|
||||
is Route.EnLesson -> {
|
||||
val l = vm.content.enLesson(r.year, r.id)
|
||||
if (l != null) SlidesScreen(vm, vm.tr(l.str("titleKey")), vm.tr(l.str("subKey")), l.arr("slides")) {
|
||||
vm.replace(Route.EnEx(r.year, r.id))
|
||||
}
|
||||
}
|
||||
is Route.EnEx -> EngExScreen(vm, r.year, r.id)
|
||||
Route.OnYears -> OnYearsScreen(vm)
|
||||
Route.OnMap -> LessonListScreen(
|
||||
vm, vm.tr("on_year1"), vm.tr("on_sub"),
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ sealed class Route(val page: String) {
|
|||
data object On4Map : Route("on4map")
|
||||
data class On4Lesson(val id: Int) : Route("on4unit$id")
|
||||
data class On4Ex(val id: Int) : Route("on4ex$id")
|
||||
data object EnYears : Route("enyears")
|
||||
data class EnMap(val year: Int) : Route("en${year}map")
|
||||
data class EnLesson(val year: Int, val id: Int) : Route("en${year}unit$id")
|
||||
data class EnEx(val year: Int, val id: Int) : Route("en${year}ex$id")
|
||||
data object LitYears : Route("lityears")
|
||||
data object LitMap : Route("litmap")
|
||||
data class LitLesson(val id: Int) : Route("litunit$id")
|
||||
|
|
@ -93,7 +97,7 @@ sealed class Route(val page: String) {
|
|||
/** Screens with their own bottom action bar; the navigation bar stays hidden there. */
|
||||
val isExercise: Boolean
|
||||
get() = this is GermanEx || this is Vocab || this is NetEx || this is HwEx ||
|
||||
this is OnEx || this is On2Ex || this is On3Ex || this is On4Ex || this is MluvEx || this is BookQuiz || this is BookPlot ||
|
||||
this is OnEx || this is On2Ex || this is On3Ex || this is On4Ex || this is EnLesson || this is EnEx || this is MluvEx || this is BookQuiz || this is BookPlot ||
|
||||
this is NetLesson || this is HwLesson || this is OnLesson || this is On2Lesson || this is On3Lesson || this is On4Lesson ||
|
||||
this is LitLesson || this is LitEx || this is Lit2Lesson || this is Lit2Ex ||
|
||||
this is Lit3Lesson || this is Lit3Ex || this is Lit4Lesson || this is Lit4Ex ||
|
||||
|
|
@ -134,6 +138,10 @@ sealed class Route(val page: String) {
|
|||
On4Map -> listOf(Subjects, OnYears, On4Map)
|
||||
is On4Lesson -> listOf(Subjects, OnYears, On4Map, this)
|
||||
is On4Ex -> listOf(Subjects, OnYears, On4Map, On4Lesson(id), this)
|
||||
EnYears -> listOf(Subjects, EnYears)
|
||||
is EnMap -> listOf(Subjects, EnYears, this)
|
||||
is EnLesson -> listOf(Subjects, EnYears, EnMap(year), this)
|
||||
is EnEx -> listOf(Subjects, EnYears, EnMap(year), EnLesson(year, id), this)
|
||||
LitYears -> listOf(Subjects, CzechMap, LitYears)
|
||||
LitMap -> listOf(Subjects, CzechMap, LitYears, LitMap)
|
||||
is LitLesson -> listOf(Subjects, CzechMap, LitYears, LitMap, this)
|
||||
|
|
@ -208,6 +216,7 @@ fun routeFromPage(page: String): Route? = when (page) {
|
|||
"on2map" -> Route.On2Map
|
||||
"on3map" -> Route.On3Map
|
||||
"on4map" -> Route.On4Map
|
||||
"enyears" -> Route.EnYears
|
||||
"lityears" -> Route.LitYears
|
||||
"litmap" -> Route.LitMap
|
||||
"lit2map" -> Route.Lit2Map
|
||||
|
|
@ -348,6 +357,15 @@ fun routeFromPage(page: String): Route? = when (page) {
|
|||
Regex("""litex(\d+)""").matchEntire(page)?.let {
|
||||
return Route.LitEx(it.groupValues[1].toInt())
|
||||
}
|
||||
Regex("""en(\d)map""").matchEntire(page)?.let {
|
||||
return Route.EnMap(it.groupValues[1].toInt())
|
||||
}
|
||||
Regex("""en(\d)unit(\d+)""").matchEntire(page)?.let {
|
||||
return Route.EnLesson(it.groupValues[1].toInt(), it.groupValues[2].toInt())
|
||||
}
|
||||
Regex("""en(\d)ex(\d+)""").matchEntire(page)?.let {
|
||||
return Route.EnEx(it.groupValues[1].toInt(), it.groupValues[2].toInt())
|
||||
}
|
||||
Regex("""on4unit(\d+)""").matchEntire(page)?.let {
|
||||
return Route.On4Lesson(it.groupValues[1].toInt())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,10 @@ class Content(root: JSONObject) {
|
|||
val on2 = raw.arr("on2")
|
||||
val on3 = raw.arr("on3")
|
||||
val on4 = raw.arr("on4")
|
||||
val en = raw.arr("en")
|
||||
val en2 = raw.arr("en2")
|
||||
val en3 = raw.arr("en3")
|
||||
val en4 = raw.arr("en4")
|
||||
val lit = raw.arr("lit")
|
||||
val lit2 = raw.arr("lit2")
|
||||
val lit3 = raw.arr("lit3")
|
||||
|
|
@ -59,6 +63,13 @@ class Content(root: JSONObject) {
|
|||
fun on2Lesson(id: Int) = on2.firstOrNull { it.int("id") == id }
|
||||
fun on3Lesson(id: Int) = on3.firstOrNull { it.int("id") == id }
|
||||
fun on4Lesson(id: Int) = on4.firstOrNull { it.int("id") == id }
|
||||
fun enYear(year: Int) = when (year) {
|
||||
2 -> en2
|
||||
3 -> en3
|
||||
4 -> en4
|
||||
else -> en
|
||||
}
|
||||
fun enLesson(year: Int, id: Int) = enYear(year).firstOrNull { it.int("id") == id }
|
||||
fun litLesson(id: Int) = lit.firstOrNull { it.int("id") == id }
|
||||
fun lit2Lesson(id: Int) = lit2.firstOrNull { it.int("id") == id }
|
||||
fun lit3Lesson(id: Int) = lit3.firstOrNull { it.int("id") == id }
|
||||
|
|
|
|||
|
|
@ -44,6 +44,9 @@ class ProgressStore(context: Context) {
|
|||
fun on4Done(id: Int) = prefs.getBoolean("on4.$id", false)
|
||||
fun markOn4(id: Int) { prefs.edit().putBoolean("on4.$id", true).apply() }
|
||||
|
||||
fun enDone(year: Int, id: Int) = prefs.getBoolean("en.$year.$id", false)
|
||||
fun markEn(year: Int, id: Int) { prefs.edit().putBoolean("en.$year.$id", true).apply() }
|
||||
|
||||
fun litDone(id: Int) = prefs.getBoolean("lit.$id", false)
|
||||
fun markLit(id: Int) { prefs.edit().putBoolean("lit.$id", true).apply() }
|
||||
fun lit2Done(id: Int) = prefs.getBoolean("lit2.$id", false)
|
||||
|
|
@ -146,6 +149,16 @@ fun summarize(content: Content, p: ProgressStore): ProgressSum {
|
|||
sum.doneUnits += 1
|
||||
}
|
||||
}
|
||||
for (year in 1..4) {
|
||||
content.enYear(year).forEach { l ->
|
||||
sum.totalEx += 1
|
||||
sum.openUnits += 1
|
||||
if (p.enDone(year, l.int("id"))) {
|
||||
sum.doneEx += 1
|
||||
sum.doneUnits += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
content.lit.forEach { l ->
|
||||
sum.totalEx += 1
|
||||
sum.openUnits += 1
|
||||
|
|
|
|||
|
|
@ -38,8 +38,15 @@ import androidx.compose.material3.MaterialTheme
|
|||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Text
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.speech.tts.TextToSpeech
|
||||
import android.speech.tts.UtteranceProgressListener
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import java.util.Locale
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
|
|
@ -1370,4 +1377,156 @@ fun PlotScreen(vm: AppViewModel, id: String) {
|
|||
put("meanings", book.o.optJSONArray("plotMeaning"))
|
||||
})
|
||||
DispatchExercise(vm, spec, vm.tr(book.str("plotTitle"))) { vm.markBookPlot(id) }
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun EngExScreen(vm: AppViewModel, year: Int, id: Int) {
|
||||
val lesson = vm.content.enLesson(year, id) ?: return
|
||||
val readQ = lesson.arr("readQuiz")
|
||||
val listenQ = lesson.arr("listenQuiz")
|
||||
val quiz = lesson.arr("quiz")
|
||||
val gapRows = lesson.arr("gaps")
|
||||
val writing = lesson.obj("writing")
|
||||
val listening = lesson.strOrNull("listening")
|
||||
val readPicks = remember(year, id) { mutableStateListOf(*Array(readQ.size) { -1 }) }
|
||||
val listenPicks = remember(year, id) { mutableStateListOf(*Array(listenQ.size) { -1 }) }
|
||||
val quizPicks = remember(year, id) { mutableStateListOf(*Array(quiz.size) { -1 }) }
|
||||
val gapText = remember(year, id) { mutableStateListOf(*Array(gapRows.size) { "" }) }
|
||||
var essay by remember(year, id) { mutableStateOf("") }
|
||||
var played by remember(year, id) { mutableStateOf(false) }
|
||||
var showScript by remember(year, id) { mutableStateOf(false) }
|
||||
var revealed by remember(year, id) { mutableStateOf(false) }
|
||||
var showModel by remember(year, id) { mutableStateOf(false) }
|
||||
var fb by remember(year, id) { mutableStateOf("" to "") }
|
||||
val context = LocalContext.current
|
||||
var tts by remember { mutableStateOf<TextToSpeech?>(null) }
|
||||
DisposableEffect(context) {
|
||||
var engine: TextToSpeech? = null
|
||||
engine = TextToSpeech(context) { status ->
|
||||
if (status == TextToSpeech.SUCCESS) engine?.language = Locale.UK
|
||||
}
|
||||
tts = engine
|
||||
onDispose {
|
||||
engine?.stop()
|
||||
engine?.shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
fun picksOk(questions: List<J>, picks: List<Int>) =
|
||||
questions.indices.all { picks[it] == questions[it].int("correct") }
|
||||
|
||||
ExerciseScaffold(vm, vm.tr(lesson.str("titleKey")), null, vm.tr("check"), {
|
||||
if (listening != null && !played) {
|
||||
fb = vm.tr("en_listen_first") to "err"
|
||||
} else {
|
||||
val readOk = picksOk(readQ, readPicks)
|
||||
val listenOk = picksOk(listenQ, listenPicks)
|
||||
val quizOk = picksOk(quiz, quizPicks)
|
||||
val gapOk = gapRows.indices.count {
|
||||
answerAccepts(normalizeAnswer(gapText[it]), gapRows[it].str("answers"))
|
||||
}
|
||||
val writeOk = if (writing == null) {
|
||||
true
|
||||
} else {
|
||||
val norm = " ${normalizeAnswer(essay)} "
|
||||
val keysOk = writing.str("keys").split("|").all { key ->
|
||||
val w = normalizeAnswer(key)
|
||||
w.isEmpty() || norm.contains(" $w ")
|
||||
}
|
||||
keysOk && normalizeAnswer(essay).split(" ").count { it.isNotEmpty() } >= writing.int("minWords", 20)
|
||||
}
|
||||
revealed = true
|
||||
val all = readOk && listenOk && quizOk && gapOk == gapRows.size && writeOk
|
||||
fb = when {
|
||||
all -> {
|
||||
showModel = true
|
||||
vm.markEn(year, id)
|
||||
vm.tr("feedback_ok") to "ok"
|
||||
}
|
||||
writing != null && !writeOk && readOk && listenOk && quizOk && gapOk == gapRows.size ->
|
||||
vm.tr("en_write_short") to "err"
|
||||
else -> vm.tr("feedback_retry_short") to "err"
|
||||
}
|
||||
}
|
||||
}, fb.first, fb.second) {
|
||||
lesson.strOrNull("reading")?.let { reading ->
|
||||
Text(vm.tr("en_sec_read"), style = MaterialTheme.typography.titleMedium, modifier = Modifier.padding(top = 8.dp))
|
||||
Text(reading)
|
||||
EngChoices(readQ, readPicks, revealed) { index, option -> readPicks[index] = option }
|
||||
}
|
||||
if (listening != null) {
|
||||
Text(vm.tr("en_sec_listen"), style = MaterialTheme.typography.titleMedium, modifier = Modifier.padding(top = 8.dp))
|
||||
Text(vm.tr("en_listen_note"), color = MaterialTheme.colorScheme.onSurfaceVariant)
|
||||
OutlinedButton(onClick = {
|
||||
played = true
|
||||
showScript = false
|
||||
val engine = tts
|
||||
if (engine == null) {
|
||||
showScript = true
|
||||
} else {
|
||||
engine.language = Locale.UK
|
||||
engine.setOnUtteranceProgressListener(object : UtteranceProgressListener() {
|
||||
override fun onStart(utteranceId: String?) {}
|
||||
override fun onDone(utteranceId: String?) {
|
||||
Handler(Looper.getMainLooper()).post { showScript = true }
|
||||
}
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun onError(utteranceId: String?) {
|
||||
Handler(Looper.getMainLooper()).post { showScript = true }
|
||||
}
|
||||
})
|
||||
engine.speak(listening, TextToSpeech.QUEUE_FLUSH, null, "en-lesson")
|
||||
val wait = (listening.split(" ").size * 420L).coerceAtLeast(2500L)
|
||||
Handler(Looper.getMainLooper()).postDelayed({ showScript = true }, wait)
|
||||
}
|
||||
}) { Text(vm.tr("en_play")) }
|
||||
if (showScript) Text(listening)
|
||||
EngChoices(listenQ, listenPicks, revealed) { index, option -> listenPicks[index] = option }
|
||||
}
|
||||
if (gapRows.isNotEmpty()) {
|
||||
Text(vm.tr("en_sec_gap"), style = MaterialTheme.typography.titleMedium, modifier = Modifier.padding(top = 8.dp))
|
||||
gapRows.forEachIndexed { i, row ->
|
||||
Text("${i + 1}. ${row.str("prompt")}", style = MaterialTheme.typography.titleSmall)
|
||||
val mark = if (!revealed) null else answerAccepts(normalizeAnswer(gapText[i]), row.str("answers"))
|
||||
WordField(gapText[i], { gapText[i] = it }, "", mark)
|
||||
if (revealed) row.strOrNull("meaning")?.let { Meaning(it, true) }
|
||||
}
|
||||
}
|
||||
if (writing != null) {
|
||||
Text(vm.tr("en_sec_write"), style = MaterialTheme.typography.titleMedium, modifier = Modifier.padding(top = 8.dp))
|
||||
Text(writing.str("prompt"))
|
||||
OutlinedTextField(
|
||||
value = essay,
|
||||
onValueChange = { essay = it },
|
||||
modifier = Modifier.fillMaxWidth().height(160.dp),
|
||||
minLines = 5,
|
||||
)
|
||||
if (showModel) {
|
||||
Text(vm.tr("en_model"), style = MaterialTheme.typography.titleSmall)
|
||||
Text(writing.str("model"))
|
||||
}
|
||||
}
|
||||
if (quiz.isNotEmpty()) {
|
||||
Text(vm.tr("en_sec_quiz"), style = MaterialTheme.typography.titleMedium, modifier = Modifier.padding(top = 8.dp))
|
||||
EngChoices(quiz, quizPicks, revealed) { index, option -> quizPicks[index] = option }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EngChoices(
|
||||
questions: List<J>,
|
||||
picks: List<Int>,
|
||||
revealed: Boolean,
|
||||
onPick: (Int, Int) -> Unit,
|
||||
) {
|
||||
questions.forEachIndexed { i, q ->
|
||||
Text("${i + 1}. ${q.str("prompt")}", style = MaterialTheme.typography.titleSmall, modifier = Modifier.padding(top = 8.dp))
|
||||
q.strs("options").forEachIndexed { o, opt ->
|
||||
val selected = picks.getOrElse(i) { -1 } == o
|
||||
val mark = if (revealed && selected) picks[i] == q.int("correct") else null
|
||||
OptionRow(opt, selected, mark) { onPick(i, o) }
|
||||
}
|
||||
if (revealed) q.strOrNull("expl")?.let { Meaning(it, true) }
|
||||
}
|
||||
}
|
||||
|
|
@ -195,6 +195,26 @@ fun CzechFlag(iconSize: Dp = 48.dp) {
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun UkFlag(iconSize: Dp = 48.dp) {
|
||||
DrawnIcon(iconSize) {
|
||||
val w = this.size.width
|
||||
val h = this.size.height
|
||||
val clip = Path().apply { addOval(androidx.compose.ui.geometry.Rect(0f, 0f, w, h)) }
|
||||
clipPath(clip) {
|
||||
drawRect(Color(0xFF012466), size = Size(w, h))
|
||||
drawLine(Color.White, Offset(0f, 0f), Offset(w, h), strokeWidth = w * 0.16f)
|
||||
drawLine(Color.White, Offset(w, 0f), Offset(0f, h), strokeWidth = w * 0.16f)
|
||||
drawLine(Color(0xFFCC0D26), Offset(0f, 0f), Offset(w, h), strokeWidth = w * 0.055f)
|
||||
drawLine(Color(0xFFCC0D26), Offset(w, 0f), Offset(0f, h), strokeWidth = w * 0.055f)
|
||||
drawRect(Color.White, topLeft = Offset(0f, h * 0.38f), size = Size(w, h * 0.24f))
|
||||
drawRect(Color.White, topLeft = Offset(w * 0.38f, 0f), size = Size(w * 0.24f, h))
|
||||
drawRect(Color(0xFFCC0D26), topLeft = Offset(0f, h * 0.43f), size = Size(w, h * 0.14f))
|
||||
drawRect(Color(0xFFCC0D26), topLeft = Offset(w * 0.43f, 0f), size = Size(w * 0.14f, h))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun BookIcon(color: Color, iconSize: Dp = 22.dp) {
|
||||
DrawnIcon(iconSize) {
|
||||
|
|
|
|||
|
|
@ -223,6 +223,7 @@ private fun SubjectIcon(icon: String, open: Boolean) {
|
|||
"chip" -> ChipIcon(tint, 26.dp)
|
||||
"people" -> Icon(Icons.Filled.Groups, null, tint = tint, modifier = Modifier.size(26.dp))
|
||||
"cz" -> CzechFlag(28.dp)
|
||||
"uk" -> UkFlag(28.dp)
|
||||
"flask" -> Icon(Icons.Filled.Science, null, tint = tint, modifier = Modifier.size(26.dp))
|
||||
"bolt" -> Icon(Icons.Filled.Bolt, null, tint = tint, modifier = Modifier.size(26.dp))
|
||||
"function" -> Icon(Icons.Filled.Functions, null, tint = tint, modifier = Modifier.size(26.dp))
|
||||
|
|
@ -306,6 +307,12 @@ private fun subjectSum(vm: AppViewModel, s: J): ProgressSum {
|
|||
sum.totalEx = vm.content.hw.size
|
||||
sum.doneEx = vm.content.hw.count { vm.progress.hwDone(it.int("id")) }
|
||||
}
|
||||
"enyears", "en1map", "en2map", "en3map", "en4map" -> {
|
||||
sum.totalEx = (1..4).sumOf { vm.content.enYear(it).size }
|
||||
sum.doneEx = (1..4).sumOf { year ->
|
||||
vm.content.enYear(year).count { vm.progress.enDone(year, it.int("id")) }
|
||||
}
|
||||
}
|
||||
"onyears", "onmap", "on2map", "on3map", "on4map" -> {
|
||||
sum.totalEx = vm.content.on.size + vm.content.on2.size + vm.content.on3.size + vm.content.on4.size
|
||||
sum.doneEx = vm.content.on.count { vm.progress.onDone(it.int("id")) } +
|
||||
|
|
@ -545,6 +552,13 @@ private fun buildSearch(vm: AppViewModel): List<Hit> {
|
|||
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "on4unit${l.int("id")}", extra = "obcanka")
|
||||
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "on4ex${l.int("id")}")
|
||||
}
|
||||
for (year in 1..4) {
|
||||
add(vm.tr("en_year$year"), vm.tr("search_lesson"), "en${year}map", extra = "anglictina english rocnik")
|
||||
vm.content.enYear(year).forEach { l ->
|
||||
add(vm.tr(l.str("titleKey")), vm.tr("search_lesson"), "en${year}unit${l.int("id")}", extra = "anglictina english")
|
||||
add(vm.tr(l.str("titleKey")), vm.tr("search_exercise"), "en${year}ex${l.int("id")}")
|
||||
}
|
||||
}
|
||||
add(vm.tr("Literatura"), vm.tr("search_lesson"), "lityears", extra = "literatura")
|
||||
add(vm.tr("lit_year1"), vm.tr("search_lesson"), "litmap", extra = "rocnik")
|
||||
add(vm.tr("lit_year2"), vm.tr("search_lesson"), "lit2map", extra = "rocnik")
|
||||
|
|
@ -722,6 +736,21 @@ fun HwYearsScreen(vm: AppViewModel) {
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun EnYearsScreen(vm: AppViewModel) {
|
||||
DetailScaffold(vm, vm.tr("English"), vm.tr("en_years_sub")) { inner ->
|
||||
LazyColumn(contentPadding = PaddingValues(top = inner.calculateTopPadding(), bottom = inner.calculateBottomPadding() + 16.dp)) {
|
||||
items(4) { index ->
|
||||
val year = index + 1
|
||||
NavRow(
|
||||
title = vm.tr("en_year$year"),
|
||||
subtitle = vm.tr("en_y${year}_sub"),
|
||||
leading = { Text("$year.", style = MaterialTheme.typography.titleMedium) },
|
||||
) { vm.go(Route.EnMap(year)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun OnYearsScreen(vm: AppViewModel) {
|
||||
DetailScaffold(vm, vm.tr("Občanská nauka"), vm.tr("on_years_sub")) { inner ->
|
||||
LazyColumn(contentPadding = PaddingValues(top = inner.calculateTopPadding(), bottom = inner.calculateBottomPadding() + 16.dp)) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue