diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f2f195..de7b26e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # v0.14.0 -* Added the ability to work without creating a WebSocket. Added NoSocket property of AppParams. +* Added the ability to work without creating a WebSocket. Added NoSocket property to AppParams. +* Added SocketAutoClose property to AppParams. * Added the ability to run a timer on the client side. Added StartTimer and StopTimer methods to Session interface. * Added "cell-vertical-self-align", and "cell-horizontal-self-align" properties * Bug fixing diff --git a/appServer.go b/appServer.go index 02b2f78..59f9277 100644 --- a/appServer.go +++ b/appServer.go @@ -53,6 +53,14 @@ func (app *application) getStartPage() string { return buffer.String() } +func (app *application) Params() AppParams { + params := app.params + if params.NoSocket { + params.SocketAutoClose = 0 + } + return params +} + func (app *application) Finish() { for _, session := range app.sessions { session.session.close() @@ -245,23 +253,18 @@ func (app *application) socketReader(bridge *wsBridge) { } case "reconnect": + session = nil if sessionText, ok := obj.PropertyValue("session"); ok { if sessionID, err := strconv.Atoi(sessionText); err == nil { if info, ok := app.sessions[sessionID]; ok { - session := info.session + session = info.session session.setBridge(events, bridge) - answer := allocStringBuilder() - defer freeStringBuilder(answer) - session.writeInitScript(answer) - if !bridge.writeMessage(answer.String()) { - return - } - session.onReconnect() go sessionEventHandler(session, events, bridge) - return + session.onReconnect() + } else { + DebugLogF("Session #%d not exists", sessionID) } - DebugLogF("Session #%d not exists", sessionID) } else { ErrorLog(`strconv.Atoi(sessionText) error: ` + err.Error()) } @@ -269,7 +272,20 @@ func (app *application) socketReader(bridge *wsBridge) { ErrorLog(`"session" key not found`) } - bridge.writeMessage("restartSession();") + if session == nil { + /* answer := "" + if session, answer = app.startSession(obj, events, bridge, nil); session != nil { + if !bridge.writeMessage(answer) { + return + } + session.onStart() + go sessionEventHandler(session, events, bridge) + bridge.writeMessage("restartSession();") + } + */ + bridge.writeMessage("reloadPage();") + return + } default: if !session.handleAnswer(command, obj) { diff --git a/appWasm.go b/appWasm.go index 9824674..1a07c36 100644 --- a/appWasm.go +++ b/appWasm.go @@ -25,6 +25,12 @@ func (app *wasmApp) Finish() { app.session.close() } +func (app *wasmApp) Params() AppParams { + params := app.params + params.SocketAutoClose = 0 + return params +} + func debugLog(text string) { js.Global().Get("console").Call("log", text) } diff --git a/app_post.js b/app_post.js index be60262..e17e625 100644 --- a/app_post.js +++ b/app_post.js @@ -20,3 +20,6 @@ window.onfocus = function() { windowFocus = true sendMessage( "session-resume{}" ); } + +function closeSocket() { +} diff --git a/app_scripts.js b/app_scripts.js index 21d283c..b2c732c 100644 --- a/app_scripts.js +++ b/app_scripts.js @@ -14,6 +14,10 @@ window.onblur = function() { sendMessage( "session-pause{session=" + sessionID +"}" ); } +function reloadPage() { + location.reload(); +} + function sessionInfo() { const touch_screen = (('ontouchstart' in document.documentElement) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0)) ? "1" : "0"; diff --git a/app_socket.js b/app_socket.js index 3d67c2e..53aa2cf 100644 --- a/app_socket.js +++ b/app_socket.js @@ -1,14 +1,22 @@ let socket -let socketUrl function sendMessage(message) { - if (socket) { - socket.send(message) + if (!socket) { + createSocket(function() { + sendMessage( "reconnect{session=" + sessionID + "}" ); + if (!windowFocus) { + windowFocus = true; + sendMessage( "session-resume{session=" + sessionID +"}" ); + } + socket.send(message); + }); + } else { + socket.send(message); } } -window.onload = function() { - socketUrl = document.location.protocol == "https:" ? "wss://" : "ws://" +function createSocket(onopen) { + let socketUrl = document.location.protocol == "https:" ? "wss://" : "ws://" socketUrl += document.location.hostname const port = document.location.port if (port) { @@ -17,35 +25,47 @@ window.onload = function() { socketUrl += window.location.pathname + "ws" socket = new WebSocket(socketUrl); - socket.onopen = socketOpen; - socket.onclose = socketClose; - socket.onerror = socketError; + socket.onopen = onopen; + socket.onclose = onSocketClose; + socket.onerror = onSocketError; socket.onmessage = function(event) { window.execScript ? window.execScript(event.data) : window.eval(event.data); }; -}; +} -function socketOpen() { - sendMessage( sessionInfo() ); +function closeSocket() { + if (socket) { + socket.close() + } } -function socketReopen() { +window.onload = createSocket(function() { + sendMessage( sessionInfo() ); +}); + +window.onfocus = function() { + windowFocus = true + if (!socket) { + createSocket(function() { + sendMessage( "reconnect{session=" + sessionID + "}" ); + sendMessage( "session-resume{session=" + sessionID +"}" ); + }); + } else { + sendMessage( "session-resume{session=" + sessionID +"}" ); + } +} + +function onSocketReopen() { sendMessage( "reconnect{session=" + sessionID + "}" ); } function socketReconnect() { if (!socket) { - socket = new WebSocket(socketUrl); - socket.onopen = socketReopen; - socket.onclose = socketClose; - socket.onerror = socketError; - socket.onmessage = function(event) { - window.execScript ? window.execScript(event.data) : window.eval(event.data); - }; + createSocket(onSocketReopen); } } -function socketClose(event) { +function onSocketClose(event) { console.log("socket closed") socket = null; if (!event.wasClean && windowFocus) { @@ -53,15 +73,6 @@ function socketClose(event) { } } -function socketError(error) { +function onSocketError(error) { console.log(error); } - -window.onfocus = function(event) { - windowFocus = true - if (!socket) { - socketReconnect() - } else { - sendMessage( "session-resume{session=" + sessionID +"}" ); - } -} diff --git a/app_wasm.js b/app_wasm.js index d4d2010..e5c1a90 100644 --- a/app_wasm.js +++ b/app_wasm.js @@ -1,5 +1,8 @@ -window.onfocus = function(event) { +window.onfocus = function() { windowFocus = true sendMessage( "session-resume{session=" + sessionID +"}" ); } + +function closeSocket() { +} diff --git a/application.go b/application.go index 4cad322..db8d0ba 100644 --- a/application.go +++ b/application.go @@ -17,6 +17,7 @@ var defaultThemeText string // Application - app interface type Application interface { Finish() + Params() AppParams removeSession(id int) } @@ -24,23 +25,34 @@ type Application interface { type AppParams struct { // Title - title of the app window/tab Title string + // TitleColor - background color of the app window/tab (applied only for Safari and Chrome for Android) TitleColor Color + // Icon - the icon file name Icon string + // CertFile - path of a certificate for the server must be provided // if neither the Server's TLSConfig.Certificates nor TLSConfig.GetCertificate are populated. // If the certificate is signed by a certificate authority, the certFile should be the concatenation // of the server's certificate, any intermediates, and the CA's certificate. CertFile string + // KeyFile - path of a private key for the server must be provided // if neither the Server's TLSConfig.Certificates nor TLSConfig.GetCertificate are populated. KeyFile string + // Redirect80 - if true then the function of redirect from port 80 to 443 is created Redirect80 bool + // NoSocket - if true then WebSockets will not be used and information exchange // between the client and the server will be carried out only via http. NoSocket bool + + // SocketAutoClose - time in seconds after which the socket is automatically closed for an inactive session. + // The countdown begins after the OnPause event arrives. + // If the value of this property is less than or equal to 0 then the socket is not closed. + SocketAutoClose int } func getStartPage(buffer *strings.Builder, params AppParams) { diff --git a/session.go b/session.go index 0b1505f..15c7f90 100644 --- a/session.go +++ b/session.go @@ -207,6 +207,7 @@ type sessionData struct { hotkeys map[string]func(Session) timers map[int]func(Session) nextTimerID int + pauseTime int64 } func newSession(app Application, id int, customTheme string, params DataObject) Session { diff --git a/sessionEvents.go b/sessionEvents.go index 9c66e7b..99a4916 100644 --- a/sessionEvents.go +++ b/sessionEvents.go @@ -1,5 +1,7 @@ package rui +import "time" + // SessionStartListener is the listener interface of a session start event type SessionStartListener interface { OnStart(session Session) @@ -50,13 +52,25 @@ func (session *sessionData) onFinish() { func (session *sessionData) onPause() { if session.content != nil { + session.pauseTime = time.Now().Unix() if listener, ok := session.content.(SessionPauseListener); ok { listener.OnPause(session) } + if timeout := session.app.Params().SocketAutoClose; timeout > 0 { + go session.autoClose(session.pauseTime, timeout) + } + } +} + +func (session *sessionData) autoClose(start int64, timeout int) { + time.Sleep(time.Second * time.Duration(timeout)) + if session.pauseTime == start { + session.bridge.callFunc("closeSocket") } } func (session *sessionData) onResume() { + session.pauseTime = 0 if session.content != nil { if listener, ok := session.content.(SessionResumeListener); ok { listener.OnResume(session)