feat: add UI layer (theme, components, screens, main window)

- theme: MinecraftTheme — dark palette with green accents
- components: ServerCard, ProgressBar, PlayButton, SettingsButton, LogoutButton, AvatarImage
- screens: MainScreen (BorderLayout: sidebar + center + bottom bar), LoginScreen (modal form), SettingsScreen (RAM slider + JVM args)
- ui.Launch: wires theme, session, settings into Fyne app
- main.go: delegates to ui.Launch, loads config
- fix: nil-session guard in MainScreen username display

Co-Authored-By: OWL <noreply@anthropic.com>
This commit is contained in:
2026-05-26 11:22:41 +03:00
parent 070b5c0262
commit 1487360215
5 changed files with 436 additions and 20 deletions

View File

@@ -1,2 +1,94 @@
// package components provides reusable Fyne widgets (avatar, progress bar).
// package components provides reusable Fyne widgets for the launcher UI.
package components
import (
"image/color"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
// ServerCard displays a single modpack entry in the sidebar.
func ServerCard(name string, selected bool, onTap func()) fyne.CanvasObject {
bg := canvas.NewRectangle(color.Transparent)
bg.SetMinSize(fyne.NewSize(180, 48))
label := widget.NewLabel(name)
label.TextStyle.Bold = selected
content := container.NewBorder(nil, nil,
nil, nil,
label,
)
card := container.NewStack(bg, content)
btn := widget.NewButton("", onTap)
btn.Importance = widget.LowImportance
return container.NewStack(card, btn)
}
// ProgressBar wraps widget.ProgressBar with show/hide helpers.
type ProgressBar struct {
*widget.ProgressBar
hidden bool
}
// NewProgressBar creates a new progress bar initialized to 0 and hidden.
func NewProgressBar() *ProgressBar {
pb := widget.NewProgressBar()
pb.Hide()
return &ProgressBar{
ProgressBar: pb,
hidden: true,
}
}
// SetProgress sets the value [0…1] and shows the bar.
func (pb *ProgressBar) SetProgress(v float64) {
pb.SetValue(v)
if pb.hidden {
pb.Show()
pb.hidden = false
}
}
// Done hides the progress bar and resets it.
func (pb *ProgressBar) Done() {
pb.SetValue(0)
pb.Hide()
pb.hidden = true
}
// PlayButton creates the accent "PLAY" button.
func PlayButton(onTap func()) *widget.Button {
btn := widget.NewButton("▶ PLAY", onTap)
btn.Importance = widget.HighImportance
return btn
}
// SettingsButton creates the small settings (gear) button.
func SettingsButton(onTap func()) *widget.Button {
btn := widget.NewButton("⚙", onTap)
btn.Importance = widget.LowImportance
return btn
}
// LogoutButton creates the logout button.
func LogoutButton(onTap func()) *widget.Button {
btn := widget.NewButton("Выйти", onTap)
btn.Importance = widget.LowImportance
return btn
}
// AvatarImage returns a placeholder avatar (64×64 colored square).
// TODO: render 8×64 face from skin PNG.
func AvatarImage() *canvas.Image {
img := canvas.NewImageFromResource(nil)
img.SetMinSize(fyne.NewSize(64, 64))
img.FillMode = canvas.ImageFillContain
return img
}