client/client.go

215 lines
4.8 KiB
Go
Raw Normal View History

2024-10-13 23:12:55 +08:00
package client
import (
_ "embed"
"strings"
"sync"
"time"
"apigo.cc/gojs"
"apigo.cc/gojs/goja"
"github.com/ssgo/tool/watcher"
)
// TODO 桌面应用使用 https://github.com/neutralinojs/neutralinojs
// TODO App使用 https://pkg.go.dev/golang.org/x/mobile/cmd/gomobile
2024-10-13 23:12:55 +08:00
//go:embed client.ts
var clientTS string
//go:embed README.md
var clientMD string
//go:embed app.js
var appCode string
var binds = map[string]any{}
var bindsLock = sync.RWMutex{}
var windowsId uint64
var windows = map[uint64]*Webview{}
var windowsLock = sync.RWMutex{}
var waitChan chan bool
func Bind(name string, fn any) {
bindsLock.Lock()
binds[name] = fn
bindsLock.Unlock()
}
func Unbind(name string) {
bindsLock.Lock()
delete(binds, name)
bindsLock.Unlock()
}
func Wait() {
// 如果有窗口在运行,等待窗口关闭
windowsLock.RLock()
if len(windows) > 0 {
waitChan = make(chan bool, 1)
}
windowsLock.RUnlock()
// fmt.Println("====== wait start")
if waitChan != nil {
<-waitChan
waitChan = nil
}
// fmt.Println("====== wait end")
}
func CloseAll() {
windows1 := map[uint64]*Webview{}
windowsLock.Lock()
for id, w := range windows {
windows1[id] = w
}
windowsLock.Unlock()
for _, w := range windows1 {
w.close()
}
}
func (w *Webview) SetTitle(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
w.setTitle(args.Str(0))
return nil
2024-10-13 23:12:55 +08:00
}
func (w *Webview) SetSize(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(2)
w.setSize(args.Int(0), args.Int(1), args.Str(2))
return nil
2024-10-13 23:12:55 +08:00
}
func (w *Webview) Eval(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
w.eval(args.Str(0))
return nil
2024-10-13 23:12:55 +08:00
}
func (w *Webview) Close(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
w.close()
return nil
}
func (w *Webview) LoadHtml(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
w.loadHtml(args.Str(0))
return nil
}
func (w *Webview) LoadURL(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
w.loadURL(args.Str(0))
return nil
}
func init() {
obj := map[string]any{
"open": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm)
title := ""
width := 800
height := 600
sizeMode := "none"
isDebug := false
html := ""
url := ""
if opt := args.Obj(0); opt != nil {
if titleV := opt.Str("title"); titleV != "" {
title = titleV
}
if widthV := opt.Int("width"); widthV != 0 {
width = widthV
}
if heightV := opt.Int("height"); heightV != 0 {
height = heightV
}
if sizeModeV := opt.Str("sizeMode"); sizeModeV != "" {
sizeMode = sizeModeV
}
if isDebugV := opt.Bool("isDebug"); isDebugV {
isDebug = isDebugV
}
if htmlV := opt.Str("html"); htmlV != "" {
html = htmlV
}
if urlV := opt.Str("url"); urlV != "" {
url = urlV
if strings.HasPrefix(url, "file://") {
url = url[7:]
}
}
}
w := &Webview{isDebug: isDebug, html: html, url: url}
2024-10-24 13:29:33 +08:00
// startChan := make(chan bool, 1)
// fmt.Println("====== start")
2024-10-24 13:29:33 +08:00
gojs.RunInMain(func() {
// fmt.Println("====== gojs.RunInMain")
2024-10-13 23:12:55 +08:00
windowsLock.Lock()
w.id = windowsId
windowsId++
windows[w.id] = w
windowsLock.Unlock()
// fmt.Println("====== w.New()")
w.New(isDebug)
// fmt.Println("====== 1")
w.setTitle(title)
// fmt.Println("====== 2")
w.setSize(width, height, sizeMode)
// fmt.Println("====== 3")
2024-10-13 23:12:55 +08:00
w.binds()
// fmt.Println("====== w.Run()")
2024-10-13 23:12:55 +08:00
if w.isDebug {
var isWaitingRun = false
if w.webRoot == "" && w.html != "" {
w.webRoot = "."
}
if w.webRoot != "" {
w.watcher, _ = watcher.Start([]string{w.webRoot}, []string{"html", "js", "css"}, nil, func(filename string, event string) {
2024-10-13 23:12:55 +08:00
if !isWaitingRun {
isWaitingRun = true
go func() {
time.Sleep(time.Millisecond * 10)
isWaitingRun = false
w.eval("location.reload()")
2024-10-13 23:12:55 +08:00
}()
}
})
}
}
w.isRunning = true
// fmt.Println("====== w.reload()")
2024-10-13 23:12:55 +08:00
w.reload()
2024-10-24 13:29:33 +08:00
// startChan <- true
// fmt.Println("====== w.Run()")
w.Run()
// fmt.Println("====== w.Run() end")
2024-10-13 23:12:55 +08:00
w.doClose()
2024-10-24 13:29:33 +08:00
})
2024-10-13 23:12:55 +08:00
2024-10-24 13:29:33 +08:00
// <-startChan
2024-10-13 23:12:55 +08:00
return vm.ToValue(gojs.MakeMap(w))
},
"closeAll": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
CloseAll()
return nil
},
}
gojs.Register("apigo.cc/gojs/client", gojs.Module{
Object: obj,
Desc: "web client framework by github.com/chromedp/chromedp or github.com/webview/webview",
2024-10-13 23:12:55 +08:00
TsCode: clientTS,
Example: clientMD,
WaitForStop: Wait,
2024-10-24 13:29:33 +08:00
OnKill: CloseAll,
2024-10-13 23:12:55 +08:00
})
}