Merge pull request #2751 from riadvice/emoji-status

Implementation of emoji status for users
This commit is contained in:
Richard Alam 2015-08-31 12:46:40 -04:00
commit c7e3788af1
57 changed files with 868 additions and 927 deletions

View File

@ -4,7 +4,7 @@ name := "bbb-apps-akka"
organization := "org.bigbluebutton"
version := "0.0.1"
version := "0.0.2"
scalaVersion := "2.11.6"
@ -50,7 +50,7 @@ libraryDependencies ++= {
"com.google.code.gson" % "gson" % "1.7.1",
"redis.clients" % "jedis" % "2.7.2",
"org.apache.commons" % "commons-lang3" % "3.2",
"org.bigbluebutton" % "bbb-common-message" % "0.0.13"
"org.bigbluebutton" % "bbb-common-message" % "0.0.14"
)}
seq(Revolver.settings: _*)

View File

@ -35,8 +35,7 @@ public interface IBigBlueButtonInGW {
// Users
void validateAuthToken(String meetingId, String userId, String token, String correlationId, String sessionId);
void registerUser(String roomName, String userid, String username, String role, String externUserID, String authToken);
void userRaiseHand(String meetingId, String userId);
void lowerHand(String meetingId, String userId, String loweredBy);
void userEmojiStatus(String meetingId, String userId, String emojiStatus);
void shareWebcam(String meetingId, String userId, String stream);
void unshareWebcam(String meetingId, String userId, String stream);
void setUserStatus(String meetingID, String userID, String status, Object value);

View File

@ -23,9 +23,8 @@ import org.bigbluebutton.common.messages.UserJoinedVoiceConfMessage;
import org.bigbluebutton.common.messages.UserLeavingMessage;
import org.bigbluebutton.common.messages.UserLeftVoiceConfMessage;
import org.bigbluebutton.common.messages.UserLockedInVoiceConfMessage;
import org.bigbluebutton.common.messages.UserLoweredHandMessage;
import org.bigbluebutton.common.messages.UserMutedInVoiceConfMessage;
import org.bigbluebutton.common.messages.UserRaisedHandMessage;
import org.bigbluebutton.common.messages.UserEmojiStatusMessage;
import org.bigbluebutton.common.messages.UserShareWebcamRequestMessage;
import org.bigbluebutton.common.messages.UserTalkingInVoiceConfMessage;
import org.bigbluebutton.common.messages.UserUnshareWebcamRequestMessage;
@ -61,11 +60,8 @@ public class UsersMessageReceiver implements MessageHandler{
case AssignPresenterRequestMessage.ASSIGN_PRESENTER_REQUEST:
processAssignPresenterRequestMessage(message);
break;
case UserRaisedHandMessage.USER_RAISED_HAND:
processUserRaisedHandMessage(message);
break;
case UserLoweredHandMessage.USER_LOWERED_HAND:
processUserLoweredHandMessage(message);
case UserEmojiStatusMessage.USER_EMOJI_STATUS:
processUserEmojiStatusMessage(message);
break;
case EjectUserFromMeetingRequestMessage.EJECT_USER_FROM_MEETING_REQUEST:
processEjectUserFromMeetingRequestMessage(message);
@ -215,17 +211,10 @@ public class UsersMessageReceiver implements MessageHandler{
}
}
private void processUserRaisedHandMessage(String message) {
UserRaisedHandMessage urhm = UserRaisedHandMessage.fromJson(message);
if (urhm != null) {
bbbInGW.userRaiseHand(urhm.meetingId, urhm.userId);;
}
}
private void processUserLoweredHandMessage(String message) {
UserLoweredHandMessage ulhm = UserLoweredHandMessage.fromJson(message);
if (ulhm != null) {
bbbInGW.lowerHand(ulhm.meetingId, ulhm.userId, ulhm.loweredBy);
private void processUserEmojiStatusMessage(String message) {
UserEmojiStatusMessage uesm = UserEmojiStatusMessage.fromJson(message);
if (uesm != null) {
bbbInGW.userEmojiStatus(uesm.meetingId, uesm.userId, uesm.emojiStatus);
}
}

View File

@ -159,12 +159,8 @@ class BigBlueButtonInGW(val system: ActorSystem, recorderApp: RecorderApplicatio
}
// Users
def userRaiseHand(meetingId: String, userId: String) {
bbbActor ! new UserRaiseHand(meetingId, userId)
}
def lowerHand(meetingId: String, userId: String, loweredBy: String) {
bbbActor ! new UserLowerHand(meetingId, userId, loweredBy)
def userEmojiStatus(meetingId: String, userId: String, emojiStatus: String) {
bbbActor ! new UserEmojiStatus(meetingId, userId, emojiStatus)
}
def ejectUserFromMeeting(meetingId: String, userId: String, ejectedBy: String) {

View File

@ -68,10 +68,8 @@ class MeetingActor(val mProps: MeetingProperties, val outGW: OutMessageGateway)
handleChangeUserStatus(msg)
case msg: EjectUserFromMeeting =>
handleEjectUserFromMeeting(msg)
case msg: UserRaiseHand =>
handleUserRaiseHand(msg)
case msg: UserLowerHand =>
handleUserLowerHand(msg)
case msg: UserEmojiStatus =>
handleUserEmojiStatus(msg)
case msg: UserShareWebcam =>
handleUserShareWebcam(msg)
case msg: UserUnshareWebcam =>

View File

@ -90,8 +90,7 @@ class MessageSenderActor(val meetingId: String, val service: MessageSender)
case msg: ValidateAuthTokenReply => handleValidateAuthTokenReply(msg)
case msg: ValidateAuthTokenTimedOut => handleValidateAuthTokenTimedOut(msg)
case msg: UserJoined => handleUserJoined(msg)
case msg: UserRaisedHand => handleUserRaisedHand(msg)
case msg: UserLoweredHand => handleUserLoweredHand(msg)
case msg: UserChangedEmojiStatus => handleChangedUserEmojiStatus(msg)
case msg: UserSharedWebcam => handleUserSharedWebcam(msg)
case msg: UserUnsharedWebcam => handleUserUnsharedWebcam(msg)
case msg: UserStatusChange => handleUserStatusChange(msg)
@ -513,13 +512,8 @@ class MessageSenderActor(val meetingId: String, val service: MessageSender)
service.send(MessagingConstants.FROM_USERS_CHANNEL, json)
}
private def handleUserRaisedHand(msg: UserRaisedHand) {
val json = UsersMessageToJsonConverter.userRaisedHandToJson(msg)
service.send(MessagingConstants.FROM_USERS_CHANNEL, json)
}
private def handleUserLoweredHand(msg: UserLoweredHand) {
val json = UsersMessageToJsonConverter.userLoweredHandToJson(msg)
private def handleChangedUserEmojiStatus(msg: UserChangedEmojiStatus) {
val json = UsersMessageToJsonConverter.userChangedEmojiStatusToJson(msg)
service.send(MessagingConstants.FROM_USERS_CHANNEL, json)
}

View File

@ -59,8 +59,7 @@ class RecorderActor(val meetingId: String, val recorder: RecorderApplication)
case msg: UserJoinedVoice => handleUserJoinedVoice(msg)
case msg: UserLeftVoice => handleUserLeftVoice(msg)
case msg: RecordingStatusChanged => handleRecordingStatusChanged(msg)
case msg: UserRaisedHand => handleUserRaisedHand(msg)
case msg: UserLoweredHand => handleUserLoweredHand(msg)
case msg: UserChangedEmojiStatus => handleChangedUserEmojiStatus(msg)
case msg: UserSharedWebcam => handleUserSharedWebcam(msg)
case msg: UserUnsharedWebcam => handleUserUnsharedWebcam(msg)
case msg: VoiceRecordingStarted => handleVoiceRecordingStarted(msg)
@ -297,15 +296,9 @@ class RecorderActor(val meetingId: String, val recorder: RecorderApplication)
}
private def handleUserRaisedHand(msg: UserRaisedHand) {
private def handleChangedUserEmojiStatus(msg: UserChangedEmojiStatus) {
val status = UserStatusChange(msg.meetingID, msg.recorded,
msg.userID, "raiseHand", true: java.lang.Boolean)
handleUserStatusChange(status)
}
private def handleUserLoweredHand(msg: UserLoweredHand) {
val status = UserStatusChange(msg.meetingID, msg.recorded,
msg.userID, "raiseHand", false: java.lang.Boolean)
msg.userID, "emojiStatus", msg.emojiStatus)
handleUserStatusChange(status)
}

View File

@ -19,7 +19,6 @@ object Constants {
val EXT_USER_ID = "external_user_id"
val REQUESTER_ID = "requester_id"
val REPLY_TO = "reply_to"
val LOWERED_BY = "lowered_by"
val STREAM = "stream"
val LOCKED = "locked"
val SETTINGS = "settings"
@ -66,7 +65,7 @@ object Constants {
val ENABLE = "enable"
val PRESENTER = "presenter"
val USERS = "users"
val RAISE_HAND = "raise_hand"
val EMOJI_STATUS = "emoji_status"
val HAS_STREAM = "has_stream"
val WEBCAM_STREAM = "webcam_stream"
val PHONE_USER = "phone_user"

View File

@ -32,8 +32,7 @@ case class RegisterUser(meetingID: String, userID: String, name: String, role: R
case class UserJoining(meetingID: String, userID: String, authToken: String) extends InMessage
case class UserLeaving(meetingID: String, userID: String, sessionId: String) extends InMessage
case class GetUsers(meetingID: String, requesterID: String) extends InMessage
case class UserRaiseHand(meetingID: String, userId: String) extends InMessage
case class UserLowerHand(meetingID: String, userId: String, loweredBy: String) extends InMessage
case class UserEmojiStatus(meetingID: String, userId: String, emojiStatus: String) extends InMessage
case class EjectUserFromMeeting(meetingID: String, userId: String, ejectedBy: String) extends InMessage
case class UserShareWebcam(meetingID: String, userId: String, stream: String) extends InMessage
case class UserUnshareWebcam(meetingID: String, userId: String, stream: String) extends InMessage

View File

@ -20,8 +20,7 @@ object MessageNames {
val USER_JOINING = "user_joining_request"
val USER_LEAVING = "user_leaving_request"
val GET_USERS = "get_users_request"
val RAISE_HAND = "user_raise_hand_request"
val LOWER_HAND = "user_lower_hand_request"
val EMOJI_STATUS = "emoji_status_hand_request"
val USER_SHARE_WEBCAM = "user_share_webcam_request"
val USER_UNSHARE_WEBCAM = "user_unshare_webcam_request"
val CHANGE_USER_STATUS = "change_user_status_request"
@ -107,8 +106,7 @@ object MessageNames {
val END_AND_KICK_ALL = "end_and_kick_all_message"
val GET_USERS_REPLY = "get_users_reply"
val USER_JOINED = "user_joined_message"
val USER_RAISED_HAND = "user_raised_hand_message"
val USER_LOWERED_HAND = "user_lowered_hand_message"
val USER_EMOJI_STATUS = "user_emoji_status_message"
val USER_SHARED_WEBCAM = "user_shared_webcam_message"
val USER_UNSHARED_WEBCAM = "user_unshared_webcam_message"
val USER_STATUS_CHANGED = "user_status_changed_message"

View File

@ -45,8 +45,7 @@ case class GetUsersReply(meetingID: String, requesterID: String, users: Array[Us
case class ValidateAuthTokenTimedOut(meetingID: String, requesterId: String, token: String, valid: Boolean, correlationId: String) extends IOutMessage
case class ValidateAuthTokenReply(meetingID: String, requesterId: String, token: String, valid: Boolean, correlationId: String) extends IOutMessage
case class UserJoined(meetingID: String, recorded: Boolean, user: UserVO) extends IOutMessage
case class UserRaisedHand(meetingID: String, recorded: Boolean, raisedHand: Boolean, userID: String) extends IOutMessage
case class UserLoweredHand(meetingID: String, recorded: Boolean, raisedHand: Boolean, userID: String, loweredBy: String) extends IOutMessage
case class UserChangedEmojiStatus(meetingID: String, recorded: Boolean, emojiStatus: String, userID: String) extends IOutMessage
case class UserListeningOnly(meetingID: String, recorded: Boolean, userID: String, listenOnly: Boolean) extends IOutMessage
case class UserSharedWebcam(meetingID: String, recorded: Boolean, userID: String, stream: String) extends IOutMessage
case class UserUnsharedWebcam(meetingID: String, recorded: Boolean, userID: String, stream: String) extends IOutMessage

View File

@ -47,7 +47,7 @@ case class User(
presenter: Boolean,
callerId: CallerId,
phoneCaller: Boolean,
handRaised: Boolean,
emojiStatus: String,
muted: Boolean,
talking: Boolean)
@ -86,7 +86,7 @@ case class UserVO(
externUserID: String,
name: String,
role: Role.Role,
raiseHand: Boolean,
emojiStatus: String,
presenter: Boolean,
hasStream: Boolean,
locked: Boolean,

View File

@ -205,19 +205,11 @@ trait UsersApp {
au.toArray
}
def handleUserRaiseHand(msg: UserRaiseHand) {
def handleUserEmojiStatus(msg: UserEmojiStatus) {
usersModel.getUser(msg.userId) foreach { user =>
val uvo = user.copy(raiseHand = true)
val uvo = user.copy(emojiStatus = msg.emojiStatus)
usersModel.addUser(uvo)
outGW.send(new UserRaisedHand(mProps.meetingID, mProps.recorded, uvo.raiseHand, uvo.userID))
}
}
def handleUserLowerHand(msg: UserLowerHand) {
usersModel.getUser(msg.userId) foreach { user =>
val uvo = user.copy(raiseHand = false)
usersModel.addUser(uvo)
outGW.send(new UserLoweredHand(mProps.meetingID, mProps.recorded, uvo.raiseHand, uvo.userID, msg.loweredBy))
outGW.send(new UserChangedEmojiStatus(mProps.meetingID, mProps.recorded, msg.emojiStatus, uvo.userID))
}
}
@ -289,7 +281,7 @@ trait UsersApp {
}
val uvo = new UserVO(msg.userID, ru.externId, ru.name,
ru.role, raiseHand = false, presenter = false,
ru.role, emojiStatus = "none", presenter = false,
hasStream = false, locked = getInitialLockStatus(ru.role),
webcamStreams = new ListSet[String](), phoneUser = false, vu, listenOnly = false)
@ -368,7 +360,7 @@ trait UsersApp {
val sessionId = "PHONE-" + webUserId;
val uvo = new UserVO(webUserId, webUserId, msg.callerIdName,
Role.VIEWER, raiseHand = false, presenter = false,
Role.VIEWER, emojiStatus = "none", presenter = false,
hasStream = false, locked = getInitialLockStatus(Role.VIEWER), webcamStreams = new ListSet[String](),
phoneUser = true, vu, listenOnly = false)

View File

@ -2,7 +2,7 @@ package org.bigbluebutton.core.models
import org.bigbluebutton.core.api.Role._
case class Status(isPresenter: Boolean = false, handRaised: Boolean = false)
case class Status(isPresenter: Boolean = false, emojiStatus: String = "none")
case class CallerId(num: String = "", name: String = "")

View File

@ -33,8 +33,7 @@ class UsersEventRedisPublisher(service: MessageSender) extends OutMessageListene
case msg: ValidateAuthTokenReply => handleValidateAuthTokenReply(msg)
case msg: ValidateAuthTokenTimedOut => handleValidateAuthTokenTimedOut(msg)
case msg: UserJoined => handleUserJoined(msg)
case msg: UserRaisedHand => handleUserRaisedHand(msg)
case msg: UserLoweredHand => handleUserLoweredHand(msg)
case msg: UserChangedEmojiStatus => handleChangedUserEmojiStatus(msg)
case msg: UserSharedWebcam => handleUserSharedWebcam(msg)
case msg: UserUnsharedWebcam => handleUserUnsharedWebcam(msg)
case msg: UserStatusChange => handleUserStatusChange(msg)
@ -139,13 +138,8 @@ class UsersEventRedisPublisher(service: MessageSender) extends OutMessageListene
service.send(MessagingConstants.FROM_USERS_CHANNEL, json)
}
private def handleUserRaisedHand(msg: UserRaisedHand) {
val json = UsersMessageToJsonConverter.userRaisedHandToJson(msg)
service.send(MessagingConstants.FROM_USERS_CHANNEL, json)
}
private def handleUserLoweredHand(msg: UserLoweredHand) {
val json = UsersMessageToJsonConverter.userLoweredHandToJson(msg)
private def handleChangedUserEmojiStatus(msg: UserChangedEmojiStatus) {
val json = UsersMessageToJsonConverter.userChangedEmojiStatusToJson(msg)
service.send(MessagingConstants.FROM_USERS_CHANNEL, json)
}

View File

@ -16,7 +16,7 @@ object UsersMessageToJsonConverter {
wuser += "extern_userid" -> user.externUserID
wuser += "name" -> user.name
wuser += "role" -> user.role.toString()
wuser += "raise_hand" -> user.raiseHand
wuser += "emoji_status" -> user.emojiStatus
wuser += "presenter" -> user.presenter
wuser += "has_stream" -> user.hasStream
wuser += "locked" -> user.locked
@ -169,24 +169,13 @@ object UsersMessageToJsonConverter {
Util.buildJson(header, payload)
}
def userRaisedHandToJson(msg: UserRaisedHand): String = {
def userChangedEmojiStatusToJson(msg: UserChangedEmojiStatus): String = {
val payload = new java.util.HashMap[String, Any]()
payload.put(Constants.MEETING_ID, msg.meetingID)
payload.put(Constants.RAISE_HAND, msg.raisedHand)
payload.put(Constants.EMOJI_STATUS, msg.emojiStatus)
payload.put(Constants.USER_ID, msg.userID)
val header = Util.buildHeader(MessageNames.USER_RAISED_HAND, None)
Util.buildJson(header, payload)
}
def userLoweredHandToJson(msg: UserLoweredHand): String = {
val payload = new java.util.HashMap[String, Any]()
payload.put(Constants.MEETING_ID, msg.meetingID)
payload.put(Constants.RAISE_HAND, msg.raisedHand)
payload.put(Constants.USER_ID, msg.userID)
payload.put(Constants.LOWERED_BY, msg.loweredBy)
val header = Util.buildHeader(MessageNames.USER_LOWERED_HAND, None)
val header = Util.buildHeader(MessageNames.USER_EMOJI_STATUS, None)
Util.buildJson(header, payload)
}

View File

@ -4,7 +4,7 @@ name := "bbb-common-message"
organization := "org.bigbluebutton"
version := "0.0.13"
version := "0.0.14"
// We want to have our jar files in lib_managed dir.
// This way we'll have the right path when we import

View File

@ -16,10 +16,9 @@ public class Constants {
public static final String AUTH_TOKEN = "auth_token";
public static final String ROLE = "role";
public static final String EXT_USER_ID = "external_user_id";
public static final String EXTERN_USERID = "extern_userid";
public static final String EXTERN_USERID = "extern_userid";
public static final String REQUESTER_ID = "requester_id";
public static final String REPLY_TO = "reply_to";
public static final String LOWERED_BY = "lowered_by";
public static final String STREAM = "stream";
public static final String LOCKED = "locked";
public static final String SETTINGS = "settings";
@ -63,14 +62,14 @@ public class Constants {
public static final String USER = "user";
public static final String MUTED = "muted";
public static final String VOICE_USER = "voice_user";
public static final String VOICEUSER = "voiceUser";
public static final String VOICEUSER = "voiceUser";
public static final String RECORDING_FILE = "recording_file";
public static final String ANNOTATION = "annotation";
public static final String WHITEBOARD_ID = "whiteboard_id";
public static final String ENABLE = "enable";
public static final String PRESENTER = "presenter";
public static final String USERS = "users";
public static final String RAISE_HAND = "raise_hand";
public static final String EMOJI_STATUS = "emoji_status";
public static final String HAS_STREAM = "has_stream";
public static final String WEBCAM_STREAM = "webcam_stream";
public static final String PHONE_USER = "phone_user";
@ -126,5 +125,3 @@ public class Constants {
public static final String PERM_LOCK_ON_JOIN_CONFIG = "lockOnJoinConfigurable";
public static final String ENABLED = "enabled";
}

View File

@ -6,32 +6,32 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
public class UserRaisedHandMessage implements ISubscribedMessage {
public static final String USER_RAISED_HAND = "user_raised_hand_message";
public class UserEmojiStatusMessage implements ISubscribedMessage {
public static final String USER_EMOJI_STATUS = "user_emoji_status_message";
public static final String VERSION = "0.0.1";
public final String meetingId;
public final String userId;
public final Boolean raisedHand;
public final String emojiStatus;
public UserRaisedHandMessage(String meetingId, String userId, Boolean raisedHand) {
public UserEmojiStatusMessage(String meetingId, String userId, String emojiStatus) {
this.meetingId = meetingId;
this.userId = userId;
this.raisedHand = raisedHand;
this.emojiStatus = emojiStatus;
}
public String toJson() {
HashMap<String, Object> payload = new HashMap<String, Object>();
payload.put(Constants.MEETING_ID, meetingId);
payload.put(Constants.USER_ID, userId);
payload.put(Constants.RAISE_HAND, raisedHand);
payload.put(Constants.EMOJI_STATUS, emojiStatus);
java.util.HashMap<String, Object> header = MessageBuilder.buildHeader(USER_RAISED_HAND, VERSION, null);
java.util.HashMap<String, Object> header = MessageBuilder.buildHeader(USER_EMOJI_STATUS, VERSION, null);
return MessageBuilder.buildJson(header, payload);
}
public static UserRaisedHandMessage fromJson(String message) {
public static UserEmojiStatusMessage fromJson(String message) {
JsonParser parser = new JsonParser();
JsonObject obj = (JsonObject) parser.parse(message);
@ -41,14 +41,14 @@ public class UserRaisedHandMessage implements ISubscribedMessage {
if (header.has("name")) {
String messageName = header.get("name").getAsString();
if (USER_RAISED_HAND.equals(messageName)) {
if (USER_EMOJI_STATUS.equals(messageName)) {
if (payload.has(Constants.MEETING_ID)
&& payload.has(Constants.USER_ID)
&& payload.has(Constants.RAISE_HAND)) {
&& payload.has(Constants.EMOJI_STATUS)) {
String id = payload.get(Constants.MEETING_ID).getAsString();
String userid = payload.get(Constants.USER_ID).getAsString();
Boolean raisedHand = payload.get(Constants.RAISE_HAND).getAsBoolean();
return new UserRaisedHandMessage(id, userid, raisedHand);
String emojiStatus = payload.get(Constants.EMOJI_STATUS).getAsString();
return new UserEmojiStatusMessage(id, userid, emojiStatus);
}
}
}

View File

@ -1,64 +0,0 @@
package org.bigbluebutton.common.messages;
import java.util.HashMap;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
public class UserLoweredHandMessage implements ISubscribedMessage {
public static final String USER_LOWERED_HAND = "user_lowered_hand_message";
public static final String VERSION = "0.0.1";
public final String meetingId;
public final String userId;
public final Boolean raisedHand;
public final String loweredBy;
public UserLoweredHandMessage(String meetingId, String userId, Boolean raisedHand, String loweredBy) {
this.meetingId = meetingId;
this.userId = userId;
this.raisedHand = raisedHand;
this.loweredBy = loweredBy;
}
public String toJson() {
HashMap<String, Object> payload = new HashMap<String, Object>();
payload.put(Constants.MEETING_ID, meetingId);
payload.put(Constants.USER_ID, userId);
payload.put(Constants.RAISE_HAND, raisedHand);
payload.put(Constants.LOWERED_BY, loweredBy);
java.util.HashMap<String, Object> header = MessageBuilder.buildHeader(USER_LOWERED_HAND, VERSION, null);
return MessageBuilder.buildJson(header, payload);
}
public static UserLoweredHandMessage fromJson(String message) {
JsonParser parser = new JsonParser();
JsonObject obj = (JsonObject) parser.parse(message);
if (obj.has("header") && obj.has("payload")) {
JsonObject header = (JsonObject) obj.get("header");
JsonObject payload = (JsonObject) obj.get("payload");
if (header.has("name")) {
String messageName = header.get("name").getAsString();
if (USER_LOWERED_HAND.equals(messageName)) {
if (payload.has(Constants.MEETING_ID)
&& payload.has(Constants.USER_ID)
&& payload.has(Constants.RAISE_HAND)
&& payload.has(Constants.LOWERED_BY)) {
String id = payload.get(Constants.MEETING_ID).getAsString();
String userid = payload.get(Constants.USER_ID).getAsString();
Boolean raisedHand = payload.get(Constants.RAISE_HAND).getAsBoolean();
String loweredBy = payload.get(Constants.LOWERED_BY).getAsString();
return new UserLoweredHandMessage(id, userid, raisedHand, loweredBy);
}
}
}
}
return null;
}
}

View File

@ -71,7 +71,7 @@ public class Util {
public Map<String, Object> extractUser(JsonObject user) {
if (user.has(Constants.USER_ID) && user.has(Constants.NAME)
&& user.has(Constants.HAS_STREAM) && user.has(Constants.LISTENONLY)
&& user.has(Constants.RAISE_HAND) && user.has(Constants.PHONE_USER)
&& user.has(Constants.EMOJI_STATUS) && user.has(Constants.PHONE_USER)
&& user.has(Constants.PRESENTER) && user.has(Constants.LOCKED)
&& user.has(Constants.EXTERN_USERID) && user.has(Constants.ROLE)
&& user.has(Constants.VOICEUSER) && user.has(Constants.WEBCAM_STREAM)){
@ -82,7 +82,7 @@ public class Util {
String username = user.get(Constants.NAME).getAsString();
Boolean hasStream = user.get(Constants.HAS_STREAM).getAsBoolean();
Boolean listenOnly = user.get(Constants.LISTENONLY).getAsBoolean();
Boolean raiseHand = user.get(Constants.RAISE_HAND).getAsBoolean();
String emojiStatus = user.get(Constants.EMOJI_STATUS).getAsString();
Boolean phoneUser = user.get(Constants.PHONE_USER).getAsBoolean();
Boolean presenter = user.get(Constants.PRESENTER).getAsBoolean();
Boolean locked = user.get(Constants.LOCKED).getAsBoolean();
@ -97,7 +97,7 @@ public class Util {
userMap.put("listenOnly", listenOnly);
userMap.put("hasStream", hasStream);
userMap.put("webcamStream", webcamStreams);
userMap.put("raiseHand", raiseHand);
userMap.put("emojiStatus", emojiStatus);
userMap.put("externUserID", extUserId);
userMap.put("phoneUser", phoneUser);
userMap.put("locked", locked);

View File

@ -105,7 +105,7 @@ dependencies {
compile 'com.google.code.gson:gson:1.7.1'
providedCompile 'org.apache.commons:commons-lang3:3.2'
compile 'org.bigbluebutton:bbb-common-message:0.0.13'
compile 'org.bigbluebutton:bbb-common-message:0.0.14'
}
test {

View File

@ -12,13 +12,12 @@ import org.bigbluebutton.common.messages.GetUsersReplyMessage;
import org.bigbluebutton.common.messages.LockLayoutMessage;
import org.bigbluebutton.common.messages.PresenterAssignedMessage;
import org.bigbluebutton.common.messages.RecordingStatusChangedMessage;
import org.bigbluebutton.common.messages.UserEmojiStatusMessage;
import org.bigbluebutton.common.messages.UserJoinedMessage;
import org.bigbluebutton.common.messages.UserJoinedVoiceMessage;
import org.bigbluebutton.common.messages.UserLeftMessage;
import org.bigbluebutton.common.messages.UserLeftVoiceMessage;
import org.bigbluebutton.common.messages.UserListeningOnlyMessage;
import org.bigbluebutton.common.messages.UserLoweredHandMessage;
import org.bigbluebutton.common.messages.UserRaisedHandMessage;
import org.bigbluebutton.common.messages.UserSharedWebcamMessage;
import org.bigbluebutton.common.messages.UserStatusChangedMessage;
import org.bigbluebutton.common.messages.UserUnsharedWebcamMessage;
@ -92,10 +91,10 @@ public class UserClientMessageSender {
processUserStatusChangedMessage(usm);
}
break;
case UserRaisedHandMessage.USER_RAISED_HAND:
UserRaisedHandMessage urhm = UserRaisedHandMessage.fromJson(message);
case UserEmojiStatusMessage.USER_EMOJI_STATUS:
UserEmojiStatusMessage urhm = UserEmojiStatusMessage.fromJson(message);
if (urhm != null) {
processUserRaisedHandMessage(urhm);
processUserEmojiStatusMessage(urhm);
}
break;
case UserListeningOnlyMessage.USER_LISTENING_ONLY:
@ -104,12 +103,6 @@ public class UserClientMessageSender {
processUserListeningOnlyMessage(ulom);
}
break;
case UserLoweredHandMessage.USER_LOWERED_HAND:
UserLoweredHandMessage ulhm = UserLoweredHandMessage.fromJson(message);
if (ulhm != null) {
processUserLoweredHandMessage(ulhm);
}
break;
case UserSharedWebcamMessage.USER_SHARED_WEBCAM:
UserSharedWebcamMessage uswm = UserSharedWebcamMessage.fromJson(message);
if (uswm != null) {
@ -295,22 +288,23 @@ public class UserClientMessageSender {
service.sendMessage(m);
}
private void processUserRaisedHandMessage(UserRaisedHandMessage msg) {
private void processUserEmojiStatusMessage(UserEmojiStatusMessage msg) {
Map<String, Object> args = new HashMap<String, Object>();
args.put("userId", msg.userId);
args.put("emojiStatus", msg.emojiStatus);
Map<String, Object> message = new HashMap<String, Object>();
Gson gson = new Gson();
message.put("msg", gson.toJson(args));
BroadcastClientMessage m = new BroadcastClientMessage(msg.meetingId, "userRaisedHand", message);
BroadcastClientMessage m = new BroadcastClientMessage(msg.meetingId, "userEmojiStatus", message);
service.sendMessage(m);
}
private void processUserListeningOnlyMessage(UserListeningOnlyMessage msg) {
Map<String, Object> args = new HashMap<String, Object>();
args.put("userId", msg.userId);
args.put("listenOnly", msg.listenOnly);
args.put("listenOnly", msg.listenOnly);
Map<String, Object> message = new HashMap<String, Object>();
Gson gson = new Gson();
@ -320,19 +314,6 @@ public class UserClientMessageSender {
service.sendMessage(m);
}
private void processUserLoweredHandMessage(UserLoweredHandMessage msg) {
Map<String, Object> args = new HashMap<String, Object>();
args.put("userId", msg.userId);
args.put("loweredBy", msg.loweredBy);
Map<String, Object> message = new HashMap<String, Object>();
Gson gson = new Gson();
message.put("msg", gson.toJson(args));
BroadcastClientMessage m = new BroadcastClientMessage(msg.meetingId, "userLoweredHand", message);
service.sendMessage(m);
}
private void processUserStatusChangedMessage(UserStatusChangedMessage msg) {
Map<String, Object> args = new HashMap<String, Object>();
args.put("userID", msg.userId);

View File

@ -62,13 +62,8 @@ public class MessagePublisher {
sender.send(MessagingConstants.TO_MEETING_CHANNEL, msg.toJson());
}
public void userRaiseHand(String meetingId, String userId) {
UserRaisedHandMessage msg = new UserRaisedHandMessage(meetingId, userId, true);
sender.send(MessagingConstants.TO_USERS_CHANNEL, msg.toJson());
}
public void lowerHand(String meetingId, String userId, String loweredBy) {
UserLoweredHandMessage msg = new UserLoweredHandMessage(meetingId, userId, false, loweredBy);
public void userEmojiStatus(String meetingId, String userId, String emojiStatus) {
UserEmojiStatusMessage msg = new UserEmojiStatusMessage(meetingId, userId, emojiStatus);
sender.send(MessagingConstants.TO_USERS_CHANNEL, msg.toJson());
}

View File

@ -54,20 +54,12 @@ public class ParticipantsService {
red5InGW.getUsers(meetingId, userId);
}
public void userRaiseHand() {
IScope scope = Red5.getConnectionLocal().getScope();
String meetingId = scope.getName();
String userId = getBbbSession().getInternalUserID();
red5InGW.userRaiseHand(meetingId, userId);
}
public void lowerHand(Map<String, String> msg) {
public void userEmojiStatus(Map<String, String> msg) {
IScope scope = Red5.getConnectionLocal().getScope();
String meetingId = scope.getName();
String userId = (String) msg.get("userId");
String loweredBy = (String) msg.get("loweredBy");
red5InGW.lowerHand(meetingId, userId, loweredBy);
String emojiStatus = (String) msg.get("emojiStatus");
red5InGW.userEmojiStatus(meetingId, userId, emojiStatus);
}
public void ejectUserFromMeeting(Map<String, String> msg) {

View File

@ -872,11 +872,11 @@ Alert {
.statusMessageStyle {
fontSize: 12;
paddingTop: 0;
}
.statusTimeStyle {
fontSize: 10;
paddingTop: 0;
}
.statusTimeStyle {
fontSize: 10;
paddingTop: 0;
}
PollChoicesModal {
@ -891,4 +891,21 @@ PollChoicesModal {
textRollOverColor: #000000;
textSelectedColor: #000000;
fontFamily: Arial;
}
}
EmojiGrid {
backgroundColor: #ffffff;
horizontalAlign: center;
paddingRight: 10;
paddingTop: 10;
}
.emojiGridTile {
paddingBottom: 10;
paddingLeft: 10;
paddingRight: 4;
paddingTop: 4;
verticalGap: 6;
horizontalGap: 6;
}

View File

@ -130,9 +130,8 @@ bbb.users.settings.webcamSettings = Webcam Settings
bbb.users.settings.muteAll = Mute All Users
bbb.users.settings.muteAllExcept = Mute All Users Except Presenter
bbb.users.settings.unmuteAll = Unmute All Users
bbb.users.settings.lowerAllHands = Lower All Hands
bbb.users.raiseHandBtn.toolTip = Raise Hand
bbb.users.raiseHandBtn.toolTip2 = Lower Hand
bbb.users.settings.resetAllStatuses = Resets All Statuses
bbb.users.emojiStatusBtn.toolTip = Update my emoji status
bbb.users.roomMuted.text = Viewers Muted
bbb.users.roomLocked.text = Viewers Locked
bbb.users.pushToTalk.toolTip = Talk
@ -149,9 +148,14 @@ bbb.users.usersGrid.statusItemRenderer = Status
bbb.users.usersGrid.statusItemRenderer.changePresenter = Click To Make Presenter
bbb.users.usersGrid.statusItemRenderer.presenter = Presenter
bbb.users.usersGrid.statusItemRenderer.moderator = Moderator
bbb.users.usersGrid.statusItemRenderer.lowerHand = Lower Hand
bbb.users.usersGrid.statusItemRenderer.handRaised = Hand Raised
bbb.users.usersGrid.statusItemRenderer.raiseHand = Hand Raised
bbb.users.usersGrid.statusItemRenderer.happy = Happy
bbb.users.usersGrid.statusItemRenderer.smile = Smiling
bbb.users.usersGrid.statusItemRenderer.unhappy = Unhappy
bbb.users.usersGrid.statusItemRenderer.confused = Confused
bbb.users.usersGrid.statusItemRenderer.viewer = Viewer
bbb.users.usersGrid.statusItemRenderer.streamIcon.toolTip = Sharing webcam.
bbb.users.usersGrid.statusItemRenderer.presIcon.toolTip = Is Presenter.
bbb.users.usersGrid.mediaItemRenderer = Media
bbb.users.usersGrid.mediaItemRenderer.talking = Talking
bbb.users.usersGrid.mediaItemRenderer.webcam = Sharing Webcam
@ -165,6 +169,12 @@ bbb.users.usersGrid.mediaItemRenderer.webcam = Webcam shared
bbb.users.usersGrid.mediaItemRenderer.micOff = Microphone off
bbb.users.usersGrid.mediaItemRenderer.micOn = Microphone on
bbb.users.usersGrid.mediaItemRenderer.noAudio = Not in audio conference
bbb.users.emojiStatus.remove = Remove
bbb.users.emojiStatus.raiseHand = Raise hand
bbb.users.emojiStatus.happy = Happy
bbb.users.emojiStatus.smile = Smile
bbb.users.emojiStatus.unhappy = Unhappy
bbb.users.emojiStatus.confused = Confused
bbb.presentation.title = Presentation
bbb.presentation.titleWithPres = Presentation: {0}
bbb.presentation.quickLink.label = Presentation Window

View File

@ -35,7 +35,7 @@
<module name="UsersModule" url="http://HOST/client/UsersModule.swf?v=VERSION"
uri="rtmp://HOST/bigbluebutton"
allowKickUser="true"
enableRaiseHand="true"
enableEmojiStatus="true"
enableSettingsButton="true"
baseTabIndex="301"
/>

View File

@ -225,8 +225,8 @@ var getMeetingID = function() {
});
}
var raiseHand = function(raiseHand) {
BBB.raiseHand(raiseHand);
var emojiStatus = function(emojiStatus) {
BBB.emojiStatus(emojiStatus);
}
var muteMe = function() {

View File

@ -77,14 +77,14 @@
* Raise user's hand.
*
* Param:
* raiseHand - [true/false]
* emojiStatus - [string]
*
*/
BBB.raiseHand = function(raiseHand) {
BBB.emojiStatus = function(emojiStatus) {
var swfObj = getSwfObj();
if (swfObj) {
console.log("Request to raise hand [" + raiseHand + "]");
swfObj.raiseHandRequest(raiseHand);
console.log("Request to change emoji status [" + emojiStatus + "]");
swfObj.emojiStatusRequest(emojiStatus);
}
}

View File

@ -52,9 +52,6 @@ package org.bigbluebutton.common
[Embed(source="assets/images/sound_new.png")]
public var sound_new:Class;
[Embed(source="assets/images/hand_new.png")]
public var hand_new:Class;
[Embed(source="assets/images/moderator.png")]
public var moderator:Class;
@ -145,9 +142,6 @@ package org.bigbluebutton.common
[Embed(source="assets/images/participant-mute.png")]
public var participant_mute:Class;
[Embed(source="assets/images/raisehand.png")]
public var raisehand:Class;
[Embed(source="assets/images/mic_muted.png")]
public var sound_mute:Class;
@ -312,5 +306,20 @@ package org.bigbluebutton.common
[Embed(source="assets/images/presenter_white.png")]
public var presenter_white:Class;
[Embed(source="assets/images/emoji_raiseHand.png")]
public var emoji_raiseHand:Class;
[Embed(source="assets/images/emoji_smile.png")]
public var emoji_smile:Class;
[Embed(source="assets/images/emoji_happy.png")]
public var emoji_happy:Class;
[Embed(source="assets/images/emoji_unhappy.png")]
public var emoji_unhappy:Class;
[Embed(source="assets/images/emoji_confused.png")]
public var emoji_confused:Class;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -1,8 +0,0 @@
package org.bigbluebutton.core.connection.messages
{
public class UserRaisedHandMessage
{
public var userId: String;
public var handRaised: Boolean;
}
}

View File

@ -7,7 +7,7 @@ package org.bigbluebutton.core.model.users
private var _name: String;
private var _externId: String;
private var _role: String;
private var _handRaised: Boolean;
private var _emojiStatus: String;
private var _presenter: Boolean;
private var _hasStream: Boolean;
private var _webcamStream: String;

View File

@ -7,7 +7,7 @@ package org.bigbluebutton.core.model.users
private var _externId: String;
private var _role: String;
private var _presenter: Boolean;
private var _handRaised: Boolean;
private var _emojiStatus: Boolean;
private var _hasStream: Boolean;
private var _webcamStream: Boolean;
private var _voice: VoiceUser;

View File

@ -46,7 +46,7 @@ package org.bigbluebutton.core.services
nu.externId = u.externUserID;
nu.name = u.name;
nu.role = u.role;
nu.handRaised = u.handRaised;
nu.emojiStatus = u.emojiStatus;
nu.presenter = u.presenter;
nu.hasStream = u.hasStream;
nu.webcamStream = u.webcamStream;

View File

@ -6,7 +6,7 @@ package org.bigbluebutton.core.vo
public var externId: String;
public var name: String;
public var role: String;
public var handRaised: Boolean;
public var emojiStatus: String;
public var presenter: Boolean;
public var hasStream: Boolean;
public var webcamStream: String;
@ -20,7 +20,7 @@ package org.bigbluebutton.core.vo
nu.externId = externId;
nu.name = name;
nu.role = role;
nu.handRaised = handRaised;
nu.emojiStatus = emojiStatus;
nu.presenter = presenter;
nu.hasStream = hasStream;
nu.webcamStream = webcamStream;

View File

@ -35,8 +35,8 @@ package org.bigbluebutton.main.api
import org.bigbluebutton.core.managers.UserManager;
import org.bigbluebutton.core.vo.CameraSettingsVO;
import org.bigbluebutton.main.events.BBBEvent;
import org.bigbluebutton.main.model.users.events.EmojiStatusEvent;
import org.bigbluebutton.main.model.users.events.KickUserEvent;
import org.bigbluebutton.main.model.users.events.RaiseHandEvent;
import org.bigbluebutton.main.model.users.events.RoleChangeEvent;
import org.bigbluebutton.modules.deskshare.events.DeskshareAppletLaunchedEvent;
import org.bigbluebutton.modules.phone.events.AudioSelectionWindowEvent;
@ -61,7 +61,7 @@ package org.bigbluebutton.main.api
private function init():void {
if (ExternalInterface.available) {
ExternalInterface.addCallback("raiseHandRequest", handleRaiseHandRequest);
ExternalInterface.addCallback("emojiStatusRequest", handleEmojiStatusRequest);
ExternalInterface.addCallback("ejectUserRequest", handleEjectUserRequest);
ExternalInterface.addCallback("switchPresenterRequest", handleSwitchPresenterRequest);
ExternalInterface.addCallback("getMyUserInfoSync", handleGetMyUserInfoSynch);
@ -138,10 +138,9 @@ package org.bigbluebutton.main.api
}
}
private function handleRaiseHandRequest(handRaised:Boolean):void {
LOGGER.debug("Received raise hand request from JS API [{0}]", [handRaised]);
var e:RaiseHandEvent = new RaiseHandEvent(RaiseHandEvent.RAISE_HAND);
e.raised = handRaised;
private function handleEmojiStatusRequest(emojiStatus:String):void {
LOGGER.debug("Received emoji status request from JS API [{0}]", [emojiStatus]);
var e:EmojiStatusEvent = new EmojiStatusEvent(EmojiStatusEvent.EMOJI_STATUS, emojiStatus);
_dispatcher.dispatchEvent(e);
}

View File

@ -1,389 +1,395 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 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/>.
*
*/
package org.bigbluebutton.main.model.users
{
import com.asfusion.mate.events.Dispatcher;
import org.as3commons.logging.api.ILogger;
import org.as3commons.logging.api.getClassLogger;
import org.bigbluebutton.common.Role;
import org.bigbluebutton.core.events.LockControlEvent;
import org.bigbluebutton.core.events.VoiceConfEvent;
import org.bigbluebutton.core.managers.UserManager;
import org.bigbluebutton.core.vo.LockSettingsVO;
import org.bigbluebutton.main.model.users.events.StreamStartedEvent;
import org.bigbluebutton.modules.videoconf.events.ClosePublishWindowEvent;
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 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/>.
*
*/
package org.bigbluebutton.main.model.users
{
import com.asfusion.mate.events.Dispatcher;
import org.as3commons.logging.api.ILogger;
import org.as3commons.logging.api.getClassLogger;
import org.bigbluebutton.common.Role;
import org.bigbluebutton.core.events.LockControlEvent;
import org.bigbluebutton.core.events.VoiceConfEvent;
import org.bigbluebutton.core.managers.UserManager;
import org.bigbluebutton.core.vo.LockSettingsVO;
import org.bigbluebutton.main.model.users.events.StreamStartedEvent;
import org.bigbluebutton.modules.videoconf.events.ClosePublishWindowEvent;
import org.bigbluebutton.util.i18n.ResourceUtil;
public class BBBUser {
private static const LOGGER:ILogger = getClassLogger(BBBUser);
public static const MODERATOR:String = "MODERATOR";
public static const VIEWER:String = "VIEWER";
public static const PRESENTER:String = "PRESENTER";
// Flag to tell that user is in the process of leaving the meeting.
public var isLeavingFlag:Boolean = false;
[Bindable] public var me:Boolean = false;
[Bindable] public var userID:String = "UNKNOWN USER";
[Bindable] public var externUserID:String = "UNKNOWN USER";
[Bindable] public var name:String;
[Bindable] public var talking:Boolean = false;
[Bindable] public var phoneUser:Boolean = false;
[Bindable] public var listenOnly:Boolean = false;
[Bindable] public var disableMyCam:Boolean = false;
[Bindable] public var disableMyMic:Boolean = false;
[Bindable] public var disableMyPrivateChat:Boolean = false;
[Bindable] public var disableMyPublicChat:Boolean = false;
[Bindable] public var lockedLayout:Boolean = false;
[Bindable]
public function get hasStream():Boolean {
return streamNames.length > 0;
}
public function set hasStream(s:Boolean):void {
throw new Error("hasStream cannot be set. It is derived directly from streamName");
}
[Bindable] private var _viewingStream:Array = new Array();
[Bindable]
public function get viewingStream():Array {
return _viewingStream;
}
public function set viewingStream(v:Array):void {
throw new Error("Please use the helpers addViewingStream or removeViewingStream to handle viewingStream");
}
public function addViewingStream(streamName:String):Boolean {
LOGGER.debug("Before adding the stream {0}: {1}", [streamName, _viewingStream]);
if (isViewingStream(streamName)) {
return false;
}
_viewingStream.push(streamName);
LOGGER.debug("After adding the stream {0}: {1}", [streamName, _viewingStream]);
return true;
}
public function removeViewingStream(streamName:String):Boolean {
LOGGER.debug("Before removing the stream {0}: {1}", [streamName, _viewingStream]);
if (!isViewingStream(streamName)) {
return false;
}
_viewingStream = _viewingStream.filter(function(item:*, index:int, array:Array):Boolean { return item != streamName; });
LOGGER.debug("After removing the stream {0}: {1}", [streamName, _viewingStream]);
return true;
}
private function isViewingStream(streamName:String):Boolean {
return _viewingStream.some(function(item:*, index:int, array:Array):Boolean { return item == streamName; });
}
public function isViewingAllStreams():Boolean {
return _viewingStream.length == streamNames.length;
}
[Bindable] public var streamNames:Array = new Array();
[Bindable]
public function get streamName():String {
var streams:String = "";
for each(var stream:String in streamNames) {
streams = streams + stream + "|";
}
//Remove last |
streams = streams.slice(0, streams.length-1);
return streams;
}
private function hasThisStream(streamName:String):Boolean {
return streamNames.some(function(item:*, index:int, array:Array):Boolean { return item == streamName; });
}
public function set streamName(streamNames:String):void {
if(streamNames) {
var streamNamesList:Array = streamNames.split("|");
for each(var streamName:String in streamNamesList) {
sharedWebcam(streamName);
}
}
}
private var _presenter:Boolean = false;
[Bindable]
public function get presenter():Boolean {
return _presenter;
}
public function set presenter(p:Boolean):void {
_presenter = p;
verifyUserStatus();
}
public var raiseHandTime:Date;
private var _raiseHand:Boolean = false;
[Bindable]
public function get raiseHand():Boolean {
return _raiseHand;
}
public function set raiseHand(r:Boolean):void {
_raiseHand = r;
raiseHandTime = (r ? new Date() : null);
verifyUserStatus();
}
private var _role:String = Role.VIEWER;
[Bindable]
public function get role():String {
return _role;
}
public function set role(r:String):void {
_role = r;
verifyUserStatus();
}
[Bindable] public var room:String = "";
[Bindable] public var authToken:String = "";
[Bindable] public var selected:Boolean = false;
private var _voiceMuted:Boolean = false;
[Bindable]
public function get voiceMuted():Boolean {
return _voiceMuted;
}
public function set voiceMuted(v:Boolean):void {
_voiceMuted = v;
verifyMedia();
}
private var _voiceJoined:Boolean = false;
[Bindable]
public function get voiceJoined():Boolean {
return _voiceJoined;
}
public function set voiceJoined(v:Boolean):void {
_voiceJoined = v;
verifyMedia();
}
[Bindable] public var userLocked:Boolean = false;
[Bindable] public var status:String = "";
[Bindable] public var customdata:Object = {};
/*
* This variable is for accessibility for the Users Window. It can't be manually set
* and only changes when one of the relevant status variables changes. Use the verifyUserStatus
* method to update the value.
* Chad
*/
private var _userStatus:String = "";
[Bindable]
public function get userStatus():String {
return _userStatus;
}
private function set userStatus(s:String):void {}
private function verifyUserStatus():void {
if (presenter)
_userStatus = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.presenter');
else if (role == Role.MODERATOR)
_userStatus = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.moderator');
else if (raiseHand)
_userStatus = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.handRaised');
else
_userStatus = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.viewer');
}
/*
* This variable is for accessibility for the Users Window. It can't be manually set
* and only changes when one of the relevant media variables changes. Use the verifyMedia
* method to update the value.
* Chad
*/
private var _media:String = "";
[Bindable]
public function get media():String {
return _media;
}
private function set media(m:String):void {}
private function verifyMedia():void {
_media = (hasStream ? ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.webcam') + " " : "") +
(!voiceJoined ? ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.noAudio') :
(voiceMuted ? ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.micOff') :
ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.micOn')));
}
private var _status:StatusCollection = new StatusCollection();
public function buildStatus():void{
var showingWebcam:String = "";
var isPresenter:String = "";
var handRaised:String = "";
if (hasStream)
showingWebcam = ResourceUtil.getInstance().getString('bbb.viewers.viewersGrid.statusItemRenderer.streamIcon.toolTip');
if (presenter)
isPresenter = ResourceUtil.getInstance().getString('bbb.viewers.viewersGrid.statusItemRenderer.presIcon.toolTip');
if (raiseHand)
handRaised = ResourceUtil.getInstance().getString('bbb.viewers.viewersGrid.statusItemRenderer.raiseHand.toolTip');
status = showingWebcam + isPresenter + handRaised;
}
public function addStatus(status:Status):void {
_status.addStatus(status);
}
public function userRaiseHand(raised: Boolean):void {
raiseHand = raised;
if (me) {
UserManager.getInstance().getConference().isMyHandRaised = raised;
}
buildStatus();
}
public function sharedWebcam(stream: String):void {
if(stream && stream != "" && !hasThisStream(stream)) {
streamNames.push(stream);
sendStreamStartedEvent(stream);
}
buildStatus();
verifyMedia();
}
public function unsharedWebcam(stream: String):void {
streamNames = streamNames.filter(function(item:*, index:int, array:Array):Boolean { return item != stream });
buildStatus();
verifyMedia();
}
public function presenterStatusChanged(presenter: Boolean):void {
this.presenter = presenter;
buildStatus();
}
public function lockStatusChanged(locked: Boolean):void {
LOGGER.debug("lockStatusChanged -> {0}", [locked]);
userLocked = locked;
applyLockSettings();
buildStatus();
}
public function changeStatus(status:Status):void {
LOGGER.debug("changeStatus -> {0}", [status.name]);
//_status.changeStatus(status);
if (status.name == "presenter") {
presenter = (status.value.toString().toUpperCase() == "TRUE") ? true : false;
//As the lock settings are now not applied to presenters, when the presenter flag is changed, we need to apply the lock settings
applyLockSettings();
}
switch (status.name) {
case "presenter":
presenter = (status.value.toString().toUpperCase() == "TRUE") ? true : false;
break;
case "hasStream":
var streamInfo:Array = String(status.value).split(/,/);
/**
* Cannot use this statement as new Boolean(expression)
* return true if the expression is a non-empty string not
* when the string equals "true". See Boolean class def.
*
* hasStream = new Boolean(String(streamInfo[0]));
*/
var streamNameInfo:Array = String(streamInfo[1]).split(/=/);
streamName = streamNameInfo[1];
break;
case "raiseHand":
raiseHand = (status.value.toString().toUpperCase() == "TRUE") ? true : false;
if (me) {
UserManager.getInstance().getConference().isMyHandRaised = status.value;
}
break;
}
buildStatus();
}
public function removeStatus(name:String):void {
_status.removeStatus(name);
}
public function getStatus(name:String):Status {
return _status.getStatus(name);
}
public static function copy(user:BBBUser):BBBUser {
var n:BBBUser = new BBBUser();
n.authToken = user.authToken;
n.me = user.me;
n.userID = user.userID;
n.externUserID = user.externUserID;
n.name = user.name;
n._viewingStream = user._viewingStream;
n.streamNames = user.streamNames;
n.presenter = user.presenter;
n.raiseHand = user.raiseHand;
n.role = user.role;
n.room = user.room;
n.customdata = user.customdata;
n.media = user.media;
n.phoneUser = user.phoneUser;
n.talking = user.talking;
n.userStatus = user.userStatus;
n.voiceJoined = user.voiceJoined;
n.userLocked = user.userLocked;
n.voiceMuted = user.voiceMuted;
n.disableMyCam = user.disableMyCam;
n.disableMyMic = user.disableMyMic;
n.disableMyPrivateChat = user.disableMyPrivateChat;
n.disableMyPublicChat = user.disableMyPublicChat;
return n;
}
private function sendStreamStartedEvent(stream: String):void{
var dispatcher:Dispatcher = new Dispatcher();
dispatcher.dispatchEvent(new StreamStartedEvent(userID, name, stream));
}
public function applyLockSettings():void {
var lockSettings:LockSettingsVO = UserManager.getInstance().getConference().getLockSettings();
var lockAppliesToMe:Boolean = me && role != MODERATOR && !presenter && userLocked;
disableMyCam = lockAppliesToMe && lockSettings.getDisableCam();
disableMyMic = lockAppliesToMe && lockSettings.getDisableMic();
disableMyPrivateChat = lockAppliesToMe && lockSettings.getDisablePrivateChat();
disableMyPublicChat = lockAppliesToMe && lockSettings.getDisablePublicChat();
lockedLayout = lockAppliesToMe && lockSettings.getLockedLayout();
var dispatcher:Dispatcher = new Dispatcher();
dispatcher.dispatchEvent(new LockControlEvent(LockControlEvent.CHANGED_LOCK_SETTINGS));
if (lockAppliesToMe) {
//If it's sharing webcam, stop it
if (disableMyCam && hasStream){
dispatcher.dispatchEvent(new ClosePublishWindowEvent());
}
//If it's sharing microphone, mute it
if (disableMyMic && !UserManager.getInstance().getConference().isMyVoiceMuted()) {
var e:VoiceConfEvent = new VoiceConfEvent(VoiceConfEvent.MUTE_USER);
e.userid = UserManager.getInstance().getConference().getMyUserId();
e.mute = true;
dispatcher.dispatchEvent(e);
}
}
}
}
}
public class BBBUser {
private static const LOGGER:ILogger = getClassLogger(BBBUser);
public static const MODERATOR:String = "MODERATOR";
public static const VIEWER:String = "VIEWER";
public static const PRESENTER:String = "PRESENTER";
// Flag to tell that user is in the process of leaving the meeting.
public var isLeavingFlag:Boolean = false;
[Bindable] public var me:Boolean = false;
[Bindable] public var userID:String = "UNKNOWN USER";
[Bindable] public var externUserID:String = "UNKNOWN USER";
[Bindable] public var name:String;
[Bindable] public var talking:Boolean = false;
[Bindable] public var phoneUser:Boolean = false;
[Bindable] public var listenOnly:Boolean = false;
[Bindable] public var disableMyCam:Boolean = false;
[Bindable] public var disableMyMic:Boolean = false;
[Bindable] public var disableMyPrivateChat:Boolean = false;
[Bindable] public var disableMyPublicChat:Boolean = false;
[Bindable] public var lockedLayout:Boolean = false;
[Bindable]
public function get hasStream():Boolean {
return streamNames.length > 0;
}
public function set hasStream(s:Boolean):void {
throw new Error("hasStream cannot be set. It is derived directly from streamName");
}
[Bindable] private var _viewingStream:Array = new Array();
[Bindable]
public function get viewingStream():Array {
return _viewingStream;
}
public function set viewingStream(v:Array):void {
throw new Error("Please use the helpers addViewingStream or removeViewingStream to handle viewingStream");
}
public function addViewingStream(streamName:String):Boolean {
LOGGER.debug("Before adding the stream {0}: {1}", [streamName, _viewingStream]);
if (isViewingStream(streamName)) {
return false;
}
_viewingStream.push(streamName);
LOGGER.debug("After adding the stream {0}: {1}", [streamName, _viewingStream]);
return true;
}
public function removeViewingStream(streamName:String):Boolean {
LOGGER.debug("Before removing the stream {0}: {1}", [streamName, _viewingStream]);
if (!isViewingStream(streamName)) {
return false;
}
_viewingStream = _viewingStream.filter(function(item:*, index:int, array:Array):Boolean { return item != streamName; });
LOGGER.debug("After removing the stream {0}: {1}", [streamName, _viewingStream]);
return true;
}
private function isViewingStream(streamName:String):Boolean {
return _viewingStream.some(function(item:*, index:int, array:Array):Boolean { return item == streamName; });
}
public function isViewingAllStreams():Boolean {
return _viewingStream.length == streamNames.length;
}
[Bindable] public var streamNames:Array = new Array();
[Bindable]
public function get streamName():String {
var streams:String = "";
for each(var stream:String in streamNames) {
streams = streams + stream + "|";
}
//Remove last |
streams = streams.slice(0, streams.length-1);
return streams;
}
private function hasThisStream(streamName:String):Boolean {
return streamNames.some(function(item:*, index:int, array:Array):Boolean { return item == streamName; });
}
public function set streamName(streamNames:String):void {
if(streamNames) {
var streamNamesList:Array = streamNames.split("|");
for each(var streamName:String in streamNamesList) {
sharedWebcam(streamName);
}
}
}
private var _presenter:Boolean = false;
[Bindable]
public function get presenter():Boolean {
return _presenter;
}
public function set presenter(p:Boolean):void {
_presenter = p;
verifyUserStatus();
}
public var emojiStatusTime:Date;
private var _emojiStatus:String = "none";
[Bindable]
public function get emojiStatus():String {
return _emojiStatus;
}
public function set emojiStatus(r:String):void {
_emojiStatus = r;
emojiStatusTime = (r ? new Date() : null);
verifyUserStatus();
}
public function get hasEmojiStatus():Boolean {
return _emojiStatus != "none" && _emojiStatus != "null";
}
private var _role:String = Role.VIEWER;
[Bindable]
public function get role():String {
return _role;
}
public function set role(r:String):void {
_role = r;
verifyUserStatus();
}
[Bindable] public var room:String = "";
[Bindable] public var authToken:String = "";
[Bindable] public var selected:Boolean = false;
private var _voiceMuted:Boolean = false;
[Bindable]
public function get voiceMuted():Boolean {
return _voiceMuted;
}
public function set voiceMuted(v:Boolean):void {
_voiceMuted = v;
verifyMedia();
}
private var _voiceJoined:Boolean = false;
[Bindable]
public function get voiceJoined():Boolean {
return _voiceJoined;
}
public function set voiceJoined(v:Boolean):void {
_voiceJoined = v;
verifyMedia();
}
[Bindable] public var userLocked:Boolean = false;
[Bindable] public var status:String = "";
[Bindable] public var customdata:Object = {};
/*
* This variable is for accessibility for the Users Window. It can't be manually set
* and only changes when one of the relevant status variables changes. Use the verifyUserStatus
* method to update the value.
* Chad
*/
private var _userStatus:String = "";
[Bindable]
public function get userStatus():String {
return _userStatus;
}
private function set userStatus(s:String):void {}
private function verifyUserStatus():void {
if (presenter)
_userStatus = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.presenter');
else if (role == Role.MODERATOR)
_userStatus = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.moderator');
else if (hasEmojiStatus)
_userStatus = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.' + _emojiStatus);
else
_userStatus = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.viewer');
}
/*
* This variable is for accessibility for the Users Window. It can't be manually set
* and only changes when one of the relevant media variables changes. Use the verifyMedia
* method to update the value.
* Chad
*/
private var _media:String = "";
[Bindable]
public function get media():String {
return _media;
}
private function set media(m:String):void {}
private function verifyMedia():void {
_media = (hasStream ? ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.webcam') + " " : "") +
(!voiceJoined ? ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.noAudio') :
(voiceMuted ? ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.micOff') :
ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.micOn')));
}
private var _status:StatusCollection = new StatusCollection();
public function buildStatus():void {
var showingWebcam:String="";
var isPresenter:String="";
var hasEmoji:String = "";
if (hasStream)
showingWebcam=ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.streamIcon.toolTip');
if (presenter)
isPresenter=ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.presIcon.toolTip');
if (hasEmojiStatus)
hasEmoji = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.'+ emojiStatus +'.toolTip');
status = showingWebcam + isPresenter + hasEmoji;
}
public function addStatus(status:Status):void {
_status.addStatus(status);
}
public function userEmojiStatus(emoji: String):void {
emojiStatus = emoji;
if (me) {
UserManager.getInstance().getConference().myEmojiStatus = emoji;
}
buildStatus();
}
public function sharedWebcam(stream: String):void {
if(stream && stream != "" && !hasThisStream(stream)) {
streamNames.push(stream);
sendStreamStartedEvent(stream);
}
buildStatus();
verifyMedia();
}
public function unsharedWebcam(stream: String):void {
streamNames = streamNames.filter(function(item:*, index:int, array:Array):Boolean { return item != stream });
buildStatus();
verifyMedia();
}
public function presenterStatusChanged(presenter: Boolean):void {
this.presenter = presenter;
buildStatus();
}
public function lockStatusChanged(locked: Boolean):void {
LOGGER.debug("lockStatusChanged -> {0}", [locked]);
userLocked = locked;
applyLockSettings();
buildStatus();
}
public function changeStatus(status:Status):void {
LOGGER.debug("changeStatus -> {0}", [status.name]);
//_status.changeStatus(status);
if (status.name == "presenter") {
presenter=(status.value.toString().toUpperCase() == "TRUE") ? true : false;
//As the lock settings are now not applied to presenters, when the presenter flag is changed, we need to apply the lock settings
applyLockSettings();
}
switch (status.name) {
case "presenter":
presenter=(status.value.toString().toUpperCase() == "TRUE") ? true : false;
break;
case "hasStream":
var streamInfo:Array=String(status.value).split(/,/);
/**
* Cannot use this statement as new Boolean(expression)
* return true if the expression is a non-empty string not
* when the string equals "true". See Boolean class def.
*
* hasStream = new Boolean(String(streamInfo[0]));
*/
var streamNameInfo:Array=String(streamInfo[1]).split(/=/);
streamName=streamNameInfo[1];
break;
// @FIXME : check the coming status from the server
case "emojiStatus":
emojiStatus = status.value.toString();
if (me) {
UserManager.getInstance().getConference().myEmojiStatus=status.value.toString();
}
break;
}
buildStatus();
}
public function removeStatus(name:String):void {
_status.removeStatus(name);
}
public function getStatus(name:String):Status {
return _status.getStatus(name);
}
public static function copy(user:BBBUser):BBBUser {
var n:BBBUser = new BBBUser();
n.authToken = user.authToken;
n.me = user.me;
n.userID = user.userID;
n.externUserID = user.externUserID;
n.name = user.name;
n._viewingStream = user._viewingStream;
n.streamNames = user.streamNames;
n.presenter = user.presenter;
n.emojiStatus = user.emojiStatus;
n.role = user.role;
n.room = user.room;
n.customdata = user.customdata;
n.media = user.media;
n.phoneUser = user.phoneUser;
n.talking = user.talking;
n.userStatus = user.userStatus;
n.voiceJoined = user.voiceJoined;
n.userLocked = user.userLocked;
n.voiceMuted = user.voiceMuted;
n.disableMyCam = user.disableMyCam;
n.disableMyMic = user.disableMyMic;
n.disableMyPrivateChat = user.disableMyPrivateChat;
n.disableMyPublicChat = user.disableMyPublicChat;
return n;
}
private function sendStreamStartedEvent(stream: String):void{
var dispatcher:Dispatcher = new Dispatcher();
dispatcher.dispatchEvent(new StreamStartedEvent(userID, name, stream));
}
public function applyLockSettings():void {
var lockSettings:LockSettingsVO = UserManager.getInstance().getConference().getLockSettings();
var lockAppliesToMe:Boolean = me && role != MODERATOR && !presenter && userLocked;
disableMyCam = lockAppliesToMe && lockSettings.getDisableCam();
disableMyMic = lockAppliesToMe && lockSettings.getDisableMic();
disableMyPrivateChat = lockAppliesToMe && lockSettings.getDisablePrivateChat();
disableMyPublicChat = lockAppliesToMe && lockSettings.getDisablePublicChat();
lockedLayout = lockAppliesToMe && lockSettings.getLockedLayout();
var dispatcher:Dispatcher = new Dispatcher();
dispatcher.dispatchEvent(new LockControlEvent(LockControlEvent.CHANGED_LOCK_SETTINGS));
if (lockAppliesToMe) {
//If it's sharing webcam, stop it
if (disableMyCam && hasStream){
dispatcher.dispatchEvent(new ClosePublishWindowEvent());
}
//If it's sharing microphone, mute it
if (disableMyMic && !UserManager.getInstance().getConference().isMyVoiceMuted()) {
var e:VoiceConfEvent = new VoiceConfEvent(VoiceConfEvent.MUTE_USER);
e.userid = UserManager.getInstance().getConference().getMyUserId();
e.mute = true;
dispatcher.dispatchEvent(e);
}
}
}
}
}

View File

@ -66,27 +66,27 @@ package org.bigbluebutton.main.model.users {
else if (b.presenter)
return 1;*/
if (a.role == Role.MODERATOR && b.role == Role.MODERATOR) {
if (a.raiseHand && b.raiseHand) {
if (a.raiseHandTime < b.raiseHandTime)
if (a.hasEmojiStatus && b.hasEmojiStatus) {
if (a.emojiStatusTime < b.emojiStatusTime)
return -1;
else
return 1;
} else if (a.raiseHand)
} else if (a.hasEmojiStatus)
return -1;
else if (b.raiseHand)
else if (b.hasEmojiStatus)
return 1;
} else if (a.role == Role.MODERATOR)
return -1;
else if (b.role == Role.MODERATOR)
return 1;
else if (a.raiseHand && b.raiseHand) {
if (a.raiseHandTime < b.raiseHandTime)
else if (a.hasEmojiStatus && b.hasEmojiStatus) {
if (a.emojiStatusTime < b.emojiStatusTime)
return -1;
else
return 1;
} else if (a.raiseHand)
} else if (a.hasEmojiStatus)
return -1;
else if (b.raiseHand)
else if (b.hasEmojiStatus)
return 1;
else if (!a.phoneUser && !b.phoneUser) {
@ -271,12 +271,12 @@ package org.bigbluebutton.main.model.users {
}
[Bindable]
public function get isMyHandRaised():Boolean {
return me.raiseHand;
public function get myEmojiStatus():String {
return me.emojiStatus;
}
public function set isMyHandRaised(raiseHand:Boolean):void {
me.raiseHand = raiseHand;
public function set myEmojiStatus(emoji:String):void {
me.emojiStatus = emoji;
}
public function amIThisUser(userID:String):Boolean {
@ -379,10 +379,10 @@ package org.bigbluebutton.main.model.users {
users.removeAll();
}
public function raiseHand(userId: String, raised: Boolean):void {
public function emojiStatus(userId: String, emoji: String):void {
var aUser:BBBUser = getUser(userId);
if (aUser != null) {
aUser.userRaiseHand(raised)
aUser.userEmojiStatus(emoji)
}
users.refresh();

View File

@ -41,9 +41,8 @@ package org.bigbluebutton.main.model.users
import org.bigbluebutton.main.model.users.events.BroadcastStartedEvent;
import org.bigbluebutton.main.model.users.events.BroadcastStoppedEvent;
import org.bigbluebutton.main.model.users.events.ConferenceCreatedEvent;
import org.bigbluebutton.main.model.users.events.EmojiStatusEvent;
import org.bigbluebutton.main.model.users.events.KickUserEvent;
import org.bigbluebutton.main.model.users.events.LowerHandEvent;
import org.bigbluebutton.main.model.users.events.RaiseHandEvent;
import org.bigbluebutton.main.model.users.events.RoleChangeEvent;
import org.bigbluebutton.main.model.users.events.UsersConnectionEvent;
import org.bigbluebutton.modules.users.services.MessageReceiver;
@ -202,12 +201,9 @@ package org.bigbluebutton.main.model.users
sender.removeStream(e.userid, e.stream);
}
public function raiseHand(e:RaiseHandEvent):void {
sender.raiseHand(UserManager.getInstance().getConference().getMyUserId(), e.raised);
}
public function lowerHand(e:LowerHandEvent):void {
if (this.isModerator()) sender.raiseHand(e.userid, false);
public function emojiStatus(e:EmojiStatusEvent):void {
// If the userId is not set in the event then the event has been dispatched for the current user
sender.emojiStatus(e.userId != ""? e.userId : UserManager.getInstance().getConference().getMyUserId(), e.status);
}
public function kickUser(e:KickUserEvent):void{

View File

@ -0,0 +1,44 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 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/>.
*
*/
package org.bigbluebutton.main.model.users.events {
import flash.events.Event;
public class EmojiStatusEvent extends Event {
public static const EMOJI_STATUS:String = "EMOJI_STATUS_EVENT";
private var _status:String;
private var _userId:String;
public function EmojiStatusEvent(type:String, emoji:String, userId:String = "") {
super(type, true, false);
_status = emoji;
_userId = userId;
}
public function get status():String {
return _status;
}
public function get userId():String {
return _userId;
}
}
}

View File

@ -1,36 +0,0 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 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/>.
*
*/
package org.bigbluebutton.main.model.users.events
{
import flash.events.Event;
public class LowerHandEvent extends Event
{
public static const LOWER_HAND_EVENT:String = "LOWER_HAND_EVENT";
public var userid:String;
public function LowerHandEvent(userid:String)
{
super(LOWER_HAND_EVENT,true);
this.userid = userid;
}
}
}

View File

@ -1,34 +0,0 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 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/>.
*
*/
package org.bigbluebutton.main.model.users.events
{
import flash.events.Event;
public class RaiseHandEvent extends Event
{
public static const RAISE_HAND:String = "RAISE_HAND_EVENT";
public var raised:Boolean;
public function RaiseHandEvent(type:String)
{
super(type, true, false);
}
}
}

View File

@ -23,20 +23,20 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<EventMap xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="http://mate.asfusion.com/" >
<mx:Script>
<![CDATA[
import mx.events.FlexEvent;
import org.bigbluebutton.core.events.LockControlEvent;
import org.bigbluebutton.core.events.VoiceConfEvent;
import org.bigbluebutton.main.events.BBBEvent;
import org.bigbluebutton.main.events.LogoutEvent;
import org.bigbluebutton.main.events.UserServicesEvent;
import org.bigbluebutton.main.model.users.UserService;
import org.bigbluebutton.main.model.users.events.BroadcastStartedEvent;
import org.bigbluebutton.main.model.users.events.BroadcastStoppedEvent;
import org.bigbluebutton.main.model.users.events.KickUserEvent;
import org.bigbluebutton.main.model.users.events.LowerHandEvent;
import org.bigbluebutton.main.model.users.events.RaiseHandEvent;
import org.bigbluebutton.main.model.users.events.RoleChangeEvent;
import org.bigbluebutton.main.model.users.events.UsersConnectionEvent;
import mx.events.FlexEvent;
import org.bigbluebutton.core.events.LockControlEvent;
import org.bigbluebutton.core.events.VoiceConfEvent;
import org.bigbluebutton.main.events.BBBEvent;
import org.bigbluebutton.main.events.LogoutEvent;
import org.bigbluebutton.main.events.UserServicesEvent;
import org.bigbluebutton.main.model.users.UserService;
import org.bigbluebutton.main.model.users.events.BroadcastStartedEvent;
import org.bigbluebutton.main.model.users.events.BroadcastStoppedEvent;
import org.bigbluebutton.main.model.users.events.EmojiStatusEvent;
import org.bigbluebutton.main.model.users.events.KickUserEvent;
import org.bigbluebutton.main.model.users.events.RoleChangeEvent;
import org.bigbluebutton.main.model.users.events.UsersConnectionEvent;
]]>
</mx:Script>
@ -62,12 +62,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
</EventHandlers>
<!-- Viewers Stuff -->
<EventHandlers type="{RaiseHandEvent.RAISE_HAND}" >
<MethodInvoker generator="{UserService}" method="raiseHand" arguments="{event}" />
</EventHandlers>
<EventHandlers type="{LowerHandEvent.LOWER_HAND_EVENT}" >
<MethodInvoker generator="{UserService}" method="lowerHand" arguments="{event}" />
<EventHandlers type="{EmojiStatusEvent.EMOJI_STATUS}" >
<MethodInvoker generator="{UserService}" method="emojiStatus" arguments="{event}" />
</EventHandlers>
<EventHandlers type="{BroadcastStartedEvent.BROADCAST_STARTED_EVENT}" >

View File

@ -35,7 +35,7 @@ package org.bigbluebutton.modules.users.model
public var allowKickUser:Boolean = true;
[Bindable]
public var enableRaiseHand:Boolean = true;
public var enableEmojiStatus:Boolean = true;
[Bindable]
public var enableSettingsButton:Boolean = true;
@ -54,8 +54,8 @@ package org.bigbluebutton.modules.users.model
if (vxml.@allowKickUser != undefined) {
allowKickUser = (vxml.@allowKickUser.toString().toUpperCase() == "TRUE") ? true : false;
}
if (vxml.@enableRaiseHand != undefined) {
enableRaiseHand = (vxml.@enableRaiseHand.toString().toUpperCase() == "TRUE") ? true : false;
if (vxml.@enableEmojiStatus != undefined) {
enableEmojiStatus = (vxml.@enableEmojiStatus.toString().toUpperCase() == "TRUE") ? true : false;
}
if (vxml.@enableSettingsButton != undefined) {
enableSettingsButton = (vxml.@enableSettingsButton.toString().toUpperCase() == "TRUE") ? true : false;

View File

@ -102,11 +102,8 @@ package org.bigbluebutton.modules.users.services
case "voiceUserTalking":
handleVoiceUserTalking(message);
break;
case "userRaisedHand":
handleUserRaisedHand(message);
break;
case "userLoweredHand":
handleUserLoweredHand(message);
case "userEmojiStatus":
handleEmojiStatusHand(message);
break;
case "userSharedWebcam":
handleUserSharedWebcam(message);
@ -503,16 +500,10 @@ package org.bigbluebutton.modules.users.services
dispatcher.dispatchEvent(roleEvent);
}
private function handleUserRaisedHand(msg: Object): void {
LOGGER.debug("*** handleUserRaisedHand {0} **** \n", [msg.msg]);
private function handleEmojiStatusHand(msg: Object): void {
LOGGER.debug("*** handleEmojiStatusHand {0} **** \n", [msg.msg]);
var map:Object = JSON.parse(msg.msg);
UserManager.getInstance().getConference().raiseHand(map.userId, true);
}
private function handleUserLoweredHand(msg: Object):void {
LOGGER.debug("*** handleUserLoweredHand {0} **** \n", [msg.msg]);
var map:Object = JSON.parse(msg.msg);
UserManager.getInstance().getConference().raiseHand(map.userId, false);
UserManager.getInstance().getConference().emojiStatus(map.userId, map.emojiStatus);
}
private function handleUserSharedWebcam(msg: Object):void {
@ -580,7 +571,7 @@ package org.bigbluebutton.modules.users.services
}
UserManager.getInstance().getConference().presenterStatusChanged(user.userID, joinedUser.presenter);
UserManager.getInstance().getConference().raiseHand(user.userID, joinedUser.raiseHand);
UserManager.getInstance().getConference().emojiStatus(user.userID, joinedUser.emojiStatus);
var joinEvent:UserJoinedEvent = new UserJoinedEvent(UserJoinedEvent.JOINED);
joinEvent.userID = user.userID;

View File

@ -74,34 +74,24 @@ package org.bigbluebutton.modules.users.services
message
);
}
public function raiseHand(userID:String, raise:Boolean):void {
var _nc:ConnectionManager = BBB.initConnectionManager();
if (raise) {
_nc.sendMessage("participants.userRaiseHand",
function(result:String):void { // On successful result
LOGGER.debug(result);
},
function(status:String):void { // status - On error occurred
LOGGER.error(status);
}
);
} else {
var message:Object = new Object();
message["userId"] = userID;
message["loweredBy"] = userID;
_nc.sendMessage("participants.lowerHand",
function(result:String):void { // On successful result
LOGGER.debug(result);
},
function(status:String):void { // status - On error occurred
LOGGER.error(status);
},
message
);
}
}
public function emojiStatus(userID:String, emoji:String):void
{
var message:Object = new Object();
message["emojiStatus"] = emoji;
message["userId"] = userID;
var _nc:ConnectionManager=BBB.initConnectionManager();
_nc.sendMessage("participants.userEmojiStatus", function(result:String):void
{ // On successful result
LOGGER.debug(result);
}, function(status:String):void
{ // status - On error occurred
LOGGER.error(status);
},
message
);
}
public function addStream(userID:String, streamName:String):void {
var _nc:ConnectionManager = BBB.initConnectionManager();

View File

@ -0,0 +1,105 @@
/**
* 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/>.
*
*/
package org.bigbluebutton.modules.users.views {
import com.asfusion.mate.events.Dispatcher;
import flash.events.MouseEvent;
import mx.containers.Tile;
import mx.containers.VBox;
import mx.controls.Button;
import mx.core.ScrollPolicy;
import mx.events.FlexMouseEvent;
import mx.managers.PopUpManager;
import org.bigbluebutton.common.Images;
import org.bigbluebutton.core.managers.UserManager;
import org.bigbluebutton.main.model.users.events.EmojiStatusEvent;
import org.bigbluebutton.util.i18n.ResourceUtil;
public class EmojiGrid extends VBox {
private const EMOJIS:Array = ["raiseHand", "smile", "happy", "unhappy", "confused"];
private var dispatcher:Dispatcher;
private var images:Images;
public function EmojiGrid() {
dispatcher = new Dispatcher();
images = new Images();
addEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE, mouseDownOutsideHandler, false, 0, true);
this.horizontalScrollPolicy = ScrollPolicy.OFF;
this.verticalScrollPolicy = ScrollPolicy.OFF;
width = 140;
minHeight = 80;
drawEmoji();
if (UserManager.getInstance().getConference().myEmojiStatus != "none") {
addRemoveEmoji();
}
}
private function drawEmoji():void {
var tile:Tile = new Tile();
tile.width = 140;
tile.styleName = "emojiGridTile";
tile.horizontalScrollPolicy = ScrollPolicy.OFF;
this.verticalScrollPolicy = ScrollPolicy.OFF;
for each (var emoji:String in EMOJIS) {
var button:Button = new Button();
button.id = "btn" + emoji;
button.width = 24;
button.height = 24;
button.toggle = true;
button.setStyle("icon", images["emoji_" + emoji]);
button.selected = (UserManager.getInstance().getConference().myEmojiStatus == emoji);
button.enabled = !button.selected;
button.toolTip = ResourceUtil.getInstance().getString('bbb.users.emojiStatus.' + emoji);
addEventListener(MouseEvent.CLICK, buttonMouseEventHandler);
tile.addChild(button);
}
this.addChild(tile);
}
private function addRemoveEmoji():void {
var button:Button = new Button();
button.id = "btnnone";
button.height = 64;
button.height = 24;
button.label = ResourceUtil.getInstance().getString('bbb.users.emojiStatus.remove');
button.addEventListener(MouseEvent.CLICK, buttonMouseEventHandler);
this.addChild(button);
}
protected function buttonMouseEventHandler(event:MouseEvent):void {
var emoji:String = String(event.target.id).replace("btn", "");
var e:EmojiStatusEvent = new EmojiStatusEvent(EmojiStatusEvent.EMOJI_STATUS, emoji);
dispatcher.dispatchEvent(e);
hide();
}
protected function mouseDownOutsideHandler(event:FlexMouseEvent):void {
hide();
}
/**
* Hides the menu
*/
public function hide():void {
PopUpManager.removePopUp(this);
}
}
}

View File

@ -36,12 +36,12 @@
import mx.binding.utils.BindingUtils;
import mx.binding.utils.ChangeWatcher;
import mx.events.FlexEvent;
import org.bigbluebutton.common.events.LocaleChangeEvent;
import org.bigbluebutton.common.Images;
import org.bigbluebutton.common.Role;
import org.bigbluebutton.common.events.LocaleChangeEvent;
import org.bigbluebutton.core.managers.UserManager;
import org.bigbluebutton.main.model.users.events.LowerHandEvent;
import org.bigbluebutton.main.model.users.events.EmojiStatusEvent;
import org.bigbluebutton.main.model.users.events.RoleChangeEvent;
import org.bigbluebutton.modules.users.events.UsersRollEvent;
import org.bigbluebutton.util.i18n.ResourceUtil;
@ -60,16 +60,16 @@
* make sure to delete the bindings yourself or you'll have memory leaks.
* Chad
*/
//BindingUtils.bindSetter(updateButton, data, "presenter");
//BindingUtils.bindSetter(updateButton, data, "raiseHand");
//BindingUtils.bindSetter(updateButtons, data, "presenter");
//BindingUtils.bindSetter(updateButtons, data, "raiseHand");
/* I had to bind to an Image property which is in turn bound through MXML to the data properties.
* This really needs to be changed, but it's the only way I could get it work.
* Chad
*/
BindingUtils.bindSetter(updateButton, presenterInd, "includeInLayout");
BindingUtils.bindSetter(updateButton, moderatorInd, "includeInLayout");
BindingUtils.bindSetter(updateButton, raiseHandInd, "includeInLayout");
BindingUtils.bindSetter(updateButtons, presenterInd, "includeInLayout");
BindingUtils.bindSetter(updateButtons, moderatorInd, "includeInLayout");
BindingUtils.bindSetter(updateButtons, emojiStatusHandInd, "includeInLayout");
// The next two lines should be listening for the same data to change and be updating at the same
// time, but the FlexEvent.DATA_CHANGE wasn't working consistently.
@ -77,77 +77,91 @@
ChangeWatcher.watch(this, "data", dataChangeHandler);
if (data != null) // if data has already been set
updateButton(); //initialize state
updateButtons(); //initialize state
validateNow();
}
private function dataChangeHandler(e:Event):void {
if (data != null) {
updateButton(); //reassess data state on change
updateButtons(); //reassess data state on change
}
}
private function updateButton(unneeded:Object = null):void {
private function updateButtons(unneeded:Object = null):void {
if (data != null) {
if (rolledOver && data.raiseHand) {
roleBtn.setStyle("icon", images.hand_new);
roleBtn.toolTip = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.lowerHand') + " - " + data.raiseHandTime.hours + ":" + data.raiseHandTime.minutes + ":" + data.raiseHandTime.seconds;
roleImg.visible = false;
roleBtn.visible = true;
roleBtn.enabled = true;
} else if (rolledOver && !data.presenter && !data.phoneUser) {
roleBtn.setStyle("icon", images.presenter_new);
roleBtn.toolTip = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.changePresenter');
roleImg.visible = false;
roleBtn.visible = true;
roleBtn.enabled = true;
} else if (data.raiseHand) {
roleImg.source = images.hand_new;
roleImg.toolTip = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.handRaised') + " - " + data.raiseHandTime.hours + ":" + data.raiseHandTime.minutes + ":" + data.raiseHandTime.seconds;
roleImg.visible = true;
roleBtn.visible = false;
roleBtn.enabled = false;
} else if (data.presenter) {
roleImg.source = images.presenter_new;
roleImg.toolTip = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.presenter');
roleImg.visible = true;
roleBtn.visible = false;
roleBtn.enabled = false;
} else if (data.role == Role.MODERATOR) {
roleImg.source = images.moderator;
roleImg.toolTip = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.moderator');
roleImg.visible = true;
roleBtn.visible = false;
roleBtn.enabled = false;
} else {
roleImg.source = null;
roleImg.toolTip = "";
roleImg.visible = true;
roleBtn.visible = false;
roleBtn.enabled = false;
}
updateRoleComponents();
updateEmojiComponents();
}
}
private function updateRoleComponents() : void {
if (rolledOver && !data.presenter && !data.phoneUser) {
roleBtn.setStyle("icon", images.presenter_new);
roleBtn.toolTip = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.changePresenter');
roleImg.visible = false;
roleBtn.visible = true;
roleBtn.enabled = true;
} else if (data.presenter) {
roleImg.source = images.presenter_new;
roleImg.toolTip = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.presenter');
roleImg.visible = true;
roleBtn.visible = false;
roleBtn.enabled = false;
} else if (data.role == Role.MODERATOR) {
roleImg.source = images.moderator;
roleImg.toolTip = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.moderator');
roleImg.visible = true;
roleBtn.visible = false;
roleBtn.enabled = false;
} else {
roleImg.source = null;
roleImg.toolTip = "";
roleImg.visible = true;
roleBtn.visible = false;
roleBtn.enabled = false;
}
}
private function updateEmojiComponents() : void {
if (rolledOver && data.hasEmojiStatus) {
emojiBtn.setStyle("icon", images["emoji_" + data.emojiStatus]);
emojiBtn.toolTip = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.lowerHand') + " - " + data.emojiStatusTime.hours + ":" + data.emojiStatusTime.minutes + ":" + data.emojiStatusTime.seconds;
emojiImg.visible = false;
emojiBtn.visible = true;
emojiBtn.enabled = true;
} else if (data.hasEmojiStatus) {
emojiImg.source = images["emoji_" + data.emojiStatus];
emojiImg.toolTip = ResourceUtil.getInstance().getString('bbb.users.usersGrid.statusItemRenderer.' + data.emojiStatus) + " - " + data.emojiStatusTime.hours + ":" + data.emojiStatusTime.minutes + ":" + data.emojiStatusTime.seconds;
emojiImg.visible = true;
emojiBtn.visible = false;
emojiBtn.enabled = false;
}
else {
emojiImg.source = null;
emojiImg.toolTip = "";
emojiImg.visible = true;
emojiBtn.visible = false;
emojiBtn.enabled = false;
}
}
private function onRollOver(e:UsersRollEvent):void{
if (moderator && (e.userID == data.userID) && !data.phoneUser) {
rolledOver = true;
updateButton();
updateButtons();
}
}
private function onRollOut(e:UsersRollEvent):void{
if (moderator && rolledOver) {
rolledOver = false;
updateButton();
updateButtons();
}
}
private function roleBtnClicked():void {
if (data.raiseHand) {
dispatchEvent(new LowerHandEvent(data.userID));
} else if (!data.presenter) {
if (!data.presenter) {
var e:RoleChangeEvent = new RoleChangeEvent(RoleChangeEvent.ASSIGN_PRESENTER);
e.userid = data.userID;
e.username = data.name;
@ -155,17 +169,26 @@
}
}
private function emojiBtnClicked() : void {
if (data.hasEmojiStatus) {
dispatchEvent(new EmojiStatusEvent(EmojiStatusEvent.EMOJI_STATUS, "none", data.userID));
}
}
// Need to refresh the roleBtn toolTip text on locale change
private function localeChanged(e:Event):void {
updateButton();
updateButtons();
}
]]>
</mx:Script>
<mx:Image id="emojiImg" visible="true" width="16" height="16" includeInLayout="{emojiImg.visible}" />
<mx:Button id="emojiBtn" visible="false" enabled="false" width="20" height="20" click="emojiBtnClicked()" includeInLayout="{emojiBtn.visible}" />
<mx:Image id="roleImg" visible="true" width="16" height="16" includeInLayout="{roleImg.visible}" />
<mx:Button id="roleBtn" visible="false" enabled="false" width="20" height="20" click="roleBtnClicked()" includeInLayout="{roleBtn.visible}" />
<!-- Helper objects because direct bindings to data break when the itemRenderer is recycled -->
<mx:Image id="presenterInd" includeInLayout="false" visible="{data.presenter}" />
<mx:Image id="moderatorInd" includeInLayout="false" visible="{data.role == Role.MODERATOR}" />
<mx:Image id="raiseHandInd" includeInLayout="false" visible="{data.raiseHand}" />
<mx:Image id="emojiStatusHandInd" includeInLayout="false" visible="{data.hasEmojiStatus}" />
</mx:HBox>

View File

@ -43,8 +43,10 @@
import mx.collections.ArrayCollection;
import mx.controls.Menu;
import mx.controls.listClasses.IListItemRenderer;
import mx.core.FlexGlobals;
import mx.events.ListEvent;
import mx.events.MenuEvent;
import mx.managers.PopUpManager;
import org.as3commons.logging.api.ILogger;
import org.as3commons.logging.api.getClassLogger;
@ -59,9 +61,8 @@
import org.bigbluebutton.core.vo.LockSettingsVO;
import org.bigbluebutton.main.events.ShortcutEvent;
import org.bigbluebutton.main.model.users.BBBUser;
import org.bigbluebutton.main.model.users.events.EmojiStatusEvent;
import org.bigbluebutton.main.model.users.events.KickUserEvent;
import org.bigbluebutton.main.model.users.events.LowerHandEvent;
import org.bigbluebutton.main.model.users.events.RaiseHandEvent;
import org.bigbluebutton.main.model.users.events.RoleChangeEvent;
import org.bigbluebutton.main.views.MainCanvas;
import org.bigbluebutton.modules.users.events.MeetingMutedEvent;
@ -82,8 +83,9 @@
[Bindable]
private var roomLocked:Boolean = false;
private var myMenu:Menu;
private var paramsMenu:Menu;
private var paramsMenuData:Array = [];
[Bindable]
public var partOptions:UsersOptions;
@ -103,8 +105,6 @@
private var muteMeRolled:Boolean = false;
private var myMenuData:Array = [];
private function onCreationComplete():void {
dispatcher = new Dispatcher();
@ -176,7 +176,7 @@
}
private function changeButtons(presenter:Boolean):void {
raiseHandBtn.visible = raiseHandBtn.includeInLayout = partOptions.enableRaiseHand;
emojiStatusBtn.visible = emojiStatusBtn.includeInLayout = partOptions.enableEmojiStatus;
}
/*
@ -222,59 +222,55 @@
dispatcher.dispatchEvent(rollEvent);
}
private function raiseHand():void{
var e:RaiseHandEvent = new RaiseHandEvent(RaiseHandEvent.RAISE_HAND);
if (UserManager.getInstance().getConference().isMyHandRaised) {
e.raised = false;
raiseHandBtn.accessibilityName = ResourceUtil.getInstance().getString('bbb.users.raiseHandBtn.toolTip2');
} else {
e.raised = true;
raiseHandBtn.accessibilityName = ResourceUtil.getInstance().getString('bbb.users.raiseHandBtn.toolTip');
}
dispatchEvent(e);
private function openEmojiStatusMenu() : void
{
var grid : EmojiGrid = PopUpManager.createPopUp(DisplayObject(FlexGlobals.topLevelApplication), EmojiGrid, false) as EmojiGrid;
var menuXY:Point = emojiStatusBtn.localToGlobal(new Point(emojiStatusBtn.width + 2, emojiStatusBtn.height - grid.height));
grid.x = menuXY.x;
grid.y = menuXY.y;
}
private function openSettings():void {
myMenuData = [];
myMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.lowerAllHands'), icon: images.hand_new, handler:lowerHands});
paramsMenuData = [];
paramsMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.resetAllStatuses'), icon: images.cancel, handler:resetEmojiStatuses});
if (!roomMuted) {
myMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.muteAll'), icon: images.audio_muted, handler: muteAll});
paramsMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.muteAll'), icon: images.audio_muted, handler: muteAll});
if (UserManager.getInstance().getConference().getPresenter())
myMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.muteAllExcept') + ": " + UserManager.getInstance().getConference().getPresenter().name, icon: images.audio_muted, handler:muteAlmostAll});
paramsMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.muteAllExcept') + ": " + UserManager.getInstance().getConference().getPresenter().name, icon: images.audio_muted, handler:muteAlmostAll});
} else
myMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.unmuteAll'), icon: images.audio, handler:muteAll});
paramsMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.unmuteAll'), icon: images.audio, handler:muteAll});
myMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.lockSettings'), icon: images.lock_open, handler: lockSettings});
paramsMenuData.push({label: ResourceUtil.getInstance().getString('bbb.users.settings.lockSettings'), icon: images.lock_open, handler: lockSettings});
// make sure the previous menu is closed before opening a new one
// This could be improved to include a flag that tells if the menu is open,
// but it would require an extra listener for the MenuCloseEvent.
if (myMenu) {
myMenu.removeEventListener(MenuEvent.ITEM_CLICK, menuClickHandler);
myMenu.removeEventListener(MenuEvent.MENU_SHOW, menuShowHandler);
myMenu.hide();
if (paramsMenu) {
paramsMenu.removeEventListener(MenuEvent.ITEM_CLICK, menuClickHandler);
paramsMenu.removeEventListener(MenuEvent.MENU_SHOW, menuShowHandler);
paramsMenu.hide();
}
myMenu = Menu.createMenu(null, myMenuData, true);
myMenu.variableRowHeight = false;
myMenu.addEventListener(MenuEvent.ITEM_CLICK, menuClickHandler);
myMenu.addEventListener(MenuEvent.MENU_SHOW, menuShowHandler);
myMenu.show();
paramsMenu = Menu.createMenu(null, paramsMenuData, true);
paramsMenu.variableRowHeight = false;
paramsMenu.addEventListener(MenuEvent.ITEM_CLICK, menuClickHandler);
paramsMenu.addEventListener(MenuEvent.MENU_SHOW, menuShowHandler);
paramsMenu.show();
}
private function menuClickHandler(e:MenuEvent):void {
if(myMenuData[e.index] != undefined && myMenuData[e.index].handler != undefined) {
myMenuData[e.index].handler();
if(paramsMenuData[e.index] != undefined && paramsMenuData[e.index].handler != undefined) {
paramsMenuData[e.index].handler();
}
}
private function menuShowHandler(e:MenuEvent):void {
myMenu.setFocus();
var menuXY:Point = settingsBtn.localToGlobal(new Point(settingsBtn.width + 2, settingsBtn.height - myMenu.height));
myMenu.x = menuXY.x;
myMenu.y = menuXY.y;
paramsMenu.setFocus();
var menuXY:Point = settingsBtn.localToGlobal(new Point(settingsBtn.width + 2, settingsBtn.height - paramsMenu.height));
paramsMenu.x = menuXY.x;
paramsMenu.y = menuXY.y;
}
private function handleChangedLockSettingsEvent(e:LockControlEvent):void {
@ -358,10 +354,10 @@
}
}
private function lowerHands():void {
private function resetEmojiStatuses():void {
for (var i:int = 0; i < users.length; i++) {
var p:BBBUser = users.getItemAt(i) as BBBUser;
if (p.raiseHand) dispatchEvent(new LowerHandEvent(p.userID));
if (p.hasEmojiStatus) dispatchEvent(new EmojiStatusEvent(EmojiStatusEvent.EMOJI_STATUS, "none", p.userID));
}
}
@ -384,12 +380,8 @@
maximizeRestoreBtn.accessibilityName = ResourceUtil.getInstance().getString("bbb.users.maximizeRestoreBtn.accessibilityName");
}
if (raiseHandBtn) {
if (UserManager.getInstance().getConference().isMyHandRaised) {
raiseHandBtn.accessibilityName = ResourceUtil.getInstance().getString('bbb.users.raiseHandBtn.toolTip2');
} else {
raiseHandBtn.accessibilityName = ResourceUtil.getInstance().getString('bbb.users.raiseHandBtn.toolTip');
}
if (emojiStatusBtn) {
emojiStatusBtn.accessibilityName = ResourceUtil.getInstance().getString('bbb.users.emojiStatusBtn.toolTip');
}
addContextMenuItems();
@ -444,9 +436,9 @@
}
public function remoteRaiseHand(e:ShortcutEvent):void{
raiseHand();
dispatchEvent(new EmojiStatusEvent(EmojiStatusEvent.EMOJI_STATUS, "raiseHand"));
}
private function remoteMinimize():void{
if (!minimized){
this.minimize();
@ -525,8 +517,9 @@
</mx:DataGrid>
<mx:ControlBar width="100%">
<mx:Button id="raiseHandBtn" toggle="true" icon="{images.hand_new}" selected="{UserManager.getInstance().getConference().isMyHandRaised}"
width="30" height="30" toolTip="{ResourceUtil.getInstance().getString('bbb.users.raiseHandBtn.toolTip')}" click="raiseHand()"
<mx:Button id="emojiStatusBtn" icon="{images.emoji_raiseHand}" width="30" height="30"
accessibilityName="{ResourceUtil.getInstance().getString('bbb.users.emojiStatusBtn.toolTip')}"
toolTip="{ResourceUtil.getInstance().getString('bbb.users.emojiStatusBtn.toolTip')}" click="openEmojiStatusMenu()"
visible="true" tabIndex="{partOptions.baseTabIndex+10}" />
<mx:Button id="settingsBtn" icon="{images.users_settings}" width="30" height="30"
toolTip="{ResourceUtil.getInstance().getString('bbb.users.settings.buttonTooltip')}" click="openSettings()" visible="true" tabIndex="{partOptions.baseTabIndex+15}" />