mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-02 17:39:58 +08:00
239 lines
6.4 KiB
Go
239 lines
6.4 KiB
Go
package webserver
|
|
|
|
import (
|
|
"context"
|
|
"github.com/wailsapp/wails/v2/pkg/menu"
|
|
"github.com/wailsapp/wails/v2/pkg/runtime/dialog"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/wailsapp/wails/v2/internal/logger"
|
|
ws "nhooyr.io/websocket"
|
|
"nhooyr.io/websocket/wsjson"
|
|
)
|
|
|
|
// WebClient represents an individual web session
|
|
type WebClient struct {
|
|
conn *ws.Conn
|
|
identifier string
|
|
logger *logger.Logger
|
|
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) {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) UpdateTrayMenuLabel(trayMenuJSON string) {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) MessageDialog(dialogOptions dialog.MessageDialogOptions, callbackID string) {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) SetApplicationMenu(menuJSON string) {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) UpdateTrayMenu(trayMenuJSON string) {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) UpdateContextMenu(contextMenuJSON string) {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) OpenFileDialog(dialogOptions dialog.OpenDialogOptions, callbackID string) {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
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")
|
|
}
|
|
|
|
func (wc *WebClient) WindowShow() {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) WindowHide() {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) WindowCenter() {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) WindowMaximise() {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) WindowUnmaximise() {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) WindowMinimise() {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) WindowUnminimise() {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) WindowPosition(x int, y int) {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) WindowSize(width int, height int) {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) DarkModeEnabled(callbackID string) {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) UpdateMenu(menu *menu.Menu) {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) UpdateTray(menu *menu.Menu) {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) UpdateTrayLabel(label string) {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
func (wc *WebClient) UpdateTrayIcon(name string) {
|
|
wc.logger.Info("Not implemented in server build")
|
|
}
|
|
|
|
// Quit terminates the webclient session
|
|
func (wc *WebClient) Quit() {
|
|
wc.running = false
|
|
}
|
|
|
|
// NotifyEvent sends the event
|
|
func (wc *WebClient) NotifyEvent(message string) {
|
|
wc.SendMessage("E" + message)
|
|
}
|
|
|
|
// CallResult sends the result of the Go function call back to the
|
|
// originator in the frontend
|
|
func (wc *WebClient) CallResult(message string) {
|
|
wc.SendMessage("R" + message)
|
|
}
|
|
|
|
// WindowSetTitle is a noop in the webclient
|
|
func (wc *WebClient) WindowSetTitle(title string) {}
|
|
|
|
// WindowFullscreen is a noop in the webclient
|
|
func (wc *WebClient) WindowFullscreen() {}
|
|
|
|
// WindowUnFullscreen is a noop in the webclient
|
|
func (wc *WebClient) WindowUnFullscreen() {}
|
|
|
|
// WindowSetColour is a noop in the webclient
|
|
func (wc *WebClient) WindowSetColour(colour int) {
|
|
}
|
|
|
|
// Run processes messages from the remote webclient
|
|
func (wc *WebClient) Run(w *WebServer) {
|
|
dispatcher := w.dispatcher.RegisterClient(wc)
|
|
defer w.dispatcher.RemoveClient(dispatcher)
|
|
defer w.unregisterClient(wc.identifier)
|
|
|
|
for wc.running {
|
|
var v interface{}
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
if err := wsjson.Read(ctx, wc.conn, &v); err != nil {
|
|
if ws.CloseStatus(err) == ws.StatusNormalClosure || ws.CloseStatus(err) == ws.StatusGoingAway {
|
|
break
|
|
}
|
|
if ws.CloseStatus(err) != -1 {
|
|
w.logger.Debug("Connection error: %s - %s", wc.identifier, err)
|
|
break
|
|
}
|
|
|
|
if !strings.Contains(err.Error(), "status = Status") {
|
|
w.logger.Debug("Error encountered on socket: %v", err)
|
|
break
|
|
}
|
|
}
|
|
dispatcher.DispatchMessage(v.(string))
|
|
}
|
|
|
|
err := wc.conn.Close(ws.StatusNormalClosure, "Goodbye")
|
|
if err != nil {
|
|
w.logger.Error("Error encountered on socket: %v", err)
|
|
return
|
|
}
|
|
w.logger.Debug("Connection closed: %v", wc.identifier)
|
|
}
|
|
|
|
// SendMessage converts the string to a []byte and passes it to
|
|
// the connection's Writer to send to the remote client
|
|
// The Writer itself prevents multiple users at the same time.
|
|
func (wc *WebClient) SendMessage(message string) {
|
|
wc.logger.Debug("WebClient.SendMessage() - %s", message)
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
err := wc.conn.Write(ctx, ws.MessageText, []byte(message))
|
|
if err != nil {
|
|
wc.logger.Error("Error encountered writing to webclient: %v", err)
|
|
}
|
|
}
|
|
|
|
// unregisterClient is called automatically by a WebClient session during termination
|
|
// so that it's registration can be removed
|
|
func (w *WebServer) unregisterClient(identifier string) {
|
|
w.logger.Debug("Removing WebClient : %v", identifier)
|
|
w.lock.Lock()
|
|
delete(w.connections, identifier)
|
|
w.lock.Unlock()
|
|
}
|
|
|
|
func (w *WebServer) websocketConnection(resp http.ResponseWriter, req *http.Request) {
|
|
conn, err := ws.Accept(resp, req, nil)
|
|
if err != nil {
|
|
w.logger.Debug("Failed to upgrade websocket connection")
|
|
return
|
|
}
|
|
wc := &WebClient{
|
|
conn: conn,
|
|
identifier: req.RemoteAddr,
|
|
logger: w.logger,
|
|
running: true,
|
|
}
|
|
w.lock.Lock()
|
|
w.connections[wc.identifier] = wc
|
|
w.lock.Unlock()
|
|
|
|
w.logger.Debug("Connection from: %v", wc.identifier)
|
|
|
|
go wc.Run(w)
|
|
|
|
}
|