// package win_main -- главное окно приложения package win_main import ( _ "embed" "fmt" "log" "net/url" "runtime" "sync" "time" "github.com/zserge/lorca" // "wartank/desktop/win_users" "wartank/pkg/components/safebool" "wartank/pkg/types" ) const ( strWinMainName = "win_main" // Контрольная строка для сторожа потоков ) //go:embed win_main.html var strWinHtml string // WinMain -- главное окно приложения type WinMain struct { desktop types.IDesktop store types.IStore win lorca.UI block sync.Mutex isWork *safebool.SafeBool ws types.IWebSocket } // NewWinMain -- возвращает новое окно десктопа func NewWinMain(desktop types.IDesktop) (*WinMain, error) { if desktop == nil { return nil, fmt.Errorf("NewWinMain(): IDesktop == nil") } sf := &WinMain{ desktop: desktop, store: desktop.Store(), isWork: safebool.NewSafeBool(), ws: desktop.Ws(), } args := []string{} if runtime.GOOS == "linux" { args = append(args, "--class=Lorca") } var err error sf.win, err = lorca.New("data:text/html,"+url.PathEscape(strWinHtml), "", 640, 480, args...) if err != nil { return nil, fmt.Errorf("NewWinMain(): in create win, err=\n\t%w", err) } go sf.close() return sf, nil } // Работает в отдельном потоке, главный цикл окна func (sf *WinMain) Run() { log.Println("WinMain.Run()") sf.win.Bind("close_win", sf.onClose) sf.win.Bind("bot_list", sf.onUsers) go sf.timeServer() <-sf.win.Done() // Ожидание закрытия окна sf.desktop.CancelApp() } // Открывает окно с пользователями func (sf *WinMain) onUsers() { log.Println("WinMain.onUsers()") go sf.desktop.DictBot().Show() } // Проверяет наличие работающего сервера, работает в отдельном потоке func (sf *WinMain) timeServer() { for { time.Sleep(time.Second * 2) timeBeg := time.Now().UTC().UnixMicro() dictResp, err := sf.ws.Read("/server/time") if err != nil { log.Printf("WinMain.timeServer(): in send request to server, err=\n\t%v\n", err) sf.desktop.CancelApp() return } timeEnd := time.Now().UTC().UnixMicro() - timeBeg strErr := dictResp["err"] if strErr != "" { js := fmt.Sprintf(` function SetTimeServer(){ var _el = document.getById("/server/time"); _el.innerText=%q; } SetTimeServer() `, err) sf.win.Eval(js) continue } strTime := dictResp["/server/time"] js := fmt.Sprintf(` function SetTimeServer(){ var _el = document.getElementById("/server/time"); _el.innerText=%q; } SetTimeServer() `, strTime) sf.win.Eval(js) js = fmt.Sprintf(` function SetPingServer(){ var _el = document.getElementById("/server/ping"); _el.innerText="%v мкСек"; } SetPingServer() `, timeEnd) sf.win.Eval(js) } } // Закрывает приложение func (sf *WinMain) onClose() { log.Println("WinMain.onClose()") sf.win.Close() } // close -- ожидает отмены глобального контекста func (sf *WinMain) close() { <-sf.desktop.CtxApp().Done() log.Println("WinMain.close()") sf.block.Lock() defer sf.block.Unlock() if !sf.isWork.Get() { return } sf.isWork.Reset() sf.win.Close() sf.desktop.Wg().Done(strWinMainName) }