Added SocketAutoClose property to AppParams

This commit is contained in:
anoshenko 2024-04-27 16:16:30 +03:00
parent dcc69ad777
commit 345850b552
10 changed files with 114 additions and 43 deletions

View File

@ -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

View File

@ -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) {

View File

@ -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)
}

View File

@ -20,3 +20,6 @@ window.onfocus = function() {
windowFocus = true
sendMessage( "session-resume{}" );
}
function closeSocket() {
}

View File

@ -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";

View File

@ -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 +"}" );
}
}

View File

@ -1,5 +1,8 @@
window.onfocus = function(event) {
window.onfocus = function() {
windowFocus = true
sendMessage( "session-resume{session=" + sessionID +"}" );
}
function closeSocket() {
}

View File

@ -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) {

View File

@ -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 {

View File

@ -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)