Update: catatan rilis & hint terlihat, kunci terjemahan dicek tes
- Catatan rilis ditaruh di tengah Border (VScroll di Fyne punya MinSize kecil, jadi sebagai 'top' isinya cuma dapat 32px dan terpotong) - Tombol Back sebelumnya memakai kunci terjemahan yang belum ada di tabel; ditambah tes yang memastikan semua kunci T() ada dan tidak ada kunci nganggur - README: bagian Updates + cara publish rilis
This commit is contained in:
1 parent
e8fa35d70d
commit
ffc412863a
4 files changed
+75
-12
No files matched your search
@@ -69,6 +69,23 @@ Everything stays inside the home directory — no root, no system directories.
|
||||
Filenames use a slug of the app name (`WhatsApp Web` → `whatsapp-web.desktop`);
|
||||
the `Name=` field keeps the name you typed.
|
||||
|
||||
## Updates
|
||||
|
||||
LazyRun checks the **latest release** of this repository once, a few seconds after
|
||||
start (only when running as an AppImage) and offers to install it:
|
||||
|
||||
- if [AppImageUpdate](https://github.com/AppImageCommunity/AppImageUpdate) is in
|
||||
`$PATH` it is used, so only the changed blocks are downloaded (zsync);
|
||||
- otherwise the AppImage is downloaded, verified (ELF + AppImage magic bytes) and
|
||||
swapped in atomically — if anything fails the current AppImage stays untouched;
|
||||
- *Restart now* in the dialog runs the new version.
|
||||
|
||||
*Check for Updates* in the footer runs the same flow manually.
|
||||
|
||||
**Publishing a release** so updates reach users: tag it `vX.Y.Z`, upload
|
||||
`lazyrun-X.Y.Z-x86_64.AppImage` plus the `.zsync` file produced by `build.sh` as
|
||||
release assets, and mark it as the latest release.
|
||||
|
||||
## Build
|
||||
|
||||
Requirements: Go 1.24+, cgo, and X11/OpenGL development headers (Fyne).
|
||||
|
||||
@@ -3,6 +3,7 @@ package ui
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -70,3 +71,40 @@ func TestDialogsOpenWithoutPanic(t *testing.T) {
|
||||
// jadi sisa goroutine bisa bertabrakan dengan tes berikutnya kalau dibiarkan.
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
}
|
||||
|
||||
// TestStringsCoverUsedKeys memastikan setiap kunci T() yang dipakai ada di tabel
|
||||
// terjemahan (kalau tidak, UI menampilkan nama kunci mentah).
|
||||
func TestStringsCoverUsedKeys(t *testing.T) {
|
||||
files, err := filepath.Glob("*.go")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
used := map[string]bool{}
|
||||
for _, file := range files {
|
||||
if strings.HasSuffix(file, "_test.go") {
|
||||
continue
|
||||
}
|
||||
data, err := os.ReadFile(file)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, m := range regexp.MustCompile(`T\("([a-z_]+)"\)`).FindAllStringSubmatch(string(data), -1) {
|
||||
used[m[1]] = true
|
||||
}
|
||||
}
|
||||
if len(used) == 0 {
|
||||
t.Fatal("tidak ada kunci T() yang ditemukan")
|
||||
}
|
||||
for key := range used {
|
||||
if _, ok := tr[key]; !ok {
|
||||
t.Errorf("kunci %q dipakai tapi tidak ada di tabel terjemahan", key)
|
||||
}
|
||||
}
|
||||
|
||||
// dan sebaliknya: kunci terjemahan yang tidak terpakai sebaiknya dihapus
|
||||
for key := range tr {
|
||||
if !used[key] {
|
||||
t.Errorf("kunci %q ada di tabel terjemahan tapi tidak dipakai", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
-6
@@ -30,8 +30,8 @@ var tr = map[string][2]string{
|
||||
"browse": {"Browse...", "Pilih..."},
|
||||
"install": {"Install", "Install"},
|
||||
"cancel": {"Cancel", "Batal"},
|
||||
"back": {"Back", "Kembali"},
|
||||
"delete": {"Delete", "Hapus"},
|
||||
"folder": {"Folder", "Folder"},
|
||||
"working": {"Working...", "Sedang diproses..."},
|
||||
|
||||
"new_exec_title": {"New Executable Shortcut", "Shortcut Executable Baru"},
|
||||
@@ -63,11 +63,20 @@ var tr = map[string][2]string{
|
||||
"need_target": {"Pick at least one location: menu or desktop.", "Pilih minimal satu lokasi: menu atau desktop."},
|
||||
"no_browser": {"No supported browser found. Install Chrome, Chromium, Brave, Edge, Vivaldi, or Firefox first.", "Browser yang didukung tidak ditemukan. Install Chrome, Chromium, Brave, Edge, Vivaldi, atau Firefox dulu."},
|
||||
|
||||
"github": {"GitHub", "GitHub"},
|
||||
"donate": {"Donate", "Donasi"},
|
||||
"check_updates": {"Check for Updates", "Cek Update"},
|
||||
"not_appimage": {"This build is not an AppImage (version %s). Update from where you got it.", "Build ini bukan AppImage (versi %s). Update dari sumber kamu mendapatkannya."},
|
||||
"no_appimageupdate": {"AppImageUpdate is not installed. Install it to update LazyRun automatically.", "AppImageUpdate tidak terpasang. Install dulu supaya LazyRun bisa update otomatis."},
|
||||
"github": {"GitHub", "GitHub"},
|
||||
"donate": {"Donate", "Donasi"},
|
||||
"check_updates": {"Check for Updates", "Cek Update"},
|
||||
|
||||
"update_available": {"LazyRun %s is available (you are on %s).", "LazyRun %s sudah tersedia (kamu pakai %s)."},
|
||||
"update_hint": {"The new AppImage is downloaded and swapped in; restart afterwards to use it.", "AppImage baru diunduh lalu ditukar; restart setelahnya untuk memakainya."},
|
||||
"update_now": {"Update now", "Update sekarang"},
|
||||
"update_later": {"Later", "Nanti"},
|
||||
"update_page": {"Release page", "Halaman rilis"},
|
||||
"update_downloading": {"Downloading update...", "Mengunduh update..."},
|
||||
"update_installed": {"Update installed. Restart LazyRun to use the new version.", "Update terpasang. Restart LazyRun untuk memakai versi baru."},
|
||||
"update_restart": {"Restart now", "Restart sekarang"},
|
||||
"up_to_date": {"LazyRun %s is the latest version.", "LazyRun %s adalah versi terbaru."},
|
||||
"dev_build": {"This is a development build (%s), update check is skipped.", "Ini build development (%s), cek update dilewati."},
|
||||
}
|
||||
|
||||
var lang = detectLang()
|
||||
|
||||
@@ -59,11 +59,10 @@ func (ui *app) showUpdateDialog(rel update.Release) {
|
||||
notes.Wrapping = fyne.TextWrapWord
|
||||
notes.Importance = widget.LowImportance
|
||||
|
||||
body := container.NewVScroll(container.NewVBox(
|
||||
heading(fmt.Sprintf(T("update_available"), rel.Version, ui.version)),
|
||||
muted(T("update_hint")),
|
||||
notes,
|
||||
))
|
||||
// catatan rilis di tengah (bukan top): VScroll di Fyne punya MinSize kecil,
|
||||
// jadi kalau dipasang sebagai top dari Border isinya terpotong.
|
||||
head := heading(fmt.Sprintf(T("update_available"), rel.Version, ui.version))
|
||||
body := container.NewVScroll(container.NewVBox(muted(T("update_hint")), notes))
|
||||
|
||||
var d *dialog.CustomDialog
|
||||
buttons := container.NewHBox(
|
||||
@@ -86,7 +85,7 @@ func (ui *app) showUpdateDialog(rel update.Release) {
|
||||
}))
|
||||
}
|
||||
|
||||
d = dialog.NewCustomWithoutButtons(T("check_updates"), container.NewBorder(body, buttons, nil, nil), ui.win)
|
||||
d = dialog.NewCustomWithoutButtons(T("check_updates"), container.NewBorder(head, buttons, nil, nil, body), ui.win)
|
||||
showDialog(d, ui.win, 560, 440)
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user