mirror of
https://github.com/pepaskopec-blip/Graduately.git
synced 2026-10-27 15:14:35 +00:00
Show a what's-new card on the home screen after each update.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
dd8d992bf8
commit
6556c6691b
21 changed files with 490 additions and 0 deletions
|
|
@ -32,6 +32,8 @@ class AppViewModel(app: Application) : AndroidViewModel(app) {
|
|||
private set
|
||||
var update by mutableStateOf(UpdateState())
|
||||
private set
|
||||
var showChangelog by mutableStateOf(shouldShowChangelog())
|
||||
private set
|
||||
|
||||
private val stack = mutableStateListOf<Route>(Route.Subjects)
|
||||
val route: Route get() = stack.last()
|
||||
|
|
@ -146,4 +148,21 @@ class AppViewModel(app: Application) : AndroidViewModel(app) {
|
|||
fun installUpdate() {
|
||||
updater.install { update = it }
|
||||
}
|
||||
|
||||
fun dismissChangelog() {
|
||||
progress.seenCommit = BuildConfig.COMMIT
|
||||
showChangelog = false
|
||||
}
|
||||
|
||||
private fun shouldShowChangelog(): Boolean {
|
||||
if (content.changelog.isEmpty()) return false
|
||||
return !sameBuild(BuildConfig.COMMIT, progress.seenCommit)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun sameBuild(a: String?, b: String?): Boolean {
|
||||
if (a.isNullOrEmpty() || b.isNullOrEmpty()) return false
|
||||
if (a.equals(b, ignoreCase = true)) return true
|
||||
val n = minOf(a.length, b.length)
|
||||
return n >= 7 && a.regionMatches(0, b, 0, n, ignoreCase = true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ class Content(root: JSONObject) {
|
|||
val hw = raw.arr("hw")
|
||||
val mluvnice = raw.arr("mluvnice")
|
||||
val books = raw.arr("books")
|
||||
val changelog = raw.arr("changelog")
|
||||
|
||||
fun germanUnit(id: Int) = german.firstOrNull { it.int("id") == id }
|
||||
fun netLesson(id: Int) = netLessons.firstOrNull { it.int("id") == id }
|
||||
|
|
|
|||
|
|
@ -17,6 +17,10 @@ class ProgressStore(context: Context) {
|
|||
get() = if (prefs.getString("lang", "cs") == "en") UiLang.En else UiLang.Cs
|
||||
set(v) { prefs.edit().putString("lang", if (v == UiLang.En) "en" else "cs").apply() }
|
||||
|
||||
var seenCommit: String
|
||||
get() = prefs.getString("seen_commit", "") ?: ""
|
||||
set(v) { prefs.edit().putString("seen_commit", v).apply() }
|
||||
|
||||
fun germanDone(unit: Int, ex: Int) = prefs.getBoolean("g.$unit.$ex", false)
|
||||
fun markGerman(unit: Int, ex: Int) { prefs.edit().putBoolean("g.$unit.$ex", true).apply() }
|
||||
fun vocabDone(unit: Int) = prefs.getBoolean("g.$unit.vocab", false)
|
||||
|
|
|
|||
|
|
@ -91,6 +91,9 @@ fun HomeScreen(vm: AppViewModel) {
|
|||
val sum = summarize(vm.content, vm.progress)
|
||||
val pct = if (sum.totalEx == 0) 0f else sum.doneEx / sum.totalEx.toFloat()
|
||||
RootScaffold(vm, "Maturita") {
|
||||
if (vm.showChangelog) {
|
||||
item { ChangelogCard(vm) }
|
||||
}
|
||||
item {
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
|
|
@ -141,6 +144,51 @@ fun HomeScreen(vm: AppViewModel) {
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ChangelogCard(vm: AppViewModel) {
|
||||
val langKey = if (vm.lang == UiLang.En) "en" else "cs"
|
||||
val blocks = vm.content.changelog.take(3)
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.tertiaryContainer),
|
||||
) {
|
||||
Column(Modifier.padding(20.dp)) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(
|
||||
vm.tr("changelog_title"),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
color = MaterialTheme.colorScheme.onTertiaryContainer,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
val date = blocks.firstOrNull()?.str("date").orEmpty()
|
||||
if (date.isNotEmpty()) {
|
||||
Text(
|
||||
date,
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
color = MaterialTheme.colorScheme.onTertiaryContainer.copy(alpha = 0.7f),
|
||||
)
|
||||
}
|
||||
}
|
||||
Spacer(Modifier.height(10.dp))
|
||||
blocks.forEachIndexed { index, block ->
|
||||
if (index > 0) Spacer(Modifier.height(8.dp))
|
||||
block.strs(langKey).ifEmpty { block.strs("cs") }.forEach { line ->
|
||||
Text(
|
||||
"• $line",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onTertiaryContainer,
|
||||
modifier = Modifier.padding(bottom = 4.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
Spacer(Modifier.height(8.dp))
|
||||
FilledTonalButton(onClick = { vm.dismissChangelog() }) {
|
||||
Text(vm.tr("changelog_dismiss"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun UpdateBanner(vm: AppViewModel) {
|
||||
Card(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue