5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-02 06:19:43 +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{}
func (r *RandomNumberPlugin) Shutdown() {}
func (r *RandomNumberPlugin) Name() string {
return "Random Number Plugin"
}
@ -21,8 +23,8 @@ func (r *RandomNumberPlugin) Init(_ *application.App) error {
return nil
}
func (r *RandomNumberPlugin) Call(args []any) (any, error) {
return rand.Intn(100), nil
func (r *RandomNumberPlugin) RandInt() int {
return rand.Intn(100)
}
func main() {

View File

@ -64,5 +64,10 @@ export function Call(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())
}
pluginManager := NewPluginManager(appOptions.Plugins)
srv.UseRuntimeHandler(NewMessageProcessor(pluginManager))
srv.UseRuntimeHandler(NewMessageProcessor())
result.assets = srv
globalApplication = result
@ -151,6 +150,7 @@ type App struct {
// Running
running bool
bindings *Bindings
plugins *PluginManager
// platform app
impl platformApp
@ -316,6 +316,14 @@ func (a *App) Run() error {
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
for _, window := range a.windows {
go window.run()
@ -332,7 +340,14 @@ func (a *App) Run() error {
// set the application 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) {

View File

@ -20,6 +20,12 @@ type PluginCallOptions struct {
Args []any `json:"args"`
}
var reservedPluginMethods = []string{
"Name",
"Init",
"Shutdown",
}
// Parameter defines a Go method parameter
type Parameter struct {
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][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
}

View File

@ -16,10 +16,8 @@ type MessageProcessor struct {
pluginManager *PluginManager
}
func NewMessageProcessor(pluginManager *PluginManager) *MessageProcessor {
return &MessageProcessor{
pluginManager: pluginManager,
}
func NewMessageProcessor() *MessageProcessor {
return &MessageProcessor{}
}
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.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:
m.httpError(rw, "Unknown dialog method: %s", method)
}

View File

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