5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-03 07:29:07 +08:00

Extend call subsystem to support plugins

This commit is contained in:
Lea Anthony 2023-03-18 09:12:44 +11:00
parent 4300521064
commit c774af48b7
13 changed files with 93 additions and 52 deletions

View File

@ -13,6 +13,8 @@ var assets embed.FS
type RandomNumberPlugin struct{} type RandomNumberPlugin struct{}
func (r *RandomNumberPlugin) Shutdown() {}
func (r *RandomNumberPlugin) Name() string { func (r *RandomNumberPlugin) Name() string {
return "Random Number Plugin" return "Random Number Plugin"
} }
@ -21,8 +23,8 @@ func (r *RandomNumberPlugin) Init(_ *application.App) error {
return nil return nil
} }
func (r *RandomNumberPlugin) Call(args []any) (any, error) { func (r *RandomNumberPlugin) RandInt() int {
return rand.Intn(100), nil return rand.Intn(100)
} }
func main() { func main() {

View File

@ -64,5 +64,10 @@ export function Call(options) {
} }
export function Plugin(options) { export function Plugin(options) {
return callBinding("Plugin", options); return callBinding("Call", {
packageName: "wails-plugins",
structName: options.plugin,
methodName: options.methodName,
args: options.args,
});
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -57,8 +57,7 @@ func New(appOptions Options) *App {
result.fatal(err.Error()) result.fatal(err.Error())
} }
pluginManager := NewPluginManager(appOptions.Plugins) srv.UseRuntimeHandler(NewMessageProcessor())
srv.UseRuntimeHandler(NewMessageProcessor(pluginManager))
result.assets = srv result.assets = srv
globalApplication = result globalApplication = result
@ -151,6 +150,7 @@ type App struct {
// Running // Running
running bool running bool
bindings *Bindings bindings *Bindings
plugins *PluginManager
// platform app // platform app
impl platformApp impl platformApp
@ -316,6 +316,14 @@ func (a *App) Run() error {
return err return err
} }
a.plugins = NewPluginManager(a.options.Plugins)
err = a.plugins.Init()
if err != nil {
return err
}
a.bindings.AddPlugins(a.options.Plugins)
// run windows // run windows
for _, window := range a.windows { for _, window := range a.windows {
go window.run() go window.run()
@ -332,7 +340,14 @@ func (a *App) Run() error {
// set the application Icon // set the application Icon
a.impl.setIcon(a.options.Icon) a.impl.setIcon(a.options.Icon)
return a.impl.run() err = a.impl.run()
if err != nil {
return err
}
a.plugins.Shutdown()
return nil
} }
func (a *App) handleApplicationEvent(event uint) { func (a *App) handleApplicationEvent(event uint) {

View File

@ -20,6 +20,12 @@ type PluginCallOptions struct {
Args []any `json:"args"` Args []any `json:"args"`
} }
var reservedPluginMethods = []string{
"Name",
"Init",
"Shutdown",
}
// Parameter defines a Go method parameter // Parameter defines a Go method parameter
type Parameter struct { type Parameter struct {
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
@ -96,7 +102,34 @@ func (b *Bindings) Add(structPtr interface{}) error {
b.boundMethods[packageName][structName] = make(map[string]*BoundMethod) b.boundMethods[packageName][structName] = make(map[string]*BoundMethod)
} }
b.boundMethods[packageName][structName][methodName] = method b.boundMethods[packageName][structName][methodName] = method
//b.db.AddMethod(packageName, structName, methodName, method) }
return nil
}
func (b *Bindings) AddPlugins(plugins map[string]Plugin) error {
for pluginID, plugin := range plugins {
methods, err := b.getMethods(plugin)
if err != nil {
return fmt.Errorf("cannot add plugin '%s' to app: %s", pluginID, err.Error())
}
for _, method := range methods {
if lo.Contains(reservedPluginMethods, method.Name) {
continue
}
packageName := "wails-plugins"
structName := pluginID
methodName := method.Name
// Add it as a regular method
if _, ok := b.boundMethods[packageName]; !ok {
b.boundMethods[packageName] = make(map[string]map[string]*BoundMethod)
}
if _, ok := b.boundMethods[packageName][structName]; !ok {
b.boundMethods[packageName][structName] = make(map[string]*BoundMethod)
}
b.boundMethods[packageName][structName][methodName] = method
}
} }
return nil return nil
} }

View File

@ -16,10 +16,8 @@ type MessageProcessor struct {
pluginManager *PluginManager pluginManager *PluginManager
} }
func NewMessageProcessor(pluginManager *PluginManager) *MessageProcessor { func NewMessageProcessor() *MessageProcessor {
return &MessageProcessor{ return &MessageProcessor{}
pluginManager: pluginManager,
}
} }
func (m *MessageProcessor) httpError(rw http.ResponseWriter, message string, args ...any) { func (m *MessageProcessor) httpError(rw http.ResponseWriter, message string, args ...any) {

View File

@ -58,28 +58,6 @@ func (m *MessageProcessor) processCallMethod(method string, rw http.ResponseWrit
m.callCallback(window, callID, string(jsonResult), true) m.callCallback(window, callID, string(jsonResult), true)
}() }()
m.ok(rw) m.ok(rw)
case "Plugin":
var options PluginCallOptions
err := params.ToStruct(&options)
if err != nil {
m.callErrorCallback(window, "Error parsing plugin options: %s", callID, err)
return
}
go func() {
result, err := m.pluginManager.Call(options.Name, options.Args)
if err != nil {
m.callErrorCallback(window, "Error calling plugin: %s", callID, err)
return
}
// convert result to json
jsonResult, err := json.Marshal(result)
if err != nil {
m.callErrorCallback(window, "Error converting result to json: %s", callID, err)
return
}
m.callCallback(window, callID, string(jsonResult), true)
}()
m.ok(rw)
default: default:
m.httpError(rw, "Unknown dialog method: %s", method) m.httpError(rw, "Unknown dialog method: %s", method)
} }

View File

@ -1,13 +1,9 @@
package application package application
import (
"fmt"
)
type Plugin interface { type Plugin interface {
Name() string Name() string
Init(app *App) error Init(app *App) error
Call(args []any) (any, error) Shutdown()
} }
type PluginManager struct { type PluginManager struct {
@ -31,10 +27,9 @@ func (p *PluginManager) Init() error {
return nil return nil
} }
func (p *PluginManager) Call(name string, args []any) (any, error) { func (p *PluginManager) Shutdown() {
plugin, ok := p.plugins[name] for _, plugin := range p.plugins {
if !ok { plugin.Shutdown()
return nil, fmt.Errorf("plugin '%s' not found", name) globalApplication.info("Plugin '%s' shutdown", plugin.Name())
} }
return plugin.Call(args)
} }