chore(gui): align AX naming and docs
Some checks are pending
Security Scan / security (push) Waiting to run
Test / test (push) Waiting to run

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-02 19:50:55 +00:00
parent 8db26398af
commit 81503d0968
9 changed files with 61 additions and 31 deletions

View file

@ -3,9 +3,8 @@ package display
import "github.com/wailsapp/wails/v3/pkg/application"
// App abstracts the Wails application for the orchestrator.
// After Spec D cleanup, only Quit() and Logger() remain —
// all other Wails Manager APIs are accessed via IPC.
// App abstracts the Wails application for the display orchestrator.
// The service uses Logger() for diagnostics and Quit() for shutdown.
type App interface {
Logger() Logger
Quit()

View file

@ -13,5 +13,5 @@ type TaskRequestPermission struct{}
// TaskClear clears pending notifications when the backend supports it.
type TaskClear struct{}
// ActionNotificationClicked is broadcast when a notification is clicked (future).
// ActionNotificationClicked is broadcast when a notification is clicked.
type ActionNotificationClicked struct{ ID string }

View file

@ -70,7 +70,7 @@ func (s *Service) handleQuery(c *core.Core, q core.Query) (any, bool, error) {
func (s *Service) handleTask(c *core.Core, t core.Task) (any, bool, error) {
switch t := t.(type) {
case TaskSend:
return nil, true, s.send(t.Opts)
return nil, true, s.sendNotification(t.Opts)
case TaskRequestPermission:
granted, err := s.platform.RequestPermission()
return granted, true, err
@ -84,9 +84,9 @@ func (s *Service) handleTask(c *core.Core, t core.Task) (any, bool, error) {
}
}
// send attempts native notification, falls back to dialog via IPC.
func (s *Service) send(opts NotificationOptions) error {
// Generate ID if not provided
// sendNotification attempts a native notification and falls back to a dialog via IPC.
func (s *Service) sendNotification(opts NotificationOptions) error {
// Generate an ID when the caller does not provide one.
if opts.ID == "" {
opts.ID = fmt.Sprintf("core-%d", time.Now().UnixNano())
}
@ -100,15 +100,15 @@ func (s *Service) send(opts NotificationOptions) error {
}
if err := s.platform.Send(opts); err != nil {
// Fallback: show as dialog via IPC
return s.fallbackDialog(opts)
// Fall back to a dialog when the native notification fails.
return s.showFallbackDialog(opts)
}
return nil
}
// fallbackDialog shows a dialog via IPC when native notifications fail.
func (s *Service) fallbackDialog(opts NotificationOptions) error {
// Map severity to dialog type
// showFallbackDialog shows a dialog via IPC when native notifications fail.
func (s *Service) showFallbackDialog(opts NotificationOptions) error {
// Map severity to dialog type.
var dt dialog.DialogType
switch opts.Severity {
case SeverityWarning:

View file

@ -16,5 +16,5 @@ type QueryAtPoint struct{ X, Y int }
// QueryWorkAreas returns work areas for all screens. Result: []Rect
type QueryWorkAreas struct{}
// ActionScreensChanged is broadcast when displays change (future).
// ActionScreensChanged is broadcast when displays change.
type ActionScreensChanged struct{ Screens []Screen }

View file

@ -1,3 +1,4 @@
// pkg/systray/service.go
package systray
import (
@ -76,7 +77,7 @@ func (s *Service) handleTask(c *core.Core, t core.Task) (any, bool, error) {
case TaskHidePanel:
return nil, true, s.manager.HidePanel()
case TaskShowMessage:
return nil, true, s.taskShowMessage(t.Title, t.Message)
return nil, true, s.showTrayMessage(t.Title, t.Message)
default:
return nil, false, nil
}
@ -95,7 +96,7 @@ func (s *Service) taskSetTrayMenu(t TaskSetTrayMenu) error {
return s.manager.SetMenu(t.Items)
}
func (s *Service) taskShowMessage(title, message string) error {
func (s *Service) showTrayMessage(title, message string) error {
if s.manager == nil || !s.manager.IsActive() {
_, _, err := s.Core().PERFORM(notification.TaskSend{
Opts: notification.NotificationOptions{Title: title, Message: message},
@ -104,7 +105,7 @@ func (s *Service) taskShowMessage(title, message string) error {
}
tray := s.manager.Tray()
if tray == nil {
return core.E("systray.taskShowMessage", "tray not initialised", nil)
return core.E("systray.showTrayMessage", "tray not initialised", nil)
}
if messenger, ok := tray.(interface{ ShowMessage(title, message string) }); ok {
messenger.ShowMessage(title, message)

View file

@ -1,5 +1,4 @@
// pkg/webview/messages.go
// pkg/webview/messages.go
package webview
import "time"

View file

@ -34,6 +34,7 @@ type LayoutManager struct {
}
// NewLayoutManager creates a LayoutManager loading from the default config directory.
// Use: lm := window.NewLayoutManager()
func NewLayoutManager() *LayoutManager {
lm := &LayoutManager{
layouts: make(map[string]Layout),
@ -42,30 +43,31 @@ func NewLayoutManager() *LayoutManager {
if err == nil {
lm.configDir = filepath.Join(configDir, "Core")
}
lm.load()
lm.loadLayouts()
return lm
}
// NewLayoutManagerWithDir creates a LayoutManager loading from a custom config directory.
// Useful for testing or when the default config directory is not appropriate.
// Use: lm := window.NewLayoutManagerWithDir(t.TempDir())
func NewLayoutManagerWithDir(configDir string) *LayoutManager {
lm := &LayoutManager{
configDir: configDir,
layouts: make(map[string]Layout),
}
lm.load()
lm.loadLayouts()
return lm
}
func (lm *LayoutManager) filePath() string {
func (lm *LayoutManager) layoutsFilePath() string {
return filepath.Join(lm.configDir, "layouts.json")
}
func (lm *LayoutManager) load() {
func (lm *LayoutManager) loadLayouts() {
if lm.configDir == "" {
return
}
data, err := os.ReadFile(lm.filePath())
data, err := os.ReadFile(lm.layoutsFilePath())
if err != nil {
return
}
@ -74,7 +76,7 @@ func (lm *LayoutManager) load() {
_ = json.Unmarshal(data, &lm.layouts)
}
func (lm *LayoutManager) save() {
func (lm *LayoutManager) saveLayouts() {
if lm.configDir == "" {
return
}
@ -85,10 +87,11 @@ func (lm *LayoutManager) save() {
return
}
_ = os.MkdirAll(lm.configDir, 0o755)
_ = os.WriteFile(lm.filePath(), data, 0o644)
_ = os.WriteFile(lm.layoutsFilePath(), data, 0o644)
}
// SaveLayout creates or updates a named layout.
// Use: _ = lm.SaveLayout("coding", windowStates)
func (lm *LayoutManager) SaveLayout(name string, windowStates map[string]WindowState) error {
if name == "" {
return fmt.Errorf("layout name cannot be empty")
@ -108,11 +111,12 @@ func (lm *LayoutManager) SaveLayout(name string, windowStates map[string]WindowS
}
lm.layouts[name] = layout
lm.mu.Unlock()
lm.save()
lm.saveLayouts()
return nil
}
// GetLayout returns a layout by name.
// Use: layout, ok := lm.GetLayout("coding")
func (lm *LayoutManager) GetLayout(name string) (Layout, bool) {
lm.mu.RLock()
defer lm.mu.RUnlock()
@ -121,6 +125,7 @@ func (lm *LayoutManager) GetLayout(name string) (Layout, bool) {
}
// ListLayouts returns info summaries for all layouts.
// Use: layouts := lm.ListLayouts()
func (lm *LayoutManager) ListLayouts() []LayoutInfo {
lm.mu.RLock()
defer lm.mu.RUnlock()
@ -135,9 +140,10 @@ func (lm *LayoutManager) ListLayouts() []LayoutInfo {
}
// DeleteLayout removes a layout by name.
// Use: lm.DeleteLayout("coding")
func (lm *LayoutManager) DeleteLayout(name string) {
lm.mu.Lock()
delete(lm.layouts, name)
lm.mu.Unlock()
lm.save()
lm.saveLayouts()
}

View file

@ -5,6 +5,7 @@ package window
type WindowOption func(*Window) error
// ApplyOptions creates a Window and applies all options in order.
// Use: w, err := window.ApplyOptions(window.WithName("editor"), window.WithURL("/editor"))
func ApplyOptions(opts ...WindowOption) (*Window, error) {
w := &Window{}
for _, opt := range opts {
@ -18,50 +19,74 @@ func ApplyOptions(opts ...WindowOption) (*Window, error) {
return w, nil
}
// WithName sets the window name.
// Use: window.WithName("editor")
func WithName(name string) WindowOption {
return func(w *Window) error { w.Name = name; return nil }
}
// WithTitle sets the window title.
// Use: window.WithTitle("Core Editor")
func WithTitle(title string) WindowOption {
return func(w *Window) error { w.Title = title; return nil }
}
// WithURL sets the initial window URL.
// Use: window.WithURL("/editor")
func WithURL(url string) WindowOption {
return func(w *Window) error { w.URL = url; return nil }
}
// WithSize sets the initial window size.
// Use: window.WithSize(1280, 800)
func WithSize(width, height int) WindowOption {
return func(w *Window) error { w.Width = width; w.Height = height; return nil }
}
// WithPosition sets the initial window position.
// Use: window.WithPosition(160, 120)
func WithPosition(x, y int) WindowOption {
return func(w *Window) error { w.X = x; w.Y = y; return nil }
}
// WithMinSize sets the minimum window size.
// Use: window.WithMinSize(640, 480)
func WithMinSize(width, height int) WindowOption {
return func(w *Window) error { w.MinWidth = width; w.MinHeight = height; return nil }
}
// WithMaxSize sets the maximum window size.
// Use: window.WithMaxSize(1920, 1080)
func WithMaxSize(width, height int) WindowOption {
return func(w *Window) error { w.MaxWidth = width; w.MaxHeight = height; return nil }
}
// WithFrameless toggles the native window frame.
// Use: window.WithFrameless(true)
func WithFrameless(frameless bool) WindowOption {
return func(w *Window) error { w.Frameless = frameless; return nil }
}
// WithHidden starts the window hidden.
// Use: window.WithHidden(true)
func WithHidden(hidden bool) WindowOption {
return func(w *Window) error { w.Hidden = hidden; return nil }
}
// WithAlwaysOnTop keeps the window above other windows.
// Use: window.WithAlwaysOnTop(true)
func WithAlwaysOnTop(alwaysOnTop bool) WindowOption {
return func(w *Window) error { w.AlwaysOnTop = alwaysOnTop; return nil }
}
// WithBackgroundColour sets the window background colour with alpha.
// Use: window.WithBackgroundColour(0, 0, 0, 0)
func WithBackgroundColour(r, g, b, a uint8) WindowOption {
return func(w *Window) error { w.BackgroundColour = [4]uint8{r, g, b, a}; return nil }
}
// WithFileDrop enables drag-and-drop file handling.
// Use: window.WithFileDrop(true)
func WithFileDrop(enabled bool) WindowOption {
return func(w *Window) error { w.EnableFileDrop = enabled; return nil }
}

View file

@ -295,19 +295,19 @@ func (s *Service) taskSetPosition(name string, x, y int) error {
return nil
}
func (s *Service) taskSetSize(name string, width, height, legacyWidth, legacyHeight int) error {
func (s *Service) taskSetSize(name string, width, height, fallbackWidth, fallbackHeight int) error {
pw, ok := s.manager.Get(name)
if !ok {
return fmt.Errorf("window not found: %s", name)
}
if width == 0 && height == 0 {
width, height = legacyWidth, legacyHeight
width, height = fallbackWidth, fallbackHeight
} else {
if width == 0 {
width = legacyWidth
width = fallbackWidth
}
if height == 0 {
height = legacyHeight
height = fallbackHeight
}
}
pw.SetSize(width, height)