UI: tema brand LazyRun, layout kartu, dan dialog yang lebih rapi

- Tema custom (indigo/cyan dari ikon, sudut membulat) mengikuti varian sistem
- Header compact: logo + wordmark, tombol aksi di kanan
- Kartu per shortcut: ikon, nama, meta singkat, chip lokasi, tombol ikon
- Teks satu baris pakai canvas.Text (widget.Label Fyne 2.8 memesan tinggi ~2x)
- Dialog: judul bagian, ikon folder pada Browse, tombol Install primary
This commit is contained in:
oxpoe committed 2026-10-13 08:00:12 +07:00
1 parent da31f7d7d7
commit 1935b5d83d
7 files changed
+316 -65

No files matched your search

+104
View File
@@ -0,0 +1,104 @@
package ui
import (
"os"
"strings"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
"lazyrun/assets"
)
// catatan: widget.Label di Fyne 2.8 selalu memesan tinggi ~2x ukuran font,
// jadi teks satu baris di UI utama memakai canvas.Text supaya rapat.
// textLine membuat teks satu baris berukuran & berwarna tertentu.
func textLine(text string, size float32, bold bool, col fyne.ThemeColorName) *canvas.Text {
t := canvas.NewText(text, theme.Color(col))
t.TextSize = size
t.TextStyle = fyne.TextStyle{Bold: bold}
return t
}
// heading adalah nama aplikasi di header.
func heading(text string) *canvas.Text {
return textLine(text, 22, true, theme.ColorNameForeground)
}
// subheading adalah nama shortcut di kartu.
func subheading(text string) *canvas.Text {
return textLine(text, 15, true, theme.ColorNameForeground)
}
// caption adalah teks sekunder kecil (tagline, path, versi).
func caption(text string) *canvas.Text {
return textLine(text, 12, false, colorNameMuted)
}
// sectionLabel adalah judul bagian huruf kapital.
func sectionLabel(text string) *canvas.Text {
return textLine(strings.ToUpper(text), 11, true, colorNameMuted)
}
// muted adalah teks sekunder yang bisa wrap/truncate (dipakai di dialog).
func muted(text string) *widget.Label {
label := widget.NewLabel(text)
label.Importance = widget.LowImportance
return label
}
// card membungkus konten dengan latar membulat.
func card(content fyne.CanvasObject) fyne.CanvasObject {
bg := canvas.NewRectangle(theme.Color(colorNameCard))
bg.CornerRadius = 12
return container.NewStack(bg, container.NewPadded(content))
}
// chip adalah label kecil dengan latar berwarna.
func chip(text string, bg fyne.ThemeColorName) fyne.CanvasObject {
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))
}
// iconButton adalah tombol ikon tanpa label, gaya datar.
func iconButton(icon fyne.Resource, tapped func()) *widget.Button {
button := widget.NewButtonWithIcon("", icon, tapped)
button.Importance = widget.LowImportance
return button
}
// thumb menampilkan ikon shortcut, atau fallback kalau file ikonnya hilang.
func thumb(path string, fallback fyne.Resource) fyne.CanvasObject {
var image *canvas.Image
if path != "" {
if _, err := os.Stat(path); err == nil {
image = canvas.NewImageFromURI(storage.NewFileURI(path))
}
}
if image == nil {
image = canvas.NewImageFromResource(theme.NewThemedResource(fallback))
}
image.FillMode = canvas.ImageFillContain
image.SetMinSize(fyne.NewSize(36, 36))
return container.NewGridWrap(fyne.NewSize(36, 36), image)
}
// logoImage menampilkan ikon LazyRun pada ukuran tertentu.
func logoImage(size float32) fyne.CanvasObject {
image := canvas.NewImageFromResource(fyne.NewStaticResource("lazyrun.png", assets.Icon))
image.FillMode = canvas.ImageFillContain
image.SetMinSize(fyne.NewSize(size, size))
return container.NewGridWrap(fyne.NewSize(size, size), image)
}
// spacer adalah pengisi ruang kosong.
func spacer() fyne.CanvasObject { return layout.NewSpacer() }