Label jenis aplikasi dengan auto-detect (Go/AppImage/Electron/Script/Windows/Binary/PWA)
- internal/shortcut/kind.go: deteksi dari isi berkas - build info Go, magic AppImage, resources/*.asar untuk Electron, shebang untuk script, MZ untuk .exe - .exe Windows kini boleh dipasang dan dijalankan lewat wine (Exec=wine <path>); kalau wine tidak terpasang, install ditolak dengan pesan jelas - metadata menyimpan kind; chip jenis ditampilkan di setiap baris shortcut (data lama tetap tampil sebagai Executable/PWA) - dialog menampilkan hasil deteksi setelah berkas dipilih, mis. 'winbox.exe - windows' - README: bagian label otomatis + screenshot baru
This commit is contained in:
1 parent
41ada9a506
commit
d6f6c69c5a
13 files changed
+249
-13
No files matched your search
@@ -44,7 +44,7 @@ func (ui *app) showExecutableDialog() {
|
||||
browseBin := widget.NewButtonWithIcon(T("browse"), theme.FolderOpenIcon(), func() {
|
||||
pickFile(ui.win, nil, func(path string) {
|
||||
binPath = path
|
||||
binLabel.SetText(filepath.Base(path))
|
||||
binLabel.SetText(filepath.Base(path) + " · " + detectedKind(path))
|
||||
if strings.TrimSpace(nameEntry.Text) == "" {
|
||||
nameEntry.SetText(appNameFromFile(path))
|
||||
}
|
||||
@@ -136,6 +136,15 @@ func pickFile(win fyne.Window, filter storage.FileFilter, onPick func(path strin
|
||||
fd.Show()
|
||||
}
|
||||
|
||||
// detectedKind menampilkan hasil auto-detect jenis berkas di dialog.
|
||||
func detectedKind(path string) string {
|
||||
kind := shortcut.DetectKind(path)
|
||||
if kind == "" {
|
||||
return T("kind_unknown")
|
||||
}
|
||||
return kind
|
||||
}
|
||||
|
||||
func appNameFromFile(path string) string {
|
||||
base := filepath.Base(path)
|
||||
for _, ext := range stripExts {
|
||||
|
||||
@@ -129,7 +129,8 @@ func (ui *app) row(sc store.Shortcut) *hoverCard {
|
||||
caption(metaText(sc)),
|
||||
)
|
||||
|
||||
chips := make([]fyne.CanvasObject, 0, 3)
|
||||
chips := make([]fyne.CanvasObject, 0, 4)
|
||||
chips = append(chips, chip(kindLabel(sc), colorNameChipKind))
|
||||
if sc.Targets.Menu {
|
||||
chips = append(chips, chip(T("chip_menu"), colorNameChipMenu))
|
||||
}
|
||||
@@ -157,18 +158,44 @@ func (ui *app) row(sc store.Shortcut) *hoverCard {
|
||||
actions))
|
||||
}
|
||||
|
||||
// metaText menampilkan tipe shortcut dan penanda singkatnya.
|
||||
// kindLabel adalah label jenis aplikasi hasil auto-detect.
|
||||
// Istilahnya teknis (nama teknologi), jadi tidak diterjemahkan.
|
||||
func kindLabel(sc store.Shortcut) string {
|
||||
switch sc.Kind {
|
||||
case shortcut.KindGo:
|
||||
return "Go"
|
||||
case shortcut.KindAppImage:
|
||||
return "AppImage"
|
||||
case shortcut.KindElectron:
|
||||
return "Electron"
|
||||
case shortcut.KindScript:
|
||||
return "Script"
|
||||
case shortcut.KindWindows:
|
||||
return "Windows"
|
||||
case shortcut.KindBinary:
|
||||
return "Binary"
|
||||
case shortcut.KindPWA:
|
||||
return "PWA"
|
||||
}
|
||||
// shortcut lama (sebelum ada auto-detect)
|
||||
if sc.Type == store.TypeWebApp {
|
||||
return "PWA"
|
||||
}
|
||||
return "Executable"
|
||||
}
|
||||
|
||||
// metaText menampilkan penanda singkat: nama berkas binary atau host web app.
|
||||
func metaText(sc store.Shortcut) string {
|
||||
if sc.Type == store.TypeWebApp {
|
||||
if host := hostOf(sc.URL); host != "" {
|
||||
return "Web · " + host
|
||||
return host
|
||||
}
|
||||
return "Web"
|
||||
return sc.URL
|
||||
}
|
||||
if sc.BinaryPath != "" {
|
||||
return "Executable · " + filepath.Base(sc.BinaryPath)
|
||||
return filepath.Base(sc.BinaryPath)
|
||||
}
|
||||
return "Executable"
|
||||
return sc.Name
|
||||
}
|
||||
|
||||
func fallbackIcon(sc store.Shortcut) fyne.Resource {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"fyne.io/fyne/v2/test"
|
||||
|
||||
"lazyrun/internal/shortcut"
|
||||
"lazyrun/internal/store"
|
||||
)
|
||||
|
||||
@@ -28,11 +29,37 @@ func TestBuildMainWindow(t *testing.T) {
|
||||
|
||||
func TestMetaText(t *testing.T) {
|
||||
sc := store.Shortcut{Type: store.TypeWebApp, URL: "https://example.com/x", Targets: store.Targets{Menu: true}}
|
||||
if got := metaText(sc); got != "Web · example.com" {
|
||||
if got := metaText(sc); got != "example.com" {
|
||||
t.Errorf("metaText() = %q", got)
|
||||
}
|
||||
exe := store.Shortcut{Type: store.TypeExecutable, BinaryPath: "/home/u/.local/bin/winbox"}
|
||||
if got := metaText(exe); got != "Executable · winbox" {
|
||||
if got := metaText(exe); got != "winbox" {
|
||||
t.Errorf("metaText() = %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKindLabel(t *testing.T) {
|
||||
cases := map[string]string{
|
||||
shortcut.KindGo: "Go",
|
||||
shortcut.KindAppImage: "AppImage",
|
||||
shortcut.KindElectron: "Electron",
|
||||
shortcut.KindScript: "Script",
|
||||
shortcut.KindWindows: "Windows",
|
||||
shortcut.KindBinary: "Binary",
|
||||
shortcut.KindPWA: "PWA",
|
||||
}
|
||||
for kind, want := range cases {
|
||||
sc := store.Shortcut{Kind: kind, Type: store.TypeExecutable}
|
||||
if got := kindLabel(sc); got != want {
|
||||
t.Errorf("kindLabel(%q) = %q, mau %q", kind, got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// data lama tanpa kind
|
||||
if got := kindLabel(store.Shortcut{Type: store.TypeExecutable}); got != "Executable" {
|
||||
t.Errorf("kindLabel(lama, executable) = %q", got)
|
||||
}
|
||||
if got := kindLabel(store.Shortcut{Type: store.TypeWebApp}); got != "PWA" {
|
||||
t.Errorf("kindLabel(lama, webapp) = %q", got)
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ var tr = map[string][2]string{
|
||||
"chip_desktop": {"Desktop", "Desktop"},
|
||||
"chip_broken": {"file missing", "file hilang"},
|
||||
"none": {"not selected", "belum dipilih"},
|
||||
"kind_unknown": {"unknown type", "jenis tidak dikenal"},
|
||||
"icon_auto": {"automatic", "otomatis"},
|
||||
"online": {"Online", "Online"},
|
||||
"search": {"Search", "Cari"},
|
||||
|
||||
@@ -21,6 +21,7 @@ const (
|
||||
colorNameChipMenu fyne.ThemeColorName = "lazyrunChipMenu"
|
||||
colorNameChipDesk fyne.ThemeColorName = "lazyrunChipDesktop"
|
||||
colorNameChipBroken fyne.ThemeColorName = "lazyrunChipBroken"
|
||||
colorNameChipKind fyne.ThemeColorName = "lazyrunChipKind"
|
||||
)
|
||||
|
||||
// brand menimpa sebagian warna/ukuran tema bawaan; terang/gelap tetap ikut sistem.
|
||||
@@ -51,6 +52,8 @@ func (b brand) Color(name fyne.ThemeColorName, variant fyne.ThemeVariant) color.
|
||||
return withAlpha(brandIndigo, pick[uint8](dark, 0x44, 0x26))
|
||||
case colorNameChipDesk:
|
||||
return withAlpha(brandCyan, pick[uint8](dark, 0x3D, 0x2C))
|
||||
case colorNameChipKind:
|
||||
return pick(dark, color.NRGBA{R: 0xFF, G: 0xFF, B: 0xFF, A: 0x1C}, color.NRGBA{R: 0x00, G: 0x00, B: 0x00, A: 0x12})
|
||||
case colorNameChipBroken:
|
||||
return withAlpha(color.NRGBA{R: 0xE0, G: 0x4F, B: 0x4F, A: 0xFF}, pick[uint8](dark, 0x4A, 0x2E))
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user