Index: binaries/data/config/default.cfg
===================================================================
--- binaries/data/config/default.cfg
+++ binaries/data/config/default.cfg
@@ -506,6 +506,10 @@
echelon = "echelon27" ; Name of the server-side XMPP-account that manages ratings
buddies = "," ; Comma separated list of playernames that the current user has marked as buddies
rememberpassword = true ; Whether to store the encrypted password in the user config
+awayinbackground = true ; Whether the user's presence will be set to "away" when the window is unfocussed
+awayinbackgroundtime = 1 ; Time in which the user's presence status will be set to "away" when the window is unfocussed in minutes
+awaytimeout = true ; Whether the user's presence status will be set to "away" on inactivity
+awaytimeouttime = 5 ; Time in which the user's presence status will be set to "away" on inactivity in minutes
[lobby.columns]
gamerating = false ; Show the average rating of the participating players in a column of the gamelist
Index: binaries/data/mods/public/gui/lobby/LobbyHandler.js
===================================================================
--- binaries/data/mods/public/gui/lobby/LobbyHandler.js
+++ binaries/data/mods/public/gui/lobby/LobbyHandler.js
@@ -11,15 +11,38 @@
this.leaderboardPage = new LeaderboardPage(this.xmppMessages);
this.lobbyPage = new LobbyPage(dialog, this.xmppMessages, this.leaderboardPage, this.profilePage);
- this.xmppMessages.processHistoricMessages();
+ this.inputBeforeGuiHandlers = new Set();
+ this.presenceHandler = new PresenceHandler(this);
- if (Engine.LobbyGetPlayerPresence(g_Nickname) != "available")
- Engine.LobbySetPlayerPresence("available");
+ this.xmppMessages.processHistoricMessages();
if (!dialog)
{
initMusic();
global.music.setState(global.music.states.MENU);
}
+
+ Engine.GetGUIObjectByName("lobbyWindow").onTick = this.onTick;
+ }
+
+ onTick()
+ {
+ updateTimers();
+ }
+
+ registerInputBeforeGuiHandler(handler)
+ {
+ this.inputBeforeGuiHandlers.add(handler);
+ }
+
+ unregisterInputBeforeGuiHandler(handler)
+ {
+ this.inputBeforeGuiHandlers.delete(handler);
+ }
+
+ handleInputBeforeGui(ev)
+ {
+ for (let handler of this.inputBeforeGuiHandlers)
+ handler(ev);
}
}
Index: binaries/data/mods/public/gui/lobby/LobbyPage/Buttons/QuitButton.js
===================================================================
--- binaries/data/mods/public/gui/lobby/LobbyPage/Buttons/QuitButton.js
+++ binaries/data/mods/public/gui/lobby/LobbyPage/Buttons/QuitButton.js
@@ -28,7 +28,7 @@
closeDialog()
{
- Engine.LobbySetPlayerPresence("playing");
+ g_LobbyHandler.presenceHandler.fixPresence("playing");
Engine.PopGuiPage();
}
Index: binaries/data/mods/public/gui/lobby/LobbyPage/Chat/ChatCommandHandler.js
===================================================================
--- binaries/data/mods/public/gui/lobby/LobbyPage/Chat/ChatCommandHandler.js
+++ binaries/data/mods/public/gui/lobby/LobbyPage/Chat/ChatCommandHandler.js
@@ -87,14 +87,14 @@
"away": {
"description": translate("Set your state to 'Away'."),
"handler": function(args) {
- Engine.LobbySetPlayerPresence("away");
+ g_LobbyHandler.presenceHandler.fixPresence("away");
return true;
}
},
"back": {
"description": translate("Set your state to 'Online'."),
"handler": function(args) {
- Engine.LobbySetPlayerPresence("available");
+ g_LobbyHandler.presenceHandler.unfixPresence();
return true;
}
},
Index: binaries/data/mods/public/gui/lobby/LobbyPage/PresenceHandler.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/lobby/LobbyPage/PresenceHandler.js
@@ -0,0 +1,103 @@
+/**
+ * This class handling the presence status of the user.
+ */
+class PresenceHandler
+{
+ constructor(lobbyHandler)
+ {
+ if (Engine.LobbyGetPlayerPresence(g_Nickname) != "available")
+ Engine.LobbySetPlayerPresence("available");
+
+ this.presenceFixed = false;
+
+ this.activityPresent = new Observable();
+ this.activityPresent.value = true;
+ this.lastActive = Date.now();
+ if (Engine.ConfigDB_GetValue("user", "lobby.awaytimeout") == "true")
+ setTimeout(this.checkActivity.bind(this), 1000 * 60 * +Engine.ConfigDB_GetValue("user", "lobby.awaytimeouttime"));
+
+ this.backgroundPresent = new Observable();
+ this.backgroundPresent.value = true;
+ this.windowFocus = true;
+ this.backgroundTimer = undefined;
+ let lobbyWindow = Engine.GetGUIObjectByName("lobbyWindow");
+ lobbyWindow.onWindowFocusGained = this.onWindowFocusGained.bind(this);
+ lobbyWindow.onWindowFocusLost = this.onWindowFocusLost.bind(this);
+
+ lobbyHandler.registerInputBeforeGuiHandler(this.handleInputBeforeGui.bind(this));
+
+ this.activityPresent.watch(this.setPresence.bind(this), ["value"]);
+ this.backgroundPresent.watch(this.setPresence.bind(this), ["value"]);
+ }
+
+ checkActivity()
+ {
+ let timeLeft = this.lastActive + 1000 * 60 * +Engine.ConfigDB_GetValue("user", "lobby.awaytimeouttime") - Date.now();
+ if (timeLeft <= 0)
+ {
+ this.activityPresent.value = false;
+ // Make sure we keep a timer running, so that we can set away again after a brief burst of activity.
+ setTimeout(this.checkActivity.bind(this), 1000 * 60 * +Engine.ConfigDB_GetValue("user", "lobby.awaytimeouttime"));
+ }
+ else
+ setTimeout(this.checkActivity.bind(this), timeLeft);
+ }
+
+ fixPresence(status)
+ {
+ this.presenceFixed = true;
+ if (Engine.LobbyGetPlayerPresence(g_Nickname) != status)
+ Engine.LobbySetPlayerPresence(status);
+ }
+
+ unfixPresence()
+ {
+ this.presenceFixed = false;
+ this.setPresence();
+ }
+
+ setPresence()
+ {
+ if (this.presenceFixed)
+ return;
+
+ if (this.activityPresent.value && this.backgroundPresent.value && Engine.LobbyGetPlayerPresence(g_Nickname) != "available")
+ Engine.LobbySetPlayerPresence("available");
+ else if (Engine.LobbyGetPlayerPresence(g_Nickname) != "away")
+ Engine.LobbySetPlayerPresence("away");
+ }
+
+ onWindowFocusGained()
+ {
+ this.windowFocus = true;
+ this.backgroundPresent.value = true;
+
+ if (!this.backgroundTimer)
+ return;
+
+ clearTimeout(this.backgroundTimer);
+ this.backgroundTimer = undefined;
+ }
+
+ onWindowFocusLost()
+ {
+ this.windowFocus = false;
+ if (Engine.ConfigDB_GetValue("user", "lobby.awayinbackground") == "true")
+ this.backgroundTimer = setTimeout(
+ (() => {
+ this.backgroundPresent.value = false;
+ this.setPresence();
+ }).bind(this),
+ 1000 * 60 * +Engine.ConfigDB_GetValue("user", "lobby.awayinbackgroundtime"));
+ }
+
+ handleInputBeforeGui(ev, obj)
+ {
+ // Ignore mousemotion when not focussed.
+ if (ev.type == "mousemotion" && !this.windowFocus)
+ return;
+
+ this.lastActive = Date.now();
+ this.activityPresent.value = true;
+ }
+}
Index: binaries/data/mods/public/gui/lobby/lobby.js
===================================================================
--- binaries/data/mods/public/gui/lobby/lobby.js
+++ binaries/data/mods/public/gui/lobby/lobby.js
@@ -38,3 +38,9 @@
else
error("Could not load settings");
}
+
+function handleInputBeforeGui(ev, obj)
+{
+ g_LobbyHandler?.handleInputBeforeGui(ev, obj);
+ return false;
+}
Index: binaries/data/mods/public/gui/lobby/lobby.xml
===================================================================
--- binaries/data/mods/public/gui/lobby/lobby.xml
+++ binaries/data/mods/public/gui/lobby/lobby.xml
@@ -6,7 +6,7 @@
-