Replaced fmt, strings, sort, os, io, sync, encoding/json, path/filepath, errors, log, reflect with core.Sprintf, core.E, core.Contains, core.Trim, core.Split, core.Join, core.JoinPath, slices.Sort, c.Fs(), c.Lock(), core.JSONMarshal, core.ReadAll and other CoreGO v0.8.0 primitives. Framework boundary exceptions preserved where stdlib types are required by external interfaces (Gin, net/http, CGo, Wails, bubbletea). Co-Authored-By: Virgil <virgil@lethean.io>
114 lines
2.7 KiB
Go
114 lines
2.7 KiB
Go
// pkg/contextmenu/service.go
|
|
package contextmenu
|
|
|
|
import (
|
|
"context"
|
|
|
|
corego "dappco.re/go/core"
|
|
"forge.lthn.ai/core/go/pkg/core"
|
|
)
|
|
|
|
// Options holds configuration for the context menu service.
|
|
type Options struct{}
|
|
|
|
// Service is a core.Service managing context menus via IPC.
|
|
// It maintains an in-memory registry of menus (map[string]ContextMenuDef)
|
|
// and delegates platform-level registration to the Platform interface.
|
|
type Service struct {
|
|
*core.ServiceRuntime[Options]
|
|
platform Platform
|
|
menus map[string]ContextMenuDef
|
|
}
|
|
|
|
// OnStartup registers IPC handlers.
|
|
func (s *Service) OnStartup(ctx context.Context) error {
|
|
s.Core().RegisterQuery(s.handleQuery)
|
|
s.Core().RegisterTask(s.handleTask)
|
|
return nil
|
|
}
|
|
|
|
// HandleIPCEvents is auto-discovered and registered by core.WithService.
|
|
func (s *Service) HandleIPCEvents(c *core.Core, msg core.Message) error {
|
|
return nil
|
|
}
|
|
|
|
// --- Query Handlers ---
|
|
|
|
func (s *Service) handleQuery(c *core.Core, q core.Query) (any, bool, error) {
|
|
switch q := q.(type) {
|
|
case QueryGet:
|
|
return s.queryGet(q), true, nil
|
|
case QueryList:
|
|
return s.queryList(), true, nil
|
|
default:
|
|
return nil, false, nil
|
|
}
|
|
}
|
|
|
|
// queryGet returns a single menu definition by name, or nil if not found.
|
|
func (s *Service) queryGet(q QueryGet) *ContextMenuDef {
|
|
menu, ok := s.menus[q.Name]
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return &menu
|
|
}
|
|
|
|
// queryList returns a copy of all registered menus.
|
|
func (s *Service) queryList() map[string]ContextMenuDef {
|
|
result := make(map[string]ContextMenuDef, len(s.menus))
|
|
for k, v := range s.menus {
|
|
result[k] = v
|
|
}
|
|
return result
|
|
}
|
|
|
|
// --- Task Handlers ---
|
|
|
|
func (s *Service) handleTask(c *core.Core, t core.Task) (any, bool, error) {
|
|
switch t := t.(type) {
|
|
case TaskAdd:
|
|
return nil, true, s.taskAdd(t)
|
|
case TaskRemove:
|
|
return nil, true, s.taskRemove(t)
|
|
default:
|
|
return nil, false, nil
|
|
}
|
|
}
|
|
|
|
func (s *Service) taskAdd(t TaskAdd) error {
|
|
// If menu already exists, remove it first (replace semantics)
|
|
if _, exists := s.menus[t.Name]; exists {
|
|
_ = s.platform.Remove(t.Name)
|
|
delete(s.menus, t.Name)
|
|
}
|
|
|
|
// Register on platform with a callback that broadcasts ActionItemClicked
|
|
err := s.platform.Add(t.Name, t.Menu, func(menuName, actionID, data string) {
|
|
_ = s.Core().ACTION(ActionItemClicked{
|
|
MenuName: menuName,
|
|
ActionID: actionID,
|
|
Data: data,
|
|
})
|
|
})
|
|
if err != nil {
|
|
return corego.Wrap(err, "contextmenu.add", "platform add failed")
|
|
}
|
|
|
|
s.menus[t.Name] = t.Menu
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) taskRemove(t TaskRemove) error {
|
|
if _, exists := s.menus[t.Name]; !exists {
|
|
return ErrMenuNotFound
|
|
}
|
|
|
|
err := s.platform.Remove(t.Name)
|
|
if err != nil {
|
|
return corego.Wrap(err, "contextmenu.remove", "platform remove failed")
|
|
}
|
|
|
|
delete(s.menus, t.Name)
|
|
return nil
|
|
}
|