From 39284f1d1817c576eb02209bb2d425bb68a1b6ef Mon Sep 17 00:00:00 2001 From: Richard Alam Date: Fri, 6 Apr 2018 14:52:21 -0700 Subject: [PATCH] - start implementing user inactivity timer --- .../bigbluebutton/SystemConfiguration.scala | 2 +- .../UserInactivityAuditResponseMsgHdlr.scala | 17 ++++++ .../bigbluebutton/core/models/Users2x.scala | 11 +++- .../senders/ReceivedJsonMsgHandlerActor.scala | 2 + .../core/running/MeetingActor.scala | 52 +++++++++++++++++-- .../bigbluebutton/common2/msgs/UsersMgs.scala | 9 ++++ .../locale/en_US/bbbResources.properties | 1 + .../main/views/LoggedOutWindow.mxml | 2 + .../modules/users/services/MessageReceiver.as | 7 +++ .../src/org/bigbluebutton/air/AppConfig.as | 8 ++- .../org/bigbluebutton/air/common/PageEnum.as | 6 ++- .../commands/UserInactivityTimerCommand.as | 21 ++++++++ .../UserInactivityTimerResponseCommand.as | 22 ++++++++ .../UserInactivityTimerResponseSignal.as | 12 +++++ .../commands/UserInactivityTimerSignal.as | 12 +++++ .../air/main/views/UserInactivityView.as | 41 +++++++++++++++ .../main/views/UserInactivityViewMediator.as | 11 ++++ .../air/user/services/IUsersService.as | 1 + .../air/user/services/UsersMessageReceiver.as | 12 +++++ .../air/user/services/UsersMessageSender.as | 9 ++++ .../air/user/services/UsersService.as | 8 +++ 21 files changed, 258 insertions(+), 8 deletions(-) create mode 100755 akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/UserInactivityAuditResponseMsgHdlr.scala create mode 100755 clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerCommand.as create mode 100755 clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerResponseCommand.as create mode 100755 clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerResponseSignal.as create mode 100755 clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerSignal.as create mode 100755 clients/flash/air-client/src/org/bigbluebutton/air/main/views/UserInactivityView.as create mode 100755 clients/flash/air-client/src/org/bigbluebutton/air/main/views/UserInactivityViewMediator.as 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 e047984436b9..0a90ebee722d 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala @@ -21,7 +21,7 @@ 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 userInactivityTimeout = Try(config.getInt("inactivity.timeout")).getOrElse(2 * 3600) // 2 hours lazy val inactivityTimeLeft = Try(config.getInt("inactivity.timeLeft")).getOrElse(5 * 60) // 5 minutes lazy val expireLastUserLeft = Try(config.getInt("expire.lastUserLeft")).getOrElse(60) // 1 minute 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 000000000000..04a48d9916de --- /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 a67d2c3876c2..ac45f072d4d7 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 @@ -26,6 +26,12 @@ object Users2x { users.toVector.filter(u => !u.presenter) } + def updateInactivityResponse(users: Users2x, u: UserState): UserState = { + val newUserState = modify(u)(_.inactivityResponseOn).setTo(System.currentTimeMillis()) + 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 +210,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 = 0L) case class UserIdAndName(id: String, name: String) @@ -232,4 +240,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 24ddce2377e5..e1645e8b00b1 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 bd686d3636ad..4de552827317 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 @@ -34,7 +34,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 { @@ -78,7 +78,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 +166,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 +348,8 @@ class MeetingActor( case m: ValidateConnAuthTokenSysMsg => handleValidateConnAuthTokenSysMsg(m) + case m: UserInactivityAuditResponseMsg => handleUserInactivityAuditResponseMsg(m) + case _ => log.warning("***** Cannot handle " + msg.envelope.name) } } @@ -409,6 +412,8 @@ class MeetingActor( sendRttTraceTest() setRecordingChapterBreak() + + processUserInactivityAudit() } var lastRecBreakSentOn = expiryTracker.startedOnInMs @@ -502,7 +507,46 @@ class MeetingActor( "system", MeetingStatus2x.isRecording(liveMeeting.status) ) outGW.send(event) + } + } + + var lastUserInactivitySentOn = TimeUtil.timeNowInMs() + var checkInactiveUsers = false + + def processUserInactivityAudit(): Unit = { + val now = TimeUtil.timeNowInMs() + if (now - lastUserInactivitySentOn > 30000) { + lastUserInactivitySentOn = now + checkInactiveUsers = true + val event = buildUserInactivityAuditMsg(liveMeeting.props.meetingProp.intId) + outGW.send(event) + } + if (checkInactiveUsers && now - lastUserInactivitySentOn > 10000) { + checkInactiveUsers = false + checkForInactiveUsers() } } + + def checkForInactiveUsers(): Unit = { + val now = TimeUtil.timeNowInMs() + val users = Users2x.findAll(liveMeeting.users2x) + users foreach { u => + if (now - u.inactivityResponseOn > 2000) { + 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) + val header = BbbClientMsgHeader(UserInactivityAuditMsg.NAME, meetingId, "system") + val event = UserInactivityAuditMsg(header, body) + + BbbCommonEnvCoreMsg(envelope, event) + } + } 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 00fdc483958f..acfbd844e506 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) + +object UserInactivityAuditResponseMsg { val NAME = "UserInactivityAuditResponseMsg" } +case class UserInactivityAuditResponseMsg(header: BbbClientMsgHeader, body: UserInactivityAuditResponseMsgBody) extends StandardMsg +case class UserInactivityAuditResponseMsgBody(meetingId: String, userId: String) \ No newline at end of file diff --git a/bigbluebutton-client/locale/en_US/bbbResources.properties b/bigbluebutton-client/locale/en_US/bbbResources.properties index b2f2698e37c5..60e139bcd4cc 100755 --- a/bigbluebutton-client/locale/en_US/bbbResources.properties +++ b/bigbluebutton-client/locale/en_US/bbbResources.properties @@ -551,6 +551,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/views/LoggedOutWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/LoggedOutWindow.mxml index 27312f91a2e9..c5d3aea7f4c1 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 . 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/modules/users/services/MessageReceiver.as b/bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageReceiver.as index 3a9ef1465cc7..0fde6391f4c1 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,16 @@ package org.bigbluebutton.modules.users.services case "GetGuestsWaitingApprovalRespMsg": handleGetGuestsWaitingApprovalRespMsg(message); break; + case "UserInactivityAuditMsg": + handleUserInactivityAuditMsg(message); + break; } } + private function handleUserInactivityAuditMsg(msg: Object):void { + trace("******************* RECEIVED USER INACTIVITY AUDIT!!!!! **********************"); + } + private function handleUserJoinedVoiceConfToClientEvtMsg(msg: Object): void { var header: Object = msg.header as Object; var body: Object = msg.body as Object; 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 77a37a4149ca..fee65edab4d6 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 4aebce66290b..59bad80a2570 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 = "InactivityView"; + /** * 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/commands/UserInactivityTimerCommand.as b/clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerCommand.as new file mode 100755 index 000000000000..812b36cab6ff --- /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.main.models.IUISession; + + import robotlegs.bender.bundles.mvcs.Command; + + public class UserInactivityTimerCommand extends Command + { + [Inject] + public var uiSession:IUISession + + public function UserInactivityTimerCommand() + { + super(); + } + + override public function execute():void { + trace("RECEIVED INACTIVITY TIMER MESSAGE"); + } + } +} \ 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 000000000000..3bfed946c897 --- /dev/null +++ b/clients/flash/air-client/src/org/bigbluebutton/air/main/commands/UserInactivityTimerResponseCommand.as @@ -0,0 +1,22 @@ +package org.bigbluebutton.air.main.commands +{ + import org.bigbluebutton.air.user.services.IUsersService; + + import robotlegs.bender.bundles.mvcs.Command; + + public class UserInactivityTimerResponseCommand extends Command + { + + [Inject] + public var userService:IUsersService; + + public function UserInactivityTimerResponseCommand() + { + super(); + } + + override public function execute():void { + userService.activityResponse(); + } + } +} \ 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 000000000000..e62c3d592fea --- /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 000000000000..02cf730f949a --- /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(); + } + } +} \ No newline at end of file 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 000000000000..24b27bbd731b --- /dev/null +++ b/clients/flash/air-client/src/org/bigbluebutton/air/main/views/UserInactivityView.as @@ -0,0 +1,41 @@ +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 = "Inacitivty 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 000000000000..2e5e44a2ffc6 --- /dev/null +++ b/clients/flash/air-client/src/org/bigbluebutton/air/main/views/UserInactivityViewMediator.as @@ -0,0 +1,11 @@ +package org.bigbluebutton.air.main.views +{ + import robotlegs.bender.bundles.mvcs.Mediator; + + public class UserInactivityViewMediator extends Mediator + { + public function UserInactivityViewMediator() + { + } + } +} \ 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 7d587769b0fb..dc91da3ed0cf 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 activityResponse():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 971ad4b0d1d0..31f6c5107a8d 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,20 @@ package org.bigbluebutton.air.user.services { case "UserRoleChangedEvtMsg": handleUserRoleChangedEvtMsg(message); break; + case "MeetingInactivityWarningEvtMsg": + handleInactivityWarning(message); + break; default: break; } } + private function handleInactivityWarning(m:Object):void { + var msg:Object = JSON.parse(m.msg); + trace("handleInactivityWarning: " + ObjectUtil.toString(msg)); + meetingInactivityTimerSignal.dispatch(); + } + 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 c70920342651..cbd6bb265ebb 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,14 @@ package org.bigbluebutton.air.user.services { userSession.mainConnection.sendMessage2x(defaultSuccessResponse, defaultFailureResponse, message); } + + public function activityResponse():void { + var message:Object = { + header: {name: "MeetingActivityResponseCmdMsg", meetingId: conferenceParameters.meetingID, + userId: conferenceParameters.internalUserID}, + body: {respondedBy: 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 922e5490ccde..c38cf95d6b23 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 activityResponse():void { + usersMessageSender.activityResponse(); + } } }