mirror of
https://github.com/taigrr/wails.git
synced 2026-04-17 12:15:02 -07:00
Compare commits
11 Commits
v2.0.0-alp
...
v2.0.0-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbf043585c | ||
|
|
5ae621ceaa | ||
|
|
1231b59443 | ||
|
|
b18d4fbf41 | ||
|
|
9ec5605e63 | ||
|
|
98a4de8878 | ||
|
|
5fe709f558 | ||
|
|
5231a6893b | ||
|
|
74f3ce990f | ||
|
|
998a913853 | ||
|
|
964844835c |
@@ -53,6 +53,13 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
|||||||
extensions := "go"
|
extensions := "go"
|
||||||
command.StringFlag("e", "Extensions to trigger rebuilds (comma separated) eg go,js,css,html", &extensions)
|
command.StringFlag("e", "Extensions to trigger rebuilds (comma separated) eg go,js,css,html", &extensions)
|
||||||
|
|
||||||
|
// extensions to trigger rebuilds
|
||||||
|
showWarnings := false
|
||||||
|
command.BoolFlag("w", "Show warnings", &showWarnings)
|
||||||
|
|
||||||
|
loglevel := ""
|
||||||
|
command.StringFlag("loglevel", "Loglevel to use - Trace, Debug, Info, Warning, Error", &loglevel)
|
||||||
|
|
||||||
command.Action(func() error {
|
command.Action(func() error {
|
||||||
|
|
||||||
// Create logger
|
// Create logger
|
||||||
@@ -78,7 +85,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
|||||||
|
|
||||||
// Do initial build
|
// Do initial build
|
||||||
logger.Println("Building application for development...")
|
logger.Println("Building application for development...")
|
||||||
newProcess, err := restartApp(logger, "dev", ldflags, compilerCommand, debugBinaryProcess)
|
newProcess, err := restartApp(logger, "dev", ldflags, compilerCommand, debugBinaryProcess, loglevel)
|
||||||
if newProcess != nil {
|
if newProcess != nil {
|
||||||
debugBinaryProcess = newProcess
|
debugBinaryProcess = newProcess
|
||||||
}
|
}
|
||||||
@@ -117,7 +124,9 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !rebuild {
|
if !rebuild {
|
||||||
LogDarkYellow("[File change] %s did not match extension list (%s)", event.Name, extensions)
|
if showWarnings {
|
||||||
|
LogDarkYellow("[File change] %s did not match extension list (%s)", event.Name, extensions)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +135,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
|||||||
// Do a rebuild
|
// Do a rebuild
|
||||||
|
|
||||||
// Try and build the app
|
// Try and build the app
|
||||||
newBinaryProcess, err := restartApp(logger, "dev", ldflags, compilerCommand, debugBinaryProcess)
|
newBinaryProcess, err := restartApp(logger, "dev", ldflags, compilerCommand, debugBinaryProcess, loglevel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error during build: %s", err.Error())
|
fmt.Printf("Error during build: %s", err.Error())
|
||||||
return
|
return
|
||||||
@@ -215,7 +224,7 @@ exit:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func restartApp(logger *clilogger.CLILogger, outputType string, ldflags string, compilerCommand string, debugBinaryProcess *process.Process) (*process.Process, error) {
|
func restartApp(logger *clilogger.CLILogger, outputType string, ldflags string, compilerCommand string, debugBinaryProcess *process.Process, loglevel string) (*process.Process, error) {
|
||||||
|
|
||||||
appBinary, err := buildApp(logger, outputType, ldflags, compilerCommand)
|
appBinary, err := buildApp(logger, outputType, ldflags, compilerCommand)
|
||||||
println()
|
println()
|
||||||
@@ -239,7 +248,7 @@ func restartApp(logger *clilogger.CLILogger, outputType string, ldflags string,
|
|||||||
// TODO: Generate `backend.js`
|
// TODO: Generate `backend.js`
|
||||||
|
|
||||||
// Start up new binary
|
// Start up new binary
|
||||||
newProcess := process.NewProcess(logger, appBinary)
|
newProcess := process.NewProcess(logger, appBinary, "-loglevel", loglevel)
|
||||||
err = newProcess.Start()
|
err = newProcess.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Remove binary
|
// Remove binary
|
||||||
|
|||||||
@@ -18,14 +18,14 @@ import (
|
|||||||
func AddSubcommand(app *clir.Cli, w io.Writer, currentVersion string) error {
|
func AddSubcommand(app *clir.Cli, w io.Writer, currentVersion string) error {
|
||||||
|
|
||||||
command := app.NewSubCommand("update", "Update the Wails CLI")
|
command := app.NewSubCommand("update", "Update the Wails CLI")
|
||||||
command.LongDescription(`This command allows you to update your version of Wails.`)
|
command.LongDescription(`This command allows you to update your version of the Wails CLI.`)
|
||||||
|
|
||||||
// Setup flags
|
// Setup flags
|
||||||
var prereleaseRequired bool
|
var prereleaseRequired bool
|
||||||
command.BoolFlag("pre", "Update to latest Prerelease", &prereleaseRequired)
|
command.BoolFlag("pre", "Update CLI to latest Prerelease", &prereleaseRequired)
|
||||||
|
|
||||||
var specificVersion string
|
var specificVersion string
|
||||||
command.StringFlag("version", "Install a specific version (Overrides other flags)", &specificVersion)
|
command.StringFlag("version", "Install a specific version (Overrides other flags) of the CLI", &specificVersion)
|
||||||
|
|
||||||
command.Action(func() error {
|
command.Action(func() error {
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ func updateToVersion(logger *clilogger.CLILogger, targetVersion *github.Semantic
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
logger.Print("Installing Wails " + desiredVersion + "...")
|
logger.Print("Installing Wails CLI " + desiredVersion + "...")
|
||||||
|
|
||||||
// Run command in non module directory
|
// Run command in non module directory
|
||||||
homeDir, err := os.UserHomeDir()
|
homeDir, err := os.UserHomeDir()
|
||||||
@@ -158,7 +158,7 @@ func updateToVersion(logger *clilogger.CLILogger, targetVersion *github.Semantic
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
logger.Println("Wails updated to " + desiredVersion)
|
logger.Println("Wails CLI updated to " + desiredVersion)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
var version = "v2.0.0-alpha.29"
|
var version = "v2.0.0-alpha.33"
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Init initialises the application for a debug environment
|
// Init initialises the application for a debug environment
|
||||||
@@ -19,10 +20,10 @@ func (a *App) Init() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set log levels
|
// Set log levels
|
||||||
greeting := flag.String("loglevel", "debug", "Loglevel to use - Trace, Debug, Info, Warning, Error")
|
loglevel := flag.String("loglevel", "debug", "Loglevel to use - Trace, Debug, Info, Warning, Error")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if len(*greeting) > 0 {
|
if len(*loglevel) > 0 {
|
||||||
switch strings.ToLower(*greeting) {
|
switch strings.ToLower(*loglevel) {
|
||||||
case "trace":
|
case "trace":
|
||||||
a.logger.SetLogLevel(logger.TRACE)
|
a.logger.SetLogLevel(logger.TRACE)
|
||||||
case "info":
|
case "info":
|
||||||
|
|||||||
@@ -117,14 +117,6 @@ func (a *App) Run() error {
|
|||||||
parentContext := context.WithValue(context.Background(), "waitgroup", &subsystemWaitGroup)
|
parentContext := context.WithValue(context.Background(), "waitgroup", &subsystemWaitGroup)
|
||||||
ctx, cancel := context.WithCancel(parentContext)
|
ctx, cancel := context.WithCancel(parentContext)
|
||||||
|
|
||||||
// Setup signal handler
|
|
||||||
signalsubsystem, err := signal.NewManager(ctx, cancel, a.servicebus, a.logger, a.shutdownCallback)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
a.signal = signalsubsystem
|
|
||||||
a.signal.Start()
|
|
||||||
|
|
||||||
// Start the service bus
|
// Start the service bus
|
||||||
a.servicebus.Debug()
|
a.servicebus.Debug()
|
||||||
err = a.servicebus.Start()
|
err = a.servicebus.Start()
|
||||||
@@ -132,7 +124,7 @@ func (a *App) Run() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
runtimesubsystem, err := subsystem.NewRuntime(ctx, a.servicebus, a.logger, a.startupCallback, a.shutdownCallback)
|
runtimesubsystem, err := subsystem.NewRuntime(ctx, a.servicebus, a.logger, a.startupCallback)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -207,6 +199,14 @@ func (a *App) Run() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup signal handler
|
||||||
|
signalsubsystem, err := signal.NewManager(ctx, cancel, a.servicebus, a.logger)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.signal = signalsubsystem
|
||||||
|
a.signal.Start()
|
||||||
|
|
||||||
err = a.window.Run(dispatcher, bindingDump, a.debug)
|
err = a.window.Run(dispatcher, bindingDump, a.debug)
|
||||||
a.logger.Trace("Ffenestri.Run() exited")
|
a.logger.Trace("Ffenestri.Run() exited")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -231,5 +231,10 @@ func (a *App) Run() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shutdown callback
|
||||||
|
if a.shutdownCallback != nil {
|
||||||
|
a.shutdownCallback()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ func CreateApp(appoptions *options.App) (*App, error) {
|
|||||||
|
|
||||||
// Set up logger
|
// Set up logger
|
||||||
myLogger := logger.New(appoptions.Logger)
|
myLogger := logger.New(appoptions.Logger)
|
||||||
myLogger.SetLogLevel(appoptions.LogLevel)
|
|
||||||
|
|
||||||
// Create the menu manager
|
// Create the menu manager
|
||||||
menuManager := menumanager.NewManager()
|
menuManager := menumanager.NewManager()
|
||||||
@@ -119,14 +118,6 @@ func (a *App) Run() error {
|
|||||||
parentContext := context.WithValue(context.Background(), "waitgroup", &subsystemWaitGroup)
|
parentContext := context.WithValue(context.Background(), "waitgroup", &subsystemWaitGroup)
|
||||||
ctx, cancel := context.WithCancel(parentContext)
|
ctx, cancel := context.WithCancel(parentContext)
|
||||||
|
|
||||||
// Setup signal handler
|
|
||||||
signalsubsystem, err := signal.NewManager(ctx, cancel, a.servicebus, a.logger, a.shutdownCallback)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
a.signal = signalsubsystem
|
|
||||||
a.signal.Start()
|
|
||||||
|
|
||||||
// Start the service bus
|
// Start the service bus
|
||||||
a.servicebus.Debug()
|
a.servicebus.Debug()
|
||||||
err = a.servicebus.Start()
|
err = a.servicebus.Start()
|
||||||
@@ -134,7 +125,7 @@ func (a *App) Run() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
runtimesubsystem, err := subsystem.NewRuntime(ctx, a.servicebus, a.logger, a.startupCallback, a.shutdownCallback)
|
runtimesubsystem, err := subsystem.NewRuntime(ctx, a.servicebus, a.logger, a.startupCallback)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -212,6 +203,14 @@ func (a *App) Run() error {
|
|||||||
// Generate backend.js
|
// Generate backend.js
|
||||||
a.bindings.GenerateBackendJS()
|
a.bindings.GenerateBackendJS()
|
||||||
|
|
||||||
|
// Setup signal handler
|
||||||
|
signalsubsystem, err := signal.NewManager(ctx, cancel, a.servicebus, a.logger)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.signal = signalsubsystem
|
||||||
|
a.signal.Start()
|
||||||
|
|
||||||
err = a.bridge.Run(dispatcher, a.menuManager, bindingDump, a.debug)
|
err = a.bridge.Run(dispatcher, a.menuManager, bindingDump, a.debug)
|
||||||
a.logger.Trace("Bridge.Run() exited")
|
a.logger.Trace("Bridge.Run() exited")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -236,6 +235,10 @@ func (a *App) Run() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shutdown callback
|
||||||
|
if a.shutdownCallback != nil {
|
||||||
|
a.shutdownCallback()
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -498,31 +498,6 @@ void DestroyApplication(struct Application *app) {
|
|||||||
Debug(app, "Finished Destroying Application");
|
Debug(app, "Finished Destroying Application");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quit will stop the cocoa application and free up all the memory
|
|
||||||
// used by the application
|
|
||||||
void Quit(struct Application *app) {
|
|
||||||
Debug(app, "Quit Called");
|
|
||||||
ON_MAIN_THREAD (
|
|
||||||
// Terminate app
|
|
||||||
msg(app->application, s("stop:"), NULL);
|
|
||||||
id fakeevent = msg(c("NSEvent"),
|
|
||||||
s("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:"),
|
|
||||||
15, // Type
|
|
||||||
msg(c("CGPoint"), s("init:x:y:"), 0, 0), // location
|
|
||||||
0, // flags
|
|
||||||
0, // timestamp
|
|
||||||
0, // window
|
|
||||||
NULL, // context
|
|
||||||
0, // subtype
|
|
||||||
0, // data1
|
|
||||||
0 // data2
|
|
||||||
);
|
|
||||||
msg(c("NSApp"), s("postEvent:atStart:"), fakeevent, true);
|
|
||||||
// msg(c(app->mainWindow), s("performClose:"))
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetTitle sets the main window title to the given string
|
// SetTitle sets the main window title to the given string
|
||||||
void SetTitle(struct Application *app, const char *title) {
|
void SetTitle(struct Application *app, const char *title) {
|
||||||
// Guard against calling during shutdown
|
// Guard against calling during shutdown
|
||||||
@@ -1837,6 +1812,15 @@ void Run(struct Application *app, int argc, char **argv) {
|
|||||||
MEMFREE(internalCode);
|
MEMFREE(internalCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Quit will stop the cocoa application and free up all the memory
|
||||||
|
// used by the application
|
||||||
|
void Quit(struct Application *app) {
|
||||||
|
Debug(app, "Quit Called");
|
||||||
|
msg(app->application, s("stop:"), NULL);
|
||||||
|
SetSize(app, 0, 0);
|
||||||
|
Show(app);
|
||||||
|
Hide(app);
|
||||||
|
}
|
||||||
|
|
||||||
void* NewApplication(const char *title, int width, int height, int resizable, int devtools, int fullscreen, int startHidden, int logLevel, int hideWindowOnClose) {
|
void* NewApplication(const char *title, int width, int height, int resizable, int devtools, int fullscreen, int startHidden, int logLevel, int hideWindowOnClose) {
|
||||||
|
|
||||||
|
|||||||
@@ -6,20 +6,19 @@ import (
|
|||||||
|
|
||||||
// Runtime is a means for the user to interact with the application at runtime
|
// Runtime is a means for the user to interact with the application at runtime
|
||||||
type Runtime struct {
|
type Runtime struct {
|
||||||
Browser Browser
|
Browser Browser
|
||||||
Events Events
|
Events Events
|
||||||
Window Window
|
Window Window
|
||||||
Dialog Dialog
|
Dialog Dialog
|
||||||
System System
|
System System
|
||||||
Menu Menu
|
Menu Menu
|
||||||
Store *StoreProvider
|
Store *StoreProvider
|
||||||
Log Log
|
Log Log
|
||||||
bus *servicebus.ServiceBus
|
bus *servicebus.ServiceBus
|
||||||
shutdownCallback func()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new runtime
|
// New creates a new runtime
|
||||||
func New(serviceBus *servicebus.ServiceBus, shutdownCallback func()) *Runtime {
|
func New(serviceBus *servicebus.ServiceBus) *Runtime {
|
||||||
result := &Runtime{
|
result := &Runtime{
|
||||||
Browser: newBrowser(),
|
Browser: newBrowser(),
|
||||||
Events: newEvents(serviceBus),
|
Events: newEvents(serviceBus),
|
||||||
@@ -36,11 +35,6 @@ func New(serviceBus *servicebus.ServiceBus, shutdownCallback func()) *Runtime {
|
|||||||
|
|
||||||
// Quit the application
|
// Quit the application
|
||||||
func (r *Runtime) Quit() {
|
func (r *Runtime) Quit() {
|
||||||
// Call back to user's shutdown method if defined
|
|
||||||
if r.shutdownCallback != nil {
|
|
||||||
r.shutdownCallback()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start shutdown of Wails
|
// Start shutdown of Wails
|
||||||
r.bus.Publish("quit", "runtime.Quit()")
|
r.bus.Publish("quit", "runtime.Quit()")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,25 +26,20 @@ type Manager struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
|
|
||||||
// The shutdown callback to notify the user's app that a shutdown
|
|
||||||
// has started
|
|
||||||
shutdownCallback func()
|
|
||||||
|
|
||||||
// Parent waitgroup
|
// Parent waitgroup
|
||||||
wg *sync.WaitGroup
|
wg *sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewManager creates a new signal manager
|
// NewManager creates a new signal manager
|
||||||
func NewManager(ctx context.Context, cancel context.CancelFunc, bus *servicebus.ServiceBus, logger *logger.Logger, shutdownCallback func()) (*Manager, error) {
|
func NewManager(ctx context.Context, cancel context.CancelFunc, bus *servicebus.ServiceBus, logger *logger.Logger) (*Manager, error) {
|
||||||
|
|
||||||
result := &Manager{
|
result := &Manager{
|
||||||
bus: bus,
|
bus: bus,
|
||||||
logger: logger.CustomLogger("Event Manager"),
|
logger: logger.CustomLogger("Event Manager"),
|
||||||
signalchannel: make(chan os.Signal, 2),
|
signalchannel: make(chan os.Signal, 2),
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
shutdownCallback: shutdownCallback,
|
wg: ctx.Value("waitgroup").(*sync.WaitGroup),
|
||||||
wg: ctx.Value("waitgroup").(*sync.WaitGroup),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
@@ -67,11 +62,6 @@ func (m *Manager) Start() {
|
|||||||
m.logger.Trace("Ctrl+C detected. Shutting down...")
|
m.logger.Trace("Ctrl+C detected. Shutting down...")
|
||||||
m.bus.Publish("quit", "ctrl-c pressed")
|
m.bus.Publish("quit", "ctrl-c pressed")
|
||||||
|
|
||||||
// Shutdown app first
|
|
||||||
if m.shutdownCallback != nil {
|
|
||||||
m.shutdownCallback()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start shutdown of Wails
|
// Start shutdown of Wails
|
||||||
m.cancel()
|
m.cancel()
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ type Runtime struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewRuntime creates a new runtime subsystem
|
// NewRuntime creates a new runtime subsystem
|
||||||
func NewRuntime(ctx context.Context, bus *servicebus.ServiceBus, logger *logger.Logger, startupCallback func(*runtime.Runtime), shutdownCallback func()) (*Runtime, error) {
|
func NewRuntime(ctx context.Context, bus *servicebus.ServiceBus, logger *logger.Logger, startupCallback func(*runtime.Runtime)) (*Runtime, error) {
|
||||||
|
|
||||||
// Subscribe to log messages
|
// Subscribe to log messages
|
||||||
runtimeChannel, err := bus.Subscribe("runtime:")
|
runtimeChannel, err := bus.Subscribe("runtime:")
|
||||||
@@ -52,13 +52,12 @@ func NewRuntime(ctx context.Context, bus *servicebus.ServiceBus, logger *logger.
|
|||||||
}
|
}
|
||||||
|
|
||||||
result := &Runtime{
|
result := &Runtime{
|
||||||
runtimeChannel: runtimeChannel,
|
runtimeChannel: runtimeChannel,
|
||||||
hooksChannel: hooksChannel,
|
hooksChannel: hooksChannel,
|
||||||
logger: logger.CustomLogger("Runtime Subsystem"),
|
logger: logger.CustomLogger("Runtime Subsystem"),
|
||||||
runtime: runtime.New(bus, shutdownCallback),
|
runtime: runtime.New(bus),
|
||||||
startupCallback: startupCallback,
|
startupCallback: startupCallback,
|
||||||
shutdownCallback: shutdownCallback,
|
ctx: ctx,
|
||||||
ctx: ctx,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user