mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-03 00:09:56 +08:00
[v3] Centralize the AssetServer and move it to the application
This commit is contained in:
parent
4bffc57cb5
commit
0e614b0194
@ -20,13 +20,13 @@ func main() {
|
||||
Mac: application.MacOptions{
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
},
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
},
|
||||
})
|
||||
|
||||
mainWindow := app.NewWebviewWindowWithOptions(&application.WebviewWindowOptions{
|
||||
Title: "Context Menu Demo",
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
},
|
||||
Mac: application.MacWindow{
|
||||
Backdrop: application.MacBackdropTranslucent,
|
||||
TitleBar: application.MacTitleBarHiddenInsetUnified,
|
||||
@ -36,9 +36,6 @@ func main() {
|
||||
|
||||
app.NewWebviewWindowWithOptions(&application.WebviewWindowOptions{
|
||||
Title: "Context Menu Demo",
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
},
|
||||
Mac: application.MacWindow{
|
||||
Backdrop: application.MacBackdropTranslucent,
|
||||
TitleBar: application.MacTitleBarHiddenInsetUnified,
|
||||
|
@ -20,13 +20,13 @@ func main() {
|
||||
Mac: application.MacOptions{
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
},
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
},
|
||||
})
|
||||
|
||||
window := app.NewWebviewWindowWithOptions(&application.WebviewWindowOptions{
|
||||
Title: "Drag-n-drop Demo",
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
},
|
||||
Mac: application.MacWindow{
|
||||
Backdrop: application.MacBackdropTranslucent,
|
||||
TitleBar: application.MacTitleBarHiddenInsetUnified,
|
||||
|
@ -21,6 +21,9 @@ func main() {
|
||||
Mac: application.MacOptions{
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
},
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
},
|
||||
})
|
||||
|
||||
app.Events.On("myevent", func(e *application.CustomEvent) {
|
||||
@ -40,9 +43,6 @@ func main() {
|
||||
|
||||
app.NewWebviewWindowWithOptions(&application.WebviewWindowOptions{
|
||||
Title: "Events Demo",
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
},
|
||||
Mac: application.MacWindow{
|
||||
Backdrop: application.MacBackdropTranslucent,
|
||||
TitleBar: application.MacTitleBarHiddenInsetUnified,
|
||||
@ -51,9 +51,6 @@ func main() {
|
||||
})
|
||||
app.NewWebviewWindowWithOptions(&application.WebviewWindowOptions{
|
||||
Title: "Events Demo",
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
},
|
||||
Mac: application.MacWindow{
|
||||
Backdrop: application.MacBackdropTranslucent,
|
||||
TitleBar: application.MacTitleBarHiddenInsetUnified,
|
||||
|
@ -15,9 +15,15 @@ func main() {
|
||||
Mac: application.MacOptions{
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
},
|
||||
Assets: application.AssetOptions{
|
||||
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`<html><head><title>Plain Bundle</title></head><body><div class="main"><h1>Plain Bundle</h1><p>This is a plain bundle. It has no frontend code but this was Served by the AssetServer's Handler.</p><br/><br/><p data-wml-event="clicked">Clicking this paragraph emits an event...<p></div></body></html>`))
|
||||
}),
|
||||
},
|
||||
})
|
||||
// Create window
|
||||
myWindow := app.NewWebviewWindowWithOptions(&application.WebviewWindowOptions{
|
||||
app.NewWebviewWindowWithOptions(&application.WebviewWindowOptions{
|
||||
Title: "Plain Bundle",
|
||||
CSS: `body { background-color: rgba(255, 255, 255, 0); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; user-select: none; -ms-user-select: none; -webkit-user-select: none; } .main { color: white; margin: 20%; }`,
|
||||
Mac: application.MacWindow{
|
||||
@ -26,12 +32,6 @@ func main() {
|
||||
TitleBar: application.MacTitleBarHiddenInsetUnified,
|
||||
},
|
||||
URL: "/",
|
||||
Assets: application.AssetOptions{
|
||||
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`<html><head><title>Plain Bundle</title></head><body><div class="main"><h1>Plain Bundle</h1><p>This is a plain bundle. It has no frontend code but this was Served by the AssetServer's Handler.</p><br/><br/><p data-wml-event="clicked">Clicking this paragraph emits an event...<p></div></body></html>`))
|
||||
}),
|
||||
},
|
||||
})
|
||||
|
||||
app.Events.On("clicked", func(_ *application.CustomEvent) {
|
||||
|
@ -19,15 +19,15 @@ func main() {
|
||||
Mac: application.MacOptions{
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
},
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
},
|
||||
})
|
||||
|
||||
app.NewWebviewWindowWithOptions(&application.WebviewWindowOptions{
|
||||
Title: "Screen Demo",
|
||||
Width: 800,
|
||||
Height: 600,
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
},
|
||||
Mac: application.MacWindow{
|
||||
Backdrop: application.MacBackdropTranslucent,
|
||||
TitleBar: application.MacTitleBarHiddenInsetUnified,
|
||||
|
@ -21,6 +21,9 @@ func main() {
|
||||
Mac: application.MacOptions{
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
},
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
},
|
||||
})
|
||||
|
||||
// Create a custom menu
|
||||
@ -30,11 +33,7 @@ func main() {
|
||||
windowCounter := 1
|
||||
|
||||
newWindow := func() {
|
||||
app.NewWebviewWindowWithOptions(&application.WebviewWindowOptions{
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
},
|
||||
}).
|
||||
app.NewWebviewWindowWithOptions(&application.WebviewWindowOptions{}).
|
||||
SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)).
|
||||
SetPosition(rand.Intn(1000), rand.Intn(800)).
|
||||
Show()
|
||||
|
@ -19,15 +19,15 @@ func main() {
|
||||
Mac: application.MacOptions{
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
},
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
},
|
||||
})
|
||||
|
||||
app.NewWebviewWindowWithOptions(&application.WebviewWindowOptions{
|
||||
Title: "Wails ML Demo",
|
||||
Width: 800,
|
||||
Height: 600,
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
},
|
||||
Mac: application.MacWindow{
|
||||
Backdrop: application.MacBackdropTranslucent,
|
||||
TitleBar: application.MacTitleBarHiddenInsetUnified,
|
||||
|
@ -3,14 +3,19 @@ package application
|
||||
import "C"
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/wailsapp/wails/v3/pkg/logger"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/assetserver"
|
||||
"github.com/wailsapp/wails/v2/pkg/assetserver/webview"
|
||||
assetserveroptions "github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
|
||||
wailsruntime "github.com/wailsapp/wails/v3/internal/runtime"
|
||||
"github.com/wailsapp/wails/v3/pkg/events"
|
||||
"github.com/wailsapp/wails/v3/pkg/logger"
|
||||
)
|
||||
|
||||
var globalApplication *App
|
||||
@ -39,6 +44,17 @@ func New(appOptions Options) *App {
|
||||
}
|
||||
|
||||
result.Events = NewCustomEventProcessor(result.dispatchEventToWindows)
|
||||
|
||||
opts := assetserveroptions.Options{Assets: appOptions.Assets.FS, Handler: appOptions.Assets.Handler, Middleware: appOptions.Assets.Middleware}
|
||||
// TODO ServingFrom disk?
|
||||
srv, err := assetserver.NewAssetServer("", opts, false, nil, wailsruntime.RuntimeAssetsBundle)
|
||||
if err != nil {
|
||||
result.fatal(err.Error())
|
||||
}
|
||||
|
||||
srv.UseRuntimeHandler(NewMessageProcessor())
|
||||
result.assets = srv
|
||||
|
||||
globalApplication = result
|
||||
return result
|
||||
}
|
||||
@ -85,9 +101,24 @@ type dragAndDropMessage struct {
|
||||
|
||||
var windowDragAndDropBuffer = make(chan *dragAndDropMessage)
|
||||
|
||||
var _ webview.Request = &webViewAssetRequest{}
|
||||
|
||||
const webViewRequestHeaderWindowId = "x-wails-window-id"
|
||||
|
||||
type webViewAssetRequest struct {
|
||||
webview.Request
|
||||
windowId uint
|
||||
request webview.Request
|
||||
}
|
||||
|
||||
func (r *webViewAssetRequest) Header() (http.Header, error) {
|
||||
h, err := r.Request.Header()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hh := h.Clone()
|
||||
hh.Set(webViewRequestHeaderWindowId, strconv.FormatUint(uint64(r.windowId), 10))
|
||||
return hh, nil
|
||||
}
|
||||
|
||||
var webviewRequests = make(chan *webViewAssetRequest)
|
||||
@ -127,6 +158,8 @@ type App struct {
|
||||
|
||||
contextMenus map[string]*Menu
|
||||
contextMenusLock sync.Mutex
|
||||
|
||||
assets *assetserver.AssetServer
|
||||
}
|
||||
|
||||
func (a *App) getSystemTrayID() uint {
|
||||
@ -243,9 +276,9 @@ func (a *App) Run() error {
|
||||
}()
|
||||
go func() {
|
||||
for {
|
||||
event := <-webviewRequests
|
||||
a.handleWebViewRequest(event)
|
||||
err := event.request.Release()
|
||||
request := <-webviewRequests
|
||||
a.handleWebViewRequest(request)
|
||||
err := request.Release()
|
||||
if err != nil {
|
||||
a.error("Failed to release webview request: %s", err.Error())
|
||||
}
|
||||
@ -334,17 +367,11 @@ func (a *App) handleWindowMessage(event *windowMessage) {
|
||||
window.handleMessage(event.message)
|
||||
}
|
||||
|
||||
func (a *App) handleWebViewRequest(event *webViewAssetRequest) {
|
||||
func (a *App) handleWebViewRequest(request *webViewAssetRequest) {
|
||||
// Get window from window map
|
||||
a.windowsLock.Lock()
|
||||
window, ok := a.windows[event.windowId]
|
||||
a.windowsLock.Unlock()
|
||||
if !ok {
|
||||
log.Printf("WebviewWindow #%d not found", event.windowId)
|
||||
return
|
||||
}
|
||||
// Get callback from window
|
||||
window.handleWebViewRequest(event.request)
|
||||
url, _ := request.URL()
|
||||
a.info("Window: %d, Request: %s", request.windowId, url)
|
||||
a.assets.ServeWebViewRequest(request)
|
||||
}
|
||||
|
||||
func (a *App) handleWindowEvent(event *WindowEvent) {
|
||||
|
@ -225,8 +225,8 @@ func processMessage(windowID C.uint, message *C.char) {
|
||||
//export processURLRequest
|
||||
func processURLRequest(windowID C.uint, wkUrlSchemeTask unsafe.Pointer) {
|
||||
webviewRequests <- &webViewAssetRequest{
|
||||
Request: webview.NewRequest(wkUrlSchemeTask),
|
||||
windowId: uint(windowID),
|
||||
request: webview.NewRequest(wkUrlSchemeTask),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,19 +3,19 @@ package application
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
)
|
||||
|
||||
type MessageProcessor struct {
|
||||
window *WebviewWindow
|
||||
}
|
||||
// TODO maybe we could use a new struct that has the targetWindow as an attribute so we could get rid of passing the targetWindow
|
||||
// as parameter through every function call.
|
||||
|
||||
func NewMessageProcessor(w *WebviewWindow) *MessageProcessor {
|
||||
return &MessageProcessor{
|
||||
window: w,
|
||||
}
|
||||
type MessageProcessor struct{}
|
||||
|
||||
func NewMessageProcessor() *MessageProcessor {
|
||||
return &MessageProcessor{}
|
||||
}
|
||||
|
||||
func (m *MessageProcessor) httpError(rw http.ResponseWriter, message string, args ...any) {
|
||||
@ -43,15 +43,27 @@ func (m *MessageProcessor) HandleRuntimeCall(rw http.ResponseWriter, r *http.Req
|
||||
|
||||
params := QueryParams(r.URL.Query())
|
||||
|
||||
var targetWindow = m.window
|
||||
windowID := params.UInt("windowID")
|
||||
if windowID != nil {
|
||||
// Get window for ID
|
||||
targetWindow = globalApplication.getWindowForID(*windowID)
|
||||
if targetWindow == nil {
|
||||
m.Error("Window ID %s not found", *windowID)
|
||||
var windowID uint
|
||||
if hWindowID := r.Header.Get(webViewRequestHeaderWindowId); hWindowID != "" {
|
||||
// Get windowID out of the request header
|
||||
wID, err := strconv.ParseUint(hWindowID, 10, 64)
|
||||
if err != nil {
|
||||
m.Error("Window ID '%s' not parsable: %s", hWindowID, err)
|
||||
return
|
||||
}
|
||||
|
||||
windowID = uint(wID)
|
||||
}
|
||||
|
||||
if qWindowID := params.UInt("windowID"); qWindowID != nil {
|
||||
// Get windowID out of the query parameters if provided
|
||||
windowID = *qWindowID
|
||||
}
|
||||
|
||||
targetWindow := globalApplication.getWindowForID(windowID)
|
||||
if targetWindow == nil {
|
||||
m.Error("Window ID %s not found", windowID)
|
||||
return
|
||||
}
|
||||
|
||||
switch object {
|
||||
@ -79,10 +91,6 @@ func (m *MessageProcessor) HandleRuntimeCall(rw http.ResponseWriter, r *http.Req
|
||||
|
||||
}
|
||||
|
||||
func (m *MessageProcessor) ProcessMessage(message string) {
|
||||
m.Info("ProcessMessage from front end:", message)
|
||||
}
|
||||
|
||||
func (m *MessageProcessor) Error(message string, args ...any) {
|
||||
fmt.Printf("[MessageProcessor] Error: "+message, args...)
|
||||
}
|
||||
|
@ -7,19 +7,19 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (m *MessageProcessor) callErrorCallback(message string, callID *string, err error) {
|
||||
func (m *MessageProcessor) callErrorCallback(window *WebviewWindow, message string, callID *string, err error) {
|
||||
errorMsg := fmt.Sprintf(message, err)
|
||||
m.Error(errorMsg)
|
||||
msg := "_wails.callErrorCallback('" + *callID + "', " + strconv.Quote(errorMsg) + ");"
|
||||
m.window.ExecJS(msg)
|
||||
window.ExecJS(msg)
|
||||
}
|
||||
|
||||
func (m *MessageProcessor) callCallback(callID *string, result string, isJSON bool) {
|
||||
func (m *MessageProcessor) callCallback(window *WebviewWindow, callID *string, result string, isJSON bool) {
|
||||
msg := fmt.Sprintf("_wails.callCallback('%s', %s, %v);", *callID, strconv.Quote(result), isJSON)
|
||||
m.window.ExecJS(msg)
|
||||
window.ExecJS(msg)
|
||||
}
|
||||
|
||||
func (m *MessageProcessor) processCallMethod(method string, rw http.ResponseWriter, _ *http.Request, _ *WebviewWindow, params QueryParams) {
|
||||
func (m *MessageProcessor) processCallMethod(method string, rw http.ResponseWriter, _ *http.Request, window *WebviewWindow, params QueryParams) {
|
||||
args, err := params.Args()
|
||||
if err != nil {
|
||||
m.httpError(rw, "Unable to parse arguments: %s", err)
|
||||
@ -35,27 +35,27 @@ func (m *MessageProcessor) processCallMethod(method string, rw http.ResponseWrit
|
||||
var options CallOptions
|
||||
err := params.ToStruct(&options)
|
||||
if err != nil {
|
||||
m.callErrorCallback("Error parsing call options: %s", callID, err)
|
||||
m.callErrorCallback(window, "Error parsing call options: %s", callID, err)
|
||||
return
|
||||
}
|
||||
bindings := globalApplication.bindings.Get(&options)
|
||||
if bindings == nil {
|
||||
m.callErrorCallback("Error getting binding for method: %s", callID, fmt.Errorf("'%s' not found", options.MethodName))
|
||||
m.callErrorCallback(window, "Error getting binding for method: %s", callID, fmt.Errorf("'%s' not found", options.MethodName))
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
result, err := bindings.Call(options.Args)
|
||||
if err != nil {
|
||||
m.callErrorCallback("Error calling method: %s", callID, err)
|
||||
m.callErrorCallback(window, "Error calling method: %s", callID, err)
|
||||
return
|
||||
}
|
||||
// convert result to json
|
||||
jsonResult, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
m.callErrorCallback("Error converting result to json: %s", callID, err)
|
||||
m.callErrorCallback(window, "Error converting result to json: %s", callID, err)
|
||||
return
|
||||
}
|
||||
m.callCallback(callID, string(jsonResult), true)
|
||||
m.callCallback(window, callID, string(jsonResult), true)
|
||||
}()
|
||||
m.ok(rw)
|
||||
default:
|
||||
|
@ -8,16 +8,16 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (m *MessageProcessor) dialogErrorCallback(message string, dialogID *string, err error) {
|
||||
func (m *MessageProcessor) dialogErrorCallback(window *WebviewWindow, message string, dialogID *string, err error) {
|
||||
errorMsg := fmt.Sprintf(message, err)
|
||||
m.Error(errorMsg)
|
||||
msg := "_wails.dialogErrorCallback('" + *dialogID + "', " + strconv.Quote(errorMsg) + ");"
|
||||
m.window.ExecJS(msg)
|
||||
window.ExecJS(msg)
|
||||
}
|
||||
|
||||
func (m *MessageProcessor) dialogCallback(dialogID *string, result string, isJSON bool) {
|
||||
func (m *MessageProcessor) dialogCallback(window *WebviewWindow, dialogID *string, result string, isJSON bool) {
|
||||
msg := fmt.Sprintf("_wails.dialogCallback('%s', %s, %v);", *dialogID, strconv.Quote(result), isJSON)
|
||||
m.window.ExecJS(msg)
|
||||
window.ExecJS(msg)
|
||||
}
|
||||
|
||||
func (m *MessageProcessor) processDialogMethod(method string, rw http.ResponseWriter, r *http.Request, window *WebviewWindow, params QueryParams) {
|
||||
@ -37,7 +37,7 @@ func (m *MessageProcessor) processDialogMethod(method string, rw http.ResponseWr
|
||||
var options MessageDialogOptions
|
||||
err := params.ToStruct(&options)
|
||||
if err != nil {
|
||||
m.dialogErrorCallback("Error parsing dialog options: %s", dialogID, err)
|
||||
m.dialogErrorCallback(window, "Error parsing dialog options: %s", dialogID, err)
|
||||
return
|
||||
}
|
||||
if len(options.Buttons) == 0 {
|
||||
@ -63,7 +63,7 @@ func (m *MessageProcessor) processDialogMethod(method string, rw http.ResponseWr
|
||||
for _, button := range options.Buttons {
|
||||
label := button.Label
|
||||
button.OnClick(func() {
|
||||
m.dialogCallback(dialogID, label, false)
|
||||
m.dialogCallback(window, dialogID, label, false)
|
||||
})
|
||||
}
|
||||
dialog.AddButtons(options.Buttons)
|
||||
@ -82,23 +82,23 @@ func (m *MessageProcessor) processDialogMethod(method string, rw http.ResponseWr
|
||||
if options.AllowsMultipleSelection {
|
||||
files, err := dialog.PromptForMultipleSelection()
|
||||
if err != nil {
|
||||
m.dialogErrorCallback("Error getting selection: %s", dialogID, err)
|
||||
m.dialogErrorCallback(window, "Error getting selection: %s", dialogID, err)
|
||||
return
|
||||
} else {
|
||||
result, err := json.Marshal(files)
|
||||
if err != nil {
|
||||
m.dialogErrorCallback("Error marshalling files: %s", dialogID, err)
|
||||
m.dialogErrorCallback(window, "Error marshalling files: %s", dialogID, err)
|
||||
return
|
||||
}
|
||||
m.dialogCallback(dialogID, string(result), true)
|
||||
m.dialogCallback(window, dialogID, string(result), true)
|
||||
}
|
||||
} else {
|
||||
file, err := dialog.PromptForSingleSelection()
|
||||
if err != nil {
|
||||
m.dialogErrorCallback("Error getting selection: %s", dialogID, err)
|
||||
m.dialogErrorCallback(window, "Error getting selection: %s", dialogID, err)
|
||||
return
|
||||
}
|
||||
m.dialogCallback(dialogID, file, false)
|
||||
m.dialogCallback(window, dialogID, file, false)
|
||||
}
|
||||
}()
|
||||
m.ok(rw)
|
||||
@ -114,10 +114,10 @@ func (m *MessageProcessor) processDialogMethod(method string, rw http.ResponseWr
|
||||
go func() {
|
||||
file, err := dialog.PromptForSingleSelection()
|
||||
if err != nil {
|
||||
m.dialogErrorCallback("Error getting selection: %s", dialogID, err)
|
||||
m.dialogErrorCallback(window, "Error getting selection: %s", dialogID, err)
|
||||
return
|
||||
}
|
||||
m.dialogCallback(dialogID, file, false)
|
||||
m.dialogCallback(window, dialogID, file, false)
|
||||
}()
|
||||
m.ok(rw)
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
package application
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"net/http"
|
||||
|
||||
"github.com/wailsapp/wails/v3/pkg/logger"
|
||||
)
|
||||
|
||||
@ -14,4 +17,14 @@ type Options struct {
|
||||
Silent bool
|
||||
CustomLoggers []logger.Output
|
||||
}
|
||||
Assets AssetOptions
|
||||
}
|
||||
|
||||
type AssetOptions struct {
|
||||
// FS to use for loading assets from
|
||||
FS fs.FS
|
||||
// Handler is a custom handler to use for serving assets. If this is set, the `URL` and `FS` fields are ignored.
|
||||
Handler http.Handler
|
||||
// Middleware is a custom middleware to use for serving assets. If this is set, the `URL` and `FS` fields are ignored.
|
||||
Middleware func(http.Handler) http.Handler
|
||||
}
|
||||
|
@ -1,10 +1,5 @@
|
||||
package application
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type WindowState int
|
||||
|
||||
const (
|
||||
@ -29,7 +24,6 @@ type WebviewWindowOptions struct {
|
||||
StartState WindowState
|
||||
Mac MacWindow
|
||||
BackgroundColour *RGBA
|
||||
Assets AssetOptions
|
||||
HTML string
|
||||
JS string
|
||||
CSS string
|
||||
@ -49,14 +43,6 @@ var WebviewWindowDefaults = &WebviewWindowOptions{
|
||||
URL: "",
|
||||
}
|
||||
|
||||
type AssetOptions struct {
|
||||
// FS to use for loading assets from
|
||||
FS fs.FS
|
||||
// Handler is a custom handler to use for serving assets. If this is set, the `URL` and `FS` fields are ignored.
|
||||
Handler http.Handler
|
||||
// Middleware is a custom middleware to use for serving assets. If this is set, the `URL` and `FS` fields are ignored.
|
||||
Middleware func(http.Handler) http.Handler
|
||||
}
|
||||
|
||||
type RGBA struct {
|
||||
Red, Green, Blue, Alpha uint8
|
||||
|
@ -7,10 +7,6 @@ import (
|
||||
|
||||
"github.com/wailsapp/wails/v3/pkg/logger"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/assetserver"
|
||||
"github.com/wailsapp/wails/v2/pkg/assetserver/webview"
|
||||
assetserveroptions "github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
"github.com/wailsapp/wails/v3/internal/runtime"
|
||||
"github.com/wailsapp/wails/v3/pkg/events"
|
||||
)
|
||||
|
||||
@ -72,9 +68,6 @@ type WebviewWindow struct {
|
||||
implLock sync.RWMutex
|
||||
id uint
|
||||
|
||||
assets *assetserver.AssetServer
|
||||
messageProcessor *MessageProcessor
|
||||
|
||||
eventListeners map[uint][]func(ctx *WindowEventContext)
|
||||
eventListenersLock sync.RWMutex
|
||||
|
||||
@ -103,25 +96,13 @@ func NewWindow(options *WebviewWindowOptions) *WebviewWindow {
|
||||
options.URL = "/"
|
||||
}
|
||||
|
||||
opts := assetserveroptions.Options{Assets: options.Assets.FS, Handler: options.Assets.Handler, Middleware: options.Assets.Middleware}
|
||||
// TODO Bindings, ServingFrom disk?
|
||||
srv, err := assetserver.NewAssetServer("", opts, false, nil, runtime.RuntimeAssetsBundle)
|
||||
if err != nil {
|
||||
globalApplication.fatal(err.Error())
|
||||
}
|
||||
|
||||
result := &WebviewWindow{
|
||||
id: getWindowID(),
|
||||
options: options,
|
||||
eventListeners: make(map[uint][]func(ctx *WindowEventContext)),
|
||||
contextMenus: make(map[string]*Menu),
|
||||
|
||||
assets: srv,
|
||||
}
|
||||
|
||||
result.messageProcessor = NewMessageProcessor(result)
|
||||
srv.UseRuntimeHandler(result.messageProcessor)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -383,16 +364,10 @@ func (w *WebviewWindow) handleMessage(message string) {
|
||||
if message == "test" {
|
||||
w.SetTitle("Hello World")
|
||||
}
|
||||
w.messageProcessor.ProcessMessage(message)
|
||||
w.info("ProcessMessage from front end:", message)
|
||||
|
||||
}
|
||||
|
||||
func (w *WebviewWindow) handleWebViewRequest(request webview.Request) {
|
||||
url, _ := request.URL()
|
||||
w.info("Request: %s", url)
|
||||
w.assets.ServeWebViewRequest(request)
|
||||
}
|
||||
|
||||
func (w *WebviewWindow) Center() {
|
||||
if w.impl == nil {
|
||||
return
|
||||
|
@ -790,6 +790,7 @@ static void windowSetFrameless(void *window, bool frameless) {
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"net/url"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
@ -969,13 +970,17 @@ func (w *macosWebviewWindow) execJS(js string) {
|
||||
C.windowExecJS(w.nsWindow, C.CString(js))
|
||||
}
|
||||
|
||||
func (w *macosWebviewWindow) setURL(url string) {
|
||||
if url == "/" {
|
||||
// TODO handle this in a central location and handle all urls without scheme and host. This might be platform
|
||||
// dependant
|
||||
url = "wails://wails/"
|
||||
func (w *macosWebviewWindow) setURL(uri string) {
|
||||
if uri != "" {
|
||||
url, err := url.Parse(uri)
|
||||
if err == nil && url.Scheme == "" && url.Host == "" {
|
||||
// TODO handle this in a central location, the scheme and host might be platform dependant.
|
||||
url.Scheme = "wails"
|
||||
url.Host = "wails"
|
||||
uri = url.String()
|
||||
}
|
||||
C.navigationLoadURL(w.nsWindow, C.CString(url))
|
||||
}
|
||||
C.navigationLoadURL(w.nsWindow, C.CString(uri))
|
||||
}
|
||||
|
||||
func (w *macosWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) {
|
||||
|
Loading…
Reference in New Issue
Block a user