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

[v2] [broken - WIP] Major refactor of runtime in progress

This commit is contained in:
Lea Anthony 2021-07-18 20:00:01 +10:00
parent 5d2cc81123
commit b80a64b0ee
157 changed files with 493 additions and 13909 deletions

View File

@ -1,14 +1,13 @@
package main package main
import ( import (
"context"
"fmt" "fmt"
"github.com/wailsapp/wails/v2"
) )
// App struct // App struct
type App struct { type App struct {
runtime *wails.Runtime runtime context.Context
} }
// NewApp creates a new App application struct // NewApp creates a new App application struct
@ -17,10 +16,12 @@ func NewApp() *App {
} }
// startup is called at application startup // startup is called at application startup
func (b *App) startup(runtime *wails.Runtime) { func (b *App) startup(ctx context.Context) {
// Perform your setup here // Perform your setup here
b.runtime = runtime //TODO: move to new runtime layout
runtime.Window.SetTitle("{{.ProjectName}}")
//b.runtime = runtime
//runtime.Window.SetTitle("{{.ProjectName}}")
} }
// shutdown is called at application termination // shutdown is called at application termination

View File

@ -51,7 +51,7 @@ type App struct {
appconfigStore *runtime.Store appconfigStore *runtime.Store
// Startup/Shutdown // Startup/Shutdown
startupCallback func(*runtime.Runtime) startupCallback func(ctx context.Context)
shutdownCallback func() shutdownCallback func()
} }

View File

@ -1,7 +1,7 @@
package bridge package bridge
import ( import (
"github.com/wailsapp/wails/v2/pkg/options/dialog" "github.com/wailsapp/wails/v2/pkg/runtime/dialog"
) )
type BridgeClient struct { type BridgeClient struct {
@ -34,23 +34,23 @@ func (b BridgeClient) CallResult(message string) {
b.session.sendMessage("c" + message) b.session.sendMessage("c" + message)
} }
func (b BridgeClient) OpenFileDialog(dialogOptions *dialog.OpenDialog, callbackID string) { func (b BridgeClient) OpenFileDialog(dialogOptions dialog.OpenDialogOptions, callbackID string) {
// Handled by dialog_client // Handled by dialog_client
} }
func (b BridgeClient) OpenMultipleFilesDialog(dialogOptions *dialog.OpenDialog, callbackID string) { func (b BridgeClient) OpenMultipleFilesDialog(dialogOptions dialog.OpenDialogOptions, callbackID string) {
// Handled by dialog_client // Handled by dialog_client
} }
func (b BridgeClient) OpenDirectoryDialog(dialogOptions *dialog.OpenDialog, callbackID string) { func (b BridgeClient) OpenDirectoryDialog(dialogOptions dialog.OpenDialogOptions, callbackID string) {
// Handled by dialog_client // Handled by dialog_client
} }
func (b BridgeClient) SaveDialog(dialogOptions *dialog.SaveDialog, callbackID string) { func (b BridgeClient) SaveDialog(dialogOptions dialog.SaveDialogOptions, callbackID string) {
// Handled by dialog_client // Handled by dialog_client
} }
func (b BridgeClient) MessageDialog(dialogOptions *dialog.MessageDialog, callbackID string) { func (b BridgeClient) MessageDialog(dialogOptions dialog.MessageDialogOptions, callbackID string) {
// Handled by dialog_client // Handled by dialog_client
} }

View File

@ -11,7 +11,7 @@ import (
"github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/logger"
"github.com/leaanthony/slicer" "github.com/leaanthony/slicer"
"github.com/wailsapp/wails/v2/pkg/options/dialog" "github.com/wailsapp/wails/v2/pkg/runtime/dialog"
) )
type DialogClient struct { type DialogClient struct {
@ -37,17 +37,17 @@ func (d *DialogClient) NotifyEvent(message string) {
func (d *DialogClient) CallResult(message string) { func (d *DialogClient) CallResult(message string) {
} }
func (d *DialogClient) OpenDirectoryDialog(dialogOptions *dialog.OpenDialog, callbackID string) { func (d *DialogClient) OpenDirectoryDialog(options dialog.OpenDialogOptions, callbackID string) {
} }
func (d *DialogClient) OpenFileDialog(dialogOptions *dialog.OpenDialog, callbackID string) { func (d *DialogClient) OpenFileDialog(options dialog.OpenDialogOptions, callbackID string) {
} }
func (d *DialogClient) OpenMultipleFilesDialog(dialogOptions *dialog.OpenDialog, callbackID string) { func (d *DialogClient) OpenMultipleFilesDialog(options dialog.OpenDialogOptions, callbackID string) {
} }
func (d *DialogClient) SaveDialog(dialogOptions *dialog.SaveDialog, callbackID string) { func (d *DialogClient) SaveDialog(options dialog.SaveDialogOptions, callbackID string) {
} }
func (d *DialogClient) MessageDialog(dialogOptions *dialog.MessageDialog, callbackID string) { func (d *DialogClient) MessageDialog(options dialog.MessageDialogOptions, callbackID string) {
osa, err := exec.LookPath("osascript") osa, err := exec.LookPath("osascript")
if err != nil { if err != nil {
@ -58,23 +58,23 @@ func (d *DialogClient) MessageDialog(dialogOptions *dialog.MessageDialog, callba
var btns slicer.StringSlicer var btns slicer.StringSlicer
defaultButton := "" defaultButton := ""
cancelButton := "" cancelButton := ""
for index, btn := range dialogOptions.Buttons { for index, btn := range options.Buttons {
btns.Add(strconv.Quote(btn)) btns.Add(strconv.Quote(btn))
if btn == dialogOptions.DefaultButton { if btn == options.DefaultButton {
defaultButton = fmt.Sprintf("default button %d", index+1) defaultButton = fmt.Sprintf("default button %d", index+1)
} }
if btn == dialogOptions.CancelButton { if btn == options.CancelButton {
cancelButton = fmt.Sprintf("cancel button %d", index+1) cancelButton = fmt.Sprintf("cancel button %d", index+1)
} }
} }
buttons := "{" + btns.Join(",") + "}" buttons := "{" + btns.Join(",") + "}"
script := fmt.Sprintf("display dialog \"%s\" buttons %s %s %s with title \"%s\"", dialogOptions.Message, buttons, defaultButton, cancelButton, dialogOptions.Title) script := fmt.Sprintf("display dialog \"%s\" buttons %s %s %s with title \"%s\"", options.Message, buttons, defaultButton, cancelButton, options.Title)
go func() { go func() {
out, err := exec.Command(osa, "-e", script).Output() out, err := exec.Command(osa, "-e", script).Output()
if err != nil { if err != nil {
// Assume user has pressed cancel button // Assume user has pressed cancel button
if dialogOptions.CancelButton != "" { if options.CancelButton != "" {
d.dispatcher.DispatchMessage("DM" + callbackID + "|" + dialogOptions.CancelButton) d.dispatcher.DispatchMessage("DM" + callbackID + "|" + options.CancelButton)
return return
} }
d.log.Error("Dialog had bad exit code. If this was a Cancel button, add 'CancelButton' to the dialog.MessageDialog struct. Error: %s", err.Error()) d.log.Error("Dialog had bad exit code. If this was a Cancel button, add 'CancelButton' to the dialog.MessageDialog struct. Error: %s", err.Error())

View File

@ -12,7 +12,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/wailsapp/wails/v2/pkg/options/dialog" "github.com/wailsapp/wails/v2/pkg/runtime/dialog"
"github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/logger"
) )
@ -127,7 +127,7 @@ func (c *Client) WindowSetColour(colour int) {
} }
// OpenFileDialog will open a dialog with the given title and filter // OpenFileDialog will open a dialog with the given title and filter
func (c *Client) OpenFileDialog(dialogOptions *dialog.OpenDialog, callbackID string) { func (c *Client) OpenFileDialog(dialogOptions dialog.OpenDialogOptions, callbackID string) {
filters := []string{} filters := []string{}
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
for _, filter := range dialogOptions.Filters { for _, filter := range dialogOptions.Filters {
@ -150,9 +150,8 @@ func (c *Client) OpenFileDialog(dialogOptions *dialog.OpenDialog, callbackID str
) )
} }
// OpenDirectoryDialog will open a dialog with the given title and filter // OpenDirectoryDialog will open a dialog with the given title and filter
func (c *Client) OpenDirectoryDialog(dialogOptions *dialog.OpenDialog, callbackID string) { func (c *Client) OpenDirectoryDialog(dialogOptions dialog.OpenDialogOptions, callbackID string) {
filters := []string{} filters := []string{}
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
for _, filter := range dialogOptions.Filters { for _, filter := range dialogOptions.Filters {
@ -166,7 +165,7 @@ func (c *Client) OpenDirectoryDialog(dialogOptions *dialog.OpenDialog, callbackI
c.app.string2CString(dialogOptions.DefaultFilename), c.app.string2CString(dialogOptions.DefaultFilename),
c.app.string2CString(dialogOptions.DefaultDirectory), c.app.string2CString(dialogOptions.DefaultDirectory),
c.app.bool2Cint(false), // Files c.app.bool2Cint(false), // Files
c.app.bool2Cint(true), // Directories c.app.bool2Cint(true), // Directories
c.app.bool2Cint(false), // Multiple c.app.bool2Cint(false), // Multiple
c.app.bool2Cint(dialogOptions.ShowHiddenFiles), c.app.bool2Cint(dialogOptions.ShowHiddenFiles),
c.app.bool2Cint(dialogOptions.CanCreateDirectories), c.app.bool2Cint(dialogOptions.CanCreateDirectories),
@ -176,7 +175,7 @@ func (c *Client) OpenDirectoryDialog(dialogOptions *dialog.OpenDialog, callbackI
} }
// OpenMultipleFilesDialog will open a dialog with the given title and filter // OpenMultipleFilesDialog will open a dialog with the given title and filter
func (c *Client) OpenMultipleFilesDialog(dialogOptions *dialog.OpenDialog, callbackID string) { func (c *Client) OpenMultipleFilesDialog(dialogOptions dialog.OpenDialogOptions, callbackID string) {
filters := []string{} filters := []string{}
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
for _, filter := range dialogOptions.Filters { for _, filter := range dialogOptions.Filters {
@ -220,7 +219,7 @@ func (c *Client) SaveDialog(dialogOptions *dialog.SaveDialog, callbackID string)
} }
// MessageDialog will open a message dialog with the given options // MessageDialog will open a message dialog with the given options
func (c *Client) MessageDialog(dialogOptions *dialog.MessageDialog, callbackID string) { func (c *Client) MessageDialog(dialogOptions dialog.MessageDialogOptions, callbackID string) {
// Sanity check button length // Sanity check button length
if len(dialogOptions.Buttons) > 4 { if len(dialogOptions.Buttons) > 4 {

View File

@ -15,7 +15,7 @@ import (
"strconv" "strconv"
"syscall" "syscall"
"github.com/wailsapp/wails/v2/pkg/options/dialog" "github.com/wailsapp/wails/v2/pkg/runtime/dialog"
"github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/logger"
) )
@ -140,7 +140,7 @@ func convertFilters(filters []dialog.FileFilter) []cfd.FileFilter {
} }
// OpenFileDialog will open a dialog with the given title and filter // OpenFileDialog will open a dialog with the given title and filter
func (c *Client) OpenFileDialog(options *dialog.OpenDialog, callbackID string) { func (c *Client) OpenFileDialog(options dialog.OpenDialogOptions, callbackID string) {
config := cfd.DialogConfig{ config := cfd.DialogConfig{
Folder: options.DefaultDirectory, Folder: options.DefaultDirectory,
FileFilters: convertFilters(options.Filters), FileFilters: convertFilters(options.Filters),
@ -166,7 +166,7 @@ func (c *Client) OpenFileDialog(options *dialog.OpenDialog, callbackID string) {
} }
// OpenDirectoryDialog will open a dialog with the given title and filter // OpenDirectoryDialog will open a dialog with the given title and filter
func (c *Client) OpenDirectoryDialog(dialogOptions *dialog.OpenDialog, callbackID string) { func (c *Client) OpenDirectoryDialog(dialogOptions dialog.OpenDialogOptions, callbackID string) {
config := cfd.DialogConfig{ config := cfd.DialogConfig{
Title: dialogOptions.Title, Title: dialogOptions.Title,
Role: "PickFolder", Role: "PickFolder",
@ -191,7 +191,7 @@ func (c *Client) OpenDirectoryDialog(dialogOptions *dialog.OpenDialog, callbackI
} }
// OpenMultipleFilesDialog will open a dialog with the given title and filter // OpenMultipleFilesDialog will open a dialog with the given title and filter
func (c *Client) OpenMultipleFilesDialog(dialogOptions *dialog.OpenDialog, callbackID string) { func (c *Client) OpenMultipleFilesDialog(dialogOptions dialog.OpenDialogOptions, callbackID string) {
config := cfd.DialogConfig{ config := cfd.DialogConfig{
Title: dialogOptions.Title, Title: dialogOptions.Title,
Role: "OpenMultipleFiles", Role: "OpenMultipleFiles",
@ -222,7 +222,7 @@ func (c *Client) OpenMultipleFilesDialog(dialogOptions *dialog.OpenDialog, callb
} }
// SaveDialog will open a dialog with the given title and filter // SaveDialog will open a dialog with the given title and filter
func (c *Client) SaveDialog(dialogOptions *dialog.SaveDialog, callbackID string) { func (c *Client) SaveDialog(dialogOptions dialog.SaveDialogOptions, callbackID string) {
saveDialog, err := cfd.NewSaveFileDialog(cfd.DialogConfig{ saveDialog, err := cfd.NewSaveFileDialog(cfd.DialogConfig{
Title: dialogOptions.Title, Title: dialogOptions.Title,
Role: "SaveFile", Role: "SaveFile",
@ -246,7 +246,7 @@ func (c *Client) SaveDialog(dialogOptions *dialog.SaveDialog, callbackID string)
} }
// MessageDialog will open a message dialog with the given options // MessageDialog will open a message dialog with the given options
func (c *Client) MessageDialog(options *dialog.MessageDialog, callbackID string) { func (c *Client) MessageDialog(options dialog.MessageDialogOptions, callbackID string) {
title, err := syscall.UTF16PtrFromString(options.Title) title, err := syscall.UTF16PtrFromString(options.Title)
if err != nil { if err != nil {

View File

@ -6,7 +6,7 @@ import (
"github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/internal/messagedispatcher/message" "github.com/wailsapp/wails/v2/internal/messagedispatcher/message"
"github.com/wailsapp/wails/v2/internal/servicebus" "github.com/wailsapp/wails/v2/internal/servicebus"
"github.com/wailsapp/wails/v2/pkg/options/dialog" "github.com/wailsapp/wails/v2/pkg/runtime/dialog"
) )
// Client defines what a frontend client can do // Client defines what a frontend client can do
@ -14,11 +14,11 @@ type Client interface {
Quit() Quit()
NotifyEvent(message string) NotifyEvent(message string)
CallResult(message string) CallResult(message string)
OpenFileDialog(dialogOptions *dialog.OpenDialog, callbackID string) OpenFileDialog(dialogOptions dialog.OpenDialogOptions, callbackID string)
OpenMultipleFilesDialog(dialogOptions *dialog.OpenDialog, callbackID string) OpenMultipleFilesDialog(dialogOptions dialog.OpenDialogOptions, callbackID string)
OpenDirectoryDialog(dialogOptions *dialog.OpenDialog, callbackID string) OpenDirectoryDialog(dialogOptions dialog.OpenDialogOptions, callbackID string)
SaveDialog(dialogOptions *dialog.SaveDialog, callbackID string) SaveDialog(dialogOptions dialog.SaveDialogOptions, callbackID string)
MessageDialog(dialogOptions *dialog.MessageDialog, callbackID string) MessageDialog(dialogOptions dialog.MessageDialogOptions, callbackID string)
WindowSetTitle(title string) WindowSetTitle(title string)
WindowShow() WindowShow()
WindowHide() WindowHide()

View File

@ -7,7 +7,7 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/wailsapp/wails/v2/pkg/options/dialog" "github.com/wailsapp/wails/v2/pkg/runtime/dialog"
"github.com/wailsapp/wails/v2/internal/crypto" "github.com/wailsapp/wails/v2/internal/crypto"
"github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/logger"
@ -411,7 +411,7 @@ func (d *Dispatcher) processDialogMessage(result *servicebus.Message) {
dialogType := splitTopic[2] dialogType := splitTopic[2]
switch dialogType { switch dialogType {
case "open": case "open":
dialogOptions, ok := result.Data().(*dialog.OpenDialog) dialogOptions, ok := result.Data().(dialog.OpenDialogOptions)
if !ok { if !ok {
d.logger.Error("Invalid data for 'dialog:select:open' : %#v", result.Data()) d.logger.Error("Invalid data for 'dialog:select:open' : %#v", result.Data())
return return
@ -425,7 +425,7 @@ func (d *Dispatcher) processDialogMessage(result *servicebus.Message) {
client.frontend.OpenFileDialog(dialogOptions, callbackID) client.frontend.OpenFileDialog(dialogOptions, callbackID)
} }
case "openmultiple": case "openmultiple":
dialogOptions, ok := result.Data().(*dialog.OpenDialog) dialogOptions, ok := result.Data().(dialog.OpenDialogOptions)
if !ok { if !ok {
d.logger.Error("Invalid data for 'dialog:select:openmultiple' : %#v", result.Data()) d.logger.Error("Invalid data for 'dialog:select:openmultiple' : %#v", result.Data())
return return
@ -439,7 +439,7 @@ func (d *Dispatcher) processDialogMessage(result *servicebus.Message) {
client.frontend.OpenMultipleFilesDialog(dialogOptions, callbackID) client.frontend.OpenMultipleFilesDialog(dialogOptions, callbackID)
} }
case "directory": case "directory":
dialogOptions, ok := result.Data().(*dialog.OpenDialog) dialogOptions, ok := result.Data().(dialog.OpenDialogOptions)
if !ok { if !ok {
d.logger.Error("Invalid data for 'dialog:select:directory' : %#v", result.Data()) d.logger.Error("Invalid data for 'dialog:select:directory' : %#v", result.Data())
return return
@ -453,7 +453,7 @@ func (d *Dispatcher) processDialogMessage(result *servicebus.Message) {
client.frontend.OpenDirectoryDialog(dialogOptions, callbackID) client.frontend.OpenDirectoryDialog(dialogOptions, callbackID)
} }
case "save": case "save":
dialogOptions, ok := result.Data().(*dialog.SaveDialog) dialogOptions, ok := result.Data().(dialog.SaveDialogOptions)
if !ok { if !ok {
d.logger.Error("Invalid data for 'dialog:select:save' : %#v", result.Data()) d.logger.Error("Invalid data for 'dialog:select:save' : %#v", result.Data())
return return
@ -467,7 +467,7 @@ func (d *Dispatcher) processDialogMessage(result *servicebus.Message) {
client.frontend.SaveDialog(dialogOptions, callbackID) client.frontend.SaveDialog(dialogOptions, callbackID)
} }
case "message": case "message":
dialogOptions, ok := result.Data().(*dialog.MessageDialog) dialogOptions, ok := result.Data().(dialog.MessageDialogOptions)
if !ok { if !ok {
d.logger.Error("Invalid data for 'dialog:select:message' : %#v", result.Data()) d.logger.Error("Invalid data for 'dialog:select:message' : %#v", result.Data())
return return

View File

@ -1,172 +1,172 @@
package runtime package runtime
import ( //
"fmt" //import (
// "fmt"
"github.com/wailsapp/wails/v2/internal/crypto" // "github.com/wailsapp/wails/v2/internal/crypto"
"github.com/wailsapp/wails/v2/internal/servicebus" // "github.com/wailsapp/wails/v2/internal/servicebus"
dialogoptions "github.com/wailsapp/wails/v2/pkg/options/dialog" // d "github.com/wailsapp/wails/v2/pkg/runtime/dialog"
) //)
//
// Dialog defines all Dialog related operations //// Dialog defines all Dialog related operations
type Dialog interface { //type Dialog interface {
OpenFile(dialogOptions *dialogoptions.OpenDialog) (string, error) // OpenFile(options d.OpenDialogOptions) (string, error)
OpenMultipleFiles(dialogOptions *dialogoptions.OpenDialog) ([]string, error) // OpenMultipleFiles(options d.OpenDialogOptions) ([]string, error)
OpenDirectory(dialogOptions *dialogoptions.OpenDialog) (string, error) // OpenDirectory(options d.OpenDialogOptions) (string, error)
SaveFile(dialogOptions *dialogoptions.SaveDialog) (string, error) // SaveFile(options d.SaveDialogOptions) (string, error)
Message(dialogOptions *dialogoptions.MessageDialog) (string, error) // Message(options d.MessageDialogOptions) (string, error)
} //}
//
// dialog exposes the Dialog interface //// dialog exposes the Dialog interface
type dialog struct { //type dialog struct {
bus *servicebus.ServiceBus // bus *servicebus.ServiceBus
} //}
//
// newDialogs creates a new Dialogs struct //// newDialogs creates a new Dialogs struct
func newDialog(bus *servicebus.ServiceBus) Dialog { //func newDialog(bus *servicebus.ServiceBus) *dialog {
return &dialog{ // return &dialog{
bus: bus, // bus: bus,
} // }
} //}
//
// processTitleAndFilter return the title and filter from the given params. //// processTitleAndFilter return the title and filter from the given params.
// title is the first string, filter is the second //// title is the first string, filter is the second
func (r *dialog) processTitleAndFilter(params ...string) (string, string) { //func (r *dialog) processTitleAndFilter(params ...string) (string, string) {
//
var title, filter string // var title, filter string
//
if len(params) > 0 { // if len(params) > 0 {
title = params[0] // title = params[0]
} // }
//
if len(params) > 1 { // if len(params) > 1 {
filter = params[1] // filter = params[1]
} // }
//
return title, filter // return title, filter
} //}
//
// OpenDirectory prompts the user to select a directory //// OpenDirectory prompts the user to select a directory
func (r *dialog) OpenDirectory(dialogOptions *dialogoptions.OpenDialog) (string, error) { //func (r *dialog) OpenDirectory(dialogOptions d.OpenDialogOptions) (string, error) {
//
// Create unique dialog callback // // Create unique dialog callback
uniqueCallback := crypto.RandomID() // uniqueCallback := crypto.RandomID()
//
// Subscribe to the respose channel // // Subscribe to the respose channel
responseTopic := "dialog:opendirectoryselected:" + uniqueCallback // responseTopic := "dialog:opendirectoryselected:" + uniqueCallback
dialogResponseChannel, err := r.bus.Subscribe(responseTopic) // dialogResponseChannel, err := r.bus.Subscribe(responseTopic)
if err != nil { // if err != nil {
return "", fmt.Errorf("ERROR: Cannot subscribe to bus topic: %+v\n", err.Error()) // return "", fmt.Errorf("ERROR: Cannot subscribe to bus topic: %+v\n", err.Error())
} // }
//
message := "dialog:select:directory:" + uniqueCallback // message := "dialog:select:directory:" + uniqueCallback
r.bus.Publish(message, dialogOptions) // r.bus.Publish(message, dialogOptions)
//
// Wait for result // // Wait for result
var result = <-dialogResponseChannel // var result = <-dialogResponseChannel
//
// Delete subscription to response topic // // Delete subscription to response topic
r.bus.UnSubscribe(responseTopic) // r.bus.UnSubscribe(responseTopic)
//
return result.Data().(string), nil // return result.Data().(string), nil
} //}
//
// OpenFile prompts the user to select a file //// OpenFile prompts the user to select a file
func (r *dialog) OpenFile(dialogOptions *dialogoptions.OpenDialog) (string, error) { //func (r *dialog) OpenFile(dialogOptions d.OpenDialogOptions) (string, error) {
//
// Create unique dialog callback // // Create unique dialog callback
uniqueCallback := crypto.RandomID() // uniqueCallback := crypto.RandomID()
//
// Subscribe to the respose channel // // Subscribe to the respose channel
responseTopic := "dialog:openselected:" + uniqueCallback // responseTopic := "dialog:openselected:" + uniqueCallback
dialogResponseChannel, err := r.bus.Subscribe(responseTopic) // dialogResponseChannel, err := r.bus.Subscribe(responseTopic)
if err != nil { // if err != nil {
return "", fmt.Errorf("ERROR: Cannot subscribe to bus topic: %+v\n", err.Error()) // return "", fmt.Errorf("ERROR: Cannot subscribe to bus topic: %+v\n", err.Error())
} // }
//
message := "dialog:select:open:" + uniqueCallback // message := "dialog:select:open:" + uniqueCallback
r.bus.Publish(message, dialogOptions) // r.bus.Publish(message, dialogOptions)
//
// Wait for result // // Wait for result
var result = <-dialogResponseChannel // var result = <-dialogResponseChannel
//
// Delete subscription to response topic // // Delete subscription to response topic
r.bus.UnSubscribe(responseTopic) // r.bus.UnSubscribe(responseTopic)
//
return result.Data().(string), nil // return result.Data().(string), nil
} //}
//
// OpenMultipleFiles prompts the user to select a file //// OpenMultipleFiles prompts the user to select a file
func (r *dialog) OpenMultipleFiles(dialogOptions *dialogoptions.OpenDialog) ([]string, error) { //func (r *dialog) OpenMultipleFiles(dialogOptions d.OpenDialogOptions) ([]string, error) {
//
// Create unique dialog callback // // Create unique dialog callback
uniqueCallback := crypto.RandomID() // uniqueCallback := crypto.RandomID()
//
// Subscribe to the respose channel // // Subscribe to the respose channel
responseTopic := "dialog:openmultipleselected:" + uniqueCallback // responseTopic := "dialog:openmultipleselected:" + uniqueCallback
dialogResponseChannel, err := r.bus.Subscribe(responseTopic) // dialogResponseChannel, err := r.bus.Subscribe(responseTopic)
if err != nil { // if err != nil {
return nil, fmt.Errorf("ERROR: Cannot subscribe to bus topic: %+v\n", err.Error()) // return nil, fmt.Errorf("ERROR: Cannot subscribe to bus topic: %+v\n", err.Error())
} // }
//
message := "dialog:select:openmultiple:" + uniqueCallback // message := "dialog:select:openmultiple:" + uniqueCallback
r.bus.Publish(message, dialogOptions) // r.bus.Publish(message, dialogOptions)
//
// Wait for result // // Wait for result
var result = <-dialogResponseChannel // var result = <-dialogResponseChannel
//
// Delete subscription to response topic // // Delete subscription to response topic
r.bus.UnSubscribe(responseTopic) // r.bus.UnSubscribe(responseTopic)
//
return result.Data().([]string), nil // return result.Data().([]string), nil
} //}
//
// SaveFile prompts the user to select a file //// SaveFile prompts the user to select a file
func (r *dialog) SaveFile(dialogOptions *dialogoptions.SaveDialog) (string, error) { //func (r *dialog) SaveFile(dialogOptions d.SaveDialogOptions) (string, error) {
//
// Create unique dialog callback // // Create unique dialog callback
uniqueCallback := crypto.RandomID() // uniqueCallback := crypto.RandomID()
//
// Subscribe to the respose channel // // Subscribe to the respose channel
responseTopic := "dialog:saveselected:" + uniqueCallback // responseTopic := "dialog:saveselected:" + uniqueCallback
dialogResponseChannel, err := r.bus.Subscribe(responseTopic) // dialogResponseChannel, err := r.bus.Subscribe(responseTopic)
if err != nil { // if err != nil {
return "", fmt.Errorf("ERROR: Cannot subscribe to bus topic: %+v\n", err.Error()) // return "", fmt.Errorf("ERROR: Cannot subscribe to bus topic: %+v\n", err.Error())
} // }
//
message := "dialog:select:save:" + uniqueCallback // message := "dialog:select:save:" + uniqueCallback
r.bus.Publish(message, dialogOptions) // r.bus.Publish(message, dialogOptions)
//
// Wait for result // // Wait for result
var result = <-dialogResponseChannel // var result = <-dialogResponseChannel
//
// Delete subscription to response topic // // Delete subscription to response topic
r.bus.UnSubscribe(responseTopic) // r.bus.UnSubscribe(responseTopic)
//
return result.Data().(string), nil // return result.Data().(string), nil
} //}
//
// Message show a message to the user //// Message show a message to the user
func (r *dialog) Message(dialogOptions *dialogoptions.MessageDialog) (string, error) { //func (r *dialog) Message(dialogOptions d.MessageDialogOptions) (string, error) {
//
// Create unique dialog callback // // Create unique dialog callback
uniqueCallback := crypto.RandomID() // uniqueCallback := crypto.RandomID()
//
// Subscribe to the respose channel // // Subscribe to the respose channel
responseTopic := "dialog:messageselected:" + uniqueCallback // responseTopic := "dialog:messageselected:" + uniqueCallback
dialogResponseChannel, err := r.bus.Subscribe(responseTopic) // dialogResponseChannel, err := r.bus.Subscribe(responseTopic)
if err != nil { // if err != nil {
return "", fmt.Errorf("ERROR: Cannot subscribe to bus topic: %+v\n", err.Error()) // return "", fmt.Errorf("ERROR: Cannot subscribe to bus topic: %+v\n", err.Error())
} // }
//
message := "dialog:select:message:" + uniqueCallback // message := "dialog:select:message:" + uniqueCallback
r.bus.Publish(message, dialogOptions) // r.bus.Publish(message, dialogOptions)
//
// Wait for result // // Wait for result
var result = <-dialogResponseChannel // var result = <-dialogResponseChannel
//
// Delete subscription to response topic // // Delete subscription to response topic
r.bus.UnSubscribe(responseTopic) // r.bus.UnSubscribe(responseTopic)
//
return result.Data().(string), nil // return result.Data().(string), nil
} //}

View File

@ -9,7 +9,6 @@ type Runtime struct {
Browser Browser Browser Browser
Events Events Events Events
Window Window Window Window
Dialog Dialog
System System System System
Menu Menu Menu Menu
Store *StoreProvider Store *StoreProvider
@ -23,7 +22,6 @@ func New(serviceBus *servicebus.ServiceBus) *Runtime {
Browser: newBrowser(), Browser: newBrowser(),
Events: newEvents(serviceBus), Events: newEvents(serviceBus),
Window: newWindow(serviceBus), Window: newWindow(serviceBus),
Dialog: newDialog(serviceBus),
System: newSystem(serviceBus), System: newSystem(serviceBus),
Menu: newMenu(serviceBus), Menu: newMenu(serviceBus),
Log: newLog(serviceBus), Log: newLog(serviceBus),

View File

@ -4,11 +4,10 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/wailsapp/wails/v2/pkg/runtime/dialog"
"strings" "strings"
"sync" "sync"
"github.com/wailsapp/wails/v2/pkg/options/dialog"
"github.com/wailsapp/wails/v2/internal/binding" "github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/internal/messagedispatcher/message" "github.com/wailsapp/wails/v2/internal/messagedispatcher/message"
@ -135,34 +134,34 @@ func (c *Call) processSystemCall(payload *message.CallMessage, clientID string)
darkModeEnabled := c.runtime.System.IsDarkMode() darkModeEnabled := c.runtime.System.IsDarkMode()
c.sendResult(darkModeEnabled, payload, clientID) c.sendResult(darkModeEnabled, payload, clientID)
case "Dialog.Open": case "Dialog.Open":
dialogOptions := new(dialog.OpenDialog) var dialogOptions dialog.OpenDialogOptions
err := json.Unmarshal(payload.Args[0], dialogOptions) err := json.Unmarshal(payload.Args[0], dialogOptions)
if err != nil { if err != nil {
c.logger.Error("Error decoding: %s", err) c.logger.Error("Error decoding: %s", err)
} }
result, err := c.runtime.Dialog.OpenFile(dialogOptions) result, err := dialog.OpenFile(c.ctx, dialogOptions)
if err != nil { if err != nil {
c.logger.Error("Error: %s", err) c.logger.Error("Error: %s", err)
} }
c.sendResult(result, payload, clientID) c.sendResult(result, payload, clientID)
case "Dialog.Save": case "Dialog.Save":
dialogOptions := new(dialog.SaveDialog) var dialogOptions dialog.SaveDialogOptions
err := json.Unmarshal(payload.Args[0], dialogOptions) err := json.Unmarshal(payload.Args[0], dialogOptions)
if err != nil { if err != nil {
c.logger.Error("Error decoding: %s", err) c.logger.Error("Error decoding: %s", err)
} }
result, err := c.runtime.Dialog.SaveFile(dialogOptions) result, err := dialog.SaveFile(c.ctx, dialogOptions)
if err != nil { if err != nil {
c.logger.Error("Error: %s", err) c.logger.Error("Error: %s", err)
} }
c.sendResult(result, payload, clientID) c.sendResult(result, payload, clientID)
case "Dialog.Message": case "Dialog.Message":
dialogOptions := new(dialog.MessageDialog) var dialogOptions dialog.MessageDialogOptions
err := json.Unmarshal(payload.Args[0], dialogOptions) err := json.Unmarshal(payload.Args[0], dialogOptions)
if err != nil { if err != nil {
c.logger.Error("Error decoding: %s", err) c.logger.Error("Error decoding: %s", err)
} }
result, err := c.runtime.Dialog.Message(dialogOptions) result, err := dialog.Message(c.ctx, dialogOptions)
if err != nil { if err != nil {
c.logger.Error("Error: %s", err) c.logger.Error("Error: %s", err)
} }

View File

@ -17,7 +17,7 @@ type Runtime struct {
// The hooks channel allows us to hook into frontend startup // The hooks channel allows us to hook into frontend startup
hooksChannel <-chan *servicebus.Message hooksChannel <-chan *servicebus.Message
startupCallback func(*runtime.Runtime) startupCallback func(ctx context.Context)
shutdownCallback func() shutdownCallback func()
// quit flag // quit flag
@ -39,7 +39,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)) (*Runtime, error) { func NewRuntime(ctx context.Context, bus *servicebus.ServiceBus, logger *logger.Logger, startupCallback func(context.Context)) (*Runtime, error) {
// Subscribe to log messages // Subscribe to log messages
runtimeChannel, err := bus.Subscribe("runtime:") runtimeChannel, err := bus.Subscribe("runtime:")
@ -59,9 +59,9 @@ func NewRuntime(ctx context.Context, bus *servicebus.ServiceBus, logger *logger.
logger: logger.CustomLogger("Runtime Subsystem"), logger: logger.CustomLogger("Runtime Subsystem"),
runtime: runtime.New(bus), runtime: runtime.New(bus),
startupCallback: startupCallback, startupCallback: startupCallback,
ctx: ctx,
bus: bus, bus: bus,
} }
result.ctx = context.WithValue(ctx, "bus", bus)
return result, nil return result, nil
} }
@ -83,8 +83,7 @@ func (r *Runtime) Start() error {
if r.startupCallback != nil { if r.startupCallback != nil {
r.startupOnce.Do(func() { r.startupOnce.Do(func() {
go func() { go func() {
r.startupCallback(r.runtime) r.startupCallback(r.ctx)
// If we got a url, publish it now startup completed // If we got a url, publish it now startup completed
url, ok := hooksMessage.Data().(string) url, ok := hooksMessage.Data().(string)
if ok && len(url) > 0 { if ok && len(url) > 0 {

View File

@ -3,7 +3,7 @@ package webserver
import ( import (
"context" "context"
"github.com/wailsapp/wails/v2/pkg/menu" "github.com/wailsapp/wails/v2/pkg/menu"
"github.com/wailsapp/wails/v2/pkg/options/dialog" "github.com/wailsapp/wails/v2/pkg/runtime/dialog"
"net/http" "net/http"
"strings" "strings"
@ -20,6 +20,18 @@ type WebClient struct {
running bool running bool
} }
func (wc *WebClient) WindowSetMinSize(width int, height int) {
wc.logger.Info("Not implemented in server build")
}
func (wc *WebClient) WindowSetMaxSize(width int, height int) {
wc.logger.Info("Not implemented in server build")
}
func (wc *WebClient) DeleteTrayMenuByID(id string) {
wc.logger.Info("Not implemented in server build")
}
func (wc *WebClient) SetTrayMenu(trayMenuJSON string) { func (wc *WebClient) SetTrayMenu(trayMenuJSON string) {
wc.logger.Info("Not implemented in server build") wc.logger.Info("Not implemented in server build")
} }
@ -28,7 +40,7 @@ func (wc *WebClient) UpdateTrayMenuLabel(trayMenuJSON string) {
wc.logger.Info("Not implemented in server build") wc.logger.Info("Not implemented in server build")
} }
func (wc *WebClient) MessageDialog(dialogOptions *dialog.MessageDialog, callbackID string) { func (wc *WebClient) MessageDialog(dialogOptions dialog.MessageDialogOptions, callbackID string) {
wc.logger.Info("Not implemented in server build") wc.logger.Info("Not implemented in server build")
} }
@ -44,11 +56,19 @@ func (wc *WebClient) UpdateContextMenu(contextMenuJSON string) {
wc.logger.Info("Not implemented in server build") wc.logger.Info("Not implemented in server build")
} }
func (wc *WebClient) OpenDialog(dialogOptions *dialog.OpenDialog, callbackID string) { func (wc *WebClient) OpenFileDialog(dialogOptions dialog.OpenDialogOptions, callbackID string) {
wc.logger.Info("Not implemented in server build") wc.logger.Info("Not implemented in server build")
} }
func (wc *WebClient) SaveDialog(dialogOptions *dialog.SaveDialog, callbackID string) { func (wc *WebClient) OpenMultipleFilesDialog(dialogOptions dialog.OpenDialogOptions, callbackID string) {
wc.logger.Info("Not implemented in server build")
}
func (wc *WebClient) OpenDirectoryDialog(dialogOptions dialog.OpenDialogOptions, callbackID string) {
wc.logger.Info("Not implemented in server build")
}
func (wc *WebClient) SaveDialog(dialogOptions dialog.SaveDialogOptions, callbackID string) {
wc.logger.Info("Not implemented in server build") wc.logger.Info("Not implemented in server build")
} }

View File

@ -1,52 +0,0 @@
package dialog
// FileFilter defines a filter for dialog boxes
type FileFilter struct {
DisplayName string // Filter information EG: "Image Files (*.jpg, *.png)"
Pattern string // semi-colon separated list of extensions, EG: "*.jpg;*.png"
}
// OpenDialog contains the options for the OpenDialog runtime method
type OpenDialog struct {
DefaultDirectory string
DefaultFilename string
Title string
Filters []FileFilter
AllowFiles bool
AllowDirectories bool
ShowHiddenFiles bool
CanCreateDirectories bool
ResolvesAliases bool
TreatPackagesAsDirectories bool
}
// SaveDialog contains the options for the SaveDialog runtime method
type SaveDialog struct {
DefaultDirectory string
DefaultFilename string
Title string
Filters []FileFilter
ShowHiddenFiles bool
CanCreateDirectories bool
TreatPackagesAsDirectories bool
}
type DialogType string
const (
InfoDialog DialogType = "info"
WarningDialog DialogType = "warning"
ErrorDialog DialogType = "error"
QuestionDialog DialogType = "question"
)
// MessageDialog contains the options for the Message dialogs, EG Info, Warning, etc runtime methods
type MessageDialog struct {
Type DialogType
Title string
Message string
Buttons []string
DefaultButton string
CancelButton string
Icon string
}

View File

@ -1,12 +1,12 @@
package options package options
import ( import (
"context"
"log" "log"
"runtime" "runtime"
"github.com/wailsapp/wails/v2/pkg/options/windows" "github.com/wailsapp/wails/v2/pkg/options/windows"
wailsruntime "github.com/wailsapp/wails/v2/internal/runtime"
"github.com/wailsapp/wails/v2/pkg/menu" "github.com/wailsapp/wails/v2/pkg/menu"
"github.com/imdario/mergo" "github.com/imdario/mergo"
@ -37,8 +37,8 @@ type App struct {
Mac *mac.Options Mac *mac.Options
Logger logger.Logger `json:"-"` Logger logger.Logger `json:"-"`
LogLevel logger.LogLevel LogLevel logger.LogLevel
Startup func(*wailsruntime.Runtime) `json:"-"` Startup func(ctx context.Context) `json:"-"`
Shutdown func() `json:"-"` Shutdown func() `json:"-"`
Bind []interface{} Bind []interface{}
} }

View File

@ -0,0 +1,235 @@
package dialog
import (
"context"
"fmt"
"github.com/pkg/errors"
"github.com/wailsapp/wails/v2/internal/crypto"
"github.com/wailsapp/wails/v2/internal/servicebus"
)
// FileFilter defines a filter for dialog boxes
type FileFilter struct {
DisplayName string // Filter information EG: "Image Files (*.jpg, *.png)"
Pattern string // semi-colon separated list of extensions, EG: "*.jpg;*.png"
}
// OpenDialogOptions contains the options for the OpenDialogOptions runtime method
type OpenDialogOptions struct {
DefaultDirectory string
DefaultFilename string
Title string
Filters []FileFilter
AllowFiles bool
AllowDirectories bool
ShowHiddenFiles bool
CanCreateDirectories bool
ResolvesAliases bool
TreatPackagesAsDirectories bool
}
// SaveDialogOptions contains the options for the SaveDialog runtime method
type SaveDialogOptions struct {
DefaultDirectory string
DefaultFilename string
Title string
Filters []FileFilter
ShowHiddenFiles bool
CanCreateDirectories bool
TreatPackagesAsDirectories bool
}
type DialogType string
const (
InfoDialog DialogType = "info"
WarningDialog DialogType = "warning"
ErrorDialog DialogType = "error"
QuestionDialog DialogType = "question"
)
// MessageDialogOptions contains the options for the Message dialogs, EG Info, Warning, etc runtime methods
type MessageDialogOptions struct {
Type DialogType
Title string
Message string
Buttons []string
DefaultButton string
CancelButton string
Icon string
}
func extractBus(ctx context.Context) (*servicebus.ServiceBus, error) {
bus := ctx.Value("bus")
if bus == nil {
return nil, errors.New("wails runtime has not been initialised correctly")
}
return bus.(*servicebus.ServiceBus), nil
}
// processTitleAndFilter return the title and filter from the given params.
// title is the first string, filter is the second
func processTitleAndFilter(params ...string) (string, string) {
var title, filter string
if len(params) > 0 {
title = params[0]
}
if len(params) > 1 {
filter = params[1]
}
return title, filter
}
// OpenDirectory prompts the user to select a directory
func OpenDirectory(ctx context.Context, dialogOptions OpenDialogOptions) (string, error) {
bus, err := extractBus(ctx)
if err != nil {
return "", errors.Wrap(err, "OpenDirectory")
}
// Create unique dialog callback
uniqueCallback := crypto.RandomID()
// Subscribe to the respose channel
responseTopic := "dialog:opendirectoryselected:" + uniqueCallback
dialogResponseChannel, err := bus.Subscribe(responseTopic)
if err != nil {
return "", fmt.Errorf("ERROR: Cannot subscribe to bus topic: %+v\n", err.Error())
}
message := "dialog:select:directory:" + uniqueCallback
bus.Publish(message, dialogOptions)
// Wait for result
var result = <-dialogResponseChannel
// Delete subscription to response topic
bus.UnSubscribe(responseTopic)
return result.Data().(string), nil
}
// OpenFile prompts the user to select a file
func OpenFile(ctx context.Context, dialogOptions OpenDialogOptions) (string, error) {
bus, err := extractBus(ctx)
if err != nil {
return "", errors.Wrap(err, "OpenFile")
}
// Create unique dialog callback
uniqueCallback := crypto.RandomID()
// Subscribe to the respose channel
responseTopic := "dialog:openselected:" + uniqueCallback
dialogResponseChannel, err := bus.Subscribe(responseTopic)
if err != nil {
return "", fmt.Errorf("ERROR: Cannot subscribe to bus topic: %+v\n", err.Error())
}
message := "dialog:select:open:" + uniqueCallback
bus.Publish(message, dialogOptions)
// Wait for result
var result = <-dialogResponseChannel
// Delete subscription to response topic
bus.UnSubscribe(responseTopic)
return result.Data().(string), nil
}
// OpenMultipleFiles prompts the user to select a file
func OpenMultipleFiles(ctx context.Context, dialogOptions OpenDialogOptions) ([]string, error) {
bus, err := extractBus(ctx)
if err != nil {
return nil, errors.Wrap(err, "OpenMultipleFiles")
}
// Create unique dialog callback
uniqueCallback := crypto.RandomID()
// Subscribe to the respose channel
responseTopic := "dialog:openmultipleselected:" + uniqueCallback
dialogResponseChannel, err := bus.Subscribe(responseTopic)
if err != nil {
return nil, fmt.Errorf("ERROR: Cannot subscribe to bus topic: %+v\n", err.Error())
}
message := "dialog:select:openmultiple:" + uniqueCallback
bus.Publish(message, dialogOptions)
// Wait for result
var result = <-dialogResponseChannel
// Delete subscription to response topic
bus.UnSubscribe(responseTopic)
return result.Data().([]string), nil
}
// SaveFile prompts the user to select a file
func SaveFile(ctx context.Context, dialogOptions SaveDialogOptions) (string, error) {
bus, err := extractBus(ctx)
if err != nil {
return "", errors.Wrap(err, "SaveFile")
}
// Create unique dialog callback
uniqueCallback := crypto.RandomID()
// Subscribe to the respose channel
responseTopic := "dialog:saveselected:" + uniqueCallback
dialogResponseChannel, err := bus.Subscribe(responseTopic)
if err != nil {
return "", fmt.Errorf("ERROR: Cannot subscribe to bus topic: %+v\n", err.Error())
}
message := "dialog:select:save:" + uniqueCallback
bus.Publish(message, dialogOptions)
// Wait for result
var result = <-dialogResponseChannel
// Delete subscription to response topic
bus.UnSubscribe(responseTopic)
return result.Data().(string), nil
}
// Message show a message to the user
func Message(ctx context.Context, dialogOptions MessageDialogOptions) (string, error) {
bus, err := extractBus(ctx)
if err != nil {
return "", errors.Wrap(err, "Message")
}
// Create unique dialog callback
uniqueCallback := crypto.RandomID()
// Subscribe to the respose channel
responseTopic := "dialog:messageselected:" + uniqueCallback
dialogResponseChannel, err := bus.Subscribe(responseTopic)
if err != nil {
return "", fmt.Errorf("ERROR: Cannot subscribe to bus topic: %+v\n", err.Error())
}
message := "dialog:select:message:" + uniqueCallback
bus.Publish(message, dialogOptions)
// Wait for result
var result = <-dialogResponseChannel
// Delete subscription to response topic
bus.UnSubscribe(responseTopic)
return result.Data().(string), nil
}

View File

@ -1,35 +0,0 @@
package main
import (
"fmt"
"github.com/wailsapp/wails/v2"
)
// Basic application struct
type Basic struct {
runtime *wails.Runtime
}
// newBasic creates a new Basic application struct
func newBasic() *Basic {
return &Basic{}
}
// WailsInit is called at application startup
func (b *Basic) WailsInit(runtime *wails.Runtime) error {
// Perform your setup here
b.runtime = runtime
runtime.Window.SetTitle("minmax")
return nil
}
// WailsShutdown is called at application termination
func (b *Basic) WailsShutdown() {
// Perform your teardown here
}
// Greet returns a greeting for the given name
func (b *Basic) Greet(name string) string {
return fmt.Sprintf("Hello %s!", name)
}

View File

@ -1,18 +0,0 @@
<html>
<head>
<link rel="stylesheet" href="/main.css">
</head>
<body>
<div id="logo"></div>
<div id="input">
<input id="name" type="text"></input>
<button onclick="greet()">Greet</button>
</div>
<div id="result"></div>
<script src="/main.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@ -1,16 +0,0 @@
// Get input + focus
var nameElement = document.getElementById("name");
nameElement.focus();
// Stup the greet function
window.greet = function () {
// Get name
var name = nameElement.value;
// Call Basic.Greet(name)
window.backend.main.Basic.Greet(name).then((result) => {
// Update result with data back from Basic.Greet()
document.getElementById("result").innerText = result;
});
}

View File

@ -1,21 +0,0 @@
package main
import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
)
func main() {
// Create application with options
app := wails.CreateAppWithOptions(&options.App{
Title: "disable resize",
Width: 1024,
Height: 768,
DisableResize: true,
})
app.Bind(newBasic())
app.Run()
}

View File

@ -1,5 +0,0 @@
{
"name": "disable-resize",
"outputfilename": "disable-resize",
"html": "frontend/index.html"
}

View File

@ -1,40 +0,0 @@
package main
//goland:noinspection GoRedundantImportAlias
import (
"fmt"
"github.com/wailsapp/wails/v2"
)
// Basic application struct
type Basic struct {
runtime *wails.Runtime
}
// newBasic creates a new Basic application struct
func newBasic() *Basic {
return &Basic{}
}
// WailsInit is called at application startup
func (b *Basic) WailsInit(runtime *wails.Runtime) error {
// Perform your setup here
b.runtime = runtime
return nil
}
// WailsShutdown is called at application termination
func (b *Basic) WailsShutdown() {
// Perform your teardown here
}
// Greet returns a greeting for the given name
func (b *Basic) Greet(name string) string {
return fmt.Sprintf("Hello %s!", name)
}
// Close shuts down the application
func (b *Basic) Close() {
b.runtime.Quit()
}

View File

@ -1,19 +0,0 @@
<html>
<head>
<link rel="stylesheet" href="/main.css">
</head>
<body data-wails-drag>
<div id="logo"></div>
<div id="input" data-wails-no-drag>
<a id="close" onclick="closeme()">X</a>
<input id="name" type="text"></input>
<button onclick="greet()">Greet</button>
</div>
<div id="result"></div>
<script src="/main.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@ -1,21 +0,0 @@
// Get input + focus
var nameElement = document.getElementById("name");
nameElement.focus();
// Stup the greet function
window.greet = function () {
// Get name
var name = nameElement.value;
// Call Basic.Greet(name)
window.backend.main.Basic.Greet(name).then((result) => {
// Update result with data back from Basic.Greet()
document.getElementById("result").innerText = result;
});
}
window.closeme = function () {
console.log('here');
window.backend.main.Basic.Close();
}

View File

@ -1,28 +0,0 @@
package main
import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/mac"
)
func main() {
// Create application with options
app := wails.CreateAppWithOptions(&options.App{
Title: "Frameless Demo",
Width: 1024,
Height: 768,
MinWidth: 800,
MinHeight: 600,
MaxWidth: 1280,
MaxHeight: 1024,
Mac: &mac.Options{
TitleBar: mac.TitleBarHidden(),
},
})
app.Bind(newBasic())
app.Run()
}

View File

@ -1,5 +0,0 @@
{
"name": "frameless",
"outputfilename": "frameless",
"html": "frontend/index.html"
}

View File

@ -1,44 +0,0 @@
package main
import (
"fmt"
"time"
"github.com/wailsapp/wails/v2"
)
// Basic application struct
type Basic struct {
runtime *wails.Runtime
}
// newBasic creates a new Basic application struct
func newBasic() *Basic {
return &Basic{}
}
// WailsInit is called at application startup
func (b *Basic) WailsInit(runtime *wails.Runtime) error {
// Perform your setup here
b.runtime = runtime
// Show window after 5 seconds
time.AfterFunc(5*time.Second, func() { b.runtime.Window.Show() })
return nil
}
// WailsShutdown is called at application termination
func (b *Basic) WailsShutdown() {
// Perform your teardown here
}
// Greet returns a greeting for the given name
func (b *Basic) Greet(name string) string {
return fmt.Sprintf("Hello %s!", name)
}
// Close shuts down the application
func (b *Basic) Close() {
b.runtime.Quit()
}

View File

@ -1,19 +0,0 @@
<html>
<head>
<link rel="stylesheet" href="/main.css">
</head>
<body data-wails-drag>
<div id="logo"></div>
<div id="input" data-wails-no-drag>
<a id="close" onclick="closeme()">X</a>
<input id="name" type="text"></input>
<button onclick="greet()">Greet</button>
</div>
<div id="result"></div>
<script src="/main.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@ -1,21 +0,0 @@
// Get input + focus
var nameElement = document.getElementById("name");
nameElement.focus();
// Stup the greet function
window.greet = function () {
// Get name
var name = nameElement.value;
// Call Basic.Greet(name)
window.backend.main.Basic.Greet(name).then((result) => {
// Update result with data back from Basic.Greet()
document.getElementById("result").innerText = result;
});
}
window.closeme = function () {
console.log('here');
window.backend.main.Basic.Close();
}

View File

@ -1,21 +0,0 @@
package main
import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
)
func main() {
// Create application with options
app := wails.CreateAppWithOptions(&options.App{
Title: "Hidden Demo",
Width: 1024,
Height: 768,
StartHidden: true,
})
app.Bind(newBasic())
app.Run()
}

View File

@ -1,5 +0,0 @@
{
"name": "hidden",
"outputfilename": "hidden",
"html": "frontend/index.html"
}

View File

@ -1 +0,0 @@
Info.plist

View File

@ -1,59 +0,0 @@
# Assets Directory
The assets directory is used to house all the assets of your application.
The structure is:
* dialog - Icons for dialogs
* tray - Icons for the system tray
* custom - A place for assets you wish to bundle in the application
* mac - MacOS specific files
* linux - Linux specific files
* windows - Windows specific files
## Dialog Icons
Place any PNG file in this directory to be able to use them in message dialogs.
The files should have names in the following format: `name[-(light|dark)][2x].png`
Examples:
* `mypic.png` - Standard definition icon with ID `mypic`
* `mypic-light.png` - Standard definition icon with ID `mypic`, used when system theme is light
* `mypic-dark.png` - Standard definition icon with ID `mypic`, used when system theme is dark
* `mypic2x.png` - High definition icon with ID `mypic`
* `mypic-light2x.png` - High definition icon with ID `mypic`, used when system theme is light
* `mypic-dark2x.png` - High definition icon with ID `mypic`, used when system theme is dark
### Order of preference
Icons are selected with the following order of preference:
For High Definition displays:
* name-(theme)2x.png
* name2x.png
* name-(theme).png
* name.png
For Standard Definition displays:
* name-(theme).png
* name.png
## Tray
Place any PNG file in this directory to be able to use them as tray icons.
The name of the filename will be the ID to reference the image.
Example:
* `mypic.png` - May be referenced using `runtime.Tray.SetIcon("mypic")`
## Custom
Any file in this directory will be embedded into the app using the Wails asset bundler.
Assets can be retrieved using the following methods:
* `wails.Assets().Read(filename string) ([]byte, error)`
* `wails.Assets().String(filename string) (string, error)`
The filename should include the path to the file relative to the `custom` directory.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -1,23 +0,0 @@
package main
import (
"github.com/wailsapp/wails/v2"
)
// Browser struct
type Browser struct {
runtime *wails.Runtime
}
// WailsInit is called at application startup
func (l *Browser) WailsInit(runtime *wails.Runtime) error {
// Perform your setup here
l.runtime = runtime
return nil
}
// Open will open the default browser with the given target
func (l *Browser) Open(target string) error {
// Perform your setup here
return l.runtime.Browser.Open(target)
}

View File

@ -1,55 +0,0 @@
package main
import (
"fmt"
"sync"
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/menu"
)
// ContextMenu struct
type ContextMenu struct {
runtime *wails.Runtime
counter int
lock sync.Mutex
testContextMenu *menu.ContextMenu
clickedMenu *menu.MenuItem
}
// WailsInit is called at application startup
func (c *ContextMenu) WailsInit(runtime *wails.Runtime) error {
// Perform your setup here
c.runtime = runtime
return nil
}
// Setup Menu Listeners
func (c *ContextMenu) updateContextMenu(_ *menu.CallbackData) {
c.lock.Lock()
c.counter++
c.clickedMenu.Label = fmt.Sprintf("Clicked %d times", c.counter)
c.lock.Unlock()
c.runtime.Menu.UpdateContextMenu(c.testContextMenu)
}
func (c *ContextMenu) createContextMenus() []*menu.ContextMenu {
c.clickedMenu = menu.Text("Clicked 0 times", nil, c.updateContextMenu)
c.testContextMenu = menu.NewContextMenu("test", menu.NewMenuFromItems(
c.clickedMenu,
menu.Separator(),
menu.Checkbox("I am a checkbox", false, nil, nil),
menu.Separator(),
menu.Radio("Radio Option 1", true, nil, nil),
menu.Radio("Radio Option 2", false, nil, nil),
menu.Radio("Radio Option 3", false, nil, nil),
menu.Separator(),
menu.SubMenu("A Submenu", menu.NewMenuFromItems(
menu.Text("Hello", nil, nil),
)),
))
return []*menu.ContextMenu{
c.testContextMenu,
}
}

View File

@ -1,33 +0,0 @@
package main
import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options/dialog"
)
// Dialog struct
type Dialog struct {
runtime *wails.Runtime
}
// WailsInit is called at application startup
func (l *Dialog) WailsInit(runtime *wails.Runtime) error {
// Perform your setup here
l.runtime = runtime
return nil
}
// Open Dialog
func (l *Dialog) Open(options *dialog.OpenDialog) []string {
return l.runtime.Dialog.Open(options)
}
// Save Dialog
func (l *Dialog) Save(options *dialog.SaveDialog) string {
return l.runtime.Dialog.Save(options)
}
// Message Dialog
func (l *Dialog) Message(options *dialog.MessageDialog) string {
return l.runtime.Dialog.Message(options)
}

View File

@ -1,59 +0,0 @@
package main
import (
"github.com/wailsapp/wails/v2"
)
// Events struct
type Events struct {
runtime *wails.Runtime
}
// WailsInit is called at application startup
func (e *Events) WailsInit(runtime *wails.Runtime) error {
// Perform your setup here
e.runtime = runtime
return nil
}
// On will subscribe to the given event name
func (e *Events) On(eventName string) {
e.runtime.Events.On(eventName, func(args ...interface{}) {
type callbackData struct {
Name string
Data []interface{}
}
result := callbackData{Name: eventName, Data: args}
e.runtime.Events.Emit("event fired by go subscriber", result)
})
}
// Once will subscribe to the given event name
func (e *Events) Once(eventName string) {
e.runtime.Events.Once(eventName, func(args ...interface{}) {
type callbackData struct {
Name string
Data []interface{}
}
result := callbackData{Name: eventName, Data: args}
e.runtime.Events.Emit("once event fired by go subscriber", result)
})
}
// OnMultiple will subscribe to the given event name, with a maximum
// set by maxCallbacks
func (e *Events) OnMultiple(eventName string, maxCallbacks int) {
e.runtime.Events.OnMultiple(eventName, func(args ...interface{}) {
type callbackData struct {
Name string
Data []interface{}
}
result := callbackData{Name: eventName, Data: args}
e.runtime.Events.Emit("onmultiple event fired by go subscriber", result)
}, maxCallbacks)
}
// Emit will emit
func (e *Events) Emit(eventName string, data []interface{}) {
e.runtime.Events.Emit(eventName, data...)
}

View File

@ -1,4 +0,0 @@
/node_modules/
/public/build/
.DS_Store

View File

@ -1,93 +0,0 @@
*Looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)*
---
# svelte app
This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
```bash
npx degit sveltejs/template svelte-app
cd svelte-app
```
*Note that you will need to have [Node.js](https://nodejs.org) installed.*
## Get started
Install the dependencies...
```bash
cd svelte-app
npm install
```
...then start [Rollup](https://rollupjs.org):
```bash
npm run dev
```
Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
## Building and running in production mode
To create an optimised version of the app:
```bash
npm run build
```
You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
## Single-page app mode
By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
```js
"start": "sirv public --single"
```
## Deploying to the web
### With [now](https://zeit.co/now)
Install `now` if you haven't already:
```bash
npm install -g now
```
Then, from within your project folder:
```bash
cd public
now deploy --name my-project
```
As an alternative, use the [Now desktop client](https://zeit.co/download) and simply drag the unzipped project folder to the taskbar icon.
### With [surge](https://surge.sh/)
Install `surge` if you haven't already:
```bash
npm install -g surge
```
Then, from within your project folder:
```bash
npm run build
surge public my-project.surge.sh
```

File diff suppressed because it is too large Load Diff

View File

@ -1,31 +0,0 @@
{
"name": "svelte-app",
"version": "1.0.0",
"scripts": {
"build": "rollup -c --failAfterWarnings",
"dev": "rollup -c -w --failAfterWarnings",
"start": "sirv public",
"start:dev": "sirv public --single --host 0.0.0.0 --dev"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^11.0.0",
"@rollup/plugin-node-resolve": "^7.0.0",
"@rollup/plugin-url": "^5.0.1",
"@wails/runtime": "^1.2.22",
"focus-visible": "^5.2.0",
"halfmoon": "^1.1.1",
"postcss": "^8.2.2",
"postcss-import": "^12.0.1",
"rollup": "^2.35.1",
"rollup-plugin-livereload": "^1.0.0",
"rollup-plugin-postcss": "^3.1.8",
"rollup-plugin-string": "^3.0.0",
"rollup-plugin-svelte": "~6.1.1",
"rollup-plugin-terser": "^5.1.2",
"sirv-cli": "^0.4.4",
"svelte": "^3.31.0",
"svelte-highlight": "^0.6.2",
"svelte-preprocess": "^4.6.1"
},
"dependencies": {}
}

View File

@ -1,5 +0,0 @@
module.exports = {
plugins: [
require('postcss-import'),
],
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -1,24 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="apple-mobile-web-app-title" content="svelte-mui" />
<meta name="application-name" content="svelte-mui" />
<meta name="theme-color" content="#212121" />
<title>Svelte app</title>
<link rel='icon' type='image/png' href='/favicon.png'>
<link rel='stylesheet' href='/bundle.css'>
<script defer src='/bundle.js'></script>
</head>
<body>
<noscript>Please enable JavaScript.</noscript>
</body>
</html>

View File

@ -1,110 +0,0 @@
import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import postcss from 'rollup-plugin-postcss';
import autoPreprocess from 'svelte-preprocess';
import { string } from "rollup-plugin-string";
import url from '@rollup/plugin-url';
const production = !process.env.ROLLUP_WATCH;
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/bundle.js'
},
onwarn: handleRollupWarning,
plugins: [
// Embed binary files
url({
include: ['**/*.woff', '**/*.woff2'],
limit: Infinity,
}),
// Embed text files
string({
include: ["**/*.jsx","**/*.go", "**/*.txt"],
}),
svelte({
preprocess: autoPreprocess(),
// enable run-time checks when not in production
dev: !production,
// we'll extract any component CSS out into
// a separate file - better for performance
css: css => {
css.write('public/bundle.css');
},
emitCss: true,
}),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration -
// consult the documentation for details:
// https://github.com/rollup/plugins/tree/master/packages/commonjs
resolve({
browser: true,
dedupe: ['svelte']
}),
commonjs(),
// PostCSS preprocessing
postcss({
extensions: ['.css', '.scss'],
extract: true,
minimize: false,
use: [
['sass', {
includePaths: [
'./src/theme',
'./node_modules'
]
}]
],
}),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload('public'),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser()
],
watch: {
clearScreen: false
}
};
function handleRollupWarning(warning) {
console.error('ERROR: ' + warning.toString());
process.exit(1);
}
function serve() {
let started = false;
return {
writeBundle() {
if (!started) {
started = true;
require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
}
}
};
}

View File

@ -1,128 +0,0 @@
:root {
--lm-base-body-bg-color: #0000;
--dm-base-body-bg-color: #0000;
--lm-sidebar-bg-color: #0000;
--dm-sidebar-bg-color: #0000;
--dm-sidebar-link-text-color: white;
--dm-sidebar-link-text-color-hover: rgb(255, 214, 0);
--lm-sidebar-link-text-color: black;
--lm-sidebar-link-text-color-hover: rgb(158, 158, 255);
--dm-sidebar-link-text-color-active: rgb(255, 214, 0);
--dm-sidebar-link-text-color-active-hover: rgb(255, 214, 0);
--sidebar-title-font-size: 1.75rem;
--sidebar-brand-font-size: 2.3rem;
--base-font-size: 1.5rem;
/* Switch */
--dm-switch-bg-color: rgb(28,173,213);
--lm-switch-bg-color: rgb(28,173,213);
--dm-switch-bg-color-checked: rgb(186,167,49);
--lm-switch-bg-color-checked: rgb(186,167,49);
--lm-switch-slider-bg-color: #FFF;
--dm-switch-slider-bg-color: #FFF;
--dm-base-text-color: white;
--lm-base-text-color: black;
}
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-thumb {
background-color: rgba(128,128,128,.25);
border: 2px solid transparent;
border-radius: 10px;
background-clip: padding-box;
}
&:hover {
background-color: rgba(128,128,128,.5);
}
::-webkit-scrollbar-track {
background-color: rgba(128,128,128,0);
}
.sidebar-link {
cursor: pointer;
}
.rhs {
background-color: #333;
}
.inner-content {
position: absolute;
top: 20px;
bottom: 20px;
width: 99%;
overflow-y: hidden;
}
.content-wrapper {
overflow: hidden;
}
.dark-content-wrapper {
background-color: #25282c;
}
/*
.sidebar {
background-color: #0000;
} */
.sidebar-brand {
padding-top: 35px;
padding-bottom: 25px;
cursor: pointer;
}
.sidebar-menu {
background-color: #0000;
}
/* Credit: https://stackoverflow.com/a/4407335 */
.noselect {
cursor: default;
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Old versions of Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently
supported by Chrome, Edge, Opera and Firefox */
}
.allow-select {
-webkit-touch-callout: initial; /* iOS Safari */
-webkit-user-select: initial; /* Safari */
-khtml-user-select: initial; /* Konqueror HTML */
-moz-user-select: initial; /* Old versions of Firefox */
-ms-user-select: initial; /* Internet Explorer/Edge */
user-select: initial; /* Non-prefixed version, currently
supported by Chrome, Edge, Opera and Firefox */
}
.list {
margin-top: 1.5rem;
margin-left: 1.5rem;
}
.list li {
margin-bottom: 0.5rem;
}
.page-header {
position: fixed;
top: 50px;
}
html {
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";
}

View File

@ -1,79 +0,0 @@
<script>
import { darkMode, selectedPage } from './Store';
import MainPage from './MainPage.svelte';
import { Browser } from '@wails/runtime';
// Hightlight CSS
import { atomOneDark, atomOneLight } from "svelte-highlight/styles";
$: css = $darkMode ? atomOneDark : atomOneLight;
function linkClicked(event) {
let linkText = event.target.innerText;
selectedPage.set(linkText);
console.log(event.target.innerText);
}
function homepageClicked() {
selectedPage.set(null);
}
function openSite(url) {
Browser.Open(url)
}
let runtimePages = [
'Logging',
'Events',
'Dialog',
'Browser',
'File System',
'Window',
'Tray',
'System'
];
</script>
<svelte:head>
{@html css}
</svelte:head>
<div data-wails-drag class="page-wrapper with-sidebar" class:dark-mode="{$darkMode}" data-sidebar-type="full-height" >
<!-- Sticky alerts (toasts), empty container -->
<div class="sticky-alerts"></div>
<!-- Sidebar -->
<div class="sidebar noselect" data-wails-context-menu-id="test" data-wails-context-menu-data="hello!">
<div data-wails-no-drag class="sidebar-menu">
<!-- Sidebar brand -->
<div on:click="{ homepageClicked }" class="sidebar-brand">
Wails Kitchen Sink
</div>
<!-- Sidebar links and titles -->
<h5 class="sidebar-title">Runtime</h5>
<div class="sidebar-divider"></div>
{#each runtimePages as link}
<span on:click="{linkClicked}" class="sidebar-link" class:active="{$selectedPage === link}">{link}</span>
{/each}
<br />
<h5 class="sidebar-title">Links</h5>
<div class="sidebar-divider"></div>
<span on:click="{() => openSite('https://github.com/wailsapp/wails')}" class="sidebar-link">Github</span>
<span on:click="{() => openSite('https://wails.app')}" class="sidebar-link">Website</span>
</div>
</div>
<!-- Content wrapper -->
<div class="content-wrapper noselect" class:dark-content-wrapper="{$darkMode}">
<div class="inner-content">
<MainPage/>
</div>
</div>
</div>
<style global>
@import 'halfmoon/css/halfmoon-variables.min.css';
/* @import './assets/fonts/roboto.css'; */
@import './App.css';
</style>

View File

@ -1,43 +0,0 @@
<script>
import {selectedPage} from './Store';
import TitlePage from './pages/TitlePage.svelte';
import Logging from './pages/Logging/Logging.svelte';
import Events from './pages/Events/Events.svelte';
import Browser from './pages/Browser/Browser.svelte';
import Dialog from './pages/Dialog/Dialog.svelte';
import System from './pages/System/System.svelte';
import Window from './pages/Window/Window.svelte';
import Tray from './pages/Tray/Tray.svelte';
</script>
<h4 class="title">{$selectedPage || "" }</h4>
<div class="mainpage">
{#if $selectedPage == undefined} <TitlePage></TitlePage> {/if}
{#if $selectedPage == "Logging"} <Logging></Logging> {/if}
{#if $selectedPage == "Events"} <Events></Events> {/if}
{#if $selectedPage == "Browser"} <Browser></Browser> {/if}
{#if $selectedPage == "Dialog"} <Dialog></Dialog> {/if}
{#if $selectedPage == "System"} <System></System> {/if}
{#if $selectedPage == "Window"} <Window></Window> {/if}
{#if $selectedPage == "Tray"} <Tray></Tray> {/if}
</div>
<style>
.title {
position: fixed;
top: 50px;
margin-left: 20px;
}
.mainpage {
position: absolute;
top: 70px;
margin-left: 20px;
padding-right: 10px;
margin-top: 20px;
overflow-y: auto;
height: calc(100% - 100px);
width: calc(100% - 20px);
}
</style>

View File

@ -1,23 +0,0 @@
import { writable } from 'svelte/store';
import runtime from '@wails/runtime';
export let selectedPage = writable();
export let darkMode = writable(runtime.System.DarkModeEnabled());
// Handle Dark/Light themes automatically
runtime.System.OnThemeChange( (isDarkMode) => {
darkMode.set(isDarkMode);
});
// LogLevel
// Create a svelte store for the logLevel and initialise with
// the loglevel stored in the Wails runtime
const defaultLogLevel = runtime.System.LogLevel.get();
export let logLevel = writable(defaultLogLevel);
// Bind updates to the Wails store to the Svelte Store
runtime.System.LogLevel.subscribe( (newValue) => {
logLevel.set(newValue);
})

File diff suppressed because one or more lines are too long

View File

@ -1,177 +0,0 @@
<script>
import { darkMode } from '../Store';
import { Highlight } from "svelte-highlight";
import { go, javascript } from "svelte-highlight/languages";
// Default to Go
export let isJs = false;
export let title;
export let description;
// Calculate CSS to use
$: lang = isJs ? javascript : go;
// Calculate Code for code block
export let jsCode = "Hi from JS!";
export let goCode = "Hi from Go!";
$: code = isJs ? jsCode : goCode;
// Handle hiding example
let showCode = false;
function toggleExample() {
showCode = !showCode;
}
export let id = "toggle-" + Date.now().toString() + Math.random().toString();
// Handle hiding example
export let showRun = false;
function toggleRun() {
showRun = !showRun;
}
</script>
<div data-wails-no-drag class={$darkMode ? "codeblock" : "codeblock-light"}>
<div class="header">
<span class="title">{title}</span>
<span class="toggle">
<span>Go</span>
<span class="custom-switch">
<input type="checkbox" {id} value="" bind:checked={isJs}>
<label for={id}>Javascript</label>
</span>
</span>
{#if description}
<div class="description">{@html description}</div>
{/if}
</div>
<div class="run">
<div class="{showRun ? 'run-title-open' : 'run-title-closed'}" on:click="{toggleRun}">
<span class="arrow">{showRun?'▼':'▶'}</span>
Try Me!
</div>
{#if showRun}
<div class={$darkMode ? "run-content-dark" : "run-content-light"}>
<slot></slot>
</div>
{/if}
</div>
<div class="example allow-select">
<div class="{showCode ? 'code-title-open' : 'code-title-closed'}" on:click="{toggleExample}" >
<span class="arrow">{showCode?'▼':'▶'}</span>
Example Code
</div>
{#if showCode}
<Highlight style="margin-bottom: 0" language="{lang}" {code}/>
{/if}
</div>
</div>
<style>
.arrow {
display: inline-block;
width: calc(var(--base-font-size));
padding: 2px;
}
.header {
display: flex;
justify-content: space-between;
border-bottom: 1px solid #5555;
flex-wrap: wrap;
align-items: center;
padding-bottom: 5px;
padding-left: 5px;
padding-right: 5px;
}
.title {
font-size: calc(var(--base-font-size) * 1.1);
}
.code-title-open {
margin-top: 5px;
margin-bottom: -5px;
padding-left: 5px;
cursor: pointer;
}
.code-title-closed {
margin-top: 5px;
padding-left: 5px;
padding-bottom: 5px;
cursor: pointer;
}
.run-content-dark {
padding: 15px;
background-color: #282c34;
}
.run-content-light {
padding: 15px;
background-color: #fafafa;
}
.run-title-open {
margin-top: 5px;
margin-bottom: 5px;
padding-bottom: 0;
padding-left: 5px;
cursor: pointer;
}
.run-title-closed {
margin-top: 5px;
margin-bottom: 5px;
padding-left: 5px;
cursor: pointer;
}
.toggle {
float: right;
margin-top: 2px;
font-size: calc(var(--base-font-size) * 0.9);
}
.example {
border-top: 1px solid #5555;
}
.custom-switch {
display: inline-block;
margin-left: 5px;
}
.codeblock {
/* background-color: #3F3F4B; */
border-radius: 5px;
border: 1px solid #555;
padding: 5px;
margin-top: 20px;
margin-bottom: 10px;
}
.codeblock-light {
/* background-color: #e5e5e5; */
border-radius: 5px;
border: 1px solid #ccc;
padding: 5px;
margin-top: 20px;
margin-bottom: 10px;
}
.description {
border-top: 1px solid #5555;
margin-top: 10px;
padding-top: 5px;
width: 100%;
}
</style>

View File

@ -1,43 +0,0 @@
<script>
import { darkMode } from '../Store';
import { Highlight } from "svelte-highlight";
import { go, javascript } from "svelte-highlight/languages";
// Default to Go
export let isJs = false;
// Calculate CSS to use
$: lang = isJs ? javascript : go;
// Calculate Code for code block
export let jsCode = "Hi from JS!";
export let goCode = "Hi from Go!";
$: code = isJs ? jsCode : goCode;
</script>
<div data-wails-no-drag class="allow-select {$darkMode ? 'codeblock' : 'codeblock-light'}">
<Highlight language="{lang}" {code} style="margin: -5px;"/>
</div>
<style>
.codeblock {
background-color: #3F3F4B;
border: 1px solid #555;
padding: 5px;
margin-top: 20px;
margin-bottom: 10px;
}
.codeblock-light {
background-color: #e5e5e5;
border: 1px solid #ccc;
padding: 5px;
margin-top: 20px;
margin-bottom: 10px;
}
</style>

View File

@ -1,55 +0,0 @@
<script>
import { afterUpdate } from 'svelte';
import { darkMode } from '../Store';
$: termClass = $darkMode ? 'faketerm-dark' : 'faketerm-light';
let termElement;
afterUpdate( () => {
termElement.scrollTop = termElement.scrollHeight;
});
export let text = "";
export let style = null;
</script>
<div bind:this={termElement} class="common {termClass}" {style}>
<pre>
{#if text && text.length > 0}
{text}
{:else}
<slot></slot>
{/if}
</pre>
</div>
<style>
pre {
margin: 0;
padding: 5px;
}
.common {
font-family: 'Courier New', Courier, monospace;
padding: 5px;
white-space: pre-line;
margin-top: 10px;
margin-bottom: 10px;
border: 1px solid #5555;
overflow-y: auto;
overflow-wrap: break-word;
}
.faketerm-dark {
background-color: black;
color: white;
}
.faketerm-light {
background-color: #ddd;
color: black;
}
</style>

View File

@ -1,37 +0,0 @@
<script>
import runtime from '@wails/runtime';
import { darkMode } from '../Store';
export let href;
$: linkclass = darkMode ? 'dark' : 'light';
function openLink() {
runtime.Browser.Open(href);
}
</script>
<span class="link {linkclass}" on:click="{openLink}"><slot></slot></span>
<style>
.link {
text-decoration: underline;
cursor: pointer;
}
.link.dark:hover {
color: #ff8bfb;
}
.link.dark {
color: #ff8bfb88;
}
.link.light {
color: #5c5cff;
text-decoration: underline;
}
</style>

View File

@ -1,10 +0,0 @@
import App from './App.svelte';
const app = new App({
target: document.body,
props: {
name: 'Wails User'
}
});
export default app;

View File

@ -1,17 +0,0 @@
<script>
import Link from '../../components/Link.svelte';
import Browser from './Browser/Browser.svelte';
</script>
<div>
Sometimes it is necessary to redirect users to external websites. The Wails runtime offers this ability through the <code>runtime.Browser</code> component.
By using <code>runtime.Browser.Open</code>, it is possible to open the user's default browser to either navigate to a url (pass in a URL), or open a local file (provide a local filepath).
<Link href="https://wails.app">Here</Link> is an example.
<br/><br/>
<Browser/>
</div>

View File

@ -1,45 +0,0 @@
<script>
import { Browser } from '@wails/runtime';
import CodeBlock from '../../../components/CodeBlock.svelte';
import CodeSnippet from '../../../components/CodeSnippet.svelte';
import jsCode from './code.jsx';
import goCode from './code.go';
var isJs = false;
$: lang = isJs ? 'Javascript' : 'Go';
var id = "Browser";
var userInput = "";
function processOpen() {
if( userInput.length > 0 ) {
if( isJs ) {
Browser.Open(userInput)
} else {
backend.main.Browser.Open(userInput)
}
}
}
$: encodedMessage = userInput.replace(`"`, `\"`);
$: testcodeJs = "import { runtime } from '@wails/runtime';\nruntime.Browser.Open(`" + encodedMessage + "`);";
$: testcodeGo = '// runtime is given through WailsInit()\nruntime.Browser.Open("' + encodedMessage + '")';
</script>
<CodeBlock bind:isJs={isJs} {jsCode} {goCode} title="Open" {id} showRun=true>
<div class="browser-form">
<form data-wails-no-drag class="mw-full">
<div class="form-group">
<label for="{id}-userInput" class="required">Enter Filename or URL</label>
<input type="text" class="form-control" id="{id}-userInput" placeholder="https://www.duckduckgo.com" bind:value="{userInput}" required="required">
</div>
<input class="btn btn-primary" type="button" on:click="{processOpen}" value="Open using {lang} runtime">
<CodeSnippet bind:isJs={isJs} jsCode={testcodeJs} goCode={testcodeGo}/>
</form>
</div>
</CodeBlock>

View File

@ -1,11 +0,0 @@
package main
import "github.com/wailsapp/wails/v2"
type MyStruct struct {
runtime *wails.Runtime
}
func (l *MyStruct) ShowHelp() {
l.runtime.Browser.Open("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
}

View File

@ -1,6 +0,0 @@
import { Browser } from '@wails/runtime';
function showHelp() {
// Do some things
Browser.Open("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
}

View File

@ -1,23 +0,0 @@
<script>
import Open from './Open/Open.svelte';
import Save from './Save/Save.svelte';
import Message from "./Message/Message.svelte";
</script>
<div>
Sometimes there is a need to prompt the user for input. Dialogs are a good approach to this and Wails provides access to native dialogs. The dialog types supported are:
<ul class="list">
<li>Open - Prompts the user to select one or more files or folders</li>
<li>Save - Prompts the user to select a file or input a filename</li>
<li>Message - Prompts the user with information and optionally provides action buttons</li>
</ul>
<br/><br/>
<Open/>
<br/>
<Save/>
<br/>
<Message/>
</div>

View File

@ -1,159 +0,0 @@
<script>
import {Dialog} from '@wails/runtime';
import CodeBlock from '../../../components/CodeBlock.svelte';
import CodeSnippet from '../../../components/CodeSnippet.svelte';
import jsCode from './code.jsx';
import goCode from './code.go';
let isJs = false;
$: lang = isJs ? 'Javascript' : 'Go';
let id = "MessageDialog";
let options = {
"Type": "info",
"Title": "",
"Message": "",
"Buttons": [],
"DefaultButton": "",
"CancelButton": "",
"Icon": "",
}
function processMessage() {
if( isJs ) {
console.log(options);
Dialog.Message(options);
} else {
backend.main.Dialog.Message(options).then( (result) => {
console.log(result);
});
}
}
function prettyPrintArray(json) {
if (typeof json === 'string') {
json = JSON.parse(json);
}
return JSON.stringify(json, function (k, v) {
if (v instanceof Array)
return JSON.stringify(v);
return v;
}, 2).replace(/\\/g, '')
.replace(/"\[/g, '[')
.replace(/]"/g, ']')
.replace(/"{/g, '{')
.replace(/}"/g, '}');
}
let dialogTypes = ["Info", "Warning", "Error", "Question"];
let dialogTypeSelected = dialogTypes[0];
let buttonInputs = ["","","",""];
// Keep buttons in sync
$: {
options.Buttons = [];
buttonInputs.forEach( (button) => {
if ( button.length > 0 ) {
options.Buttons.push(button);
}
})
}
// Keep options in sync with dialog type selected
$: options.Type = dialogTypeSelected.toLowerCase();
// Inspired by: https://stackoverflow.com/a/54931396
$: encodedJSOptions = JSON.stringify(options, function (k, v) {
if (v instanceof Array)
return JSON.stringify(v);
return v;
}, 4)
.replace(/\\/g, '')
.replace(/"\[/g, '[')
.replace(/]"/g, ']')
.replace(/"{/g, '{')
.replace(/}"/g, '}');
$: encodedGoOptions = encodedJSOptions
.replace(/ {2}"(.*)":/mg, " $1:")
.replace(/Type: "(.*)"/mg, "Type: options." + dialogTypeSelected + "Dialog")
.replace(/Buttons: \[(.*)],/mg, "Buttons: []string{$1},")
.replace(/\n}/, ",\n}");
$: testcodeJs = "import { Dialog } from '@wails/runtime';\n\nDialog.Message(" + encodedJSOptions + ");";
$: testcodeGo = '// runtime is given through WailsInit()\nimport "github.com/wailsapp/wails/v2/pkg/options"\n\nselectedFiles := runtime.Dialog.Message( &options.MessageDialog' + encodedGoOptions + ')';
</script>
<CodeBlock bind:isJs={isJs} {jsCode} {goCode} title="Message" {id} showRun=true>
<div class="browser-form">
<form data-wails-no-drag class="mw-full">
<div class="form-row row-eq-spacing-sm">
<div class="form-group">
<div>Dialog Type</div>
{#each dialogTypes as option}
<div class="custom-radio">
<input type="radio" name="dialogType" bind:group="{dialogTypeSelected}" id="{id}-{option}" value="{option}">
<label for="{id}-{option}">{option}</label>
</div>
{/each}
</div>
</div>
<div class="form-row row-eq-spacing-sm">
<div class="col-sm">
<label for="{id}-Title">Title</label>
<input type="text" class="form-control" id="{id}-Title" bind:value="{options.Title}">
<div class="form-text"> The title for the dialog </div>
</div>
<div class="col-sm">
<label for="{id}-Message">Message</label>
<input type="text" class="form-control" id="{id}-Message" bind:value="{options.Message}">
<div class="form-text"> The dialog message </div>
</div>
</div>
<div class="form-row row-eq-spacing-sm">
<div class="col-sm">
<label for="{id}-Button1">Button 1</label>
<input type="text" class="form-control" id="{id}-Button1" bind:value="{buttonInputs[0]}">
</div>
<div class="col-sm">
<label for="{id}-Button2">Button 2</label>
<input type="text" class="form-control" id="{id}-Button2" bind:value="{buttonInputs[1]}">
</div>
<div class="col-sm">
<label for="{id}-Button3">Button 3</label>
<input type="text" class="form-control" id="{id}-Button3" bind:value="{buttonInputs[2]}">
</div>
<div class="col-sm">
<label for="{id}-Button4">Button 4</label>
<input type="text" class="form-control" id="{id}-Button4" bind:value="{buttonInputs[3]}">
</div>
</div>
<div class="form-row row-eq-spacing-sm">
<div class="col-sm">
<label for="{id}-DefaultButton">Default Button</label>
<input type="text" class="form-control" id="{id}-DefaultButton" bind:value="{options.DefaultButton}">
<div class="form-text"> The button that is the default option</div>
</div>
<div class="col-sm">
<label for="{id}-CancelButton">Cancel Button</label>
<input type="text" class="form-control" id="{id}-CancelButton" bind:value="{options.CancelButton}">
<div class="form-text"> The button that is the cancel option </div>
</div>
</div>
<div class="form-row row-eq-spacing-sm">
<div class="col-sm">
<label for="{id}-Icon">Icon</label>
<input type="text" class="form-control" id="{id}-Icon" bind:value="{options.Icon}">
<div class="form-text"> The icon to use in the dialog </div>
</div>
</div>
<input class="btn btn-primary" type="button" on:click="{processMessage}" value="Show message dialog using {lang} runtime">
<CodeSnippet bind:isJs={isJs} jsCode={testcodeJs} goCode={testcodeGo}/>
</form>
</div>
</CodeBlock>

View File

@ -1,42 +0,0 @@
package main
import (
"github.com/wailsapp/wails/v2/pkg/options/dialog"
"io/ioutil"
"github.com/wailsapp/wails/v2"
)
type Notepad struct {
runtime *wails.Runtime
}
func (n *Notepad) WailsInit(runtime *wails.Runtime) error {
n.runtime = runtime
return nil
}
// SaveNotes attempts to save the given notes to disk.
// Returns false if the user cancelled the save, true on
// successful save.
func (n *Notepad) SaveNotes(notes string) (bool, error) {
selectedFile := n.runtime.Dialog.Save(&dialog.SaveDialog{
DefaultFilename: "notes.md",
Filters: "*.md",
})
// Check if the user pressed cancel
if selectedFile == "" {
// Cancelled
return false, nil
}
// Save notes
err := ioutil.WriteFile(selectedFile, []byte(notes), 0700)
if err != nil {
return false, err
}
return true, nil
}

View File

@ -1,23 +0,0 @@
import { Dialog } from '@wails/runtime';
let notes = "";
function saveNotes() {
// Prompt the user to select a single file
let filename = Dialog.Save({
"DefaultFilename": "notes.md",
"Filters": "*.md",
});
// Do something with the file
backend.main.SaveNotes(filename, notes).then( (result) => {
if ( !result ) {
// Cancelled
return
}
showMessage('Notes saved!');
}).catch( (err) => {
// Show an alert
showAlert(err);
})
}

View File

@ -1,102 +0,0 @@
<script>
import { Dialog } from '@wails/runtime';
import CodeBlock from '../../../components/CodeBlock.svelte';
import CodeSnippet from '../../../components/CodeSnippet.svelte';
import jsCode from './code.jsx';
import goCode from './code.go';
var isJs = false;
$: lang = isJs ? 'Javascript' : 'Go';
var id = "OpenDialog";
let options = {
"DefaultDirectory": "",
"DefaultFilename": "",
"Title": "",
"Filters": "",
"AllowFiles": false,
"AllowDirectories": false,
"AllowMultiple": false,
"ShowHiddenFiles": false,
"CanCreateDirectories": false,
"ResolvesAliases": false,
"TreatPackagesAsDirectories": false
}
function processOpen() {
if( isJs ) {
console.log(options);
Dialog.Open(options);
} else {
backend.main.Dialog.Open(options).then( (result) => {
console.log(result);
});
}
}
$: encodedJSOptions = JSON.stringify(options, null, " ");
$: encodedGoOptions = encodedJSOptions
.replace(/\ {2}"(.*)":/mg, " $1:")
.replace(/\n}/, ",\n}");
$: testcodeJs = "import { runtime } from '@wails/runtime';\nruntime.Dialog.Open(" + encodedJSOptions + ");";
$: testcodeGo = '// runtime is given through WailsInit()\nimport "github.com/wailsapp/wails/v2/pkg/options"\n\nselectedFiles := runtime.Dialog.Open( &options.OpenDialog' + encodedGoOptions + ')';
</script>
<CodeBlock bind:isJs={isJs} {jsCode} {goCode} title="Open" {id} showRun=true>
<div class="browser-form">
<form data-wails-no-drag class="mw-full">
<div class="form-row row-eq-spacing-sm">
<div class="col-sm">
<label for="{id}-Title">Title</label>
<input type="text" class="form-control" id="{id}-Title" bind:value="{options.Title}">
<div class="form-text"> The title for the dialog </div>
</div>
<div class="col-sm">
<label for="{id}-defaultDirectory">Default Directory</label>
<input type="text" class="form-control" id="{id}-defaultDirectory" bind:value="{options.DefaultDirectory}">
<div class="form-text"> The directory the dialog will default to </div>
</div>
</div>
<div class="form-row row-eq-spacing-sm">
<div class="col-sm">
<label for="{id}-defaultFilename">Default Filename</label>
<input type="text" class="form-control" id="{id}-defaultFilename" bind:value="{options.DefaultFilename}">
<div class="form-text"> The filename the dialog will suggest to use </div>
</div>
<div class="col-sm">
<label for="{id}-Filters">Filters</label>
<input type="text" class="form-control" id="{id}-Filters" bind:value="{options.Filters}">
<div class="form-text"> A list of extensions eg <code>*.jpg,*.jpeg</code> </div>
</div>
</div>
<div class="form-row row-eq-spacing-sm">
<div class="col-sm">
<input type="checkbox" id="{id}-AllowFiles" bind:checked="{options.AllowFiles}">
<label for="{id}-AllowFiles">Allow files to be selected</label>
</div>
<div class="col-sm">
<input type="checkbox" id="{id}-AllowDirectories" bind:checked="{options.AllowDirectories}">
<label for="{id}-AllowDirectories">Allow directories to be selected</label>
</div>
</div>
<div class="form-row row-eq-spacing-sm">
<div class="col-sm">
<input type="checkbox" id="{id}-AllowMultiple" bind:checked="{options.AllowMultiple}">
<label for="{id}-AllowMultiple">Allow multiple selection</label>
</div>
<div class="col-sm">
<input type="checkbox" id="{id}-CanCreateDirectories" bind:checked="{options.CanCreateDirectories}">
<label for="{id}-CanCreateDirectories">Can create directories</label>
</div>
</div>
<input class="btn btn-primary" type="button" on:click="{processOpen}" value="Open using {lang} runtime">
<CodeSnippet bind:isJs={isJs} jsCode={testcodeJs} goCode={testcodeGo}></CodeSnippet>
</form>
</div>
</CodeBlock>

View File

@ -1,40 +0,0 @@
package main
import (
"github.com/wailsapp/wails/v2/pkg/options/dialog"
"io/ioutil"
"github.com/wailsapp/wails/v2"
)
type Notepad struct {
runtime *wails.Runtime
}
func (n *Notepad) WailsInit(runtime *wails.Runtime) error {
n.runtime = runtime
return nil
}
func (n *Notepad) LoadNotes() (string, error) {
selectedFiles := n.runtime.Dialog.Open(&dialog.OpenDialog{
DefaultFilename: "notes.md",
Filters: "*.md",
AllowFiles: true,
})
// selectedFiles is a string slice. Get the first selection
if len(selectedFiles) == 0 {
// Cancelled
return "", nil
}
// Load notes
noteData, err := ioutil.ReadFile(selectedFiles[0])
if err != nil {
return "", err
}
return string(noteData), nil
}

View File

@ -1,25 +0,0 @@
import { Dialog } from '@wails/runtime';
let notes = "";
function loadNotes() {
// Prompt the user to select a single file
let filename = Dialog.Open({
"DefaultFilename": "notes.md",
"Filters": "*.md",
"AllowFiles": true,
});
// Do something with the file
backend.main.LoadNotes(filename).then( (result) => {
if (result.length == 0) {
// Cancelled
return
}
// We only prompted for a single file
notes = result[0];
}).catch( (err) => {
// Show an alert
showAlert(err);
})
}

View File

@ -1,84 +0,0 @@
<script>
import { Dialog } from '@wails/runtime';
import CodeBlock from '../../../components/CodeBlock.svelte';
import CodeSnippet from '../../../components/CodeSnippet.svelte';
import jsCode from './code.jsx';
import goCode from './code.go';
var isJs = false;
$: lang = isJs ? 'Javascript' : 'Go';
var id = "SaveDialog";
let options = {
"DefaultDirectory": "",
"DefaultFilename": "",
"Title": "",
"Filters": "",
"ShowHiddenFiles": false,
"CanCreateDirectories": false,
"TreatPackagesAsDirectories": false
}
function processSave() {
if( isJs ) {
console.log(options);
Dialog.Save(options);
} else {
backend.main.Dialog.Save(options).then( (result) => {
console.log(result);
});
}
}
$: encodedJSOptions = JSON.stringify(options, null, " ");
$: encodedGoOptions = encodedJSOptions
.replace(/\ {2}"(.*)":/mg, " $1:")
.replace(/\n}/, ",\n}");
$: testcodeJs = "import { runtime } from '@wails/runtime';\nruntime.Dialog.Save(" + encodedJSOptions + ");";
$: testcodeGo = '// runtime is given through WailsInit()\nimport "github.com/wailsapp/wails/v2/pkg/options"\n\nselectedFiles := runtime.Dialog.Save( &options.SaveDialog' + encodedGoOptions + ')';
</script>
<CodeBlock bind:isJs={isJs} {jsCode} {goCode} title="Save" {id} showRun=true>
<div class="browser-form">
<form data-wails-no-drag class="mw-full">
<div class="form-row row-eq-spacing-sm">
<div class="col-sm">
<label for="{id}-Title">Title</label>
<input type="text" class="form-control" id="{id}-Title" bind:value="{options.Title}">
<div class="form-text"> The title for the dialog </div>
</div>
<div class="col-sm">
<label for="{id}-defaultDirectory">Default Directory</label>
<input type="text" class="form-control" id="{id}-defaultDirectory" bind:value="{options.DefaultDirectory}">
<div class="form-text"> The directory the dialog will default to </div>
</div>
</div>
<div class="form-row row-eq-spacing-sm">
<div class="col-sm">
<label for="{id}-defaultFilename">Default Filename</label>
<input type="text" class="form-control" id="{id}-defaultFilename" bind:value="{options.DefaultFilename}">
<div class="form-text"> The filename the dialog will suggest to use </div>
</div>
<div class="col-sm">
<label for="{id}-Filters">Filters</label>
<input type="text" class="form-control" id="{id}-Filters" bind:value="{options.Filters}">
<div class="form-text"> A list of extensions eg <code>*.jpg,*.jpeg</code> </div>
</div>
</div>
<div class="form-row row-eq-spacing-sm">
<div class="col-sm">
<input type="checkbox" id="{id}-CanCreateDirectories" bind:checked="{options.CanCreateDirectories}">
<label for="{id}-CanCreateDirectories">Can create directories</label>
</div>
</div>
<input class="btn btn-primary" type="button" on:click="{processSave}" value="Save using {lang} runtime">
<CodeSnippet bind:isJs={isJs} jsCode={testcodeJs} goCode={testcodeGo}></CodeSnippet>
</form>
</div>
</CodeBlock>

View File

@ -1,42 +0,0 @@
package main
import (
"github.com/wailsapp/wails/v2/pkg/options/dialog"
"io/ioutil"
"github.com/wailsapp/wails/v2"
)
type Notepad struct {
runtime *wails.Runtime
}
func (n *Notepad) WailsInit(runtime *wails.Runtime) error {
n.runtime = runtime
return nil
}
// SaveNotes attempts to save the given notes to disk.
// Returns false if the user cancelled the save, true on
// successful save.
func (n *Notepad) SaveNotes(notes string) (bool, error) {
selectedFile := n.runtime.Dialog.Save(&dialog.SaveDialog{
DefaultFilename: "notes.md",
Filters: "*.md",
})
// Check if the user pressed cancel
if selectedFile == "" {
// Cancelled
return false, nil
}
// Save notes
err := ioutil.WriteFile(selectedFile, []byte(notes), 0700)
if err != nil {
return false, err
}
return true, nil
}

View File

@ -1,23 +0,0 @@
import { Dialog } from '@wails/runtime';
let notes = "";
function saveNotes() {
// Prompt the user to select a single file
let filename = Dialog.Save({
"DefaultFilename": "notes.md",
"Filters": "*.md",
});
// Do something with the file
backend.main.SaveNotes(filename, notes).then( (result) => {
if ( !result ) {
// Cancelled
return
}
showMessage('Notes saved!');
}).catch( (err) => {
// Show an alert
showAlert(err);
})
}

View File

@ -1,66 +0,0 @@
<script>
import { Log } from '@wails/runtime';
import CodeBlock from '../../../components/CodeBlock.svelte';
import CodeSnippet from '../../../components/CodeSnippet.svelte';
import jsCode from './code.jsx';
import goCode from './code.go';
import { logLevel } from '../../../Store';
var message = '';
var isJs = false;
const loglevels = ["Trace", "Debug", "Info", "Warning", "Error", "Fatal", "Print"];
var loglevel = loglevels[0];
$: lang = isJs ? 'Javascript' : 'Go';
var id = "Logging";
function sendLogMessage() {
if( message.length > 0 ) {
if( isJs ) {
// Call JS runtime
Log[loglevel](message);
} else {
// Call Go method which calls Go Runtime
backend.main.Logger[loglevel](message);
}
}
}
$: encodedMessage = message.replace(`"`, `\"`);
$: testcodeJs = "import { runtime } from '@wails/runtime';\nruntime.Log." + loglevel + "(`" + encodedMessage + "`);";
$: testcodeGo = '// runtime is given through WailsInit()\nruntime.Log.' + loglevel + '("' + encodedMessage + '")';
</script>
<CodeBlock bind:isJs={isJs} {jsCode} {goCode} title="Logging" {id}>
<div class="logging-form">
<form data-wails-no-drag class="mw-full">
<div class="form-group">
<div>Select Log Method</div>
{#each loglevels as option, index}
{#if (index + 1) === $logLevel}
<span style="margin-top: 5px; height: 20px; display: inline-block;"><hr style="width: 270px;display: inline-block; vertical-align: middle; margin-right: 10px"/> Current Log Level </span>
{/if}
<div class="custom-radio">
<input type="radio" name="logging" bind:group="{loglevel}" id="{id}-{option}" value="{option}">
<label for="{id}-{option}">{option}</label>
</div>
{/each}
</div>
<div class="form-group">
<label for="{id}-message" class="required">Message</label>
<input type="text" class="form-control" id="{id}-message" placeholder="Hello World!" bind:value="{message}" required="required">
</div>
<input class="btn btn-primary" type="button" on:click="{sendLogMessage}" value="Log using {lang} runtime">
<CodeSnippet bind:isJs={isJs} jsCode={testcodeJs} goCode={testcodeGo}/>
</form>
</div>
</CodeBlock>

View File

@ -1,22 +0,0 @@
package main
import "github.com/wailsapp/wails/v2"
type MyStruct struct {
runtime *wails.Runtime
}
func (l *MyStruct) WailsInit(runtime *wails.Runtime) error {
message := "Hello World!"
runtime.Log.Print(message)
// runtime.Log.Trace(message)
// runtime.Log.Debug(message)
// runtime.Log.Info(message)
// runtime.Log.Warning(message)
// runtime.Log.Error(message)
// runtime.Log.Fatal(message)
l.runtime = runtime
return nil
}

View File

@ -1,17 +0,0 @@
import { Log } from '@wails/runtime';
function doSomeOperation() {
// Do things
let value = doSomething();
Log.Print("A raw message");
Log.Trace("I got: " + value);
Log.Debug("A debug message");
Log.Info("An Info message");
Log.Warning("A Warning message");
Log.Error("An Error message");
}
function abort() {
// Do some things
Log.Fatal("I accidentally the whole application!");
}

View File

@ -1,46 +0,0 @@
<script>
import FakeTerm from '../../components/FakeTerm.svelte';
import Link from '../../components/Link.svelte';
import Log from './Log/Log.svelte';
import SetLogLevel from './SetLogLevel/SetLogLevel.svelte';
const loglevels = ["Trace", "Debug", "Info", "Warning", "Error", "Fatal", "Print"];
</script>
<div>
Logging is part of the Wails Runtime and is accessed through the <code>runtime.Log</code> object.
There are {loglevels.length} methods available:
<ol class="list">
{#each loglevels as option}
<li>{option}</li>
{/each}
</ol>
<br/>
Logs are only output if they are above or equal to the current log level. Example: If the current log level is
<code>Info</code>, then <code>Trace</code> and <code>Debug</code> messages will be surpressed. <br/><br/>
<code>Fatal</code> will log the message and then immediately exit the program.<br/><br/>
<code>Print</code> will send a raw message to the log regardless of log level.<br/><br/>
The default logger will log messages to the console in the following format:<br/>
<FakeTerm>
TRACE | I am a Trace message
DEBUG | I am a Debug message
INFO | I am an Info message
WARN | I am a Warning message
ERROR | I am an Error message
FATAL | I am a Fatal message
I am a Print message
</FakeTerm>
<br/>
Custom loggers may be given to your Wails application. More details <Link href="https://wails.app">here</Link>.
<br/><br/>
<Log/>
<br/>
<SetLogLevel/>
</div>

View File

@ -1,48 +0,0 @@
<script>
import CodeBlock from '../../../components/CodeBlock.svelte';
import CodeSnippet from '../../../components/CodeSnippet.svelte';
import { logLevel } from '../../../Store';
import { Log } from '@wails/runtime';
import jsCode from './code.jsx';
import goCode from './code.go';
var options = ["Trace", "Debug", "Info", "Warning", "Error"];
let isJs = false;
var id = "SetLogLevel";
let loglevelText = options[$logLevel-1];
$: setLogLevelMethod = isJs ? Log.SetLogLevel : backend.main.Logger.SetLogLevel;
function setLogLevel() {
let logLevelUpper = loglevelText.toUpperCase();
let logLevelMethod = Log.Level[logLevelUpper];
setLogLevelMethod(logLevelMethod);
}
$: lang = isJs ? 'Javascript' : 'Go';
let description = `You can set the log level using Log.SetLogLevel(). It accepts a log level (number) but there are consts available which may be used. See example code for more details.`;
$: testcodeJs = "import { Log } from '@wails/runtime';\nLog.SetLogLevel(Log.Level." + loglevelText.toUpperCase() + ");";
$: testcodeGo = 'import "github.com/wailsapp/wails/v2/pkg/logger"\n\n// runtime is given through WailsInit()\nruntime.Log.SetLogLevel(logger.' + loglevelText.toUpperCase() + ')';
</script>
<CodeBlock bind:isJs={isJs} {jsCode} {goCode} title="SetLogLevel" {id} {description}>
<div class="logging-form">
<form data-wails-no-drag class="mw-full">
<!-- Radio -->
<div class="form-group">
<div>Select Logging Level</div>
{#each options as option}
<div class="custom-radio">
<input type="radio" name="logging" bind:group="{loglevelText}" id="{id}-{option}" value="{option}">
<label for="{id}-{option}">{option}</label>
</div>
{/each}
</div>
<input class="btn btn-primary" type="button" on:click="{setLogLevel}" value="SetLogLevel using {lang} runtime">
<CodeSnippet bind:isJs={isJs} jsCode={testcodeJs} goCode={testcodeGo}/>
</form>
</div>
</CodeBlock>

View File

@ -1,23 +0,0 @@
package main
import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/logger"
)
// Logger struct
type Logger struct {
runtime *wails.Runtime
}
func (l *Logger) WailsInit(runtime *wails.Runtime) error {
runtime.Log.SetLogLevel(logger.TRACE)
// runtime.Log.SetLogLevel(logger.DEBUG)
// runtime.Log.SetLogLevel(logger.INFO)
// runtime.Log.SetLogLevel(logger.WARNING)
// runtime.Log.SetLogLevel(logger.ERROR)
l.runtime = runtime
return nil
}

View File

@ -1,9 +0,0 @@
import { Log } from '@wails/runtime';
function setLogLevel() {
Log.SetLogLevel(Log.Level.TRACE);
// Log.SetLogLevel(Log.Level.DEBUG);
// Log.SetLogLevel(Log.Level.INFO);
// Log.SetLogLevel(Log.Level.WARNING);
// Log.SetLogLevel(Log.Level.ERROR);
}

View File

@ -1,50 +0,0 @@
<script>
import CodeBlock from '../../../components/CodeBlock.svelte';
import CodeSnippet from '../../../components/CodeSnippet.svelte';
import FakeTerm from '../../../components/FakeTerm.svelte';
import jsCode from './code.jsx';
import goCode from './code.go';
import { writable } from 'svelte/store';
import { System } from '@wails/runtime';
import description from './description.txt';
var isJs = false;
$: lang = isJs ? 'Javascript' : 'Go';
var id = "Platform";
let output = writable("");
function log(message) {
output.update( (current) => {
current += message;
return current;
});
}
function getPlatform() {
if( isJs ) {
log("Platform from JS runtime: " + System.Platform() + "\n");
} else {
backend.main.System.Platform().then( (platformFromGo) => {
log("Platform from Go runtime: " + platformFromGo + "\n");
})
}
}
$: testcodeJs = "import { runtime } from '@wails/runtime';\nruntime.Log.Info('Platform from JS runtime: ' + runtime.System.Platform());";
$: testcodeGo = '// runtime is given through WailsInit()\nruntime.Log.Info("Platform from Go runtime: " + runtime.System.Platform())';
</script>
<CodeBlock bind:isJs={isJs} {jsCode} {goCode} {description} title="Platform()" {id} showRun=true>
<div class="browser-form">
<form data-wails-no-drag class="mw-full">
<input class="btn btn-primary" type="button" on:click="{getPlatform}" value="Fetch platform using {lang} runtime">
<CodeSnippet bind:isJs={isJs} jsCode={testcodeJs} goCode={testcodeGo}></CodeSnippet>
<FakeTerm text={$output} style="height: 100px; overflow: scroll"></FakeTerm>
</form>
</div>
</CodeBlock>

View File

@ -1,14 +0,0 @@
package main
import (
"github.com/wailsapp/wails/v2"
)
type MyStruct struct {
runtime *wails.Runtime
}
// ShowPlatformHelp shows specific help for the platform
func (l *MyStruct) ShowPlatformHelp() {
l.runtime.Browser.Open("https://wails.app/gettingstarted/" + l.runtime.System.Platform())
}

View File

@ -1,6 +0,0 @@
import { System, Browser } from '@wails/runtime';
function showPlatformHelp() {
// Do things
Browser.Open("https://wails.app/gettingstarted/" + System.Platform());
}

View File

@ -1 +0,0 @@
System.Platform() returns the platform that the application in running on. It uses the same values as Go's <code>runtime.GOOS</code>

View File

@ -1,11 +0,0 @@
<script>
import Platform from "./Platform/Platform.svelte";
</script>
<div>
The Wails runtime offers the ability to query system information through the <code>runtime.System</code> component.
<br/>
<Platform></Platform>
</div>

View File

@ -1,12 +0,0 @@
<div class="mainpage">
<h2>Wails Kitchen Sink</h2>
This application is a demonstation of the capabilities of Wails.
</div>
<style>
.mainpage {
text-align: center;
}
</style>

View File

@ -1,55 +0,0 @@
<script>
import { Tray } from '@wails/runtime';
import CodeBlock from '../../../components/CodeBlock.svelte';
import CodeSnippet from '../../../components/CodeSnippet.svelte';
import description from './description.txt';
import { UniqueID } from '../../../utils/utils';
import jsCode from './code.jsx';
import goCode from './code.go';
import { darkMode } from '../../../Store';
let isJs = false;
$: lang = isJs ? 'Javascript' : 'Go';
let id = UniqueID('tray');
var icons = ["light", "dark", "svelte"];
let darkmode = $darkmode;
let iconName = darkMode ? 'light' : 'dark';
function setIcon() {
console.log(iconName);
if( isJs ) {
Tray.SetIcon(iconName);
} else {
backend.main.Tray.SetIcon(iconName);
}
}
$: exampleCodeJS = `import { Tray } from '@wails/runtime';\n\nTray.SetIcon('` + iconName + `');`;
$: exampleCodeGo = `// runtime is given through WailsInit()\nruntime.Tray.SetIcon("` + iconName + `");`;
</script>
<CodeBlock bind:isJs={isJs} {jsCode} {goCode} {id} title="Tray.SetIcon(trayIconID)" {description}>
<div class="logging-form">
<form data-wails-no-drag class="mw-full">
<!-- Radio -->
<div class="form-group">
<div>Select Tray Icon</div>
{#each icons as option}
<div class="custom-radio">
<input type="radio" name="trayicon" bind:group="{iconName}" id="{id}-{option}" value="{option}">
<label for="{id}-{option}">{option}</label>
</div>
{/each}
</div>
<input class="btn btn-primary" type="button" on:click="{setIcon}" value="Set Icon using {lang} runtime">
<CodeSnippet bind:isJs={isJs} jsCode={exampleCodeJS} goCode={exampleCodeGo}></CodeSnippet>
</form>
</div>
</CodeBlock>

View File

@ -1,26 +0,0 @@
package main
import (
"io/ioutil"
"github.com/wailsapp/wails/v2"
)
type MyStruct struct {
runtime *wails.Runtime
}
func (m *MyStruct) WailsInit(runtime *wails.Runtime) error {
// Load notes
data, err := ioutil.ReadFile("notes.txt")
if err != nil {
return err
}
// SetIcon an event with the loaded data
runtime.Events.Emit("notes loaded", string(data))
m.runtime = runtime
return nil
}

View File

@ -1,6 +0,0 @@
import { Events } from '@wails/runtime';
function processButtonPress(name, address) {
Events.Emit("new user", name, address);
}

View File

@ -1 +0,0 @@
<code>SetIcon(trayIconID)</code> is used to set the tray icon.

View File

@ -1,17 +0,0 @@
<script>
import SetIcon from "./SetIcon/SetIcon.svelte";
</script>
<div>
Wails includes support for adding icons/menus to the system tray. Tray icons are read from the "trayicons" directory in the project directory and bundled during the compilation phase.
The filenames follow a convention and only PNG icons are supported. The file `&lt;projectroot&gt;/trayicons/light.png` is given a tray icon ID of 'light'. This is used
when setting the icon.
<div style="padding: 15px"></div>
<SetIcon></SetIcon>
<br/>
</div>
<style>
</style>

View File

@ -1,11 +0,0 @@
<script>
import Window from './Window/Window.svelte';
</script>
<div>
The Wails runtime offers extensive control over the appliation window. This is available through the <code>runtime.Window</code> component.
<br/><br/>
<Window></Window>
</div>

Some files were not shown because too many files have changed in this diff Show More