mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-03 04:11:05 +08:00
[v3] Add start_at_login plugin
[v3] Fix plugin startup/shutdown order
This commit is contained in:
parent
7ecbc846b4
commit
755e869fe7
1
.gitignore
vendored
1
.gitignore
vendored
@ -35,3 +35,4 @@ v2/cmd/wails/internal/commands/initialise/templates/testtemplates/
|
|||||||
/v3/.task
|
/v3/.task
|
||||||
/v3/examples/build/bin/testapp
|
/v3/examples/build/bin/testapp
|
||||||
/websitev3/site/
|
/websitev3/site/
|
||||||
|
/v3/examples/plugins/bin/testapp
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 0 B After Width: | Height: | Size: 130 KiB |
@ -14,6 +14,7 @@ require (
|
|||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
|
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/samber/lo v1.37.0 // indirect
|
github.com/samber/lo v1.37.0 // indirect
|
||||||
github.com/wailsapp/mimetype v1.4.1 // indirect
|
github.com/wailsapp/mimetype v1.4.1 // indirect
|
||||||
|
@ -24,6 +24,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
|||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 h1:acNfDZXmm28D2Yg/c3ALnZStzNaZMSagpbr96vY6Zjc=
|
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 h1:acNfDZXmm28D2Yg/c3ALnZStzNaZMSagpbr96vY6Zjc=
|
||||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
BIN
v3/examples/plugins/icon.ico
Normal file
BIN
v3/examples/plugins/icon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
BIN
v3/examples/plugins/icons.icns
Normal file
BIN
v3/examples/plugins/icons.icns
Normal file
Binary file not shown.
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/wailsapp/wails/v3/plugins/log"
|
"github.com/wailsapp/wails/v3/plugins/log"
|
||||||
"github.com/wailsapp/wails/v3/plugins/single_instance"
|
"github.com/wailsapp/wails/v3/plugins/single_instance"
|
||||||
"github.com/wailsapp/wails/v3/plugins/sqlite"
|
"github.com/wailsapp/wails/v3/plugins/sqlite"
|
||||||
|
"github.com/wailsapp/wails/v3/plugins/start_at_login"
|
||||||
"os"
|
"os"
|
||||||
"plugin_demo/plugins/hashes"
|
"plugin_demo/plugins/hashes"
|
||||||
)
|
)
|
||||||
@ -27,7 +28,9 @@ func main() {
|
|||||||
"hashes": hashes.NewPlugin(),
|
"hashes": hashes.NewPlugin(),
|
||||||
"browser": browser.NewPlugin(),
|
"browser": browser.NewPlugin(),
|
||||||
"log": log.NewPlugin(),
|
"log": log.NewPlugin(),
|
||||||
"sqlite": sqlite.NewPlugin(&sqlite.Config{}),
|
"sqlite": sqlite.NewPlugin(&sqlite.Config{
|
||||||
|
DBFile: "test.db",
|
||||||
|
}),
|
||||||
"kvstore": kvstore.NewPlugin(&kvstore.Config{
|
"kvstore": kvstore.NewPlugin(&kvstore.Config{
|
||||||
Filename: "store.json",
|
Filename: "store.json",
|
||||||
AutoSave: true,
|
AutoSave: true,
|
||||||
@ -36,6 +39,7 @@ func main() {
|
|||||||
// When true, the original app will be activated when a second instance is launched
|
// When true, the original app will be activated when a second instance is launched
|
||||||
ActivateAppOnSubsequentLaunch: true,
|
ActivateAppOnSubsequentLaunch: true,
|
||||||
}),
|
}),
|
||||||
|
"start_at_login": start_at_login.NewPlugin(),
|
||||||
},
|
},
|
||||||
Assets: application.AssetOptions{
|
Assets: application.AssetOptions{
|
||||||
FS: assets,
|
FS: assets,
|
||||||
|
@ -67,11 +67,6 @@ func New(appOptions Options) *App {
|
|||||||
println("Fatal error in application initialisation: ", err.Error())
|
println("Fatal error in application initialisation: ", err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
err = result.bindings.AddPlugins(appOptions.Plugins)
|
|
||||||
if err != nil {
|
|
||||||
println("Fatal error in application initialisation: ", err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
result.plugins = NewPluginManager(appOptions.Plugins, srv)
|
result.plugins = NewPluginManager(appOptions.Plugins, srv)
|
||||||
err = result.plugins.Init()
|
err = result.plugins.Init()
|
||||||
@ -80,6 +75,12 @@ func New(appOptions Options) *App {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = result.bindings.AddPlugins(appOptions.Plugins)
|
||||||
|
if err != nil {
|
||||||
|
println("Fatal error in application initialisation: ", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
v3/pkg/mac/mac.go
Normal file
24
v3/pkg/mac/mac.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
//go:build darwin
|
||||||
|
|
||||||
|
// Package mac provides a set of functions to interact with the macOS platform.
|
||||||
|
package mac
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -x objective-c
|
||||||
|
#cgo LDFLAGS: -framework Foundation -framework ServiceManagement
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <ServiceManagement/ServiceManagement.h>
|
||||||
|
|
||||||
|
// Get the bundle ID
|
||||||
|
char* getBundleID() {
|
||||||
|
NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier];
|
||||||
|
return (char*)[bundleID UTF8String];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
// GetBundleID returns the bundle ID of the application.
|
||||||
|
func GetBundleID() string {
|
||||||
|
return C.GoString(C.getBundleID())
|
||||||
|
}
|
@ -4,12 +4,20 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"github.com/wailsapp/wails/v3/pkg/application"
|
"github.com/wailsapp/wails/v3/pkg/application"
|
||||||
_ "modernc.org/sqlite"
|
_ "modernc.org/sqlite"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed plugin.js
|
//go:embed sqlite_close.js
|
||||||
var js string
|
var closejs string
|
||||||
|
|
||||||
|
//go:embed sqlite_open.js
|
||||||
|
var openjs string
|
||||||
|
|
||||||
|
//go:embed sqlite_execute_select.js
|
||||||
|
var executeselectjs string
|
||||||
|
|
||||||
// ---------------- Plugin Setup ----------------
|
// ---------------- Plugin Setup ----------------
|
||||||
// This is the main plugin struct. It can be named anything you like.
|
// This is the main plugin struct. It can be named anything you like.
|
||||||
@ -28,6 +36,7 @@ type Plugin struct {
|
|||||||
app *application.App
|
app *application.App
|
||||||
conn *sql.DB
|
conn *sql.DB
|
||||||
callableMethods []string
|
callableMethods []string
|
||||||
|
js string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPlugin(config *Config) *Plugin {
|
func NewPlugin(config *Config) *Plugin {
|
||||||
@ -56,18 +65,24 @@ func (p *Plugin) Name() string {
|
|||||||
func (p *Plugin) Init(app *application.App) error {
|
func (p *Plugin) Init(app *application.App) error {
|
||||||
p.app = app
|
p.app = app
|
||||||
p.callableMethods = []string{"Execute", "Select"}
|
p.callableMethods = []string{"Execute", "Select"}
|
||||||
|
p.js = executeselectjs
|
||||||
if p.config.CanOpenFromJS {
|
if p.config.CanOpenFromJS {
|
||||||
p.callableMethods = append(p.callableMethods, "Open")
|
p.callableMethods = append(p.callableMethods, "Open")
|
||||||
|
p.js += openjs
|
||||||
}
|
}
|
||||||
if p.config.CanCloseFromJS {
|
if p.config.CanCloseFromJS {
|
||||||
p.callableMethods = append(p.callableMethods, "Close")
|
p.callableMethods = append(p.callableMethods, "Close")
|
||||||
|
p.js += closejs
|
||||||
}
|
}
|
||||||
if p.config.DBFile != "" {
|
if p.config.DBFile == "" {
|
||||||
_, err := p.Open(p.config.DBFile)
|
return errors.New(`no database file specified. Please set DBFile in the config to either a filename or use ":memory:" to use an in-memory database`)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
_, err := p.Open(p.config.DBFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.js += fmt.Sprintf("\nwindow.sqlite = { %s };", strings.Join(p.callableMethods, ", "))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +92,7 @@ func (p *Plugin) CallableByJS() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Plugin) InjectJS() string {
|
func (p *Plugin) InjectJS() string {
|
||||||
return js
|
return p.js
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------- Plugin Methods ----------------
|
// ---------------- Plugin Methods ----------------
|
||||||
|
8
v3/plugins/sqlite/sqlite_close.js
Normal file
8
v3/plugins/sqlite/sqlite_close.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* Close a sqlite DB.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
function Close() {
|
||||||
|
return wails.Plugin("sqlite", "Close");
|
||||||
|
}
|
@ -1,19 +1,3 @@
|
|||||||
/**
|
|
||||||
* Open a sqlite DB.
|
|
||||||
* @param filename {string} - file to open.
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
function Open(filename) {
|
|
||||||
return wails.Plugin("sqlite", "Open", filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close a sqlite DB.
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
function Close() {
|
|
||||||
return wails.Plugin("sqlite", "Close");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a SQL statement.
|
* Execute a SQL statement.
|
||||||
@ -34,11 +18,3 @@ function Execute(statement, ...args) {
|
|||||||
function Select(statement, ...args) {
|
function Select(statement, ...args) {
|
||||||
return wails.Plugin("sqlite", "Select", statement, ...args);
|
return wails.Plugin("sqlite", "Select", statement, ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.sqlite = {
|
|
||||||
Open: Open,
|
|
||||||
Close: Close,
|
|
||||||
Execute: Execute,
|
|
||||||
Select: Select
|
|
||||||
};
|
|
||||||
|
|
8
v3/plugins/sqlite/sqlite_open.js
Normal file
8
v3/plugins/sqlite/sqlite_open.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* Open a sqlite DB.
|
||||||
|
* @param filename {string} - file to open.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
function Open(filename) {
|
||||||
|
return wails.Plugin("sqlite", "Open", filename);
|
||||||
|
}
|
34
v3/plugins/start_at_login/README.md
Normal file
34
v3/plugins/start_at_login/README.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# start_at_login Plugin
|
||||||
|
|
||||||
|
This example plugin provides a way to generate hashes of strings.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Add the plugin to the `Plugins` option in the Applications options:
|
||||||
|
|
||||||
|
```go
|
||||||
|
Plugins: map[string]application.Plugin{
|
||||||
|
"start_at_login": start_at_login.NewPlugin(),
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
You can then call the methods from the frontend:
|
||||||
|
|
||||||
|
```js
|
||||||
|
wails.Plugin("start_at_login","StartAtLogin", true).then((result) => console.log(result))
|
||||||
|
wails.Plugin("start_at_login","IsStartAtLogin").then((result) => console.log(result))
|
||||||
|
```
|
||||||
|
|
||||||
|
To use this from Go, create a new instance of the plugin, then call the methods on that:
|
||||||
|
|
||||||
|
```go
|
||||||
|
start_at_login := start_at_login.NewPlugin()
|
||||||
|
start_at_login.StartAtLogin(true)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
If you find a bug in this plugin, please raise a ticket [here](https://github.com/plugin/repository).
|
||||||
|
Please do not contact the Wails team for support.
|
54
v3/plugins/start_at_login/plugin.go
Normal file
54
v3/plugins/start_at_login/plugin.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package start_at_login
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/wailsapp/wails/v3/pkg/application"
|
||||||
|
"github.com/wailsapp/wails/v3/pkg/logger"
|
||||||
|
"github.com/wailsapp/wails/v3/pkg/mac"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Plugin struct {
|
||||||
|
app *application.App
|
||||||
|
disabled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPlugin() *Plugin {
|
||||||
|
return &Plugin{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shutdown is called when the app is shutting down
|
||||||
|
// You can use this to clean up any resources you have allocated
|
||||||
|
func (p *Plugin) Shutdown() {}
|
||||||
|
|
||||||
|
// Name returns the name of the plugin.
|
||||||
|
// You should use the go module format e.g. github.com/myuser/myplugin
|
||||||
|
func (p *Plugin) Name() string {
|
||||||
|
return "github.com/wailsapp/wails/v3/plugins/start_at_login"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) Init(app *application.App) error {
|
||||||
|
p.app = app
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
bundleID := mac.GetBundleID()
|
||||||
|
if bundleID == "" {
|
||||||
|
p.app.Log(&logger.Message{
|
||||||
|
Level: "INFO",
|
||||||
|
Message: "Application is not in bundle. StartAtLogin will not work.",
|
||||||
|
})
|
||||||
|
p.disabled = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) CallableByJS() []string {
|
||||||
|
return []string{
|
||||||
|
"StartAtLogin",
|
||||||
|
"IsStartAtLogin",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) InjectJS() string {
|
||||||
|
return ""
|
||||||
|
}
|
11
v3/plugins/start_at_login/plugin.toml
Normal file
11
v3/plugins/start_at_login/plugin.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# This is the plugin definition file for the "start_at_login" plugin.
|
||||||
|
|
||||||
|
Name = "start_at_login"
|
||||||
|
Description = "Plugin to control whether the application should start at login"
|
||||||
|
Author = "Lea Anthony"
|
||||||
|
Version = "v1.0.0"
|
||||||
|
Website = "https://wails.io/plugins/start_at_login"
|
||||||
|
Repository = "https://github.com/wailsapp/wails/v3/plugins/start_at_login"
|
||||||
|
License = "MIT"
|
||||||
|
|
||||||
|
|
66
v3/plugins/start_at_login/plugin_darwin.go
Normal file
66
v3/plugins/start_at_login/plugin_darwin.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
//go:build darwin
|
||||||
|
|
||||||
|
package start_at_login
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/samber/lo"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *Plugin) StartAtLogin(enabled bool) error {
|
||||||
|
if p.disabled {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
exe, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "Error running os.Executable:")
|
||||||
|
}
|
||||||
|
binName := filepath.Base(exe)
|
||||||
|
if !strings.HasSuffix(exe, "/Contents/MacOS/"+binName) {
|
||||||
|
return fmt.Errorf("app needs to be running as package.app file to start at login")
|
||||||
|
}
|
||||||
|
appPath := strings.TrimSuffix(exe, "/Contents/MacOS/"+binName)
|
||||||
|
var command string
|
||||||
|
if enabled {
|
||||||
|
command = fmt.Sprintf("tell application \"System Events\" to make login item at end with properties {name: \"%s\",path:\"%s\", hidden:false}", binName, appPath)
|
||||||
|
} else {
|
||||||
|
command = fmt.Sprintf("tell application \"System Events\" to delete login item \"%s\"", binName)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command("osascript", "-e", command)
|
||||||
|
_, err = cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) IsStartAtLogin() (bool, error) {
|
||||||
|
if p.disabled {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
exe, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
binName := filepath.Base(exe)
|
||||||
|
if !strings.HasSuffix(exe, "/Contents/MacOS/"+binName) {
|
||||||
|
return false, fmt.Errorf("app needs to be running as package.app file to start at login")
|
||||||
|
}
|
||||||
|
appPath := strings.TrimSuffix(exe, "/Contents/MacOS/"+binName)
|
||||||
|
appName := strings.TrimSuffix(filepath.Base(appPath), ".app")
|
||||||
|
cmd := exec.Command("osascript", "-e", `tell application "System Events" to get the name of every login item`)
|
||||||
|
results, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
resultsString := strings.TrimSpace(string(results))
|
||||||
|
startupApps := strings.Split(resultsString, ", ")
|
||||||
|
result := lo.Contains(startupApps, appName)
|
||||||
|
return result, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user