Add a self-updater that installs new releases.

Bake the release tag into the binary so the app knows what it is running;
plain builds keep the "dev" default and never offer an update. The CI
workflow already exported the tag on Linux and macOS, so only the Windows
job needed it.

Read the newest version from the redirect GitHub serves for
/releases/latest, which avoids the REST API and its unauthenticated rate
limit and needs no JSON parser. Networking goes through the curl command
rather than a linked library: curl handles TLS, redirects and proxies, it
ships on all three platforms, and it keeps the bundling scripts free of
another shared library.

An application cannot reliably replace its own files while running, so
every platform follows one shape: unpack beside the current install,
write a script that waits for this process to exit before swapping, then
launch it detached and quit. Staging beside the install keeps the move on
one filesystem and fails early when the location is read-only. The
Windows script copies without mirroring so the progress files kept inside
the install directory survive.

Check quietly a few seconds after startup and offer the result in a
banner above the pages, with a manual check in the settings popover.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
pepaskopec-blip 2026-09-17 15:04:55 +02:00
commit 91a848b408
10 changed files with 1084 additions and 4 deletions

30
i18n.c
View file

@ -19,6 +19,35 @@ const TrEntry tr_ui[] = {
{"mode_light", "Světlý", "Light"},
{"theme", "TÉMA", "THEME"},
{"language", "JAZYK", "LANGUAGE"},
{"updates", "AKTUALIZACE", "UPDATES"},
{"update_current", "Verze %s", "Version %s"},
{"update_checking", "Hledám aktualizace…", "Checking for updates…"},
{"update_uptodate", "Máte nejnovější verzi (%s).",
"You are up to date (%s)."},
{"update_available", "Je dostupná verze %s.", "Version %s is available."},
{"update_downloading", "Stahuji aktualizaci…", "Downloading the update…"},
{"update_staged", "Aktualizace je připravená — restartujte aplikaci.",
"The update is ready — restart the app to finish."},
{"update_check", "Zkontrolovat", "Check"},
{"update_install", "Aktualizovat", "Update"},
{"update_restart", "Restartovat", "Restart"},
{"update_later", "Později", "Later"},
{"update_failed", "Aktualizace se nepovedla.", "The update failed."},
{"update_err_network", "Nepodařilo se zjistit nejnovější verzi.",
"Could not find out the latest version."},
{"update_err_download", "Stahování se nepovedlo.", "The download failed."},
{"update_err_curl", "V systému chybí curl, aktualizace nejsou dostupné.",
"curl is missing, so updates are unavailable."},
{"update_err_unsupported", "Pro tuto platformu se aktualizace nevydává.",
"No update is published for this platform."},
{"update_err_readonly",
"Do umístění aplikace nelze zapisovat. Přesuňte ji třeba do Aplikací.",
"The app's location is not writable. Move it somewhere else, for "
"example to Applications."},
{"update_err_stage", "Aktualizaci nešlo připravit.",
"Could not prepare the update."},
{"update_err_devbuild", "Tento build nemá číslo verze (dev).",
"This build carries no version number (dev)."},
{"welcome_body",
"maturita.C je vzdělávací program pro studenty středních škol a "
"gymnázií na přípravu k maturitě.\n\n"
@ -1474,6 +1503,7 @@ void apply_language(void) {
i18n_apply_one(&g_array_index(i18n_binds, I18nBind, i));
refresh_welcome_heading();
refresh_stats_ui();
update_apply_lang();
net_lessons_apply_lang();
hw_lessons_apply_lang();
}