diff --git a/akka-bbb-apps/src/main/resources/application.conf b/akka-bbb-apps/src/main/resources/application.conf index 826aa0ec080f07aec5e533450f583ceae2a19886..c77900571b3c2ebf2aba7339ede3c79cd2d5a7a3 100755 --- a/akka-bbb-apps/src/main/resources/application.conf +++ b/akka-bbb-apps/src/main/resources/application.conf @@ -90,4 +90,9 @@ voiceConf { recording { chapterBreakLengthInMinutes = 180 +} + +inactivityAudit { + timer = 120 + responseDuration = 5 } \ No newline at end of file diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala index e047984436b90e0bd2719adf0f5acd611c38c289..0d9346271334f352849ccf68a4e5f39ff0c96134 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala @@ -21,8 +21,8 @@ trait SystemConfiguration { lazy val red5DeskShareIP = Try(config.getString("red5.deskshareip")).getOrElse("127.0.0.1") lazy val red5DeskShareApp = Try(config.getString("red5.deskshareapp")).getOrElse("") - lazy val inactivityDeadline = Try(config.getInt("inactivity.deadline")).getOrElse(2 * 3600) // 2 hours - lazy val inactivityTimeLeft = Try(config.getInt("inactivity.timeLeft")).getOrElse(5 * 60) // 5 minutes + lazy val userInactivityAuditTimer = Try(config.getInt("inactivityAudit.timer")).getOrElse(120) // 2 hours + lazy val userInactivityAuditResponseDuration = Try(config.getInt("inactivityAudit.responseDuration")).getOrElse(5) // 5 minutes lazy val expireLastUserLeft = Try(config.getInt("expire.lastUserLeft")).getOrElse(60) // 1 minute lazy val expireNeverJoined = Try(config.getInt("expire.neverJoined")).getOrElse(5 * 60) // 5 minutes diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/UserInactivityAuditResponseMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/UserInactivityAuditResponseMsgHdlr.scala new file mode 100755 index 0000000000000000000000000000000000000000..d97f2a83985b15a0dfa4ed02043ffa9b4e8f52fb --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/UserInactivityAuditResponseMsgHdlr.scala @@ -0,0 +1,17 @@ +package org.bigbluebutton.core.apps.users + +import org.bigbluebutton.common2.msgs.UserInactivityAuditResponseMsg +import org.bigbluebutton.core.models.Users2x +import org.bigbluebutton.core.running.MeetingActor + +trait UserInactivityAuditResponseMsgHdlr { + this: MeetingActor => + + def handleUserInactivityAuditResponseMsg(msg: UserInactivityAuditResponseMsg): Unit = { + for { + user <- Users2x.findWithIntId(liveMeeting.users2x, msg.body.userId) + } yield { + Users2x.updateInactivityResponse(liveMeeting.users2x, user) + } + } +} diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Users2x.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Users2x.scala index a67d2c3876c2b3e8777b8303ab968d734da84497..ff12fe2043ab5725d6b6efbf4f5718754065d980 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Users2x.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Users2x.scala @@ -1,6 +1,7 @@ package org.bigbluebutton.core.models import com.softwaremill.quicklens._ +import org.bigbluebutton.core.util.TimeUtil object Users2x { def findWithIntId(users: Users2x, intId: String): Option[UserState] = { @@ -26,6 +27,12 @@ object Users2x { users.toVector.filter(u => !u.presenter) } + def updateInactivityResponse(users: Users2x, u: UserState): UserState = { + val newUserState = modify(u)(_.inactivityResponseOn).setTo(TimeUtil.timeNowInMs()) + users.save(newUserState) + newUserState + } + def changeRole(users: Users2x, u: UserState, newRole: String): UserState = { val newUserState = modify(u)(_.role).setTo(newRole).modify(_.roleChangedOn).setTo(System.currentTimeMillis()) users.save(newUserState) @@ -204,7 +211,9 @@ case class OldPresenter(userId: String, changedPresenterOn: Long) case class UserState(intId: String, extId: String, name: String, role: String, guest: Boolean, authed: Boolean, guestStatus: String, emoji: String, locked: Boolean, - presenter: Boolean, avatar: String, roleChangedOn: Long = System.currentTimeMillis()) + presenter: Boolean, avatar: String, + roleChangedOn: Long = System.currentTimeMillis(), + inactivityResponseOn: Long = TimeUtil.timeNowInMs()) case class UserIdAndName(id: String, name: String) @@ -232,4 +241,5 @@ object EjectReasonCode { val EJECT_USER = "user_requested_eject_reason" val SYSTEM_EJECT_USER = "system_requested_eject_reason" val VALIDATE_TOKEN = "validate_token_failed_eject_reason" + val USER_INACTIVITY = "user_inactivity_eject_reason" } diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala index 24ddce2377e59b932825a2844521c93a7e39933f..e1645e8b00b1a84e13ea7a5683d5aba2a8c5c3ce 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala @@ -94,6 +94,8 @@ class ReceivedJsonMsgHandlerActor( routeGenericMsg[RemoveUserFromPresenterGroupCmdMsg](envelope, jsonNode) case GetPresenterGroupReqMsg.NAME => routeGenericMsg[GetPresenterGroupReqMsg](envelope, jsonNode) + case UserInactivityAuditResponseMsg.NAME => + routeGenericMsg[UserInactivityAuditResponseMsg](envelope, jsonNode) // Poll case StartCustomPollReqMsg.NAME => diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala index bd686d3636ad4c2cbe0d4c8fbf4369f7e147c65f..00a97f8517b88aa6c68ff20d2f23fc85d066bcf0 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala @@ -4,6 +4,7 @@ import java.io.{ PrintWriter, StringWriter } import akka.actor._ import akka.actor.SupervisorStrategy.Resume +import org.bigbluebutton.SystemConfiguration import org.bigbluebutton.core.apps.groupchats.{ GroupChatApp, GroupChatHdlrs } import org.bigbluebutton.core.apps.presentationpod._ import org.bigbluebutton.core.apps.users._ @@ -34,7 +35,7 @@ import scala.concurrent.duration._ import org.bigbluebutton.core.apps.layout.LayoutApp2x import org.bigbluebutton.core.apps.meeting.{ SyncGetMeetingInfoRespMsgHdlr, ValidateConnAuthTokenSysMsgHdlr } import org.bigbluebutton.core.apps.users.ChangeLockSettingsInMeetingCmdMsgHdlr -import org.bigbluebutton.core2.message.senders.MsgBuilder +import org.bigbluebutton.core2.message.senders.{ MsgBuilder, Sender } import org.bigbluebutton.core2.testdata.FakeTestData object MeetingActor { @@ -54,6 +55,7 @@ class MeetingActor( val liveMeeting: LiveMeeting ) extends BaseMeetingActor + with SystemConfiguration with GuestsApp with LayoutApp2x with VoiceApp2x @@ -78,7 +80,8 @@ class MeetingActor( with ChangeLockSettingsInMeetingCmdMsgHdlr with SyncGetMeetingInfoRespMsgHdlr with ClientToServerLatencyTracerMsgHdlr - with ValidateConnAuthTokenSysMsgHdlr { + with ValidateConnAuthTokenSysMsgHdlr + with UserInactivityAuditResponseMsgHdlr { override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) { case e: Exception => { @@ -165,11 +168,11 @@ class MeetingActor( // Set webcamsOnlyForModerator property in case we didn't after meeting creation MeetingStatus2x.setWebcamsOnlyForModerator(liveMeeting.status, liveMeeting.props.usersProp.webcamsOnlyForModerator) - /*******************************************************************/ + /** *****************************************************************/ // Helper to create fake users for testing (ralam jan 5, 2018) //object FakeTestData extends FakeTestData //FakeTestData.createFakeUsers(liveMeeting) - /*******************************************************************/ + /** *****************************************************************/ def receive = { //============================= @@ -347,6 +350,8 @@ class MeetingActor( case m: ValidateConnAuthTokenSysMsg => handleValidateConnAuthTokenSysMsg(m) + case m: UserInactivityAuditResponseMsg => handleUserInactivityAuditResponseMsg(m) + case _ => log.warning("***** Cannot handle " + msg.envelope.name) } } @@ -409,6 +414,8 @@ class MeetingActor( sendRttTraceTest() setRecordingChapterBreak() + + processUserInactivityAudit() } var lastRecBreakSentOn = expiryTracker.startedOnInMs @@ -502,7 +509,49 @@ class MeetingActor( "system", MeetingStatus2x.isRecording(liveMeeting.status) ) outGW.send(event) + } + } + + var lastUserInactivitySentOn = TimeUtil.timeNowInMs() + var checkInactiveUsers = false + + def processUserInactivityAudit(): Unit = { + val now = TimeUtil.timeNowInMs() + val auditTimerMs = TimeUtil.minutesToMillis(userInactivityAuditTimer) + if (now - lastUserInactivitySentOn > auditTimerMs) { + lastUserInactivitySentOn = now + checkInactiveUsers = true + val event = buildUserInactivityAuditMsg(liveMeeting.props.meetingProp.intId) + outGW.send(event) + } + val auditResponseMs = TimeUtil.minutesToMillis(userInactivityAuditResponseDuration) + if (checkInactiveUsers && now - lastUserInactivitySentOn > auditResponseMs) { + checkInactiveUsers = false + checkForInactiveUsers() } } + + def checkForInactiveUsers(): Unit = { + val auditResponseMs = TimeUtil.minutesToMillis(userInactivityAuditResponseDuration) + val users = Users2x.findAll(liveMeeting.users2x) + users foreach { u => + val respondedOntIme = lastUserInactivitySentOn < u.inactivityResponseOn && (lastUserInactivitySentOn + auditResponseMs) > u.inactivityResponseOn + if (!respondedOntIme) { + UsersApp.ejectUserFromMeeting(outGW, liveMeeting, u.intId, SystemUser.ID, "User inactive for too long.", EjectReasonCode.USER_INACTIVITY) + Sender.sendDisconnectClientSysMsg(liveMeeting.props.meetingProp.intId, u.intId, SystemUser.ID, EjectReasonCode.USER_INACTIVITY, outGW) + } + } + } + + def buildUserInactivityAuditMsg(meetingId: String): BbbCommonEnvCoreMsg = { + val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "system") + val envelope = BbbCoreEnvelope(UserInactivityAuditMsg.NAME, routing) + val body = UserInactivityAuditMsgBody(meetingId, TimeUtil.minutesToSeconds(userInactivityAuditResponseDuration)) + val header = BbbClientMsgHeader(UserInactivityAuditMsg.NAME, meetingId, "system") + val event = UserInactivityAuditMsg(header, body) + + BbbCommonEnvCoreMsg(envelope, event) + } + } diff --git a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/meeting/AllowedMessageNames.scala b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/meeting/AllowedMessageNames.scala index 6b322b5b34aca966b5a0fb93196f0a39a57754ff..07dac9fb098eefcc6d4600e8986b9d8d9712f6eb 100755 --- a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/meeting/AllowedMessageNames.scala +++ b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/meeting/AllowedMessageNames.scala @@ -34,6 +34,7 @@ object AllowedMessageNames { GetGuestPolicyReqMsg.NAME, SetGuestPolicyCmdMsg.NAME, GuestsWaitingApprovedMsg.NAME, + UserInactivityAuditResponseMsg.NAME, // Webcams GetWebcamsOnlyForModeratorReqMsg.NAME, diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/UsersMgs.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/UsersMgs.scala index 00fdc483958f309d3860de29fa4edbdad80aed47..3abf0819f0f8efd36f4a8d4e6bd57b7c5ea8da01 100755 --- a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/UsersMgs.scala +++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/UsersMgs.scala @@ -358,3 +358,12 @@ case class GetPresenterGroupReqMsgBody(requesterId: String) object GetPresenterGroupRespMsg { val NAME = "GetPresenterGroupRespMsg" } case class GetPresenterGroupRespMsg(header: BbbClientMsgHeader, body: GetPresenterGroupRespMsgBody) extends StandardMsg case class GetPresenterGroupRespMsgBody(presenterGroup: Vector[String], requesterId: String) + + +object UserInactivityAuditMsg { val NAME = "UserInactivityAuditMsg" } +case class UserInactivityAuditMsg(header: BbbClientMsgHeader, body: UserInactivityAuditMsgBody) extends StandardMsg +case class UserInactivityAuditMsgBody(meetingId: String, responseDuration: Long) + +object UserInactivityAuditResponseMsg { val NAME = "UserInactivityAuditResponseMsg" } +case class UserInactivityAuditResponseMsg(header: BbbClientMsgHeader, body: UserInactivityAuditResponseMsgBody) extends StandardMsg +case class UserInactivityAuditResponseMsgBody(userId: String) diff --git a/bigbluebutton-client/locale/en_US/bbbResources.properties b/bigbluebutton-client/locale/en_US/bbbResources.properties index b2f2698e37c54fd5fb18cb6c3c2421516c3db387..0651c28fd2b9b8aaedfe16a28fc3062a57c3e390 100755 --- a/bigbluebutton-client/locale/en_US/bbbResources.properties +++ b/bigbluebutton-client/locale/en_US/bbbResources.properties @@ -94,6 +94,9 @@ bbb.inactivityWarning.title = No activity detected bbb.inactivityWarning.message = This meeting seems to be inactive. Automatically shutting it down... bbb.shuttingDown.message = This meeting is being closed due to inactivity bbb.inactivityWarning.cancel = Cancel +bbb.userInactivityAudit.title = User activity check +bbb.userInactivityAudit.message = Check if user is still in meeting +bbb.userInactive.message = User is not in meeting. Ejecting. bbb.mainToolbar.helpBtn = Help bbb.mainToolbar.logoutBtn = Logout bbb.mainToolbar.logoutBtn.toolTip = Log Out @@ -551,6 +554,7 @@ bbb.logout.breakoutRoomClose = Your browser window will be closed bbb.logout.duplicateUserEjectReason = Duplicate user trying to join meeting. bbb.logout.permissionEjectReason = Ejected due to permission violation. bbb.logout.validateTokenFailedEjectReason = Failed to validate authorization token. +bbb.logout.userInactivityEjectReason = User inactive for too long. bbb.logout.ejectedFromMeeting = You have been removed from the meeting. bbb.logout.refresh.message = If this logout was unexpected click the button below to reconnect. bbb.logout.refresh.label = Reconnect diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/events/BBBEvent.as b/bigbluebutton-client/src/org/bigbluebutton/main/events/BBBEvent.as index 13d252a0b76db72af80a872c424ff7aa3f0a3893..f2bb00e2faa570917b0f944ae03a5923b1da38f8 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/main/events/BBBEvent.as +++ b/bigbluebutton-client/src/org/bigbluebutton/main/events/BBBEvent.as @@ -69,6 +69,9 @@ package org.bigbluebutton.main.events { public static const CANCEL_RECONNECTION_EVENT:String = "CANCEL_RECONNECTION_EVENT"; public static const WEBRTC_MONITOR_UPDATE_EVENT:String = "WEBRTC_MONITOR_UPDATE_EVENT"; + + public static const USER_INACTIVITY_AUDIT_EVENT:String = "user_inactivity_audit_event"; + public static const USER_INACTIVITY_AUDIT_RESPONSE_EVENT:String = "user_inactivity_audit_response_event"; public var message:String; public var payload:Object = new Object(); diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UserService.as b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UserService.as index 6b5b4e4e622178cc58cfad7f049d69b9297af593..970ac101fa15c831c0b5e9fbd4c203f0fcf4239d 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UserService.as +++ b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UserService.as @@ -188,6 +188,10 @@ package org.bigbluebutton.main.model.users sender.activityResponse(); } + public function userInactivityAuditResponse():void { + sender.userInactivityAuditResponse(); + } + private function queryForRecordingStatus():void { sender.queryForRecordingStatus(); } diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/LoggedOutWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/LoggedOutWindow.mxml index 27312f91a2e91a1df6066f104040a6d6e1ca2a8d..c5d3aea7f4c1363cca1d0c10c825f6e21a3600f6 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/main/views/LoggedOutWindow.mxml +++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/LoggedOutWindow.mxml @@ -126,6 +126,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. message = ResourceUtil.getInstance().getString('bbb.logout.ejectedFromMeeting'); } else if (reasonCode == "validate_token_failed_eject_reason") { message = ResourceUtil.getInstance().getString('bbb.logout.validateTokenFailedEjectReason'); + } else if (reasonCode == "user_inactivity_eject_reason") { + message = ResourceUtil.getInstance().getString('bbb.logout.userInactivityEjectReason'); } break; case ConnectionFailedEvent.USER_LOGGED_OUT: diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/MainApplicationShell.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/MainApplicationShell.mxml index b85a5cb8575f1c33139f2a4d23ab2977e586cd48..9eb9657ba7081c0e549e7cfc652446b62d6a2997 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/main/views/MainApplicationShell.mxml +++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/MainApplicationShell.mxml @@ -60,6 +60,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. <mate:Listener type="{ShortcutEvent.OPEN_SHORTCUT_WIN}" method="openShortcutHelpWindow" /> <mate:Listener type="{BBBEvent.OPEN_WEBCAM_PREVIEW}" method="openVideoPreviewWindow" /> <mate:Listener type="{BBBEvent.INACTIVITY_WARNING_EVENT}" method="handleInactivityWarningEvent" /> + <mate:Listener type="{BBBEvent.USER_INACTIVITY_AUDIT_EVENT}" method="handleUserInactivityAuditEvent" /> <mate:Listener type="{LockControlEvent.OPEN_LOCK_SETTINGS}" method="openLockSettingsWindow" /> <mate:Listener type="{BreakoutRoomEvent.OPEN_BREAKOUT_ROOMS_PANEL}" method="openBreakoutRoomsWindow" /> @@ -131,7 +132,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. import org.bigbluebutton.main.model.options.LanguageOptions; import org.bigbluebutton.main.model.options.LayoutOptions; import org.bigbluebutton.main.model.users.events.ConferenceCreatedEvent; - import org.bigbluebutton.main.model.users.events.ConnectionFailedEvent; import org.bigbluebutton.modules.phone.events.AudioSelectionWindowEvent; import org.bigbluebutton.modules.phone.events.FlashMicSettingsEvent; import org.bigbluebutton.modules.phone.events.WebRTCCallEvent; @@ -496,6 +496,12 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. mdiCanvas.addChild(e.component); } + private function handleUserInactivityAuditEvent(e:BBBEvent):void { + var inactivityWarning:UserInactivityAuditWindow = PopUpUtil.createModalPopUp(FlexGlobals.topLevelApplication as DisplayObject, + UserInactivityAuditWindow, true) as UserInactivityAuditWindow; + inactivityWarning.duration = e.payload.duration; + } + private function handleInactivityWarningEvent(e:BBBEvent):void { var inactivityWarning:InactivityWarningWindow = PopUpUtil.createModalPopUp(FlexGlobals.topLevelApplication as DisplayObject, InactivityWarningWindow, true) as InactivityWarningWindow; inactivityWarning.duration = e.payload.duration; diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/UserInactivityAuditWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/UserInactivityAuditWindow.mxml new file mode 100755 index 0000000000000000000000000000000000000000..54ee5745f205e442581c5b9c865394759dc4b7c7 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/UserInactivityAuditWindow.mxml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + +BigBlueButton open source conferencing system - http://www.bigbluebutton.org/ + +Copyright (c) 2015 BigBlueButton Inc. and by respective authors (see below). + +This program is free software; you can redistribute it and/or modify it under the +terms of the GNU Lesser General Public License as published by the Free Software +Foundation; either version 3.0 of the License, or (at your option) any later +version. + +BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. + +--> + +<mx:Panel xmlns:mx="library://ns.adobe.com/flex/mx" + xmlns:fx="http://ns.adobe.com/mxml/2009" + xmlns:mate="http://mate.asfusion.com/" + verticalScrollPolicy="off" + horizontalScrollPolicy="off" + horizontalAlign="center" + width="500" + height="120" + styleName="inactivityWarningTextStyle" + title="{ResourceUtil.getInstance().getString('bbb.userInactivityAudit.title')}" + creationComplete="onCreationComplete()"> + + <fx:Script> + <![CDATA[ + import com.asfusion.mate.events.Dispatcher; + + import mx.managers.PopUpManager; + + import org.as3commons.logging.api.ILogger; + import org.as3commons.logging.api.getClassLogger; + import org.bigbluebutton.main.events.BBBEvent; + import org.bigbluebutton.util.i18n.ResourceUtil; + + private static const LOGGER:ILogger = getClassLogger(InactivityWarningWindow); + + public var duration:Number = 0; + private var tickTimer:Timer; + + [Bindable] + private var cancelButtonLabel:String = ResourceUtil.getInstance().getString('bbb.inactivityWarning.cancel'); + + private function onCreationComplete():void { + tickTimer = new Timer(1000, 0); + tickTimer.addEventListener(TimerEvent.TIMER, tick); + + cancelButton.width = cancelButton.measureText(genCancelButtonLabel(duration)).width + + cancelButton.getStyle("paddingRight") + + cancelButton.getStyle("paddingLeft") + + 8; // 8 is magic number + + tickTimer.start(); + cancelButton.label = ResourceUtil.getInstance().getString('bbb.inactivityWarning.cancel'); + cancelButton.visible = true; + } + + private function tick(e:TimerEvent):void { + if (duration > 0) { + warningMessage.text = genCancelButtonLabel(duration); + duration--; + } else { + tickTimer.stop(); + cancelButton.visible = false; + cancelButton.includeInLayout = false; + warningMessage.text = ResourceUtil.getInstance().getString('bbb.userInactive.message'); + PopUpManager.removePopUp(this); + } + } + + private function genCancelButtonLabel(timeLeft:Number):String { + return ResourceUtil.getInstance().getString('bbb.userInactivityAudit.message') + " (" + timeLeft.toString() + ")"; + } + + private function cancelButtonClicked():void { + var dispatcher:Dispatcher = new Dispatcher(); + var bbbEvent:BBBEvent = new BBBEvent(BBBEvent.USER_INACTIVITY_AUDIT_RESPONSE_EVENT); + dispatcher.dispatchEvent(bbbEvent); + tickTimer.stop(); + PopUpManager.removePopUp(this); + } + ]]> + </fx:Script> + <mx:VBox width="100%" height="100%" paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5" horizontalAlign="center" verticalAlign="middle"> + <mx:Text id="warningMessage" selectable="false" text="{ResourceUtil.getInstance().getString('bbb.userInactivityAudit.message')}" styleName="inactivityWarningTextStyle"/> + <mx:Button id="cancelButton" click="cancelButtonClicked()" visible="false" styleName="inactivityWarningWindowCancelButtonStyle"/> + </mx:VBox> +</mx:Panel> \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/users/maps/UsersMainEventMap.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/users/maps/UsersMainEventMap.mxml index b7a4122612374e81793f1d5c5eef35676b29228c..e2a5f5d6b110babd1cf2bda5c81460f07c32f3a7 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/users/maps/UsersMainEventMap.mxml +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/users/maps/UsersMainEventMap.mxml @@ -113,6 +113,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. <EventHandlers type="{BBBEvent.ACTIVITY_RESPONSE_EVENT}"> <MethodInvoker generator="{UserService}" method="activityResponse" /> </EventHandlers> + + <EventHandlers type="{BBBEvent.USER_INACTIVITY_AUDIT_RESPONSE_EVENT}"> + <MethodInvoker generator="{UserService}" method="userInactivityAuditResponse" /> + </EventHandlers> <EventHandlers type="{TokenValidEvent.TOKEN_VALID_EVENT}" > <MethodInvoker generator="{UserService}" method="tokenValidEventHandler" arguments="{event}" /> diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageReceiver.as b/bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageReceiver.as index 3a9ef1465cc7402fae11d0843bbec8abd72acdf5..8297b2091d9fd9978e85323f18d6f04d998d6bf3 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageReceiver.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageReceiver.as @@ -205,9 +205,21 @@ package org.bigbluebutton.modules.users.services case "GetGuestsWaitingApprovalRespMsg": handleGetGuestsWaitingApprovalRespMsg(message); break; + case "UserInactivityAuditMsg": + handleUserInactivityAuditMsg(message); + break; } } + private function handleUserInactivityAuditMsg(msg: Object):void { + var header: Object = msg.header as Object; + var body: Object = msg.body as Object; + + var bbbEvent:BBBEvent = new BBBEvent(BBBEvent.USER_INACTIVITY_AUDIT_EVENT); + bbbEvent.payload.duration = body.responseDuration as Number; + globalDispatcher.dispatchEvent(bbbEvent); + } + private function handleUserJoinedVoiceConfToClientEvtMsg(msg: Object): void { var header: Object = msg.header as Object; var body: Object = msg.body as Object; diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageSender.as b/bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageSender.as index 4e5d030a454b57070659dbce154232df6ed5ec53..4a4d50226ecd273a0ad1c8150949b489275faa6c 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageSender.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageSender.as @@ -321,6 +321,27 @@ package org.bigbluebutton.modules.users.services JSON.stringify(message) ); //_netConnection.call } + + public function userInactivityAuditResponse():void { + var message:Object = { + header: {name: "UserInactivityAuditResponseMsg", meetingId: UsersUtil.getInternalMeetingID(), + userId: UsersUtil.getMyUserID()}, + body: {userId: UsersUtil.getMyUserID()} + }; + + var _nc:ConnectionManager = BBB.initConnectionManager(); + _nc.sendMessage2x( + function(result:String):void { // On successful result + }, + function(status:String):void { // status - On error occurred + var logData:Object = UsersUtil.initLogData(); + logData.tags = ["apps"]; + logData.message = "Error occured activity response."; + LOGGER.info(JSON.stringify(logData)); + }, + JSON.stringify(message) + ); //_netConnection.call + } public function changeRecordingStatus(userID:String, recording:Boolean):void { var message:Object = { diff --git a/clients/flash/air-client/src/css/hdpi.css b/clients/flash/air-client/src/css/hdpi.css index 00d3df54134a071e4199082cf32a3a319654bd62..bcb7e8ae9cf860b0b8e3f40db9754338e100ec4f 100755 --- a/clients/flash/air-client/src/css/hdpi.css +++ b/clients/flash/air-client/src/css/hdpi.css @@ -73,7 +73,7 @@ padding: 22.50; } - main|ExitView, main|DisconnectView { + main|ExitView, main|DisconnectView, main|UserInactivityView { gap: 22.50; padding: 22.50; } diff --git a/clients/flash/air-client/src/css/ldpi.css b/clients/flash/air-client/src/css/ldpi.css index 215ed93a288476636ea7aef722ed3d4b9f9407d7..2ac80b9964b2b448e76e85f9c2f0329e8c680bd7 100755 --- a/clients/flash/air-client/src/css/ldpi.css +++ b/clients/flash/air-client/src/css/ldpi.css @@ -73,7 +73,7 @@ padding: 11.250; } - main|ExitView, main|DisconnectView { + main|ExitView, main|DisconnectView, main|UserInactivityView { gap: 11.250; padding: 11.250; } diff --git a/clients/flash/air-client/src/css/mdpi.css b/clients/flash/air-client/src/css/mdpi.css index a67a638ffe55b00004f17651753e7932a67275a2..aad476eca3eaf85b256b88817060bb3f4c6cccdd 100755 --- a/clients/flash/air-client/src/css/mdpi.css +++ b/clients/flash/air-client/src/css/mdpi.css @@ -73,7 +73,7 @@ padding: 15.0; } - main|ExitView, main|DisconnectView { + main|ExitView, main|DisconnectView, main|UserInactivityView { gap: 15.0; padding: 15.0; } diff --git a/clients/flash/air-client/src/css/xhdpi.css b/clients/flash/air-client/src/css/xhdpi.css index 432547ca997e2f364836a97371daa0d3c59f10a4..c7c384c956b1be8bd58526a8748f98b6f0bb4c11 100755 --- a/clients/flash/air-client/src/css/xhdpi.css +++ b/clients/flash/air-client/src/css/xhdpi.css @@ -61,7 +61,7 @@ padding: 30; } - main|ExitView, main|DisconnectView { + main|ExitView, main|DisconnectView, main|UserInactivityView { gap : 30; padding : 30; } diff --git a/clients/flash/air-client/src/css/xxhdpi.css b/clients/flash/air-client/src/css/xxhdpi.css index 200a30d00df45c242c8e95286e972d0525a9eab4..a3261e654fba8b20a9664fe7c8e6a48a932c7c04 100755 --- a/clients/flash/air-client/src/css/xxhdpi.css +++ b/clients/flash/air-client/src/css/xxhdpi.css @@ -73,7 +73,7 @@ padding: 45.0; } - main|ExitView, main|DisconnectView { + main|ExitView, main|DisconnectView, main|UserInactivityView { gap: 45.0; padding: 45.0; } diff --git a/clients/flash/air-client/src/css/xxxhdpi.css b/clients/flash/air-client/src/css/xxxhdpi.css index 24cf693ebcbd5018273ac19f146efc2f4344ea37..24d5b4896e5a972244765b8987b34c2bc2143278 100755 --- a/clients/flash/air-client/src/css/xxxhdpi.css +++ b/clients/flash/air-client/src/css/xxxhdpi.css @@ -73,7 +73,7 @@ padding: 60; } - main|ExitView, main|DisconnectView { + main|ExitView, main|DisconnectView, main|UserInactivityView { gap: 60; padding: 60; } diff --git a/clients/flash/air-client/src/org/bigbluebutton/air/AppConfig.as b/clients/flash/air-client/src/org/bigbluebutton/air/AppConfig.as index 77a37a4149caedc05b1a1f39a70ee11cd33610b0..fee65edab4d6324ba150bad974f043309b586644 100755 --- a/clients/flash/air-client/src/org/bigbluebutton/air/AppConfig.as +++ b/clients/flash/air-client/src/org/bigbluebutton/air/AppConfig.as @@ -20,6 +20,10 @@ package org.bigbluebutton.air { import org.bigbluebutton.air.main.commands.KickUserSignal; import org.bigbluebutton.air.main.commands.LockUserCommand; import org.bigbluebutton.air.main.commands.LockUserSignal; + import org.bigbluebutton.air.main.commands.UserInactivityTimerCommand; + import org.bigbluebutton.air.main.commands.UserInactivityTimerResponseCommand; + import org.bigbluebutton.air.main.commands.UserInactivityTimerResponseSignal; + import org.bigbluebutton.air.main.commands.UserInactivityTimerSignal; import org.bigbluebutton.air.main.commands.PresenterCommand; import org.bigbluebutton.air.main.commands.PresenterSignal; import org.bigbluebutton.air.main.models.ConferenceParameters; @@ -55,7 +59,7 @@ package org.bigbluebutton.air { import robotlegs.bender.extensions.signalCommandMap.api.ISignalCommandMap; import robotlegs.bender.framework.api.IConfig; - import robotlegs.bender.framework.api.IInjector; + import robotlegs.bender.framework.api.IInjector; public class AppConfig implements IConfig { @@ -96,6 +100,8 @@ package org.bigbluebutton.air { signalCommandMap.map(LockUserSignal).toCommand(LockUserCommand); signalCommandMap.map(ChangeUserRoleSignal).toCommand(ChangeUserRoleCommand); signalCommandMap.map(KickUserSignal).toCommand(KickUserCommand); + signalCommandMap.map(UserInactivityTimerSignal).toCommand(UserInactivityTimerCommand); + signalCommandMap.map(UserInactivityTimerResponseSignal).toCommand(UserInactivityTimerResponseCommand); } } } diff --git a/clients/flash/air-client/src/org/bigbluebutton/air/common/PageEnum.as b/clients/flash/air-client/src/org/bigbluebutton/air/common/PageEnum.as index 4aebce66290b93bb7b19d92aef8dd17c7c310ebb..cf2ba625d5c79d202d56105d5e12f218e3523db8 100755 --- a/clients/flash/air-client/src/org/bigbluebutton/air/common/PageEnum.as +++ b/clients/flash/air-client/src/org/bigbluebutton/air/common/PageEnum.as @@ -5,6 +5,7 @@ package org.bigbluebutton.air.common { import org.bigbluebutton.air.chat.views.ChatRoomView; import org.bigbluebutton.air.main.views.DisconnectView; import org.bigbluebutton.air.main.views.ExitView; + import org.bigbluebutton.air.main.views.UserInactivityView; import org.bigbluebutton.air.main.views.MainView; import org.bigbluebutton.air.participants.views.ParticipantsView; import org.bigbluebutton.air.settings.views.SettingsView; @@ -14,7 +15,7 @@ package org.bigbluebutton.air.common { import org.bigbluebutton.air.settings.views.lock.LockSettingsView; import org.bigbluebutton.air.user.views.UserDetailsView; import org.bigbluebutton.air.voice.views.EchoTestView; - import org.bigbluebutton.air.voice.views.JoinAudioView; + import org.bigbluebutton.air.voice.views.JoinAudioView; public class PageEnum { public static const MAIN:String = "main"; @@ -49,6 +50,8 @@ package org.bigbluebutton.air.common { public static const APPLICATION_SETTINGS:String = "ApplicationSettings"; + public static const INACTIVITY_VIEW:String = "UserInactivityView"; + /** * Especials */ @@ -74,6 +77,7 @@ package org.bigbluebutton.air.common { dic[DISCONNECT] = DisconnectView; // dic[DESKSHARE] = DeskshareView; dic[EXIT] = ExitView; + dic[INACTIVITY_VIEW] = UserInactivityView; dicInitiated = true; } } diff --git a/clients/flash/air-client/src/org/bigbluebutton/air/main/MainConfig.as b/clients/flash/air-client/src/org/bigbluebutton/air/main/MainConfig.as index df6e1d56112e8065d9cbf330cc0823c5a4fefe0d..64261f1910dce99890b7df390a50d7c319d126c4 100755 --- a/clients/flash/air-client/src/org/bigbluebutton/air/main/MainConfig.as +++ b/clients/flash/air-client/src/org/bigbluebutton/air/main/MainConfig.as @@ -24,6 +24,8 @@ package org.bigbluebutton.air.main { import org.bigbluebutton.air.main.views.PagesNavigatorViewMediator; import org.bigbluebutton.air.main.views.TopToolbarBase; import org.bigbluebutton.air.main.views.TopToolbarMediator; + import org.bigbluebutton.air.main.views.UserInactivityView; + import org.bigbluebutton.air.main.views.UserInactivityViewMediator; import robotlegs.bender.extensions.matching.TypeMatcher; import robotlegs.bender.extensions.mediatorMap.api.IMediatorMap; @@ -62,6 +64,7 @@ package org.bigbluebutton.air.main { mediatorMap.map(ExitView).toMediator(ExitViewMediator); mediatorMap.map(DisconnectView).toMediator(DisconnectViewMediator); mediatorMap.map(MainView).toMediator(MainViewMediator); + mediatorMap.map(UserInactivityView).toMediator(UserInactivityViewMediator); } /** diff --git a/clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerCommand.as b/clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerCommand.as new file mode 100755 index 0000000000000000000000000000000000000000..71ccee1c971403f1b132de357345c6c95067bee2 --- /dev/null +++ b/clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerCommand.as @@ -0,0 +1,21 @@ +package org.bigbluebutton.air.main.commands +{ + import org.bigbluebutton.air.common.PageEnum; + import org.bigbluebutton.air.main.models.IUISession; + + import robotlegs.bender.bundles.mvcs.Command; + + public class UserInactivityTimerCommand extends Command + { + [Inject] + public var uiSession:IUISession + + [Inject] + public var responseDuration: Number + + override public function execute():void { + trace("RECEIVED INACTIVITY TIMER MESSAGE responseDuration=" + responseDuration); + uiSession.pushPage(PageEnum.INACTIVITY_VIEW); + } + } +} \ No newline at end of file diff --git a/clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerResponseCommand.as b/clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerResponseCommand.as new file mode 100755 index 0000000000000000000000000000000000000000..80933e69bd4bb12e0c64a8fbd8be24d5ffc5c632 --- /dev/null +++ b/clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerResponseCommand.as @@ -0,0 +1,28 @@ +package org.bigbluebutton.air.main.commands +{ + import org.bigbluebutton.air.main.models.IUISession; + import org.bigbluebutton.air.user.services.IUsersService; + + import robotlegs.bender.bundles.mvcs.Command; + + public class UserInactivityTimerResponseCommand extends Command + { + + [Inject] + public var userService:IUsersService; + + [Inject] + public var uiSession:IUISession + + public function UserInactivityTimerResponseCommand() + { + super(); + } + + override public function execute():void { + uiSession.popPage(); + + userService.userInactivityAuditResponse(); + } + } +} \ No newline at end of file diff --git a/clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerResponseSignal.as b/clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerResponseSignal.as new file mode 100755 index 0000000000000000000000000000000000000000..e62c3d592fea4ff89706d1e721d2b8819f758627 --- /dev/null +++ b/clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerResponseSignal.as @@ -0,0 +1,12 @@ +package org.bigbluebutton.air.main.commands +{ + import org.osflash.signals.Signal; + + public class UserInactivityTimerResponseSignal extends Signal + { + public function UserInactivityTimerResponseSignal() + { + super(); + } + } +} \ No newline at end of file diff --git a/clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerSignal.as b/clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerSignal.as new file mode 100755 index 0000000000000000000000000000000000000000..b7fed3947d4f966cf738948c1f365aed689534f0 --- /dev/null +++ b/clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerSignal.as @@ -0,0 +1,12 @@ +package org.bigbluebutton.air.main.commands +{ + import org.osflash.signals.Signal; + + public class UserInactivityTimerSignal extends Signal + { + public function UserInactivityTimerSignal() + { + super(Number); + } + } +} \ No newline at end of file diff --git a/clients/flash/air-client/src/org/bigbluebutton/air/main/views/LoadingScreenMediator.as b/clients/flash/air-client/src/org/bigbluebutton/air/main/views/LoadingScreenMediator.as index 91195cbb365290f51f6a57c1858a9faf912553c0..cf2de0bb5b068a3d957c2f111257d5f7d50ea611 100755 --- a/clients/flash/air-client/src/org/bigbluebutton/air/main/views/LoadingScreenMediator.as +++ b/clients/flash/air-client/src/org/bigbluebutton/air/main/views/LoadingScreenMediator.as @@ -44,7 +44,7 @@ package org.bigbluebutton.air.main.views { joinRoom(url); } } - + private function onInvokeEvent(invocation:InvokeEvent):void { if (invocation.arguments.length > 0 && !Capabilities.isDebugger) { var url:String = invocation.arguments[0].toString(); @@ -60,7 +60,6 @@ package org.bigbluebutton.air.main.views { FlexGlobals.topLevelApplication.mainshell.visible = false; uiSession.popPage(); uiSession.pushPage(PageEnum.MAIN); - joinRoom(url); } } else { diff --git a/clients/flash/air-client/src/org/bigbluebutton/air/main/views/PagesNavigatorViewMediator.as b/clients/flash/air-client/src/org/bigbluebutton/air/main/views/PagesNavigatorViewMediator.as index 37380a38371ac19c0bbbf0254962285b9f64dcec..78f044984dc79d3c4a4a34722ba023394a1f332c 100755 --- a/clients/flash/air-client/src/org/bigbluebutton/air/main/views/PagesNavigatorViewMediator.as +++ b/clients/flash/air-client/src/org/bigbluebutton/air/main/views/PagesNavigatorViewMediator.as @@ -82,6 +82,7 @@ package org.bigbluebutton.air.main.views { } else if (pageRemoved) { view.popView(transition); } else if (pageName != null && pageName != "") { + trace("SWITCHING PAGE to " + pageName); view.pushView(PageEnum.getClassfromName(pageName), null, null, transition); } } diff --git a/clients/flash/air-client/src/org/bigbluebutton/air/main/views/UserInactivityView.as b/clients/flash/air-client/src/org/bigbluebutton/air/main/views/UserInactivityView.as new file mode 100755 index 0000000000000000000000000000000000000000..b2a84f2bea996ba4d83994407bc38de62fa72da1 --- /dev/null +++ b/clients/flash/air-client/src/org/bigbluebutton/air/main/views/UserInactivityView.as @@ -0,0 +1,40 @@ +package org.bigbluebutton.air.main.views +{ + import spark.components.Button; + import spark.components.Label; + import spark.layouts.VerticalLayout; + + import org.bigbluebutton.air.common.views.NoTabView; + + public class UserInactivityView extends NoTabView + { + public var okButton:Button; + + public function UserInactivityView() + { + super(); + + var l:VerticalLayout = new VerticalLayout(); + l.horizontalAlign = "center"; + layout = l; + + var messageText:Label = new Label(); + messageText.percentWidth = 90; + messageText.text = "Inactivity Timer"; + messageText.setStyle("textAlign", "center"); + messageText.styleName = "disconnectMessage"; + addElement(messageText); + + okButton = new Button(); + okButton.percentWidth = 90; + okButton.label = "Ok"; + addElement(okButton); + } + + override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { + super.updateDisplayList(unscaledWidth, unscaledHeight); + this.layout["gap"] = getStyle("gap"); + this.layout["padding"] = getStyle("padding"); + } + } +} \ No newline at end of file diff --git a/clients/flash/air-client/src/org/bigbluebutton/air/main/views/UserInactivityViewMediator.as b/clients/flash/air-client/src/org/bigbluebutton/air/main/views/UserInactivityViewMediator.as new file mode 100755 index 0000000000000000000000000000000000000000..22583c0386c49a77c5fee691a6cce6b3595d3251 --- /dev/null +++ b/clients/flash/air-client/src/org/bigbluebutton/air/main/views/UserInactivityViewMediator.as @@ -0,0 +1,31 @@ +package org.bigbluebutton.air.main.views +{ + import flash.events.Event; + import flash.events.MouseEvent; + + import org.bigbluebutton.air.main.commands.UserInactivityTimerResponseSignal; + + import robotlegs.bender.bundles.mvcs.Mediator; + + public class UserInactivityViewMediator extends Mediator + { + [Inject] + public var view:UserInactivityView; + + [Inject] + public var userInactivityTimerResponseSignal:UserInactivityTimerResponseSignal; + + override public function initialize():void { + view.okButton.visible = true; + view.okButton.addEventListener(MouseEvent.CLICK, okButtonClicked); + } + + override public function destroy():void { + view.okButton.removeEventListener(MouseEvent.CLICK, okButtonClicked); + } + + private function okButtonClicked(event:Event):void { + userInactivityTimerResponseSignal.dispatch(); + } + } +} \ No newline at end of file diff --git a/clients/flash/air-client/src/org/bigbluebutton/air/user/services/IUsersService.as b/clients/flash/air-client/src/org/bigbluebutton/air/user/services/IUsersService.as index 7d587769b0fb258314353432285feec79fb22dfb..ef0ad6b666432fb4f5a576254c8ae4c4e44ccd91 100755 --- a/clients/flash/air-client/src/org/bigbluebutton/air/user/services/IUsersService.as +++ b/clients/flash/air-client/src/org/bigbluebutton/air/user/services/IUsersService.as @@ -23,5 +23,6 @@ package org.bigbluebutton.air.user.services { function validateToken():void; function joinMeeting():void; function changeRole(userId:String, role:String):void; + function userInactivityAuditResponse():void; } } diff --git a/clients/flash/air-client/src/org/bigbluebutton/air/user/services/UsersMessageReceiver.as b/clients/flash/air-client/src/org/bigbluebutton/air/user/services/UsersMessageReceiver.as index 971ad4b0d1d03ca3f0ac6e35137e04bf9a43f170..b1a2fd537c1d1a3e2bfe962cf0f3f29c86eb6e28 100755 --- a/clients/flash/air-client/src/org/bigbluebutton/air/user/services/UsersMessageReceiver.as +++ b/clients/flash/air-client/src/org/bigbluebutton/air/user/services/UsersMessageReceiver.as @@ -4,6 +4,7 @@ package org.bigbluebutton.air.user.services { import org.bigbluebutton.air.chat.models.IChatMessagesSession; import org.bigbluebutton.air.common.models.IMessageListener; import org.bigbluebutton.air.main.commands.DisconnectUserSignal; + import org.bigbluebutton.air.main.commands.UserInactivityTimerSignal; import org.bigbluebutton.air.main.models.IConferenceParameters; import org.bigbluebutton.air.main.models.IMeetingData; import org.bigbluebutton.air.main.models.IUserSession; @@ -27,6 +28,8 @@ package org.bigbluebutton.air.user.services { public var disconnectUserSignal:DisconnectUserSignal; + public var meetingInactivityTimerSignal:UserInactivityTimerSignal; + public function UsersMessageReceiver() { } @@ -94,11 +97,19 @@ package org.bigbluebutton.air.user.services { case "UserRoleChangedEvtMsg": handleUserRoleChangedEvtMsg(message); break; + case "UserInactivityAuditMsg": + handleUserInactivityAuditMsg(message); + break; default: break; } } + private function handleUserInactivityAuditMsg(m:Object):void { + trace("handleInactivityWarning: " + ObjectUtil.toString(m)); + meetingInactivityTimerSignal.dispatch(m.body.responseDuration as Number); + } + private function handleMeetingMuted(m:Object):void { var msg:Object = JSON.parse(m.msg); trace("handleMeetingMuted: " + ObjectUtil.toString(msg)); diff --git a/clients/flash/air-client/src/org/bigbluebutton/air/user/services/UsersMessageSender.as b/clients/flash/air-client/src/org/bigbluebutton/air/user/services/UsersMessageSender.as index c7092034265144a6d9ddfabbfd727cf66e8ef2b6..20f059643ffa6a26045f853d0e6dcc7b766e5b76 100755 --- a/clients/flash/air-client/src/org/bigbluebutton/air/user/services/UsersMessageSender.as +++ b/clients/flash/air-client/src/org/bigbluebutton/air/user/services/UsersMessageSender.as @@ -231,5 +231,15 @@ package org.bigbluebutton.air.user.services { userSession.mainConnection.sendMessage2x(defaultSuccessResponse, defaultFailureResponse, message); } + + public function userInactivityAuditResponse():void { + var message:Object = { + header: {name: "UserInactivityAuditResponseMsg", meetingId: conferenceParameters.meetingID, + userId: conferenceParameters.internalUserID}, + body: {userId: conferenceParameters.internalUserID} + }; + + userSession.mainConnection.sendMessage2x(defaultSuccessResponse, defaultFailureResponse, message); + } } } diff --git a/clients/flash/air-client/src/org/bigbluebutton/air/user/services/UsersService.as b/clients/flash/air-client/src/org/bigbluebutton/air/user/services/UsersService.as index 922e5490ccdef58b40623f4319fec4963a62d671..eb2e3340b7d1166e6c41fafa7435038005317c07 100755 --- a/clients/flash/air-client/src/org/bigbluebutton/air/user/services/UsersService.as +++ b/clients/flash/air-client/src/org/bigbluebutton/air/user/services/UsersService.as @@ -2,6 +2,7 @@ package org.bigbluebutton.air.user.services { import org.bigbluebutton.air.chat.models.IChatMessagesSession; import org.bigbluebutton.air.main.commands.DisconnectUserSignal; + import org.bigbluebutton.air.main.commands.UserInactivityTimerSignal; import org.bigbluebutton.air.main.models.IConferenceParameters; import org.bigbluebutton.air.main.models.IMeetingData; import org.bigbluebutton.air.main.models.IUserSession; @@ -24,6 +25,9 @@ package org.bigbluebutton.air.user.services { [Inject] public var disconnectUserSignal:DisconnectUserSignal; + [Inject] + public var meetingInactivityTimerSignal:UserInactivityTimerSignal; + public var usersMessageSender:UsersMessageSender; public var usersMessageReceiver:UsersMessageReceiver; @@ -39,6 +43,7 @@ package org.bigbluebutton.air.user.services { usersMessageReceiver.chatMessagesSession = chatMessagesSession; usersMessageReceiver.conferenceParameters = conferenceParameters; usersMessageReceiver.disconnectUserSignal = disconnectUserSignal; + usersMessageReceiver.meetingInactivityTimerSignal = meetingInactivityTimerSignal; usersMessageSender.userSession = userSession; usersMessageSender.conferenceParameters = conferenceParameters; userSession.mainConnection.addMessageListener(usersMessageReceiver); @@ -138,5 +143,8 @@ package org.bigbluebutton.air.user.services { usersMessageSender.changeRole(userId, role); } + public function userInactivityAuditResponse():void { + usersMessageSender.userInactivityAuditResponse(); + } } }