diff --git a/v2/cmd/wails/internal/commands/dev/dev.go b/v2/cmd/wails/internal/commands/dev/dev.go index 8859765eb..096736551 100644 --- a/v2/cmd/wails/internal/commands/dev/dev.go +++ b/v2/cmd/wails/internal/commands/dev/dev.go @@ -2,6 +2,7 @@ package dev import ( "fmt" + "github.com/leaanthony/slicer" "io" "log" "os" @@ -50,6 +51,9 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error { compilerCommand := "go" command.StringFlag("compiler", "Use a different go compiler to build, eg go1.15beta1", &compilerCommand) + assetDir := "" + command.StringFlag("assets", "Serve assets from the given directory", &assetDir) + // extensions to trigger rebuilds extensions := "go" command.StringFlag("e", "Extensions to trigger rebuilds (comma separated) eg go,js,css,html", &extensions) @@ -100,7 +104,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error { // Do initial build logger.Println("Building application for development...") - newProcess, appBinary, err := restartApp(logger, ldflags, compilerCommand, debugBinaryProcess, loglevel, passthruArgs, verbosity) + newProcess, appBinary, err := restartApp(logger, ldflags, compilerCommand, debugBinaryProcess, loglevel, passthruArgs, verbosity, assetDir) if newProcess != nil { debugBinaryProcess = newProcess } @@ -152,7 +156,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error { // Do a rebuild // Try and build the app - newBinaryProcess, _, err = restartApp(logger, ldflags, compilerCommand, debugBinaryProcess, loglevel, passthruArgs, verbosity) + newBinaryProcess, _, err = restartApp(logger, ldflags, compilerCommand, debugBinaryProcess, loglevel, passthruArgs, verbosity, assetDir) if err != nil { fmt.Printf("Error during build: %s", err.Error()) return @@ -247,7 +251,7 @@ exit: } } -func restartApp(logger *clilogger.CLILogger, ldflags string, compilerCommand string, debugBinaryProcess *process.Process, loglevel string, passthruArgs []string, verbosity int) (*process.Process, string, error) { +func restartApp(logger *clilogger.CLILogger, ldflags string, compilerCommand string, debugBinaryProcess *process.Process, loglevel string, passthruArgs []string, verbosity int, assetDir string) (*process.Process, string, error) { appBinary, err := buildApp(logger, ldflags, compilerCommand, verbosity) println() @@ -271,11 +275,16 @@ func restartApp(logger *clilogger.CLILogger, ldflags string, compilerCommand str // TODO: Generate `backend.js` // Start up new binary with correct args - var args = []string{"-loglevel", loglevel} - if len(passthruArgs) > 0 { - args = append(args, passthruArgs...) + args := slicer.StringSlicer{} + args.Add("-loglevel", loglevel) + if assetDir != "" { + args.Add("-assets", assetDir) } - newProcess := process.NewProcess(logger, appBinary, args...) + + if len(passthruArgs) > 0 { + args.AddSlice(passthruArgs) + } + newProcess := process.NewProcess(logger, appBinary, args.AsSlice()...) err = newProcess.Start() if err != nil { // Remove binary diff --git a/v2/internal/app/debug.go b/v2/internal/app/debug.go index 42c4758d3..ecb7b775d 100644 --- a/v2/internal/app/debug.go +++ b/v2/internal/app/debug.go @@ -1,3 +1,4 @@ +//go:build debug // +build debug package app @@ -14,11 +15,6 @@ func (a *App) Init() error { // Indicate debug mode a.debug = true - if a.appType == "desktop" { - // Enable dev tools - a.options.DevTools = true - } - // Set log levels loglevel := flag.String("loglevel", "debug", "Loglevel to use - Trace, Debug, Info, Warning, Error") flag.Parse() diff --git a/v2/internal/appng/app_dev.go b/v2/internal/appng/app_dev.go new file mode 100644 index 000000000..f62c4c620 --- /dev/null +++ b/v2/internal/appng/app_dev.go @@ -0,0 +1,42 @@ +//go:build dev + +package appng + +import ( + "context" + "flag" + "github.com/wailsapp/wails/v2/internal/binding" + "github.com/wailsapp/wails/v2/internal/frontend" + "github.com/wailsapp/wails/v2/internal/frontend/devserver" + "github.com/wailsapp/wails/v2/internal/logger" + pkglogger "github.com/wailsapp/wails/v2/pkg/logger" + "github.com/wailsapp/wails/v2/pkg/options" + "os" +) + +func NewFrontend(appoptions *options.App, myLogger *logger.Logger, bindings *binding.Bindings, dispatcher frontend.Dispatcher) frontend.Frontend { + return devserver.NewFrontend(appoptions, myLogger, bindings, dispatcher) +} + +func PreflightChecks(options *options.App, logger *logger.Logger) error { + return nil +} + +func (a *App) Init() { + // Check for CLI Flags + assetdir := flag.String("assetdir", "", "Directory to serve assets") + loglevel := flag.String("loglevel", "debug", "Loglevel to use - Trace, Debug, Info, Warning, Error") + flag.Parse() + if assetdir != nil && *assetdir != "" { + a.ctx = context.WithValue(a.ctx, "assetdir", *assetdir) + } + if loglevel != nil && *loglevel != "" { + level, err := pkglogger.StringToLogLevel(*loglevel) + if err != nil { + println("ERROR:", err.Error()) + os.Exit(1) + } + a.logger.SetLogLevel(level) + } + +} diff --git a/v2/internal/frontend/devserver/devserver.go b/v2/internal/frontend/devserver/devserver.go new file mode 100644 index 000000000..7395f2848 --- /dev/null +++ b/v2/internal/frontend/devserver/devserver.go @@ -0,0 +1,154 @@ +package devserver + +import ( + "context" + "embed" + "github.com/wailsapp/wails/v2/internal/binding" + "github.com/wailsapp/wails/v2/internal/frontend" + "github.com/wailsapp/wails/v2/internal/logger" + "github.com/wailsapp/wails/v2/pkg/menu" + "github.com/wailsapp/wails/v2/pkg/options" + "net/http" +) + +//go:embed runtime_debug_windows.js +var wailsFS embed.FS + +type DevServer struct { + server *http.Server +} + +func (d DevServer) Run(ctx context.Context) error { + wailsfs := http.FileServer(http.FS(wailsFS)) + http.Handle("/wails/", http.StripPrefix("/wails", wailsfs)) + + assetdir := ctx.Value("assetdir") + if assetdir != nil { + println("Serving assets from:", assetdir.(string)) + fs := http.FileServer(http.Dir(assetdir.(string))) + http.Handle("/", interceptor(fs)) + } + err := d.server.ListenAndServe() + if err != nil && err != http.ErrServerClosed { + return err + } + + return nil +} + +func (d DevServer) Quit() { + panic("implement me") +} + +func (d DevServer) OpenFileDialog(dialogOptions frontend.OpenDialogOptions) (string, error) { + panic("implement me") +} + +func (d DevServer) OpenMultipleFilesDialog(dialogOptions frontend.OpenDialogOptions) ([]string, error) { + panic("implement me") +} + +func (d DevServer) OpenDirectoryDialog(dialogOptions frontend.OpenDialogOptions) (string, error) { + panic("implement me") +} + +func (d DevServer) SaveFileDialog(dialogOptions frontend.SaveDialogOptions) (string, error) { + panic("implement me") +} + +func (d DevServer) MessageDialog(dialogOptions frontend.MessageDialogOptions) (string, error) { + panic("implement me") +} + +func (d DevServer) WindowSetTitle(title string) { + panic("implement me") +} + +func (d DevServer) WindowShow() { + panic("implement me") +} + +func (d DevServer) WindowHide() { + panic("implement me") +} + +func (d DevServer) WindowCenter() { + panic("implement me") +} + +func (d DevServer) WindowMaximise() { + panic("implement me") +} + +func (d DevServer) WindowUnmaximise() { + panic("implement me") +} + +func (d DevServer) WindowMinimise() { + panic("implement me") +} + +func (d DevServer) WindowUnminimise() { + panic("implement me") +} + +func (d DevServer) WindowSetPos(x int, y int) { + panic("implement me") +} + +func (d DevServer) WindowGetPos() (int, int) { + panic("implement me") +} + +func (d DevServer) WindowSetSize(width int, height int) { + panic("implement me") +} + +func (d DevServer) WindowGetSize() (int, int) { + panic("implement me") +} + +func (d DevServer) WindowSetMinSize(width int, height int) { + panic("implement me") +} + +func (d DevServer) WindowSetMaxSize(width int, height int) { + panic("implement me") +} + +func (d DevServer) WindowFullscreen() { + panic("implement me") +} + +func (d DevServer) WindowUnFullscreen() { + panic("implement me") +} + +func (d DevServer) WindowSetColour(colour int) { + panic("implement me") +} + +func (d DevServer) SetApplicationMenu(menu *menu.Menu) { + panic("implement me") +} + +func (d DevServer) UpdateApplicationMenu() { + panic("implement me") +} + +func (d DevServer) Notify(name string, data ...interface{}) { + panic("implement me") +} + +func interceptor(nextHandler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + println("Serving file from disk:", r.RequestURI) + nextHandler.ServeHTTP(w, r) + }) +} + +func NewFrontend(appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) *DevServer { + result := &DevServer{} + result.server = &http.Server{Addr: ":34115"} + return result +} diff --git a/v2/pkg/logger/logger.go b/v2/pkg/logger/logger.go index 362f32a23..abc288265 100644 --- a/v2/pkg/logger/logger.go +++ b/v2/pkg/logger/logger.go @@ -1,5 +1,10 @@ package logger +import ( + "fmt" + "strings" +) + // LogLevel is an unsigned 8bit int type LogLevel uint8 @@ -20,6 +25,22 @@ const ( ERROR LogLevel = 5 ) +var logLevelMap = map[string]LogLevel{ + "trace": TRACE, + "debug": DEBUG, + "info": INFO, + "warning": WARNING, + "error": ERROR, +} + +func StringToLogLevel(input string) (LogLevel, error) { + result, ok := logLevelMap[strings.ToLower(input)] + if !ok { + return ERROR, fmt.Errorf("invalid log level: %s", input) + } + return result, nil +} + // Logger specifies the methods required to attach // a logger to a Wails application type Logger interface {