From c3361b7064066a2d56e6dfd5701fdbd5c8dbbace Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 14:13:58 +0000 Subject: [PATCH] refactor(gui): align gui services with ax guidance --- pkg/clipboard/service.go | 29 ++++++++++++++++++++++------- pkg/display/display.go | 18 +++++++++--------- pkg/notification/service.go | 26 +++++++++++++++++++++----- pkg/systray/menu.go | 4 ++-- pkg/systray/service.go | 23 +++++++++++++++++------ pkg/systray/tray.go | 24 ++++++++++++++++-------- 6 files changed, 87 insertions(+), 37 deletions(-) diff --git a/pkg/clipboard/service.go b/pkg/clipboard/service.go index 8f5a3dd..9c47765 100644 --- a/pkg/clipboard/service.go +++ b/pkg/clipboard/service.go @@ -3,21 +3,32 @@ package clipboard import ( "context" - "fmt" "forge.lthn.ai/core/go/pkg/core" ) -// Options holds configuration for the clipboard service. +// Options configures the clipboard service. +// +// Example: +// +// core.WithService(clipboard.Register(platform)) type Options struct{} -// Service is a core.Service managing clipboard operations via IPC. +// Service manages clipboard operations via Core queries and tasks. +// +// Example: +// +// svc := &clipboard.Service{} type Service struct { *core.ServiceRuntime[Options] platform Platform } -// Register creates a factory closure that captures the Platform adapter. +// Register creates a Core service factory for the clipboard backend. +// +// Example: +// +// core.New(core.WithService(clipboard.Register(platform))) func Register(p Platform) func(*core.Core) (any, error) { return func(c *core.Core) (any, error) { return &Service{ @@ -27,14 +38,18 @@ func Register(p Platform) func(*core.Core) (any, error) { } } -// OnStartup registers IPC handlers. +// OnStartup registers clipboard handlers with Core. +// +// Example: +// +// _ = svc.OnStartup(context.Background()) func (s *Service) OnStartup(ctx context.Context) error { s.Core().RegisterQuery(s.handleQuery) s.Core().RegisterTask(s.handleTask) return nil } -// HandleIPCEvents is auto-discovered by core.WithService. +// HandleIPCEvents satisfies Core's IPC hook. func (s *Service) HandleIPCEvents(c *core.Core, msg core.Message) error { return nil } @@ -70,7 +85,7 @@ func (s *Service) handleTask(c *core.Core, t core.Task) (any, bool, error) { if writer, ok := s.platform.(imageWriter); ok { return writer.SetImage(t.Data), true, nil } - return false, true, fmt.Errorf("clipboard image write not supported") + return false, true, core.E("clipboard.handleTask", "clipboard image write not supported", nil) default: return nil, false, nil } diff --git a/pkg/display/display.go b/pkg/display/display.go index fe89557..8a7087d 100644 --- a/pkg/display/display.go +++ b/pkg/display/display.go @@ -1562,7 +1562,7 @@ func (s *Service) ReadClipboard() (string, error) { return "", err } if !handled { - return "", fmt.Errorf("clipboard service not available") + return "", core.E("display.ReadClipboard", "clipboard service not available", nil) } content, _ := result.(clipboard.ClipboardContent) return content.Text, nil @@ -1575,10 +1575,10 @@ func (s *Service) WriteClipboard(text string) error { return err } if !handled { - return fmt.Errorf("clipboard service not available") + return core.E("display.WriteClipboard", "clipboard service not available", nil) } if ok, _ := result.(bool); !ok { - return fmt.Errorf("clipboard write failed") + return core.E("display.WriteClipboard", "clipboard write failed", nil) } return nil } @@ -1607,10 +1607,10 @@ func (s *Service) ClearClipboard() error { return err } if !handled { - return fmt.Errorf("clipboard service not available") + return core.E("display.ClearClipboard", "clipboard service not available", nil) } if ok, _ := result.(bool); !ok { - return fmt.Errorf("clipboard clear failed") + return core.E("display.ClearClipboard", "clipboard clear failed", nil) } return nil } @@ -1622,7 +1622,7 @@ func (s *Service) ReadClipboardImage() (clipboard.ClipboardImageContent, error) return clipboard.ClipboardImageContent{}, err } if !handled { - return clipboard.ClipboardImageContent{}, fmt.Errorf("clipboard service not available") + return clipboard.ClipboardImageContent{}, core.E("display.ReadClipboardImage", "clipboard service not available", nil) } content, _ := result.(clipboard.ClipboardImageContent) return content, nil @@ -1635,10 +1635,10 @@ func (s *Service) WriteClipboardImage(data []byte) error { return err } if !handled { - return fmt.Errorf("clipboard service not available") + return core.E("display.WriteClipboardImage", "clipboard service not available", nil) } if ok, _ := result.(bool); !ok { - return fmt.Errorf("clipboard image write failed") + return core.E("display.WriteClipboardImage", "clipboard image write failed", nil) } return nil } @@ -1652,7 +1652,7 @@ func (s *Service) ShowNotification(opts notification.NotificationOptions) error return err } if !handled { - return fmt.Errorf("notification service not available") + return core.E("display.ShowNotification", "notification service not available", nil) } return nil } diff --git a/pkg/notification/service.go b/pkg/notification/service.go index 34df504..2885404 100644 --- a/pkg/notification/service.go +++ b/pkg/notification/service.go @@ -10,16 +10,28 @@ import ( "forge.lthn.ai/core/gui/pkg/dialog" ) -// Options holds configuration for the notification service. +// Options configures the notification service. +// +// Example: +// +// core.WithService(notification.Register(platform)) type Options struct{} -// Service is a core.Service managing notifications via IPC. +// Service manages notifications via Core tasks and queries. +// +// Example: +// +// svc := ¬ification.Service{} type Service struct { *core.ServiceRuntime[Options] platform Platform } -// Register creates a factory closure that captures the Platform adapter. +// Register creates a Core service factory for the notification backend. +// +// Example: +// +// core.New(core.WithService(notification.Register(platform))) func Register(p Platform) func(*core.Core) (any, error) { return func(c *core.Core) (any, error) { return &Service{ @@ -29,14 +41,18 @@ func Register(p Platform) func(*core.Core) (any, error) { } } -// OnStartup registers IPC handlers. +// OnStartup registers notification handlers with Core. +// +// Example: +// +// _ = svc.OnStartup(context.Background()) func (s *Service) OnStartup(ctx context.Context) error { s.Core().RegisterQuery(s.handleQuery) s.Core().RegisterTask(s.handleTask) return nil } -// HandleIPCEvents is auto-discovered by core.WithService. +// HandleIPCEvents satisfies Core's IPC hook. func (s *Service) HandleIPCEvents(c *core.Core, msg core.Message) error { return nil } diff --git a/pkg/systray/menu.go b/pkg/systray/menu.go index 2df119b..085678a 100644 --- a/pkg/systray/menu.go +++ b/pkg/systray/menu.go @@ -1,12 +1,12 @@ // pkg/systray/menu.go package systray -import "fmt" +import "forge.lthn.ai/core/go/pkg/core" // SetMenu sets a dynamic menu on the tray from TrayMenuItem descriptors. func (m *Manager) SetMenu(items []TrayMenuItem) error { if m.tray == nil { - return fmt.Errorf("tray not initialised") + return core.E("systray.SetMenu", "tray not initialised", nil) } m.menuItems = append([]TrayMenuItem(nil), items...) menu := m.buildMenu(items) diff --git a/pkg/systray/service.go b/pkg/systray/service.go index fc05633..5a58841 100644 --- a/pkg/systray/service.go +++ b/pkg/systray/service.go @@ -2,16 +2,23 @@ package systray import ( "context" - "fmt" "forge.lthn.ai/core/go/pkg/core" "forge.lthn.ai/core/gui/pkg/notification" ) -// Options holds configuration for the systray service. +// Options configures the systray service. +// +// Example: +// +// core.WithService(systray.Register(platform)) type Options struct{} -// Service is a core.Service managing the system tray via IPC. +// Service manages system tray operations via Core tasks. +// +// Example: +// +// svc := &systray.Service{} type Service struct { *core.ServiceRuntime[Options] manager *Manager @@ -19,7 +26,11 @@ type Service struct { iconPath string } -// OnStartup queries config and registers IPC handlers. +// OnStartup loads tray config and registers task handlers. +// +// Example: +// +// _ = svc.OnStartup(context.Background()) func (s *Service) OnStartup(ctx context.Context) error { cfg, handled, _ := s.Core().QUERY(QueryConfig{}) if handled { @@ -45,7 +56,7 @@ func (s *Service) applyConfig(cfg map[string]any) { } } -// HandleIPCEvents is auto-discovered and registered by core.WithService. +// HandleIPCEvents satisfies Core's IPC hook. func (s *Service) HandleIPCEvents(c *core.Core, msg core.Message) error { return nil } @@ -95,7 +106,7 @@ func (s *Service) taskShowMessage(title, message string) error { } tray := s.manager.Tray() if tray == nil { - return fmt.Errorf("tray not initialised") + return core.E("systray.taskShowMessage", "tray not initialised", nil) } if messenger, ok := tray.(interface{ ShowMessage(title, message string) }); ok { messenger.ShowMessage(title, message) diff --git a/pkg/systray/tray.go b/pkg/systray/tray.go index cda24c0..604de51 100644 --- a/pkg/systray/tray.go +++ b/pkg/systray/tray.go @@ -3,15 +3,19 @@ package systray import ( _ "embed" - "fmt" "sync" + + "forge.lthn.ai/core/go/pkg/core" ) //go:embed assets/apptray.png var defaultIcon []byte // Manager manages the system tray lifecycle. -// State that was previously in package-level vars is now on the Manager. +// +// Example: +// +// manager := systray.NewManager(platform) type Manager struct { platform Platform tray PlatformTray @@ -25,6 +29,10 @@ type Manager struct { } // NewManager creates a systray Manager. +// +// Example: +// +// manager := systray.NewManager(platform) func NewManager(platform Platform) *Manager { return &Manager{ platform: platform, @@ -36,7 +44,7 @@ func NewManager(platform Platform) *Manager { func (m *Manager) Setup(tooltip, label string) error { m.tray = m.platform.NewTray() if m.tray == nil { - return fmt.Errorf("platform returned nil tray") + return core.E("systray.Setup", "platform returned nil tray", nil) } m.tray.SetTemplateIcon(defaultIcon) m.tray.SetTooltip(tooltip) @@ -50,7 +58,7 @@ func (m *Manager) Setup(tooltip, label string) error { // SetIcon sets the tray icon. func (m *Manager) SetIcon(data []byte) error { if m.tray == nil { - return fmt.Errorf("tray not initialised") + return core.E("systray.SetIcon", "tray not initialised", nil) } m.tray.SetIcon(data) m.hasIcon = len(data) > 0 @@ -60,7 +68,7 @@ func (m *Manager) SetIcon(data []byte) error { // SetTemplateIcon sets the template icon (macOS). func (m *Manager) SetTemplateIcon(data []byte) error { if m.tray == nil { - return fmt.Errorf("tray not initialised") + return core.E("systray.SetTemplateIcon", "tray not initialised", nil) } m.tray.SetTemplateIcon(data) m.hasTemplateIcon = len(data) > 0 @@ -70,7 +78,7 @@ func (m *Manager) SetTemplateIcon(data []byte) error { // SetTooltip sets the tray tooltip. func (m *Manager) SetTooltip(text string) error { if m.tray == nil { - return fmt.Errorf("tray not initialised") + return core.E("systray.SetTooltip", "tray not initialised", nil) } m.tray.SetTooltip(text) m.tooltip = text @@ -80,7 +88,7 @@ func (m *Manager) SetTooltip(text string) error { // SetLabel sets the tray label. func (m *Manager) SetLabel(text string) error { if m.tray == nil { - return fmt.Errorf("tray not initialised") + return core.E("systray.SetLabel", "tray not initialised", nil) } m.tray.SetLabel(text) m.label = text @@ -90,7 +98,7 @@ func (m *Manager) SetLabel(text string) error { // AttachWindow attaches a panel window to the tray. func (m *Manager) AttachWindow(w WindowHandle) error { if m.tray == nil { - return fmt.Errorf("tray not initialised") + return core.E("systray.AttachWindow", "tray not initialised", nil) } m.tray.AttachWindow(w) return nil