UI: tombol GitHub + Donasi, tombol Open per shortcut, aksen gradien
- Footer: Check for Updates, GitHub (github.com/oxpoe/lazyrun), Donate (donasi.oxpoe.qzz.io) - Baris shortcut: tombol play untuk menjalankan (pakai exec_args hasil install) - metadata shortcut menyimpan exec_args; ada fallback ke binary/URL untuk data lama - Chip jumlah shortcut di header daftar + garis gradien brand di bawah header - README: link repo & donasi absolut
This commit is contained in:
1 parent
f00662627a
commit
b12efefd6a
10 files changed
+111
-4
No files matched your search
@@ -0,0 +1,51 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"os/exec"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
|
||||
"lazyrun/internal/store"
|
||||
)
|
||||
|
||||
// Link aplikasi: repo GitHub LazyRun dan halaman donasi.
|
||||
const (
|
||||
repoURL = "https://github.com/oxpoe/lazyrun"
|
||||
donateURL = "https://donasi.oxpoe.qzz.io/"
|
||||
)
|
||||
|
||||
// openURL membuka link di browser default.
|
||||
func (ui *app) openURL(raw string) {
|
||||
u, err := url.Parse(raw)
|
||||
if err == nil {
|
||||
err = fyne.CurrentApp().OpenURL(u)
|
||||
}
|
||||
if err != nil {
|
||||
dialog.ShowError(err, ui.win)
|
||||
}
|
||||
}
|
||||
|
||||
// launch menjalankan shortcut: pakai argv hasil install, fallback ke binary/URL.
|
||||
func (ui *app) launch(sc store.Shortcut) {
|
||||
args := sc.ExecArgs
|
||||
if len(args) == 0 {
|
||||
switch {
|
||||
case sc.Type == store.TypeWebApp && sc.URL != "":
|
||||
args = []string{"xdg-open", sc.URL}
|
||||
case sc.BinaryPath != "":
|
||||
args = []string{sc.BinaryPath}
|
||||
}
|
||||
}
|
||||
if len(args) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
if err := cmd.Start(); err != nil {
|
||||
dialog.ShowError(err, ui.win)
|
||||
return
|
||||
}
|
||||
go cmd.Wait() // supaya proses anak tidak jadi zombie
|
||||
}
|
||||
@@ -5,8 +5,10 @@ import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
@@ -24,6 +26,7 @@ type app struct {
|
||||
store *store.Store
|
||||
browsers []browser.Browser
|
||||
rows *fyne.Container
|
||||
count *canvas.Text // angka jumlah shortcut di header daftar
|
||||
version string
|
||||
}
|
||||
|
||||
@@ -46,6 +49,8 @@ func build(a fyne.App, version string) (*app, error) {
|
||||
|
||||
ui.browsers = browser.Detect()
|
||||
ui.rows = container.NewVBox()
|
||||
countChip, count := chipLabel("0", colorNameChipMenu)
|
||||
ui.count = count
|
||||
ui.win = a.NewWindow(T("app_title"))
|
||||
ui.win.Resize(fyne.NewSize(840, 600))
|
||||
|
||||
@@ -64,13 +69,17 @@ func build(a fyne.App, version string) (*app, error) {
|
||||
header := container.NewBorder(nil, nil, leftHeader, rightHeader)
|
||||
|
||||
update := widget.NewButtonWithIcon(T("check_updates"), theme.DownloadIcon(), ui.checkUpdates)
|
||||
github := widget.NewButton(T("github"), func() { ui.openURL(repoURL) })
|
||||
donate := widget.NewButtonWithIcon(T("donate"),
|
||||
fyne.NewStaticResource("heart.png", assets.Heart), func() { ui.openURL(donateURL) })
|
||||
footer := container.NewBorder(
|
||||
widget.NewSeparator(), nil,
|
||||
update,
|
||||
container.NewHBox(update, github, donate),
|
||||
caption("v"+version),
|
||||
)
|
||||
|
||||
top := container.NewVBox(header, widget.NewSeparator(), sectionLabel(T("installed")))
|
||||
top := container.NewVBox(header, accentBar(),
|
||||
container.NewHBox(sectionLabel(T("installed")), countChip))
|
||||
body := container.NewBorder(
|
||||
top,
|
||||
nil, nil, nil,
|
||||
@@ -92,6 +101,8 @@ func (ui *app) reload() {
|
||||
ui.store = st
|
||||
}
|
||||
ui.rows.RemoveAll()
|
||||
ui.count.Text = strconv.Itoa(len(ui.store.Items))
|
||||
ui.count.Refresh()
|
||||
if len(ui.store.Items) == 0 {
|
||||
ui.rows.Add(emptyState())
|
||||
}
|
||||
@@ -118,6 +129,7 @@ func (ui *app) row(sc store.Shortcut) fyne.CanvasObject {
|
||||
}
|
||||
|
||||
actions := container.NewHBox(chips...)
|
||||
actions.Add(iconButton(theme.MediaPlayIcon(), func() { ui.launch(sc) }))
|
||||
actions.Add(iconButton(theme.FolderOpenIcon(), func() {
|
||||
if err := exec.Command("xdg-open", filepath.Dir(sc.DesktopPath)).Start(); err != nil {
|
||||
dialog.ShowError(err, ui.win)
|
||||
|
||||
@@ -55,6 +55,8 @@ 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."},
|
||||
|
||||
+14
-1
@@ -62,11 +62,24 @@ func card(content fyne.CanvasObject) fyne.CanvasObject {
|
||||
|
||||
// chip adalah label kecil dengan latar berwarna.
|
||||
func chip(text string, bg fyne.ThemeColorName) fyne.CanvasObject {
|
||||
object, _ := chipLabel(text, bg)
|
||||
return object
|
||||
}
|
||||
|
||||
// chipLabel mengembalikan chip sekaligus teksnya supaya bisa diperbarui.
|
||||
func chipLabel(text string, bg fyne.ThemeColorName) (fyne.CanvasObject, *canvas.Text) {
|
||||
rect := canvas.NewRectangle(theme.Color(bg))
|
||||
rect.CornerRadius = 7
|
||||
label := textLine(text, 11, true, theme.ColorNameForeground)
|
||||
label.Alignment = fyne.TextAlignCenter
|
||||
return container.NewStack(rect, container.NewPadded(label))
|
||||
return container.NewStack(rect, container.NewPadded(label)), label
|
||||
}
|
||||
|
||||
// accentBar adalah garis gradien brand di bawah header.
|
||||
func accentBar() fyne.CanvasObject {
|
||||
bar := canvas.NewLinearGradient(brandIndigo, brandCyan, 90)
|
||||
bar.SetMinSize(fyne.NewSize(0, 3))
|
||||
return bar
|
||||
}
|
||||
|
||||
// iconButton adalah tombol ikon tanpa label, gaya datar.
|
||||
|
||||
Reference in new issue
Block a user