package client import ( "apigo.cloud/git/apigo/plugin" webview "github.com/webview/webview_go" "os" "path/filepath" "sync" ) var binds = map[string]interface{}{} var bindsLock = sync.RWMutex{} func Bind(name string, fn interface{}) { bindsLock.Lock() binds[name] = fn bindsLock.Unlock() } func Unbind(name string) { bindsLock.Lock() delete(binds, name) bindsLock.Unlock() } type Webview struct { w webview.WebView isRunning bool isAsync bool } func (w *Webview) Run() { w.isRunning = true w.w.Run() if w.isRunning { w.isRunning = false w.w.Destroy() } } func (w *Webview) Close() { if w.isRunning { w.w.Terminate() } } func (w *Webview) SetHtml(html string) { w.w.SetHtml(html) } func (w *Webview) LoadURL(url string) { w.w.Navigate(url) } func (w *Webview) LoadFile(file string) { if filepath.IsAbs(file) { w.w.Navigate("file://" + file) } else { curPath, _ := os.Getwd() w.w.Navigate("file://" + filepath.Join(curPath, file)) } } func (w *Webview) Dispatch(f func()) { w.w.Dispatch(f) } func (w *Webview) SetTitle(title string) { w.w.SetTitle(title) } func (w *Webview) SetSize(width int, height int, sizeMode *string) { hint := "none" if sizeMode != nil { hint = *sizeMode } switch hint { case "none": w.w.SetSize(width, height, webview.HintNone) case "fixed": w.w.SetSize(width, height, webview.HintFixed) case "min": w.w.SetSize(width, height, webview.HintMin) case "max": w.w.SetSize(width, height, webview.HintMax) default: w.w.SetSize(width, height, webview.HintNone) } } func (w *Webview) Eval(code string) { w.w.Eval(code) } //func (w *Webview) Bind(name string, f interface{}) error { // fmt.Println(">>>>>>>>.bind", name, f) // return w.w.Bind(name, f) //} // //func (w *Webview) Unbind(name string) error { // return w.w.Unbind(name) //} func (w *Webview) binds() { tmpBinds := map[string]interface{}{} bindsLock.RLock() for k, v := range binds { tmpBinds[k] = v } bindsLock.RUnlock() for k, v := range tmpBinds { _ = w.w.Bind(k, v) } _ = w.w.Bind("__closeWindow", w.Close) _ = w.w.Bind("__setTitle", w.w.SetTitle) _ = w.w.Bind("__setSize", w.SetSize) _ = w.w.Bind("__eval", w.w.Eval) w.w.Init(dialogCode) w.w.Init(appCode) } func newWindow(title string, width int, height int, sizeMode *string, isDebug *bool) *Webview { isDebugV := false if isDebug != nil { isDebugV = *isDebug } w := &Webview{w: webview.New(isDebugV)} w.SetTitle(title) w.SetSize(width, height, sizeMode) w.binds() return w } const appCode = ` let app = { close: __closeWindow, setTitle: __setTitle, setSize: __setSize, eval: __eval, } ` const dialogCode = ` window._dialogTexts = {'zh':{'Close':'关闭','Cancel':'取消','Confirm':'确定'}} function _getDialogDefaultText(text) {return (window._dialogTexts[navigator.language] && window._dialogTexts[navigator.language][text]) || (window._dialogTexts[navigator.language.split('-')[0]] && window._dialogTexts[navigator.language.split('-')[0]][text]) || text} window.alert = function (msg, buttonText) {return showDialog(msg, [buttonText || _getDialogDefaultText('Close')])} window.confirm = function (msg, confirmButtonText, cancelButtonText) {return showDialog(msg, [cancelButtonText || _getDialogDefaultText('Cancel'), cancelButtonText || _getDialogDefaultText('Confirm')])} window.prompt = function (msg, defaultValue, confirmButtonText, cancelButtonText) {return showDialog(msg, [cancelButtonText || _getDialogDefaultText('Cancel'), cancelButtonText || _getDialogDefaultText('Confirm')], [{value:defaultValue||''}])} window.showDialog = function (msg, buttons, inputs) { if(!document.querySelector('#_dialogStyle')){ let sDom = document.createElement('style') sDom.id = '_dialogStyle' sDom.textContent = '._dialogMask {position:fixed;left:0;right:0;top:0;bottom:0;background:rgba(128,128,128,0.7);display:flex;justify-content:center;align-items:center}\n' + '._dialogPanel {background:#eee;padding:16px;min-width:300px;max-width:80%;max-height:80%;margin:auto;border-radius:10px;display:flex;flex-flow:column;overflow:auto}\n' + '._dialogMessage {font-size:0.875rem;flex:1;overflow:auto;white-space:pre-wrap}\n' + '._dialogInputs {display:flex;flex-flow:column;margin-top:8px}\n' + '._dialogInputs input {flex:1;border:1px solid #aaa;border-radius:4px;min-height:28px;padding:0 8px}\n' + '._dialogLine {text-align:end;padding:4px 0}\n' + '._dialogButtons {text-align:end}\n' + '._dialogButtons button {background:none;border:none;color:#999;min-height:28px;cursor:pointer;font-size:1rem;margin-left:10px}\n' + '._dialogButtons button:hover {color:#999}\n' + '._dialogButtons button:last-child {color:#06f}' document.head.append(sDom) } return new Promise(resolve => { let a = ['