Merge branch 'development' into as3-logging
Conflicts: bigbluebutton-client/src/BigBlueButtonMainContainer.mxml bigbluebutton-client/src/org/bigbluebutton/core/services/UsersService.as bigbluebutton-client/src/org/bigbluebutton/main/maps/ApplicationEventMap.mxml bigbluebutton-client/src/org/bigbluebutton/main/model/users/Conference.as bigbluebutton-client/src/org/bigbluebutton/main/model/users/NetConnectionDelegate.as bigbluebutton-client/src/org/bigbluebutton/main/views/MainCanvas.mxml bigbluebutton-client/src/org/bigbluebutton/main/views/WebRTCEchoTest.mxml bigbluebutton-client/src/org/bigbluebutton/modules/chat/services/MessageReceiver.as bigbluebutton-client/src/org/bigbluebutton/modules/deskshare/managers/PublishWindowManager.as bigbluebutton-client/src/org/bigbluebutton/modules/deskshare/services/red5/Connection.as bigbluebutton-client/src/org/bigbluebutton/modules/deskshare/view/components/DesktopPublishWindow.mxml bigbluebutton-client/src/org/bigbluebutton/modules/deskshare/view/components/DesktopViewWindow.mxml bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/ConnectionManager.as bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/FlashCallManager.as bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/WebRTCCallManager.as bigbluebutton-client/src/org/bigbluebutton/modules/polling/service/PollDataProcessor.as bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/business/VideoProxy.as bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/maps/VideoEventMapDelegate.as bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/UserGraphicHolder.mxml bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/business/shapes/PollResultObject.as bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/models/WhiteboardModel.as
This commit is contained in:
commit
83666a7caa
@ -18,8 +18,8 @@ object PollFactory {
|
|||||||
|
|
||||||
private def processYesNoPollType(qType: String): Question = {
|
private def processYesNoPollType(qType: String): Question = {
|
||||||
val answers = new Array[Answer](2)
|
val answers = new Array[Answer](2)
|
||||||
answers(0) = new Answer(0, "N", Some("No"))
|
answers(0) = new Answer(0, "No", Some("No"))
|
||||||
answers(1) = new Answer(1, "Y", Some("Yes"))
|
answers(1) = new Answer(1, "Yes", Some("Yes"))
|
||||||
|
|
||||||
new Question(0, PollType.YesNoPollType, false, None, answers)
|
new Question(0, PollType.YesNoPollType, false, None, answers)
|
||||||
}
|
}
|
||||||
@ -27,8 +27,8 @@ object PollFactory {
|
|||||||
private def processTrueFalsePollType(qType: String): Question = {
|
private def processTrueFalsePollType(qType: String): Question = {
|
||||||
val answers = new Array[Answer](2)
|
val answers = new Array[Answer](2)
|
||||||
|
|
||||||
answers(0) = new Answer(0, "F", Some("False"))
|
answers(0) = new Answer(0, "False", Some("False"))
|
||||||
answers(1) = new Answer(1, "T", Some("True"))
|
answers(1) = new Answer(1, "True", Some("True"))
|
||||||
|
|
||||||
new Question(0, PollType.TrueFalsePollType, false, None, answers)
|
new Question(0, PollType.TrueFalsePollType, false, None, answers)
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,9 @@ trait PollApp {
|
|||||||
val shape = new scala.collection.mutable.HashMap[String, Object]()
|
val shape = new scala.collection.mutable.HashMap[String, Object]()
|
||||||
shape += "num_respondents" -> new Integer(result.numRespondents)
|
shape += "num_respondents" -> new Integer(result.numRespondents)
|
||||||
shape += "num_responders" -> new Integer(result.numResponders)
|
shape += "num_responders" -> new Integer(result.numResponders)
|
||||||
|
shape += "type" -> "poll_result"
|
||||||
|
shape += "id" -> result.id
|
||||||
|
shape += "status" -> "DRAW_END"
|
||||||
|
|
||||||
val answers = new ArrayBuffer[java.util.HashMap[String, Object]];
|
val answers = new ArrayBuffer[java.util.HashMap[String, Object]];
|
||||||
result.answers.foreach(ans => {
|
result.answers.foreach(ans => {
|
||||||
@ -81,12 +84,13 @@ trait PollApp {
|
|||||||
val gson = new Gson()
|
val gson = new Gson()
|
||||||
shape += "result" -> gson.toJson(answers.toArray)
|
shape += "result" -> gson.toJson(answers.toArray)
|
||||||
|
|
||||||
// Hardcode poll result display location for now.
|
// Hardcode poll result display location for now to display result
|
||||||
|
// in bottom-right corner.
|
||||||
val display = new ArrayList[Double]()
|
val display = new ArrayList[Double]()
|
||||||
display.add(21.845575)
|
display.add(66.0)
|
||||||
display.add(23.145401)
|
display.add(60.0)
|
||||||
display.add(46.516006)
|
display.add(34.0)
|
||||||
display.add(61.42433)
|
display.add(40.0)
|
||||||
|
|
||||||
shape += "points" -> display
|
shape += "points" -> display
|
||||||
shape.toMap
|
shape.toMap
|
||||||
|
@ -228,6 +228,7 @@ trait UsersApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
usersModel.removeUser(msg.userId)
|
usersModel.removeUser(msg.userId)
|
||||||
|
usersModel.removeRegUser(msg.userId)
|
||||||
|
|
||||||
log.info("Ejecting user from meeting: mid=[" + mProps.meetingID + "]uid=[" + msg.userId + "]")
|
log.info("Ejecting user from meeting: mid=[" + mProps.meetingID + "]uid=[" + msg.userId + "]")
|
||||||
outGW.send(new UserEjectedFromMeeting(mProps.meetingID, mProps.recorded, msg.userId, msg.ejectedBy))
|
outGW.send(new UserEjectedFromMeeting(mProps.meetingID, mProps.recorded, msg.userId, msg.ejectedBy))
|
||||||
@ -249,11 +250,14 @@ trait UsersApp {
|
|||||||
|
|
||||||
def handleUserunshareWebcam(msg: UserUnshareWebcam) {
|
def handleUserunshareWebcam(msg: UserUnshareWebcam) {
|
||||||
usersModel.getUser(msg.userId) foreach { user =>
|
usersModel.getUser(msg.userId) foreach { user =>
|
||||||
val streams = user.webcamStreams - msg.stream
|
val streamName = user.webcamStreams find (w => w == msg.stream) foreach { streamName =>
|
||||||
val uvo = user.copy(hasStream = (!streams.isEmpty), webcamStreams = streams)
|
val streams = user.webcamStreams - streamName
|
||||||
usersModel.addUser(uvo)
|
val uvo = user.copy(hasStream = (!streams.isEmpty), webcamStreams = streams)
|
||||||
log.info("User unshared webcam: mid=[" + mProps.meetingID + "] uid=[" + uvo.userID + "] unsharedStream=[" + msg.stream + "] streams=[" + streams + "]")
|
usersModel.addUser(uvo)
|
||||||
outGW.send(new UserUnsharedWebcam(mProps.meetingID, mProps.recorded, uvo.userID, msg.stream))
|
log.info("User unshared webcam: mid=[" + mProps.meetingID + "] uid=[" + uvo.userID + "] unsharedStream=[" + msg.stream + "] streams=[" + streams + "]")
|
||||||
|
outGW.send(new UserUnsharedWebcam(mProps.meetingID, mProps.recorded, uvo.userID, msg.stream))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,7 +274,20 @@ trait UsersApp {
|
|||||||
def handleUserJoin(msg: UserJoining): Unit = {
|
def handleUserJoin(msg: UserJoining): Unit = {
|
||||||
val regUser = usersModel.getRegisteredUserWithToken(msg.authToken)
|
val regUser = usersModel.getRegisteredUserWithToken(msg.authToken)
|
||||||
regUser foreach { ru =>
|
regUser foreach { ru =>
|
||||||
val vu = new VoiceUser(msg.userID, msg.userID, ru.name, ru.name, false, false, false, false)
|
// if there was a phoneUser with the same userID, reuse the VoiceUser value object
|
||||||
|
val vu = usersModel.getUser(msg.userID) match {
|
||||||
|
case Some(u) => {
|
||||||
|
if (u.voiceUser.joined) {
|
||||||
|
u.voiceUser.copy()
|
||||||
|
} else {
|
||||||
|
new VoiceUser(msg.userID, msg.userID, ru.name, ru.name, false, false, false, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case None => {
|
||||||
|
new VoiceUser(msg.userID, msg.userID, ru.name, ru.name, false, false, false, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val uvo = new UserVO(msg.userID, ru.externId, ru.name,
|
val uvo = new UserVO(msg.userID, ru.externId, ru.name,
|
||||||
ru.role, raiseHand = false, presenter = false,
|
ru.role, raiseHand = false, presenter = false,
|
||||||
hasStream = false, locked = getInitialLockStatus(ru.role),
|
hasStream = false, locked = getInitialLockStatus(ru.role),
|
||||||
@ -286,7 +303,7 @@ trait UsersApp {
|
|||||||
outGW.send(new MeetingState(mProps.meetingID, mProps.recorded, uvo.userID, meetingModel.getPermissions(), meetingModel.isMeetingMuted()))
|
outGW.send(new MeetingState(mProps.meetingID, mProps.recorded, uvo.userID, meetingModel.getPermissions(), meetingModel.isMeetingMuted()))
|
||||||
|
|
||||||
// Become presenter if the only moderator
|
// Become presenter if the only moderator
|
||||||
if (usersModel.numModerators == 1) {
|
if ((usersModel.numModerators == 1) || (usersModel.noPresenter())) {
|
||||||
if (ru.role == Role.MODERATOR) {
|
if (ru.role == Role.MODERATOR) {
|
||||||
assignNewPresenter(msg.userID, ru.name, msg.userID)
|
assignNewPresenter(msg.userID, ru.name, msg.userID)
|
||||||
}
|
}
|
||||||
@ -309,14 +326,18 @@ trait UsersApp {
|
|||||||
|
|
||||||
/* The current presenter has left the meeting. Find a moderator and make
|
/* The current presenter has left the meeting. Find a moderator and make
|
||||||
* him presenter. This way, if there is a moderator in the meeting, there
|
* him presenter. This way, if there is a moderator in the meeting, there
|
||||||
* will always be a presenter.
|
* will always be a presenter.
|
||||||
*/
|
*/
|
||||||
val moderator = usersModel.findAModerator()
|
val moderator = usersModel.findAModerator()
|
||||||
moderator.foreach { mod =>
|
moderator.foreach { mod =>
|
||||||
log.info("Presenter left meeting: mid=[" + mProps.meetingID + "] uid=[" + u.userID + "]. Making user=[" + mod.userID + "] presenter.")
|
log.info("Presenter left meeting: mid=[" + mProps.meetingID + "] uid=[" + u.userID + "]. Making user=[" + mod.userID + "] presenter.")
|
||||||
assignNewPresenter(mod.userID, mod.name, mod.userID)
|
assignNewPresenter(mod.userID, mod.name, mod.userID)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// add VoiceUser again to the list as a phone user since we still didn't get the event from FreeSWITCH
|
||||||
|
val vu = u.voiceUser
|
||||||
|
if (vu.joined) {
|
||||||
|
this.context.self ! (new UserJoinedVoiceConfMessage(mProps.voiceBridge, vu.userId, msg.userID, vu.callerName, vu.callerNum, vu.muted, vu.talking));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,12 +356,16 @@ trait UsersApp {
|
|||||||
log.info("Voice user=[" + msg.voiceUserId + "] is already in conf=[" + mProps.voiceBridge + "]. Must be duplicate message.")
|
log.info("Voice user=[" + msg.voiceUserId + "] is already in conf=[" + mProps.voiceBridge + "]. Must be duplicate message.")
|
||||||
}
|
}
|
||||||
case None => {
|
case None => {
|
||||||
// No current web user. This means that the user called in through
|
val webUserId = if (msg.userId != msg.callerIdName) {
|
||||||
// the phone. We need to generate a new user as we are not able
|
msg.userId
|
||||||
// to match with a web user.
|
} else {
|
||||||
val webUserId = usersModel.generateWebUserId
|
// No current web user. This means that the user called in through
|
||||||
|
// the phone. We need to generate a new user as we are not able
|
||||||
|
// to match with a web user.
|
||||||
|
usersModel.generateWebUserId
|
||||||
|
}
|
||||||
val vu = new VoiceUser(msg.voiceUserId, webUserId, msg.callerIdName, msg.callerIdNum,
|
val vu = new VoiceUser(msg.voiceUserId, webUserId, msg.callerIdName, msg.callerIdNum,
|
||||||
true, false, false, false)
|
true, false, msg.muted, msg.talking)
|
||||||
|
|
||||||
val sessionId = "PHONE-" + webUserId;
|
val sessionId = "PHONE-" + webUserId;
|
||||||
|
|
||||||
|
@ -96,6 +96,10 @@ class UsersModel {
|
|||||||
uservos.values find (u => u.role == MODERATOR)
|
uservos.values find (u => u.role == MODERATOR)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def noPresenter(): Boolean = {
|
||||||
|
!getCurrentPresenter().isDefined
|
||||||
|
}
|
||||||
|
|
||||||
def getCurrentPresenter(): Option[UserVO] = {
|
def getCurrentPresenter(): Option[UserVO] = {
|
||||||
uservos.values find (u => u.presenter == true)
|
uservos.values find (u => u.presenter == true)
|
||||||
}
|
}
|
||||||
@ -127,4 +131,17 @@ class UsersModel {
|
|||||||
def getViewers(): Array[UserVO] = {
|
def getViewers(): Array[UserVO] = {
|
||||||
uservos.values filter (u => u.role == VIEWER) toArray
|
uservos.values filter (u => u.role == VIEWER) toArray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def getRegisteredUserWithUserID(userID: String): Option[RegisteredUser] = {
|
||||||
|
regUsers.values find (ru => userID contains ru.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
def removeRegUser(userID: String) {
|
||||||
|
getRegisteredUserWithUserID(userID) match {
|
||||||
|
case Some(ru) => {
|
||||||
|
regUsers -= ru.authToken
|
||||||
|
}
|
||||||
|
case None =>
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -42,6 +42,8 @@ public class BigBlueButtonApplication extends MultiThreadedApplicationAdapter {
|
|||||||
private ConnectionInvokerService connInvokerService;
|
private ConnectionInvokerService connInvokerService;
|
||||||
private MessagePublisher red5InGW;
|
private MessagePublisher red5InGW;
|
||||||
|
|
||||||
|
private final UserConnectionMapper userConnections = new UserConnectionMapper();
|
||||||
|
|
||||||
private final String APP = "BBB";
|
private final String APP = "BBB";
|
||||||
private final String CONN = "RED5-";
|
private final String CONN = "RED5-";
|
||||||
|
|
||||||
@ -166,6 +168,8 @@ public class BigBlueButtonApplication extends MultiThreadedApplicationAdapter {
|
|||||||
|
|
||||||
log.info("User joining bbb-apps: data={}", logStr);
|
log.info("User joining bbb-apps: data={}", logStr);
|
||||||
|
|
||||||
|
userConnections.addUserConnection(userId, connId);
|
||||||
|
|
||||||
return super.roomConnect(connection, params);
|
return super.roomConnect(connection, params);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -214,10 +218,15 @@ public class BigBlueButtonApplication extends MultiThreadedApplicationAdapter {
|
|||||||
Gson gson = new Gson();
|
Gson gson = new Gson();
|
||||||
String logStr = gson.toJson(logData);
|
String logStr = gson.toJson(logData);
|
||||||
|
|
||||||
log.info("User leaving bbb-apps: data={}", logStr);
|
boolean removeUser = userConnections.userDisconnected(userId, connId);
|
||||||
|
|
||||||
red5InGW.userLeft(bbbSession.getRoom(), getBbbSession().getInternalUserID(), sessionId);
|
if (removeUser) {
|
||||||
|
log.info("User leaving bbb-apps: data={}", logStr);
|
||||||
|
red5InGW.userLeft(bbbSession.getRoom(), getBbbSession().getInternalUserID(), sessionId);
|
||||||
|
} else {
|
||||||
|
log.info("User not leaving bbb-apps but just disconnected: data={}", logStr);
|
||||||
|
}
|
||||||
|
|
||||||
super.roomDisconnect(conn);
|
super.roomDisconnect(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,70 @@
|
|||||||
|
package org.bigbluebutton.red5;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class maintains the connections mapping of a user.
|
||||||
|
* This tracks the connections for a user to manage auto-reconnects.
|
||||||
|
* @author ralam
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class UserConnectionMapper {
|
||||||
|
|
||||||
|
private ConcurrentMap<String, UserConnection> users = new ConcurrentHashMap<String, UserConnection>(8, 0.9f, 1);;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a connection for a user.
|
||||||
|
* @param userId
|
||||||
|
* @param connId
|
||||||
|
*/
|
||||||
|
public synchronized void addUserConnection(String userId, String connId) {
|
||||||
|
if (users.containsKey(userId)) {
|
||||||
|
UserConnection user = users.get(userId);
|
||||||
|
user.add(connId);
|
||||||
|
} else {
|
||||||
|
UserConnection user = new UserConnection();
|
||||||
|
user.add(connId);
|
||||||
|
users.put(userId, user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removed a connection for a user. Returns true if the user doesn't have any
|
||||||
|
* connection left and thus can be removed.
|
||||||
|
* @param userId
|
||||||
|
* @param connId
|
||||||
|
* @return boolean - no more connections
|
||||||
|
*/
|
||||||
|
public synchronized boolean userDisconnected(String userId, String connId) {
|
||||||
|
if (users.containsKey(userId)) {
|
||||||
|
UserConnection user = users.get(userId);
|
||||||
|
user.remove(connId);
|
||||||
|
if (user.isEmpty()) {
|
||||||
|
users.remove(userId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class UserConnection {
|
||||||
|
private final Set<String> connections = new HashSet<String>();
|
||||||
|
|
||||||
|
public void add(String connId) {
|
||||||
|
connections.add(connId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(String connId) {
|
||||||
|
connections.remove(connId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return connections.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -100,6 +100,12 @@ ToolTip {
|
|||||||
fontFamily: Arial;
|
fontFamily: Arial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pollResondersLabelStyle {
|
||||||
|
color: #444444;
|
||||||
|
fontFamily: Arial;
|
||||||
|
fontSize: 12;
|
||||||
|
}
|
||||||
|
|
||||||
Button, .logoutButtonStyle, .chatSendButtonStyle, .helpLinkButtonStyle, .cameraDisplaySettingsWindowProfileComboStyle, .cameraDisplaySettingsWindowCameraSelector, .languageSelectorStyle, .testJavaLinkButtonStyle, .recordButtonStyleNormal, .recordButtonStyleStart, .recordButtonStyleStop, .micSettingsWindowHelpButtonStyle {
|
Button, .logoutButtonStyle, .chatSendButtonStyle, .helpLinkButtonStyle, .cameraDisplaySettingsWindowProfileComboStyle, .cameraDisplaySettingsWindowCameraSelector, .languageSelectorStyle, .testJavaLinkButtonStyle, .recordButtonStyleNormal, .recordButtonStyleStart, .recordButtonStyleStop, .micSettingsWindowHelpButtonStyle {
|
||||||
textIndent: 0;
|
textIndent: 0;
|
||||||
paddingLeft: 10;
|
paddingLeft: 10;
|
||||||
@ -408,7 +414,7 @@ DataGrid {
|
|||||||
icon: Embed('assets/images/webcam-private-chat.png');
|
icon: Embed('assets/images/webcam-private-chat.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
.presentationFileUploadWindowStyle {
|
TitleWindow {
|
||||||
borderColor: #b9babc;
|
borderColor: #b9babc;
|
||||||
borderAlpha: 1;
|
borderAlpha: 1;
|
||||||
borderThicknessLeft: 10;
|
borderThicknessLeft: 10;
|
||||||
@ -419,11 +425,8 @@ DataGrid {
|
|||||||
cornerRadius: 5;
|
cornerRadius: 5;
|
||||||
headerHeight: 20;
|
headerHeight: 20;
|
||||||
backgroundAlpha: 1;
|
backgroundAlpha: 1;
|
||||||
headerColors: #b9babc, #b9babc;
|
|
||||||
footerColors: #b9babc, #b9babc;
|
|
||||||
backgroundColor: #EFEFEF;
|
backgroundColor: #EFEFEF;
|
||||||
dropShadowEnabled: true;
|
dropShadowEnabled: true;
|
||||||
titleStyleName: "presentationFileUploadWindowTitleStyle";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.presentationFileUploadWindowTitleStyle, .presentationUploadTitleStyle {
|
.presentationFileUploadWindowTitleStyle, .presentationUploadTitleStyle {
|
||||||
@ -511,42 +514,6 @@ DataGrid {
|
|||||||
imageSource: Embed(source='assets/images/chromePluginBlocked.png');
|
imageSource: Embed(source='assets/images/chromePluginBlocked.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
.cameraDisplaySettingsWindowStyle {
|
|
||||||
borderColor: #b9babc;
|
|
||||||
borderAlpha: 1;
|
|
||||||
borderThicknessLeft: 10;
|
|
||||||
borderThicknessTop: 0;
|
|
||||||
borderThicknessBottom: 10;
|
|
||||||
borderThicknessRight: 10;
|
|
||||||
roundedBottomCorners: true;
|
|
||||||
cornerRadius: 5;
|
|
||||||
headerHeight: 20;
|
|
||||||
backgroundAlpha: 1;
|
|
||||||
headerColors: #b9babc, #b9babc;
|
|
||||||
footerColors: #b9babc, #b9babc;
|
|
||||||
backgroundColor: #EFEFEF;
|
|
||||||
dropShadowEnabled: true;
|
|
||||||
titleStyleName: "webcamSettingsWindowTitleStyle";
|
|
||||||
}
|
|
||||||
|
|
||||||
.micSettingsWindowStyle {
|
|
||||||
borderColor: #b9babc;
|
|
||||||
borderAlpha: 1;
|
|
||||||
borderThicknessLeft: 10;
|
|
||||||
borderThicknessTop: 0;
|
|
||||||
borderThicknessBottom: 10;
|
|
||||||
borderThicknessRight: 10;
|
|
||||||
roundedBottomCorners: true;
|
|
||||||
cornerRadius: 5;
|
|
||||||
headerHeight: 20;
|
|
||||||
backgroundAlpha: 1;
|
|
||||||
headerColors: #b9babc, #b9babc;
|
|
||||||
footerColors: #b9babc, #b9babc;
|
|
||||||
backgroundColor: #EFEFEF;
|
|
||||||
dropShadowEnabled: true;
|
|
||||||
titleStyleName: "micSettingsWindowTitleStyle";
|
|
||||||
}
|
|
||||||
|
|
||||||
.webcamSettingsWindowTitleStyle, .micSettingsWindowTitleStyle {
|
.webcamSettingsWindowTitleStyle, .micSettingsWindowTitleStyle {
|
||||||
fontFamily: Arial;
|
fontFamily: Arial;
|
||||||
fontSize: 20;
|
fontSize: 20;
|
||||||
@ -866,24 +833,6 @@ Alert {
|
|||||||
fontWeight: bold;
|
fontWeight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lockSettingsWindowStyle {
|
|
||||||
borderColor: #b9babc;
|
|
||||||
borderAlpha: 1;
|
|
||||||
borderThicknessLeft: 10;
|
|
||||||
borderThicknessTop: 0;
|
|
||||||
borderThicknessBottom: 10;
|
|
||||||
borderThicknessRight: 10;
|
|
||||||
roundedBottomCorners: true;
|
|
||||||
cornerRadius: 5;
|
|
||||||
headerHeight: 20;
|
|
||||||
backgroundAlpha: 1;
|
|
||||||
headerColors: #b9babc, #b9babc;
|
|
||||||
footerColors: #b9babc, #b9babc;
|
|
||||||
backgroundColor: #EFEFEF;
|
|
||||||
dropShadowEnabled: true;
|
|
||||||
titleStyleName: "micSettingsWindowTitleStyle";
|
|
||||||
}
|
|
||||||
|
|
||||||
.lockSettingsWindowTitleStyle {
|
.lockSettingsWindowTitleStyle {
|
||||||
fontFamily: Arial;
|
fontFamily: Arial;
|
||||||
fontSize: 20;
|
fontSize: 20;
|
||||||
@ -906,6 +855,7 @@ Alert {
|
|||||||
successImage: Embed(source='assets/images/status_success.png');
|
successImage: Embed(source='assets/images/status_success.png');
|
||||||
warningImage: Embed(source='assets/images/status_warning.png');
|
warningImage: Embed(source='assets/images/status_warning.png');
|
||||||
failImage: Embed(source='assets/images/status_fail.png');
|
failImage: Embed(source='assets/images/status_fail.png');
|
||||||
|
refreshImage: Embed(source='assets/images/status_refresh.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
.warningButtonStyle {
|
.warningButtonStyle {
|
||||||
@ -922,3 +872,8 @@ Alert {
|
|||||||
fontSize: 12;
|
fontSize: 12;
|
||||||
paddingTop: 0;
|
paddingTop: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.statusTimeStyle {
|
||||||
|
fontSize: 10;
|
||||||
|
paddingTop: 0;
|
||||||
|
}
|
||||||
|
@ -35,4 +35,7 @@ purchase a royalty-free license.
|
|||||||
I'm unavailable for custom icon design work. But your
|
I'm unavailable for custom icon design work. But your
|
||||||
suggestions are always welcome!
|
suggestions are always welcome!
|
||||||
<mailto:p@yusukekamiyamane.com>
|
<mailto:p@yusukekamiyamane.com>
|
||||||
====================
|
====================
|
||||||
|
Some of the client icons were generated using the following online tool:
|
||||||
|
|
||||||
|
http://romannurik.github.io/AndroidAssetStudio/icons-launcher.html#foreground.type=clipart&foreground.space.trim=1&foreground.space.pad=0.15&foreground.clipart=res%2Fclipart%2Ficons%2Fnavigation_refresh.svg&foreColor=4b4b4b%2C0&crop=0&backgroundShape=none&backColor=ffffff%2C100&effects=none
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
@ -235,6 +235,7 @@ bbb.chat.minimizeBtn.accessibilityName = Minimize the Chat Window
|
|||||||
bbb.chat.maximizeRestoreBtn.accessibilityName = Maximize the Chat Window
|
bbb.chat.maximizeRestoreBtn.accessibilityName = Maximize the Chat Window
|
||||||
bbb.chat.closeBtn.accessibilityName = Close the Chat Window
|
bbb.chat.closeBtn.accessibilityName = Close the Chat Window
|
||||||
bbb.chat.chatTabs.accessibleNotice = New messages in this tab.
|
bbb.chat.chatTabs.accessibleNotice = New messages in this tab.
|
||||||
|
bbb.chat.chatMessage.systemMessage = System
|
||||||
bbb.publishVideo.changeCameraBtn.labelText = Change Webcam
|
bbb.publishVideo.changeCameraBtn.labelText = Change Webcam
|
||||||
bbb.publishVideo.changeCameraBtn.toolTip = Open the change webcam dialog box
|
bbb.publishVideo.changeCameraBtn.toolTip = Open the change webcam dialog box
|
||||||
bbb.publishVideo.cmbResolution.tooltip = Select a webcam resolution
|
bbb.publishVideo.cmbResolution.tooltip = Select a webcam resolution
|
||||||
@ -344,6 +345,13 @@ bbb.logout.confirm.title = Confirm Logout
|
|||||||
bbb.logout.confirm.message = Are you sure you want to log out?
|
bbb.logout.confirm.message = Are you sure you want to log out?
|
||||||
bbb.logout.confirm.yes = Yes
|
bbb.logout.confirm.yes = Yes
|
||||||
bbb.logout.confirm.no = No
|
bbb.logout.confirm.no = No
|
||||||
|
bbb.connection.failure=Network failure
|
||||||
|
bbb.connection.reconnecting=Reconnecting
|
||||||
|
bbb.connection.reestablished=Connection reestablished
|
||||||
|
bbb.connection.bigbluebutton=BigBlueButton
|
||||||
|
bbb.connection.sip=SIP
|
||||||
|
bbb.connection.video=Video
|
||||||
|
bbb.connection.deskshare=Deskshare
|
||||||
bbb.notes.title = Notes
|
bbb.notes.title = Notes
|
||||||
bbb.notes.cmpColorPicker.toolTip = Text Color
|
bbb.notes.cmpColorPicker.toolTip = Text Color
|
||||||
bbb.notes.saveBtn = Save
|
bbb.notes.saveBtn = Save
|
||||||
@ -493,10 +501,13 @@ bbb.shortcutkey.chat.chatbox.debug.function = Temporary debug hotkey
|
|||||||
bbb.polling.startButton.tooltip = Start a poll
|
bbb.polling.startButton.tooltip = Start a poll
|
||||||
bbb.polling.publishButton.label = Publish
|
bbb.polling.publishButton.label = Publish
|
||||||
bbb.polling.closeButton.label = Close
|
bbb.polling.closeButton.label = Close
|
||||||
bbb.polling.answer.Y = Yes
|
bbb.polling.pollModal.title = Poll
|
||||||
bbb.polling.answer.N = No
|
bbb.polling.respondersLabel.novotes = No Users Responded
|
||||||
bbb.polling.answer.T = True
|
bbb.polling.respondersLabel.text = {0} Users Responded
|
||||||
bbb.polling.answer.F = False
|
bbb.polling.answer.Yes = Yes
|
||||||
|
bbb.polling.answer.No = No
|
||||||
|
bbb.polling.answer.True = True
|
||||||
|
bbb.polling.answer.False = False
|
||||||
bbb.polling.answer.A = A
|
bbb.polling.answer.A = A
|
||||||
bbb.polling.answer.B = B
|
bbb.polling.answer.B = B
|
||||||
bbb.polling.answer.C = C
|
bbb.polling.answer.C = C
|
||||||
@ -504,6 +515,8 @@ bbb.polling.answer.D = D
|
|||||||
bbb.polling.answer.E = E
|
bbb.polling.answer.E = E
|
||||||
bbb.polling.answer.F = F
|
bbb.polling.answer.F = F
|
||||||
bbb.polling.answer.G = G
|
bbb.polling.answer.G = G
|
||||||
|
bbb.polling.results.accessible.header = Poll Results.
|
||||||
|
bbb.polling.results.accessible.answer = Answer {0} had {1} votes.
|
||||||
|
|
||||||
bbb.publishVideo.startPublishBtn.labelText = Start Sharing
|
bbb.publishVideo.startPublishBtn.labelText = Start Sharing
|
||||||
bbb.publishVideo.changeCameraBtn.labelText = Change Webcam Settings
|
bbb.publishVideo.changeCameraBtn.labelText = Change Webcam Settings
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -3,6 +3,9 @@ if (!window.console.log) window.console.log = function () { };
|
|||||||
|
|
||||||
function startApplet(IP, useTLS , roomNumber, fullScreen, useSVC2)
|
function startApplet(IP, useTLS , roomNumber, fullScreen, useSVC2)
|
||||||
{
|
{
|
||||||
|
var deskshareElement = document.getElementById("deskshare");
|
||||||
|
if (deskshareElement == null) {
|
||||||
|
|
||||||
console.log("Starting deskshare applet.");
|
console.log("Starting deskshare applet.");
|
||||||
var div = document.createElement("div");
|
var div = document.createElement("div");
|
||||||
div.id = "deskshare";
|
div.id = "deskshare";
|
||||||
@ -21,15 +24,40 @@ function startApplet(IP, useTLS , roomNumber, fullScreen, useSVC2)
|
|||||||
"<param name=\"permissions\" value=\"all-permissions\"/>" +
|
"<param name=\"permissions\" value=\"all-permissions\"/>" +
|
||||||
"</applet>";
|
"</applet>";
|
||||||
document.body.appendChild(div);
|
document.body.appendChild(div);
|
||||||
|
} else {
|
||||||
|
console.log("Deskshare applet element already exists.");
|
||||||
|
var div = document.getElementById("deskshare");
|
||||||
|
if (div.parentNode) {
|
||||||
|
// Just rewrite the applet tag to kick off the applet. We don't remove the applet tag
|
||||||
|
// when desktop sharing is stopped to prevent Firefox (38.0.5) from asking for user permissions
|
||||||
|
// again resulting in the page reloading. (ralam june 17, 2015)
|
||||||
|
// https://code.google.com/p/bigbluebutton/issues/detail?id=1953
|
||||||
|
div.innerHTML =
|
||||||
|
"<applet code=\"org.bigbluebutton.deskshare.client.DeskShareApplet.class\"" +
|
||||||
|
"id=\"DeskShareApplet\" width=\"100\" height=\"10\" archive=\"bbb-deskshare-applet-0.9.0.jar\">" +
|
||||||
|
"<param name=\"ROOM\" value=\"" + roomNumber + "\"/>" +
|
||||||
|
"<param name=\"IP\" value=\"" + IP + "\"/>" +
|
||||||
|
"<param name=\"PORT\" value=\"9123\"/>" +
|
||||||
|
"<param name=\"SCALE\" value=\"0.8\"/>" +
|
||||||
|
"<param name=\"FULL_SCREEN\" value=\"" + fullScreen + "\"/>" +
|
||||||
|
"<param name=\"SVC2\" value=\"" + useSVC2 + "\"/>" +
|
||||||
|
"<param name=\"JavaVersion\" value=\"1.7.0_51\"/>" +
|
||||||
|
"<param name=\"permissions\" value=\"all-permissions\"/>" +
|
||||||
|
"</applet>";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function removeFrame () {
|
function removeFrame () {
|
||||||
var div = document.getElementById("deskshare");
|
var div = document.getElementById("deskshare");
|
||||||
if (div.parentNode) {
|
if (div.parentNode) {
|
||||||
// Need to set the innerHTML otherwise the applet will restart in IE.
|
// Need to set the innerHTML otherwise the applet will restart in IE.
|
||||||
// see https://code.google.com/p/bigbluebutton/issues/detail?id=1776
|
// see https://code.google.com/p/bigbluebutton/issues/detail?id=1776
|
||||||
div.innerHTML = "";
|
// Do NOT remove the applet tag as it makes Firefox (38.0.5) prompt for
|
||||||
div.parentNode.removeChild(div);
|
// permissions again resulting in the page reloading. (ralam june 17, 2015)
|
||||||
|
// div.innerHTML = "";
|
||||||
|
// div.parentNode.removeChild(div);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,4 +171,4 @@ function checkJavaVersion(minJavaVersion) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
import org.as3commons.logging.api.ILogger;
|
import org.as3commons.logging.api.ILogger;
|
||||||
import org.as3commons.logging.api.getClassLogger;
|
import org.as3commons.logging.api.getClassLogger;
|
||||||
|
import org.bigbluebutton.common.LogUtil;
|
||||||
import org.bigbluebutton.core.BBB;
|
import org.bigbluebutton.core.BBB;
|
||||||
import org.bigbluebutton.core.EventBroadcaster;
|
import org.bigbluebutton.core.EventBroadcaster;
|
||||||
import org.bigbluebutton.main.api.ExternalApiCallbacks;
|
import org.bigbluebutton.main.api.ExternalApiCallbacks;
|
||||||
@ -71,13 +72,14 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
protected function init():void {
|
protected function init():void {
|
||||||
setupTooltips();
|
setupTooltips();
|
||||||
setupAPI();
|
setupAPI();
|
||||||
EventBroadcaster.getInstance().addEventListener("configLoadedEvent", configLoadedEventHandler);
|
EventBroadcaster.getInstance().addEventListener("configLoadedEvent", configLoadedEventHandler);
|
||||||
BBB.initConfigManager();
|
BBB.initConfigManager();
|
||||||
BBB.initVideoProfileManager();
|
BBB.initVideoProfileManager();
|
||||||
globalModifier = ExternalInterface.call("determineGlobalModifier");
|
globalModifier = ExternalInterface.call("determineGlobalModifier");
|
||||||
}
|
}
|
||||||
|
|
||||||
private function configLoadedEventHandler(e:Event):void {
|
private function configLoadedEventHandler(e:Event):void {
|
||||||
|
LogUtil.initLogging();
|
||||||
LOGGER.debug("***** Config Loaded ****");
|
LOGGER.debug("***** Config Loaded ****");
|
||||||
mainShell.initOptions(null);
|
mainShell.initOptions(null);
|
||||||
ShortcutOptions.initialize();
|
ShortcutOptions.initialize();
|
||||||
|
@ -0,0 +1,199 @@
|
|||||||
|
/**
|
||||||
|
* 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.core.managers
|
||||||
|
{
|
||||||
|
import com.asfusion.mate.events.Dispatcher;
|
||||||
|
|
||||||
|
import flash.display.DisplayObject;
|
||||||
|
import flash.events.TimerEvent;
|
||||||
|
import flash.utils.Dictionary;
|
||||||
|
import flash.utils.Timer;
|
||||||
|
|
||||||
|
import mx.collections.ArrayCollection;
|
||||||
|
import mx.core.FlexGlobals;
|
||||||
|
import mx.core.IFlexDisplayObject;
|
||||||
|
import mx.managers.PopUpManager;
|
||||||
|
|
||||||
|
import org.as3commons.logging.api.ILogger;
|
||||||
|
import org.as3commons.logging.api.getClassLogger;
|
||||||
|
import org.bigbluebutton.main.events.BBBEvent;
|
||||||
|
import org.bigbluebutton.main.events.ClientStatusEvent;
|
||||||
|
import org.bigbluebutton.main.events.LogoutEvent;
|
||||||
|
import org.bigbluebutton.main.model.users.AutoReconnect;
|
||||||
|
import org.bigbluebutton.main.views.ReconnectionPopup;
|
||||||
|
import org.bigbluebutton.util.i18n.ResourceUtil;
|
||||||
|
|
||||||
|
public class ReconnectionManager
|
||||||
|
{
|
||||||
|
private static const LOGGER:ILogger = getClassLogger(AutoReconnect);
|
||||||
|
|
||||||
|
public static const BIGBLUEBUTTON_CONNECTION:String = "BIGBLUEBUTTON_CONNECTION";
|
||||||
|
public static const SIP_CONNECTION:String = "SIP_CONNECTION";
|
||||||
|
public static const VIDEO_CONNECTION:String = "VIDEO_CONNECTION";
|
||||||
|
public static const DESKSHARE_CONNECTION:String = "DESKSHARE_CONNECTION";
|
||||||
|
|
||||||
|
private var _connections:Dictionary = new Dictionary();
|
||||||
|
private var _reestablished:ArrayCollection = new ArrayCollection();
|
||||||
|
private var _reconnectTimer:Timer = new Timer(10000, 1);
|
||||||
|
private var _reconnectTimeout:Timer = new Timer(5000, 1);
|
||||||
|
private var _dispatcher:Dispatcher = new Dispatcher();
|
||||||
|
private var _popup:IFlexDisplayObject = null;
|
||||||
|
private var _canceled:Boolean = false;
|
||||||
|
|
||||||
|
public function ReconnectionManager() {
|
||||||
|
_reconnectTimer.addEventListener(TimerEvent.TIMER_COMPLETE, reconnect);
|
||||||
|
_reconnectTimeout.addEventListener(TimerEvent.TIMER_COMPLETE, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function reconnect(e:TimerEvent = null):void {
|
||||||
|
if (_connections.hasOwnProperty(BIGBLUEBUTTON_CONNECTION)) {
|
||||||
|
reconnectHelper(BIGBLUEBUTTON_CONNECTION);
|
||||||
|
} else {
|
||||||
|
for (var type:String in _connections) {
|
||||||
|
reconnectHelper(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!_reconnectTimeout.running)
|
||||||
|
_reconnectTimeout.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function timeout(e:TimerEvent = null):void {
|
||||||
|
LOGGER.debug("timeout");
|
||||||
|
_dispatcher.dispatchEvent(new BBBEvent(BBBEvent.CANCEL_RECONNECTION_EVENT));
|
||||||
|
_dispatcher.dispatchEvent(new LogoutEvent(LogoutEvent.USER_LOGGED_OUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function reconnectHelper(type:String):void {
|
||||||
|
var obj:Object = _connections[type];
|
||||||
|
obj.reconnect = new AutoReconnect();
|
||||||
|
obj.reconnect.onDisconnect(obj.callback, obj.callbackParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onDisconnected(type:String, callback:Function, parameters:Array):void {
|
||||||
|
if (!_canceled) {
|
||||||
|
LOGGER.warn("onDisconnected, type={0}, parameters={1}" + [type, parameters.toString()]);
|
||||||
|
|
||||||
|
var obj:Object = new Object();
|
||||||
|
obj.callback = callback;
|
||||||
|
obj.callbackParameters = parameters;
|
||||||
|
_connections[type] = obj;
|
||||||
|
|
||||||
|
if (!_reconnectTimer.running) {
|
||||||
|
_popup = PopUpManager.createPopUp(FlexGlobals.topLevelApplication as DisplayObject, ReconnectionPopup, true);
|
||||||
|
PopUpManager.centerPopUp(_popup);
|
||||||
|
|
||||||
|
_reconnectTimer.reset();
|
||||||
|
_reconnectTimer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onConnectionAttemptFailed(type:String):void {
|
||||||
|
LOGGER.warn("onConnectionAttemptFailed, type={0}", [type]);
|
||||||
|
if (_connections.hasOwnProperty(type)) {
|
||||||
|
_connections[type].reconnect.onConnectionAttemptFailed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function get connectionDictEmpty():Boolean {
|
||||||
|
for (var key:Object in _connections) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function dispatchReconnectionSucceededEvent(type:String):void {
|
||||||
|
var map:Object = {
|
||||||
|
BIGBLUEBUTTON_CONNECTION: BBBEvent.RECONNECT_BIGBLUEBUTTON_SUCCEEDED_EVENT,
|
||||||
|
SIP_CONNECTION: BBBEvent.RECONNECT_SIP_SUCCEEDED_EVENT,
|
||||||
|
VIDEO_CONNECTION: BBBEvent.RECONNECT_VIDEO_SUCCEEDED_EVENT,
|
||||||
|
DESKSHARE_CONNECTION: BBBEvent.RECONNECT_DESKSHARE_SUCCEEDED_EVENT
|
||||||
|
};
|
||||||
|
|
||||||
|
if (map.hasOwnProperty(type)) {
|
||||||
|
LOGGER.debug("dispatchReconnectionSucceededEvent, type={0}", [type]);
|
||||||
|
_dispatcher.dispatchEvent(new BBBEvent(map[type]));
|
||||||
|
} else {
|
||||||
|
LOGGER.debug("dispatchReconnectionSucceededEvent, couldn't find a map value for type {0}", [type]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onConnectionAttemptSucceeded(type:String):void {
|
||||||
|
LOGGER.debug("onConnectionAttemptSucceeded, type={0}", [type]);
|
||||||
|
dispatchReconnectionSucceededEvent(type);
|
||||||
|
|
||||||
|
delete _connections[type];
|
||||||
|
if (type == BIGBLUEBUTTON_CONNECTION) {
|
||||||
|
reconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
_reestablished.addItem(type);
|
||||||
|
if (connectionDictEmpty) {
|
||||||
|
var msg:String = connectionReestablishedMessage();
|
||||||
|
|
||||||
|
_dispatcher.dispatchEvent(new ClientStatusEvent(ClientStatusEvent.SUCCESS_MESSAGE_EVENT,
|
||||||
|
ResourceUtil.getInstance().getString('bbb.connection.reestablished'),
|
||||||
|
msg));
|
||||||
|
|
||||||
|
_reconnectTimeout.reset();
|
||||||
|
removePopUp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onCancelReconnection():void {
|
||||||
|
_canceled = true;
|
||||||
|
|
||||||
|
for (var type:Object in _connections) delete _connections[type];
|
||||||
|
|
||||||
|
removePopUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function removePopUp():void {
|
||||||
|
if (_popup != null) {
|
||||||
|
PopUpManager.removePopUp(_popup);
|
||||||
|
_popup = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function connectionReestablishedMessage():String {
|
||||||
|
var msg:String = "";
|
||||||
|
for each (var conn:String in _reestablished) {
|
||||||
|
switch (conn) {
|
||||||
|
case BIGBLUEBUTTON_CONNECTION:
|
||||||
|
msg += ResourceUtil.getInstance().getString('bbb.connection.bigbluebutton');
|
||||||
|
break;
|
||||||
|
case SIP_CONNECTION:
|
||||||
|
msg += ResourceUtil.getInstance().getString('bbb.connection.sip');
|
||||||
|
break;
|
||||||
|
case VIDEO_CONNECTION:
|
||||||
|
msg += ResourceUtil.getInstance().getString('bbb.connection.video');
|
||||||
|
break;
|
||||||
|
case DESKSHARE_CONNECTION:
|
||||||
|
msg += ResourceUtil.getInstance().getString('bbb.connection.deskshare');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
msg += " ";
|
||||||
|
}
|
||||||
|
_reestablished.removeAll();
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -66,7 +66,7 @@ package org.bigbluebutton.core.services
|
|||||||
// dispatch event
|
// dispatch event
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOGGER.debug("*** failed to get voice user name=[{0}] **** \n", [vu.name]);
|
LOGGER.debug("*** failed to get user name=[{0}] **** \n", [vu.name]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,4 +115,4 @@ package org.bigbluebutton.core.services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UsersServiceSingletonEnforcer{}
|
class UsersServiceSingletonEnforcer{}
|
||||||
|
@ -43,6 +43,17 @@ package org.bigbluebutton.main.events {
|
|||||||
public static const JOIN_VOICE_FOCUS_HEAD:String = "JOIN_VOICE_FOCUS_HEAD";
|
public static const JOIN_VOICE_FOCUS_HEAD:String = "JOIN_VOICE_FOCUS_HEAD";
|
||||||
public static const CHANGE_RECORDING_STATUS:String = "CHANGE_RECORDING_STATUS";
|
public static const CHANGE_RECORDING_STATUS:String = "CHANGE_RECORDING_STATUS";
|
||||||
|
|
||||||
|
public static const RECONNECT_DISCONNECTED_EVENT:String = "RECONNECT_ON_DISCONNECTED_EVENT";
|
||||||
|
public static const RECONNECT_CONNECTION_ATTEMPT_FAILED_EVENT:String = "RECONNECT_CONNECTION_ATTEMPT_FAILED_EVENT";
|
||||||
|
public static const RECONNECT_CONNECTION_ATTEMPT_SUCCEEDED_EVENT:String = "RECONNECT_CONNECTION_ATTEMPT_SUCCEEDED_EVENT";
|
||||||
|
|
||||||
|
public static const RECONNECT_BIGBLUEBUTTON_SUCCEEDED_EVENT:String = "RECONNECT_BIGBLUEBUTTON_SUCCEEDED_EVENT";
|
||||||
|
public static const RECONNECT_VIDEO_SUCCEEDED_EVENT:String = "RECONNECT_VIDEO_SUCCEEDED_EVENT";
|
||||||
|
public static const RECONNECT_SIP_SUCCEEDED_EVENT:String = "RECONNECT_SIP_SUCCEEDED_EVENT";
|
||||||
|
public static const RECONNECT_DESKSHARE_SUCCEEDED_EVENT:String = "RECONNECT_DESKSHARE_SUCCEEDED_EVENT";
|
||||||
|
|
||||||
|
public static const CANCEL_RECONNECTION_EVENT:String = "CANCEL_RECONNECTION_EVENT";
|
||||||
|
|
||||||
public var message:String;
|
public var message:String;
|
||||||
public var payload:Object = new Object();
|
public var payload:Object = new Object();
|
||||||
|
|
||||||
@ -51,4 +62,4 @@ package org.bigbluebutton.main.events {
|
|||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
-->
|
-->
|
||||||
<ObjectBuilder generator="{ModulesProxy}" cache="global" />
|
<ObjectBuilder generator="{ModulesProxy}" cache="global" />
|
||||||
<ObjectBuilder generator="{ConfigManager}" cache="global" />
|
<ObjectBuilder generator="{ConfigManager}" cache="global" />
|
||||||
|
<ObjectBuilder generator="{ReconnectionManager}" cache="global" />
|
||||||
<!--
|
<!--
|
||||||
Disabling temporarily the stream monitor
|
Disabling temporarily the stream monitor
|
||||||
-->
|
-->
|
||||||
@ -69,6 +70,22 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
<MethodInvoker generator="{ModulesProxy}" method="startAllModules" />
|
<MethodInvoker generator="{ModulesProxy}" method="startAllModules" />
|
||||||
</EventHandlers>
|
</EventHandlers>
|
||||||
|
|
||||||
|
<EventHandlers type="{BBBEvent.RECONNECT_DISCONNECTED_EVENT}">
|
||||||
|
<MethodInvoker generator="{ReconnectionManager}" method="onDisconnected" arguments="{[event.payload.type, event.payload.callback, event.payload.callbackParameters]}"/>
|
||||||
|
</EventHandlers>
|
||||||
|
|
||||||
|
<EventHandlers type="{BBBEvent.RECONNECT_CONNECTION_ATTEMPT_FAILED_EVENT}">
|
||||||
|
<MethodInvoker generator="{ReconnectionManager}" method="onConnectionAttemptFailed" arguments="{event.payload.type}"/>
|
||||||
|
</EventHandlers>
|
||||||
|
|
||||||
|
<EventHandlers type="{BBBEvent.RECONNECT_CONNECTION_ATTEMPT_SUCCEEDED_EVENT}">
|
||||||
|
<MethodInvoker generator="{ReconnectionManager}" method="onConnectionAttemptSucceeded" arguments="{event.payload.type}"/>
|
||||||
|
</EventHandlers>
|
||||||
|
|
||||||
|
<EventHandlers type="{BBBEvent.CANCEL_RECONNECTION_EVENT}">
|
||||||
|
<MethodInvoker generator="{ReconnectionManager}" method="onCancelReconnection" />
|
||||||
|
</EventHandlers>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<mx:Script>
|
<mx:Script>
|
||||||
@ -76,7 +93,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
import mx.events.FlexEvent;
|
import mx.events.FlexEvent;
|
||||||
|
|
||||||
import org.bigbluebutton.core.managers.ConfigManager;
|
import org.bigbluebutton.core.managers.ConfigManager;
|
||||||
|
import org.bigbluebutton.core.managers.ReconnectionManager;
|
||||||
import org.bigbluebutton.core.services.SkinningService;
|
import org.bigbluebutton.core.services.SkinningService;
|
||||||
|
import org.bigbluebutton.main.events.BBBEvent;
|
||||||
import org.bigbluebutton.main.events.ConfigEvent;
|
import org.bigbluebutton.main.events.ConfigEvent;
|
||||||
import org.bigbluebutton.main.events.LogoutEvent;
|
import org.bigbluebutton.main.events.LogoutEvent;
|
||||||
import org.bigbluebutton.main.events.ModuleLoadEvent;
|
import org.bigbluebutton.main.events.ModuleLoadEvent;
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* 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.main.model.users
|
||||||
|
{
|
||||||
|
import flash.events.TimerEvent;
|
||||||
|
import flash.utils.Timer;
|
||||||
|
|
||||||
|
import org.as3commons.logging.api.ILogger;
|
||||||
|
import org.as3commons.logging.api.getClassLogger;
|
||||||
|
|
||||||
|
public class AutoReconnect
|
||||||
|
{
|
||||||
|
private static const LOGGER:ILogger = getClassLogger(AutoReconnect);
|
||||||
|
|
||||||
|
private var _backoff:Number = 2000;
|
||||||
|
private var _reconnectCallback:Function;
|
||||||
|
private var _reconnectParameters:Array;
|
||||||
|
|
||||||
|
public function onDisconnect(callback:Function, parameters:Array):void {
|
||||||
|
LOGGER.debug("onDisconnect, parameters={0}", [parameters.toString()]);
|
||||||
|
_reconnectCallback = callback;
|
||||||
|
_reconnectParameters = parameters;
|
||||||
|
attemptReconnect(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onConnectionAttemptFailed():void {
|
||||||
|
LOGGER.warn("onConnectionAttemptFailed");
|
||||||
|
attemptReconnect(_backoff);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function attemptReconnect(backoff:Number):void {
|
||||||
|
LOGGER.debug("attemptReconnect backoff={0}", [backoff]);
|
||||||
|
var retryTimer:Timer = new Timer(backoff, 1);
|
||||||
|
retryTimer.addEventListener(TimerEvent.TIMER, function():void {
|
||||||
|
LOGGER.debug("Reconnecting");
|
||||||
|
_reconnectCallback.apply(null, _reconnectParameters);
|
||||||
|
});
|
||||||
|
retryTimer.start();
|
||||||
|
if (_backoff < 16000) _backoff = Math.max(backoff, 500) *2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -1,405 +1,435 @@
|
|||||||
/**
|
/**
|
||||||
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
|
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
|
* 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
|
* 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
|
* 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
|
* Foundation; either version 3.0 of the License, or (at your option) any later
|
||||||
* version.
|
* version.
|
||||||
*
|
*
|
||||||
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
* 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
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
* 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
|
* You should have received a copy of the GNU Lesser General Public License along
|
||||||
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package org.bigbluebutton.main.model.users
|
package org.bigbluebutton.main.model.users
|
||||||
{
|
{
|
||||||
import com.asfusion.mate.events.Dispatcher;
|
import com.asfusion.mate.events.Dispatcher;
|
||||||
|
|
||||||
import flash.events.AsyncErrorEvent;
|
import flash.events.AsyncErrorEvent;
|
||||||
import flash.events.IOErrorEvent;
|
import flash.events.IOErrorEvent;
|
||||||
import flash.events.NetStatusEvent;
|
import flash.events.NetStatusEvent;
|
||||||
import flash.events.SecurityErrorEvent;
|
import flash.events.SecurityErrorEvent;
|
||||||
import flash.events.TimerEvent;
|
import flash.events.TimerEvent;
|
||||||
import flash.net.NetConnection;
|
import flash.net.NetConnection;
|
||||||
import flash.net.Responder;
|
import flash.net.Responder;
|
||||||
import flash.utils.Timer;
|
import flash.utils.Timer;
|
||||||
|
|
||||||
import org.as3commons.logging.api.ILogger;
|
import org.as3commons.logging.api.ILogger;
|
||||||
import org.as3commons.logging.api.getClassLogger;
|
import org.as3commons.logging.api.getClassLogger;
|
||||||
import org.as3commons.logging.util.jsonXify;
|
import org.as3commons.logging.util.jsonXify;
|
||||||
import org.bigbluebutton.core.UsersUtil;
|
import org.bigbluebutton.core.UsersUtil;
|
||||||
import org.bigbluebutton.core.services.BandwidthMonitor;
|
import org.bigbluebutton.core.managers.ReconnectionManager;
|
||||||
import org.bigbluebutton.main.api.JSLog;
|
import org.bigbluebutton.core.services.BandwidthMonitor;
|
||||||
import org.bigbluebutton.main.events.InvalidAuthTokenEvent;
|
import org.bigbluebutton.main.api.JSLog;
|
||||||
import org.bigbluebutton.main.model.ConferenceParameters;
|
import org.bigbluebutton.main.events.BBBEvent;
|
||||||
import org.bigbluebutton.main.model.users.events.ConnectionFailedEvent;
|
import org.bigbluebutton.main.events.InvalidAuthTokenEvent;
|
||||||
|
import org.bigbluebutton.main.model.ConferenceParameters;
|
||||||
|
import org.bigbluebutton.main.model.users.events.ConnectionFailedEvent;
|
||||||
import org.bigbluebutton.main.model.users.events.UsersConnectionEvent;
|
import org.bigbluebutton.main.model.users.events.UsersConnectionEvent;
|
||||||
|
|
||||||
public class NetConnectionDelegate
|
public class NetConnectionDelegate
|
||||||
{
|
{
|
||||||
private static const LOGGER:ILogger = getClassLogger(NetConnectionDelegate);
|
private static const LOGGER:ILogger = getClassLogger(NetConnectionDelegate);
|
||||||
|
|
||||||
private var _netConnection:NetConnection;
|
private var _netConnection:NetConnection;
|
||||||
private var connectionId:Number;
|
private var connectionId:Number;
|
||||||
private var connected:Boolean = false;
|
private var connected:Boolean = false;
|
||||||
|
|
||||||
private var _userid:Number = -1;
|
private var _userid:Number = -1;
|
||||||
private var _role:String = "unknown";
|
private var _role:String = "unknown";
|
||||||
private var _applicationURI:String;
|
private var _applicationURI:String;
|
||||||
private var _conferenceParameters:ConferenceParameters;
|
private var _conferenceParameters:ConferenceParameters;
|
||||||
|
|
||||||
// These two are just placeholders. We'll get this from the server later and
|
// These two are just placeholders. We'll get this from the server later and
|
||||||
// then pass to other modules.
|
// then pass to other modules.
|
||||||
private var _authToken:String = "AUTHORIZED";
|
private var _authToken:String = "AUTHORIZED";
|
||||||
private var _room:String;
|
private var _room:String;
|
||||||
private var tried_tunneling:Boolean = false;
|
private var tried_tunneling:Boolean = false;
|
||||||
private var logoutOnUserCommand:Boolean = false;
|
private var logoutOnUserCommand:Boolean = false;
|
||||||
private var backoff:Number = 2000;
|
private var backoff:Number = 2000;
|
||||||
|
|
||||||
private var dispatcher:Dispatcher;
|
private var dispatcher:Dispatcher;
|
||||||
private var _messageListeners:Array = new Array();
|
private var _messageListeners:Array = new Array();
|
||||||
|
|
||||||
private var authenticated: Boolean = false;
|
private var authenticated: Boolean = false;
|
||||||
|
private var reconnecting:Boolean = false;
|
||||||
public function NetConnectionDelegate():void
|
|
||||||
{
|
public function NetConnectionDelegate():void
|
||||||
dispatcher = new Dispatcher();
|
{
|
||||||
|
dispatcher = new Dispatcher();
|
||||||
_netConnection = new NetConnection();
|
|
||||||
_netConnection.proxyType = "best";
|
_netConnection = new NetConnection();
|
||||||
_netConnection.client = this;
|
_netConnection.proxyType = "best";
|
||||||
_netConnection.addEventListener( NetStatusEvent.NET_STATUS, netStatus );
|
_netConnection.client = this;
|
||||||
_netConnection.addEventListener( AsyncErrorEvent.ASYNC_ERROR, netASyncError );
|
_netConnection.addEventListener( NetStatusEvent.NET_STATUS, netStatus );
|
||||||
_netConnection.addEventListener( SecurityErrorEvent.SECURITY_ERROR, netSecurityError );
|
_netConnection.addEventListener( AsyncErrorEvent.ASYNC_ERROR, netASyncError );
|
||||||
_netConnection.addEventListener( IOErrorEvent.IO_ERROR, netIOError );
|
_netConnection.addEventListener( SecurityErrorEvent.SECURITY_ERROR, netSecurityError );
|
||||||
}
|
_netConnection.addEventListener( IOErrorEvent.IO_ERROR, netIOError );
|
||||||
|
}
|
||||||
public function setUri(uri:String):void {
|
|
||||||
_applicationURI = uri;
|
public function setUri(uri:String):void {
|
||||||
}
|
_applicationURI = uri;
|
||||||
|
}
|
||||||
|
|
||||||
public function get connection():NetConnection {
|
|
||||||
return _netConnection;
|
public function get connection():NetConnection {
|
||||||
}
|
return _netConnection;
|
||||||
|
}
|
||||||
public function addMessageListener(listener:IMessageListener):void {
|
|
||||||
_messageListeners.push(listener);
|
public function addMessageListener(listener:IMessageListener):void {
|
||||||
}
|
_messageListeners.push(listener);
|
||||||
|
}
|
||||||
public function removeMessageListener(listener:IMessageListener):void {
|
|
||||||
for (var ob:int=0; ob<_messageListeners.length; ob++) {
|
public function removeMessageListener(listener:IMessageListener):void {
|
||||||
if (_messageListeners[ob] == listener) {
|
for (var ob:int=0; ob<_messageListeners.length; ob++) {
|
||||||
_messageListeners.splice (ob,1);
|
if (_messageListeners[ob] == listener) {
|
||||||
break;
|
_messageListeners.splice (ob,1);
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private function notifyListeners(messageName:String, message:Object):void {
|
|
||||||
if (messageName != null && messageName != "") {
|
private function notifyListeners(messageName:String, message:Object):void {
|
||||||
for (var notify:String in _messageListeners) {
|
if (messageName != null && messageName != "") {
|
||||||
_messageListeners[notify].onMessage(messageName, message);
|
for (var notify:String in _messageListeners) {
|
||||||
}
|
_messageListeners[notify].onMessage(messageName, message);
|
||||||
} else {
|
}
|
||||||
LOGGER.debug("Message name is undefined");
|
} else {
|
||||||
}
|
LOGGER.debug("Message name is undefined");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public function onMessageFromServer(messageName:String, msg:Object):void {
|
|
||||||
LOGGER.debug("Got message from server [{0}] user=[{1}]", [messageName, UsersUtil.getMyUsername()]);
|
public function onMessageFromServer(messageName:String, msg:Object):void {
|
||||||
if (!authenticated && (messageName == "validateAuthTokenReply")) {
|
LOGGER.debug("Got message from server [{0}] user=[{1}]", [messageName, UsersUtil.getMyUsername()]);
|
||||||
handleValidateAuthTokenReply(msg)
|
if (!authenticated && (messageName == "validateAuthTokenReply")) {
|
||||||
} else if (messageName == "validateAuthTokenTimedOut") {
|
handleValidateAuthTokenReply(msg)
|
||||||
handleValidateAuthTokenTimedOut(msg)
|
} else if (messageName == "validateAuthTokenTimedOut") {
|
||||||
} else if (authenticated) {
|
handleValidateAuthTokenTimedOut(msg)
|
||||||
notifyListeners(messageName, msg);
|
} else if (authenticated) {
|
||||||
} else {
|
notifyListeners(messageName, msg);
|
||||||
LOGGER.debug("Ignoring message=[{0}] as our token hasn't been validated yet.", [messageName]);
|
} else {
|
||||||
}
|
LOGGER.debug("Ignoring message=[{0}] as our token hasn't been validated yet.", [messageName]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private function validateToken():void {
|
|
||||||
var message:Object = new Object();
|
private function validateToken():void {
|
||||||
message["userId"] = _conferenceParameters.internalUserID;
|
var message:Object = new Object();
|
||||||
message["authToken"] = _conferenceParameters.authToken;
|
message["userId"] = _conferenceParameters.internalUserID;
|
||||||
|
message["authToken"] = _conferenceParameters.authToken;
|
||||||
sendMessage(
|
|
||||||
"validateToken",// Remote function name
|
sendMessage(
|
||||||
// result - On successful result
|
"validateToken",// Remote function name
|
||||||
function(result:Object):void {
|
// result - On successful result
|
||||||
LOGGER.debug("validating token for [{0}]", [_conferenceParameters.internalUserID]);
|
function(result:Object):void {
|
||||||
},
|
LOGGER.debug("validating token for [{0}]", [_conferenceParameters.internalUserID]);
|
||||||
// status - On error occurred
|
},
|
||||||
function(status:Object):void {
|
// status - On error occurred
|
||||||
LOGGER.error("Error occurred:");
|
function(status:Object):void {
|
||||||
for (var x:Object in status) {
|
LOGGER.error("Error occurred:");
|
||||||
LOGGER.error(x + " : " + status[x]);
|
for (var x:Object in status) {
|
||||||
}
|
LOGGER.error(x + " : " + status[x]);
|
||||||
},
|
}
|
||||||
message
|
},
|
||||||
); //_netConnection.call
|
message
|
||||||
}
|
); //_netConnection.call
|
||||||
|
}
|
||||||
private function handleValidateAuthTokenTimedOut(msg: Object):void {
|
|
||||||
LOGGER.debug("*** handleValidateAuthTokenTimedOut {0} **** \n", [msg.msg]);
|
private function handleValidateAuthTokenTimedOut(msg: Object):void {
|
||||||
var map:Object = JSON.parse(msg.msg);
|
LOGGER.debug("*** handleValidateAuthTokenTimedOut {0} **** \n", [msg.msg]);
|
||||||
var tokenValid: Boolean = map.valid as Boolean;
|
var map:Object = JSON.parse(msg.msg);
|
||||||
var userId: String = map.userId as String;
|
var tokenValid: Boolean = map.valid as Boolean;
|
||||||
|
var userId: String = map.userId as String;
|
||||||
var logData:Object = new Object();
|
|
||||||
logData.user = UsersUtil.getUserData();
|
var logData:Object = new Object();
|
||||||
JSLog.critical("Validate auth token timed out.", logData);
|
logData.user = UsersUtil.getUserData();
|
||||||
|
JSLog.critical("Validate auth token timed out.", logData);
|
||||||
if (tokenValid) {
|
|
||||||
authenticated = true;
|
if (tokenValid) {
|
||||||
LOGGER.debug("*** handleValidateAuthTokenTimedOut. valid=[{0}] **** \n", [tokenValid]);
|
authenticated = true;
|
||||||
} else {
|
LOGGER.debug("*** handleValidateAuthTokenTimedOut. valid=[{0}] **** \n", [tokenValid]);
|
||||||
LOGGER.debug("*** handleValidateAuthTokenTimedOut. valid=[{0}] **** \n", [tokenValid]);
|
} else {
|
||||||
dispatcher.dispatchEvent(new InvalidAuthTokenEvent());
|
LOGGER.debug("*** handleValidateAuthTokenTimedOut. valid=[{0}] **** \n", [tokenValid]);
|
||||||
}
|
dispatcher.dispatchEvent(new InvalidAuthTokenEvent());
|
||||||
}
|
}
|
||||||
|
if (reconnecting) {
|
||||||
private function handleValidateAuthTokenReply(msg: Object):void {
|
onReconnect();
|
||||||
LOGGER.debug("*** handleValidateAuthTokenReply {0} **** \n", [msg.msg]);
|
reconnecting = false;
|
||||||
var map:Object = JSON.parse(msg.msg);
|
}
|
||||||
var tokenValid: Boolean = map.valid as Boolean;
|
}
|
||||||
var userId: String = map.userId as String;
|
|
||||||
|
private function handleValidateAuthTokenReply(msg: Object):void {
|
||||||
if (tokenValid) {
|
LOGGER.debug("*** handleValidateAuthTokenReply {0} **** \n", [msg.msg]);
|
||||||
authenticated = true;
|
var map:Object = JSON.parse(msg.msg);
|
||||||
LOGGER.debug("*** handleValidateAuthTokenReply. valid=[{0}] **** \n", [tokenValid]);
|
var tokenValid: Boolean = map.valid as Boolean;
|
||||||
} else {
|
var userId: String = map.userId as String;
|
||||||
LOGGER.debug("*** handleValidateAuthTokenReply. valid=[{0}] **** \n", [tokenValid]);
|
|
||||||
dispatcher.dispatchEvent(new InvalidAuthTokenEvent());
|
if (tokenValid) {
|
||||||
}
|
authenticated = true;
|
||||||
}
|
LOGGER.debug("*** handleValidateAuthTokenReply. valid=[{0}] **** \n", [tokenValid]);
|
||||||
|
} else {
|
||||||
private function sendConnectionSuccessEvent(userid:String):void{
|
LOGGER.debug("*** handleValidateAuthTokenReply. valid=[{0}] **** \n", [tokenValid]);
|
||||||
var e:UsersConnectionEvent = new UsersConnectionEvent(UsersConnectionEvent.CONNECTION_SUCCESS);
|
dispatcher.dispatchEvent(new InvalidAuthTokenEvent());
|
||||||
e.userid = userid;
|
}
|
||||||
dispatcher.dispatchEvent(e);
|
if (reconnecting) {
|
||||||
|
onReconnect();
|
||||||
}
|
reconnecting = false;
|
||||||
|
}
|
||||||
public function sendMessage(service:String, onSuccess:Function, onFailure:Function, message:Object=null):void {
|
}
|
||||||
LOGGER.debug("SENDING [{0}]", [service]);
|
|
||||||
var responder:Responder = new Responder(
|
private function onReconnect():void {
|
||||||
function(result:Object):void { // On successful result
|
if (authenticated) {
|
||||||
onSuccess("Successfully sent [" + service + "].");
|
onReconnectSuccess();
|
||||||
},
|
} else {
|
||||||
function(status:Object):void { // status - On error occurred
|
onReconnectFailed();
|
||||||
var errorReason:String = "Failed to send [" + service + "]:\n";
|
}
|
||||||
for (var x:Object in status) {
|
}
|
||||||
errorReason += "\t" + x + " : " + status[x];
|
|
||||||
}
|
private function onReconnectSuccess():void {
|
||||||
}
|
var attemptSucceeded:BBBEvent = new BBBEvent(BBBEvent.RECONNECT_CONNECTION_ATTEMPT_SUCCEEDED_EVENT);
|
||||||
);
|
attemptSucceeded.payload.type = ReconnectionManager.BIGBLUEBUTTON_CONNECTION;
|
||||||
|
dispatcher.dispatchEvent(attemptSucceeded);
|
||||||
if (message == null) {
|
}
|
||||||
_netConnection.call(service, responder);
|
|
||||||
} else {
|
private function onReconnectFailed():void {
|
||||||
_netConnection.call(service, responder, message);
|
sendUserLoggedOutEvent();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private function sendConnectionSuccessEvent(userid:String):void{
|
||||||
/**
|
var e:UsersConnectionEvent = new UsersConnectionEvent(UsersConnectionEvent.CONNECTION_SUCCESS);
|
||||||
* Connect to the server.
|
e.userid = userid;
|
||||||
* uri: The uri to the conference application.
|
dispatcher.dispatchEvent(e);
|
||||||
* username: Fullname of the participant.
|
|
||||||
* role: MODERATOR/VIEWER
|
}
|
||||||
* conference: The conference room
|
|
||||||
* mode: LIVE/PLAYBACK - Live:when used to collaborate, Playback:when being used to playback a recorded conference.
|
public function sendMessage(service:String, onSuccess:Function, onFailure:Function, message:Object=null):void {
|
||||||
* room: Need the room number when playing back a recorded conference. When LIVE, the room is taken from the URI.
|
LOGGER.debug("SENDING [{0}]", [service]);
|
||||||
*/
|
var responder:Responder = new Responder(
|
||||||
public function connect(params:ConferenceParameters, tunnel:Boolean = false):void {
|
function(result:Object):void { // On successful result
|
||||||
_conferenceParameters = params;
|
onSuccess("Successfully sent [" + service + "].");
|
||||||
|
},
|
||||||
tried_tunneling = tunnel;
|
function(status:Object):void { // status - On error occurred
|
||||||
|
var errorReason:String = "Failed to send [" + service + "]:\n";
|
||||||
try {
|
for (var x:Object in status) {
|
||||||
var uri:String = _applicationURI + "/" + _conferenceParameters.room;
|
errorReason += "\t" + x + " : " + status[x];
|
||||||
|
}
|
||||||
LOGGER.debug("::Connecting to {0} [{1}]", [uri, jsonXify(_conferenceParameters)]);
|
}
|
||||||
_netConnection.connect(uri, _conferenceParameters.username, _conferenceParameters.role,
|
);
|
||||||
_conferenceParameters.room, _conferenceParameters.voicebridge,
|
|
||||||
_conferenceParameters.record, _conferenceParameters.externUserID,
|
if (message == null) {
|
||||||
_conferenceParameters.internalUserID, _conferenceParameters.muteOnStart, _conferenceParameters.lockSettings);
|
_netConnection.call(service, responder);
|
||||||
} catch(e:ArgumentError) {
|
} else {
|
||||||
// Invalid parameters.
|
_netConnection.call(service, responder, message);
|
||||||
switch (e.errorID) {
|
}
|
||||||
case 2004 :
|
}
|
||||||
LOGGER.debug("Error! Invalid server location: {0}", [uri]);
|
|
||||||
break;
|
/**
|
||||||
default :
|
* Connect to the server.
|
||||||
LOGGER.debug("UNKNOWN Error! Invalid server location: {0}", [uri]);
|
* uri: The uri to the conference application.
|
||||||
break;
|
* username: Fullname of the participant.
|
||||||
}
|
* role: MODERATOR/VIEWER
|
||||||
}
|
* conference: The conference room
|
||||||
}
|
* mode: LIVE/PLAYBACK - Live:when used to collaborate, Playback:when being used to playback a recorded conference.
|
||||||
|
* room: Need the room number when playing back a recorded conference. When LIVE, the room is taken from the URI.
|
||||||
public function disconnect(logoutOnUserCommand:Boolean):void {
|
*/
|
||||||
this.logoutOnUserCommand = logoutOnUserCommand;
|
public function connect(params:ConferenceParameters, tunnel:Boolean = false):void {
|
||||||
_netConnection.close();
|
_conferenceParameters = params;
|
||||||
}
|
|
||||||
|
tried_tunneling = tunnel;
|
||||||
|
|
||||||
public function forceClose():void {
|
try {
|
||||||
_netConnection.close();
|
var uri:String = _applicationURI + "/" + _conferenceParameters.room;
|
||||||
}
|
|
||||||
|
LOGGER.debug("::Connecting to {0} [{1}]", [uri, jsonXify(_conferenceParameters)]);
|
||||||
protected function netStatus(event:NetStatusEvent):void {
|
_netConnection.connect(uri, _conferenceParameters.username, _conferenceParameters.role,
|
||||||
handleResult( event );
|
_conferenceParameters.room, _conferenceParameters.voicebridge,
|
||||||
}
|
_conferenceParameters.record, _conferenceParameters.externUserID,
|
||||||
|
_conferenceParameters.internalUserID, _conferenceParameters.muteOnStart, _conferenceParameters.lockSettings);
|
||||||
private var _bwMon:BandwidthMonitor = new BandwidthMonitor();
|
} catch(e:ArgumentError) {
|
||||||
|
// Invalid parameters.
|
||||||
private function startMonitoringBandwidth():void {
|
switch (e.errorID) {
|
||||||
LOGGER.info("Start monitoring bandwidth.");
|
case 2004 :
|
||||||
var pattern:RegExp = /(?P<protocol>.+):\/\/(?P<server>.+)\/(?P<app>.+)/;
|
LOGGER.debug("Error! Invalid server location: {0}", [uri]);
|
||||||
var result:Array = pattern.exec(_applicationURI);
|
break;
|
||||||
_bwMon.serverURL = result.server;
|
default :
|
||||||
_bwMon.serverApplication = "video";
|
LOGGER.debug("UNKNOWN Error! Invalid server location: {0}", [uri]);
|
||||||
_bwMon.start();
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private var autoReconnectTimer:Timer = new Timer(1000, 1);
|
}
|
||||||
|
|
||||||
public function handleResult(event:Object):void {
|
public function disconnect(logoutOnUserCommand:Boolean):void {
|
||||||
var info : Object = event.info;
|
this.logoutOnUserCommand = logoutOnUserCommand;
|
||||||
var statusCode : String = info.code;
|
_netConnection.close();
|
||||||
|
}
|
||||||
var logData:Object = new Object();
|
|
||||||
logData.user = UsersUtil.getUserData();
|
|
||||||
|
public function forceClose():void {
|
||||||
switch (statusCode) {
|
_netConnection.close();
|
||||||
case "NetConnection.Connect.Success":
|
}
|
||||||
LOGGER.debug("Connection to viewers application succeeded.");
|
|
||||||
JSLog.debug("Successfully connected to BBB App.", logData);
|
protected function netStatus(event:NetStatusEvent):void {
|
||||||
|
handleResult( event );
|
||||||
validateToken();
|
}
|
||||||
|
|
||||||
break;
|
private var _bwMon:BandwidthMonitor = new BandwidthMonitor();
|
||||||
|
|
||||||
case "NetConnection.Connect.Failed":
|
private function startMonitoringBandwidth():void {
|
||||||
if (tried_tunneling) {
|
LOGGER.info("Start monitoring bandwidth.");
|
||||||
LOGGER.error(":Connection to viewers application failed...even when tunneling");
|
var pattern:RegExp = /(?P<protocol>.+):\/\/(?P<server>.+)\/(?P<app>.+)/;
|
||||||
sendConnectionFailedEvent(ConnectionFailedEvent.CONNECTION_FAILED);
|
var result:Array = pattern.exec(_applicationURI);
|
||||||
} else {
|
_bwMon.serverURL = result.server;
|
||||||
disconnect(false);
|
_bwMon.serverApplication = "video";
|
||||||
LOGGER.error(":Connection to viewers application failed...try tunneling");
|
_bwMon.start();
|
||||||
var rtmptRetryTimer:Timer = new Timer(1000, 1);
|
}
|
||||||
rtmptRetryTimer.addEventListener("timer", rtmptRetryTimerHandler);
|
|
||||||
rtmptRetryTimer.start();
|
public function handleResult(event:Object):void {
|
||||||
}
|
var info : Object = event.info;
|
||||||
break;
|
var statusCode : String = info.code;
|
||||||
|
|
||||||
case "NetConnection.Connect.Closed":
|
var logData:Object = new Object();
|
||||||
LOGGER.debug("Connection to viewers application closed");
|
logData.user = UsersUtil.getUserData();
|
||||||
sendConnectionFailedEvent(ConnectionFailedEvent.CONNECTION_CLOSED);
|
|
||||||
|
switch (statusCode) {
|
||||||
break;
|
case "NetConnection.Connect.Success":
|
||||||
|
LOGGER.debug("Connection to viewers application succeeded.");
|
||||||
case "NetConnection.Connect.InvalidApp":
|
JSLog.debug("Successfully connected to BBB App.", logData);
|
||||||
LOGGER.debug(":viewers application not found on server");
|
|
||||||
sendConnectionFailedEvent(ConnectionFailedEvent.INVALID_APP);
|
validateToken();
|
||||||
break;
|
|
||||||
|
break;
|
||||||
case "NetConnection.Connect.AppShutDown":
|
|
||||||
LOGGER.debug(":viewers application has been shutdown");
|
case "NetConnection.Connect.Failed":
|
||||||
sendConnectionFailedEvent(ConnectionFailedEvent.APP_SHUTDOWN);
|
if (tried_tunneling) {
|
||||||
break;
|
LOGGER.error(":Connection to viewers application failed...even when tunneling");
|
||||||
|
sendConnectionFailedEvent(ConnectionFailedEvent.CONNECTION_FAILED);
|
||||||
case "NetConnection.Connect.Rejected":
|
} else {
|
||||||
LOGGER.debug(":Connection to the server rejected. Uri: {0}. Check if the red5 specified in the uri exists and is running", [_applicationURI]);
|
disconnect(false);
|
||||||
sendConnectionFailedEvent(ConnectionFailedEvent.CONNECTION_REJECTED);
|
LOGGER.error(":Connection to viewers application failed...try tunneling");
|
||||||
break;
|
var rtmptRetryTimer:Timer = new Timer(1000, 1);
|
||||||
|
rtmptRetryTimer.addEventListener("timer", rtmptRetryTimerHandler);
|
||||||
case "NetConnection.Connect.NetworkChange":
|
rtmptRetryTimer.start();
|
||||||
JSLog.warn("Detected network change to BBB App", logData);
|
}
|
||||||
LOGGER.debug("Detected network change. User might be on a wireless and temporarily dropped connection. Doing nothing. Just making a note.");
|
break;
|
||||||
break;
|
|
||||||
|
case "NetConnection.Connect.Closed":
|
||||||
default :
|
LOGGER.debug("Connection to viewers application closed");
|
||||||
LOGGER.debug(":Default status to the viewers application" );
|
sendConnectionFailedEvent(ConnectionFailedEvent.CONNECTION_CLOSED);
|
||||||
sendConnectionFailedEvent(ConnectionFailedEvent.UNKNOWN_REASON);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
case "NetConnection.Connect.InvalidApp":
|
||||||
|
LOGGER.debug(":viewers application not found on server");
|
||||||
private function autoReconnectTimerHandler(event:TimerEvent):void {
|
sendConnectionFailedEvent(ConnectionFailedEvent.INVALID_APP);
|
||||||
LOGGER.debug("autoReconnectTimerHandler: {0}", [event]);
|
break;
|
||||||
connect(_conferenceParameters, tried_tunneling);
|
|
||||||
}
|
case "NetConnection.Connect.AppShutDown":
|
||||||
|
LOGGER.debug(":viewers application has been shutdown");
|
||||||
private function rtmptRetryTimerHandler(event:TimerEvent):void {
|
sendConnectionFailedEvent(ConnectionFailedEvent.APP_SHUTDOWN);
|
||||||
LOGGER.debug("rtmptRetryTimerHandler: {0}", [event]);
|
break;
|
||||||
connect(_conferenceParameters, true);
|
|
||||||
}
|
case "NetConnection.Connect.Rejected":
|
||||||
|
LOGGER.debug(":Connection to the server rejected. Uri: {0}. Check if the red5 specified in the uri exists and is running", [_applicationURI]);
|
||||||
protected function netSecurityError(event: SecurityErrorEvent):void {
|
sendConnectionFailedEvent(ConnectionFailedEvent.CONNECTION_REJECTED);
|
||||||
LOGGER.error("Security error - {0}", [event.text]);
|
break;
|
||||||
sendConnectionFailedEvent(ConnectionFailedEvent.UNKNOWN_REASON);
|
|
||||||
}
|
case "NetConnection.Connect.NetworkChange":
|
||||||
|
JSLog.warn("Detected network change to BBB App", logData);
|
||||||
protected function netIOError(event: IOErrorEvent):void {
|
LOGGER.debug("Detected network change. User might be on a wireless and temporarily dropped connection. Doing nothing. Just making a note.");
|
||||||
LOGGER.error("Input/output error - {0}", [event.text]);
|
break;
|
||||||
sendConnectionFailedEvent(ConnectionFailedEvent.UNKNOWN_REASON);
|
|
||||||
}
|
default :
|
||||||
|
LOGGER.debug(":Default status to the viewers application" );
|
||||||
protected function netASyncError(event: AsyncErrorEvent):void {
|
sendConnectionFailedEvent(ConnectionFailedEvent.UNKNOWN_REASON);
|
||||||
LOGGER.debug("Asynchronous code error - {0}", [event.toString()]);
|
break;
|
||||||
|
}
|
||||||
LOGGER.debug("Asynchronous code error - {0}", [event.toString()]);
|
}
|
||||||
sendConnectionFailedEvent(ConnectionFailedEvent.UNKNOWN_REASON);
|
|
||||||
}
|
private function rtmptRetryTimerHandler(event:TimerEvent):void {
|
||||||
|
LOGGER.debug("rtmptRetryTimerHandler: {0}", [event]);
|
||||||
private function sendConnectionFailedEvent(reason:String):void{
|
connect(_conferenceParameters, true);
|
||||||
var logData:Object = new Object();
|
}
|
||||||
|
|
||||||
if (this.logoutOnUserCommand) {
|
protected function netSecurityError(event: SecurityErrorEvent):void {
|
||||||
logData.reason = "User requested.";
|
LOGGER.error("Security error - {0}", [event.text]);
|
||||||
logData.user = UsersUtil.getUserData();
|
sendConnectionFailedEvent(ConnectionFailedEvent.UNKNOWN_REASON);
|
||||||
JSLog.debug("User logged out from BBB App.", logData);
|
}
|
||||||
sendUserLoggedOutEvent();
|
|
||||||
} else {
|
protected function netIOError(event: IOErrorEvent):void {
|
||||||
logData.reason = reason;
|
LOGGER.error("Input/output error - {0}", [event.text]);
|
||||||
logData.user = UsersUtil.getUserData();
|
sendConnectionFailedEvent(ConnectionFailedEvent.UNKNOWN_REASON);
|
||||||
JSLog.warn("User disconnected from BBB App.", logData);
|
}
|
||||||
var e:ConnectionFailedEvent = new ConnectionFailedEvent(reason);
|
|
||||||
dispatcher.dispatchEvent(e);
|
protected function netASyncError(event: AsyncErrorEvent):void {
|
||||||
}
|
LOGGER.debug("Asynchronous code error - {0}", [event.toString()]);
|
||||||
}
|
|
||||||
|
LOGGER.debug("Asynchronous code error - {0}", [event.toString()]);
|
||||||
private function sendUserLoggedOutEvent():void{
|
sendConnectionFailedEvent(ConnectionFailedEvent.UNKNOWN_REASON);
|
||||||
var e:ConnectionFailedEvent = new ConnectionFailedEvent(ConnectionFailedEvent.USER_LOGGED_OUT);
|
}
|
||||||
dispatcher.dispatchEvent(e);
|
|
||||||
}
|
private function sendConnectionFailedEvent(reason:String):void{
|
||||||
|
var logData:Object = new Object();
|
||||||
private function attemptReconnect(backoff:Number):void{
|
|
||||||
var retryTimer:Timer = new Timer(backoff, 1);
|
if (this.logoutOnUserCommand) {
|
||||||
retryTimer.addEventListener(TimerEvent.TIMER, function():void{
|
logData.reason = "User requested.";
|
||||||
connect(_conferenceParameters, tried_tunneling);
|
logData.user = UsersUtil.getUserData();
|
||||||
});
|
JSLog.debug("User logged out from BBB App.", logData);
|
||||||
retryTimer.start();
|
sendUserLoggedOutEvent();
|
||||||
if (this.backoff < 16000) this.backoff = backoff *2;
|
} else if (reason == ConnectionFailedEvent.CONNECTION_CLOSED) {
|
||||||
}
|
// do not try to reconnect if the connection failed is different than CONNECTION_CLOSED
|
||||||
|
logData.reason = reason;
|
||||||
public function onBWCheck(... rest):Number {
|
logData.user = UsersUtil.getUserData();
|
||||||
return 0;
|
JSLog.warn("User disconnected from BBB App.", logData);
|
||||||
}
|
|
||||||
|
if (reconnecting) {
|
||||||
public function onBWDone(... rest):void {
|
var attemptFailedEvent:BBBEvent = new BBBEvent(BBBEvent.RECONNECT_CONNECTION_ATTEMPT_FAILED_EVENT);
|
||||||
var p_bw:Number;
|
attemptFailedEvent.payload.type = ReconnectionManager.BIGBLUEBUTTON_CONNECTION;
|
||||||
if (rest.length > 0) p_bw = rest[0];
|
dispatcher.dispatchEvent(attemptFailedEvent);
|
||||||
// your application should do something here
|
} else {
|
||||||
// when the bandwidth check is complete
|
reconnecting = true;
|
||||||
LOGGER.debug("bandwidth = {0} Kbps.", [p_bw]);
|
authenticated = false;
|
||||||
}
|
|
||||||
}
|
var disconnectedEvent:BBBEvent = new BBBEvent(BBBEvent.RECONNECT_DISCONNECTED_EVENT);
|
||||||
}
|
disconnectedEvent.payload.type = ReconnectionManager.BIGBLUEBUTTON_CONNECTION;
|
||||||
|
disconnectedEvent.payload.callback = connect;
|
||||||
|
disconnectedEvent.payload.callbackParameters = new Array(_conferenceParameters, tried_tunneling);
|
||||||
|
dispatcher.dispatchEvent(disconnectedEvent);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var e:ConnectionFailedEvent = new ConnectionFailedEvent(reason);
|
||||||
|
dispatcher.dispatchEvent(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sendUserLoggedOutEvent():void{
|
||||||
|
var e:ConnectionFailedEvent = new ConnectionFailedEvent(ConnectionFailedEvent.USER_LOGGED_OUT);
|
||||||
|
dispatcher.dispatchEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onBWCheck(... rest):Number {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onBWDone(... rest):void {
|
||||||
|
var p_bw:Number;
|
||||||
|
if (rest.length > 0) p_bw = rest[0];
|
||||||
|
// your application should do something here
|
||||||
|
// when the bandwidth check is complete
|
||||||
|
LOGGER.debug("bandwidth = {0} Kbps.", [p_bw]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -20,7 +20,11 @@
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
titleLbl.text = value.title;
|
titleLbl.text = value.title;
|
||||||
|
if (value.occurrences > 1) {
|
||||||
|
titleLbl.text = "(" + value.occurrences + ") " + titleLbl.text;
|
||||||
|
}
|
||||||
messageTxt.htmlText = value.message;
|
messageTxt.htmlText = value.message;
|
||||||
|
timeLbl.text = value.time;
|
||||||
|
|
||||||
validateNow();
|
validateNow();
|
||||||
}
|
}
|
||||||
@ -31,4 +35,7 @@
|
|||||||
<mx:Label id="titleLbl" width="100%" styleName="statusTitleStyle"/>
|
<mx:Label id="titleLbl" width="100%" styleName="statusTitleStyle"/>
|
||||||
<mx:Text id="messageTxt" width="100%" styleName="statusMessageStyle"/>
|
<mx:Text id="messageTxt" width="100%" styleName="statusMessageStyle"/>
|
||||||
</mx:VBox>
|
</mx:VBox>
|
||||||
|
<mx:VBox height="100%" verticalAlign="bottom">
|
||||||
|
<mx:Label id="timeLbl" width="100%" styleName="statusTimeStyle"/>
|
||||||
|
</mx:VBox>
|
||||||
</mx:HBox>
|
</mx:HBox>
|
||||||
|
@ -72,11 +72,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
//LogUtil.debug("Progress: " + totalProgress);
|
//LogUtil.debug("Progress: " + totalProgress);
|
||||||
this.setProgress(totalProgress/numModules, 100);
|
this.setProgress(totalProgress/numModules, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function allModulesLoaded(e:ModuleLoadEvent):void{
|
private function allModulesLoaded(e:ModuleLoadEvent):void{
|
||||||
parent.removeChild(this);
|
if (parent != null) parent.removeChild(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function testRTMP(e:PortTestEvent):void{
|
private function testRTMP(e:PortTestEvent):void{
|
||||||
//- Cannot get locale string this early in loading process
|
//- Cannot get locale string this early in loading process
|
||||||
portUpdateStr += "."
|
portUpdateStr += "."
|
||||||
|
@ -23,7 +23,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
|
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
|
||||||
title="{ResourceUtil.getInstance().getString('bbb.logout.title')}" showCloseButton="false" creationComplete="init()"
|
title="{ResourceUtil.getInstance().getString('bbb.logout.title')}" showCloseButton="false" creationComplete="init()"
|
||||||
verticalScrollPolicy="off" horizontalScrollPolicy="off"
|
verticalScrollPolicy="off" horizontalScrollPolicy="off"
|
||||||
x="168" y="86" layout="vertical" width="400" height="200" horizontalAlign="center">
|
x="168" y="86" layout="vertical" width="400" height="110" horizontalAlign="center">
|
||||||
<mx:Script>
|
<mx:Script>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
import mx.core.FlexGlobals;
|
import mx.core.FlexGlobals;
|
||||||
@ -52,6 +52,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
request.method = URLRequestMethod.GET;
|
request.method = URLRequestMethod.GET;
|
||||||
urlLoader = new URLLoader();
|
urlLoader = new URLLoader();
|
||||||
urlLoader.addEventListener(Event.COMPLETE, handleComplete);
|
urlLoader.addEventListener(Event.COMPLETE, handleComplete);
|
||||||
|
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, handleRedirectError);
|
||||||
urlLoader.load(request);
|
urlLoader.load(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,6 +78,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
PopUpManager.removePopUp(this);
|
PopUpManager.removePopUp(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function handleRedirectError(e:IOErrorEvent):void {
|
||||||
|
PopUpManager.removePopUp(this);
|
||||||
|
}
|
||||||
|
|
||||||
private function onUserLoggedOutWindowClose(e:Event):void {
|
private function onUserLoggedOutWindowClose(e:Event):void {
|
||||||
PopUpManager.removePopUp(this);
|
PopUpManager.removePopUp(this);
|
||||||
}
|
}
|
||||||
@ -110,17 +115,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function reconnect():void {
|
|
||||||
ExternalInterface.call("document.location.reload", true);
|
|
||||||
}
|
|
||||||
]]>
|
]]>
|
||||||
</mx:Script>
|
</mx:Script>
|
||||||
<mx:VBox width="100%" height="100%" horizontalAlign="center">
|
<mx:VBox width="100%" height="100%" horizontalAlign="center">
|
||||||
<mx:Text text="{message}"/>
|
<mx:Text text="{message}"/>
|
||||||
<mx:Button id="okBtn" label="{ResourceUtil.getInstance().getString('bbb.logout.button.label')}" click="redirect()"/>
|
<mx:Button id="okBtn" label="{ResourceUtil.getInstance().getString('bbb.logout.button.label')}" click="redirect()"/>
|
||||||
<mx:HRule width="100%" />
|
|
||||||
<mx:Text width="380" textAlign="center" text="{ResourceUtil.getInstance().getString('bbb.logout.refresh.message')}" />
|
|
||||||
<mx:Button id="reconnectBtn" label="{ResourceUtil.getInstance().getString('bbb.logout.refresh.label')}" click="reconnect()" />
|
|
||||||
</mx:VBox>
|
</mx:VBox>
|
||||||
</mx:TitleWindow>
|
</mx:TitleWindow>
|
||||||
|
@ -83,7 +83,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
import org.as3commons.logging.api.getClassLogger;
|
import org.as3commons.logging.api.getClassLogger;
|
||||||
import org.bigbluebutton.common.IBbbModuleWindow;
|
import org.bigbluebutton.common.IBbbModuleWindow;
|
||||||
import org.bigbluebutton.common.Images;
|
import org.bigbluebutton.common.Images;
|
||||||
import org.bigbluebutton.common.LogUtil;
|
|
||||||
import org.bigbluebutton.common.events.AddUIComponentToMainCanvas;
|
import org.bigbluebutton.common.events.AddUIComponentToMainCanvas;
|
||||||
import org.bigbluebutton.common.events.CloseWindowEvent;
|
import org.bigbluebutton.common.events.CloseWindowEvent;
|
||||||
import org.bigbluebutton.common.events.OpenWindowEvent;
|
import org.bigbluebutton.common.events.OpenWindowEvent;
|
||||||
@ -164,7 +163,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function initOptions(e:Event):void {
|
public function initOptions(e:Event):void {
|
||||||
LogUtil.initLogging();
|
|
||||||
UserManager.getInstance().getConference().configLockSettings();
|
UserManager.getInstance().getConference().configLockSettings();
|
||||||
layoutOptions = new LayoutOptions();
|
layoutOptions = new LayoutOptions();
|
||||||
layoutOptions.parseOptions();
|
layoutOptions.parseOptions();
|
||||||
@ -585,6 +583,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
private function handleInvalidAuthToken(event:InvalidAuthTokenEvent):void {
|
private function handleInvalidAuthToken(event:InvalidAuthTokenEvent):void {
|
||||||
showlogoutWindow(ResourceUtil.getInstance().getString('bbb.mainshell.invalidAuthToken'));
|
showlogoutWindow(ResourceUtil.getInstance().getString('bbb.mainshell.invalidAuthToken'));
|
||||||
|
globalDispatcher.dispatchEvent(new BBBEvent(BBBEvent.CANCEL_RECONNECTION_EVENT));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleRemoveToolbarComponent(event:ToolbarButtonEvent):void {
|
private function handleRemoveToolbarComponent(event:ToolbarButtonEvent):void {
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
|
||||||
|
|
||||||
|
Copyright (c) 2015 BigBlueButton Inc. and by respective authors (see below).
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU Lesser General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3.0 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml"
|
||||||
|
xmlns:mate="http://mate.asfusion.com/"
|
||||||
|
verticalScrollPolicy="off"
|
||||||
|
horizontalScrollPolicy="off"
|
||||||
|
horizontalAlign="center"
|
||||||
|
width="250"
|
||||||
|
title="{ResourceUtil.getInstance().getString('bbb.connection.failure')}">
|
||||||
|
|
||||||
|
<mx:Script>
|
||||||
|
<![CDATA[
|
||||||
|
import org.bigbluebutton.util.i18n.ResourceUtil;
|
||||||
|
]]>
|
||||||
|
</mx:Script>
|
||||||
|
<mx:HBox width="100%" height="100%" verticalAlign="middle">
|
||||||
|
<mx:Box
|
||||||
|
paddingBottom="10"
|
||||||
|
paddingTop="10"
|
||||||
|
paddingLeft="10"
|
||||||
|
paddingRight="10"
|
||||||
|
>
|
||||||
|
<mx:Image id="typeImg" source="{typeImg.getStyle('refreshImage')}" width="34" height="34" styleName="statusImageStyle" />
|
||||||
|
</mx:Box>
|
||||||
|
<mx:Text
|
||||||
|
selectable="false"
|
||||||
|
text="{ResourceUtil.getInstance().getString('bbb.connection.reconnecting')}"
|
||||||
|
width="100%"/>
|
||||||
|
</mx:HBox>
|
||||||
|
</mx:Panel>
|
@ -33,6 +33,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
<mx:Script>
|
<mx:Script>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
|
import flash.globalization.DateTimeFormatter;
|
||||||
|
import flash.globalization.DateTimeStyle;
|
||||||
|
import flash.globalization.LocaleID;
|
||||||
|
|
||||||
import mx.controls.ToolTip;
|
import mx.controls.ToolTip;
|
||||||
import mx.core.FlexGlobals;
|
import mx.core.FlexGlobals;
|
||||||
import mx.managers.PopUpManager;
|
import mx.managers.PopUpManager;
|
||||||
@ -58,24 +62,38 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function handleSuccessMessageEvent(e:ClientStatusEvent):void {
|
private function handleSuccessMessageEvent(e:ClientStatusEvent):void {
|
||||||
if(isUniqueMessage("success", e.title, e.message)) {
|
handleMessageEvent("success", e);
|
||||||
messages.push({type:"success",title:e.title,message:e.message});
|
|
||||||
showNotification();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleWarningMessageEvent(e:ClientStatusEvent):void {
|
private function handleWarningMessageEvent(e:ClientStatusEvent):void {
|
||||||
if(isUniqueMessage("warning", e.title, e.message)) {
|
handleMessageEvent("warning", e);
|
||||||
messages.push({type:"warning",title:e.title,message:e.message});
|
|
||||||
showNotification();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleFailMessageEvent(e:ClientStatusEvent):void {
|
private function handleFailMessageEvent(e:ClientStatusEvent):void {
|
||||||
if(isUniqueMessage("fail", e.title, e.message)) {
|
handleMessageEvent("fail", e);
|
||||||
messages.push({type:"fail",title:e.title,message:e.message});
|
}
|
||||||
showNotification();
|
|
||||||
|
private function handleMessageEvent(type:String, e:ClientStatusEvent):void {
|
||||||
|
var index:Number = getMessageIndex(type, e.title, e.message);
|
||||||
|
var obj:Object;
|
||||||
|
if (index != -1) {
|
||||||
|
obj = messages.splice(index, 1)[0];
|
||||||
|
obj.occurrences++;
|
||||||
|
} else {
|
||||||
|
obj = {
|
||||||
|
type: type,
|
||||||
|
title: e.title,
|
||||||
|
message: e.message,
|
||||||
|
occurrences: 1
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var dtf:DateTimeFormatter = new DateTimeFormatter(LocaleID.DEFAULT, DateTimeStyle.NONE, DateTimeStyle.MEDIUM);
|
||||||
|
var time:String = dtf.format(new Date());
|
||||||
|
obj.time = time;
|
||||||
|
|
||||||
|
messages.push(obj);
|
||||||
|
showNotification();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function showNotification():void {
|
private function showNotification():void {
|
||||||
@ -92,12 +110,12 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function isUniqueMessage(type:String, title:String, message:String):Boolean {
|
private function getMessageIndex(type:String, title:String, message:String):int {
|
||||||
for (var i:Number=0; i<messages.length; i++) {
|
for (var i:Number=0; i<messages.length; i++) {
|
||||||
if (messages[i].type == type && messages[i].title == title && messages[i].message == message)
|
if (messages[i].type == type && messages[i].title == title && messages[i].message == message)
|
||||||
return false;
|
return i;
|
||||||
}
|
}
|
||||||
return true;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleButtonClick():void {
|
private function handleButtonClick():void {
|
||||||
|
@ -116,12 +116,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
private function noButtonClicked():void {
|
private function noButtonClicked():void {
|
||||||
userClosed = true;
|
userClosed = true;
|
||||||
LOGGER.warn("Echo test failed.");
|
LOGGER.warn("Echo test failed.");
|
||||||
|
|
||||||
var logData:Object = new Object();
|
|
||||||
logData.reason = "User requested.";
|
|
||||||
logData.user = UsersUtil.getUserData();
|
|
||||||
JSLog.info("WebRtc Echo test failed.", logData);
|
|
||||||
|
|
||||||
var dispatcher:Dispatcher = new Dispatcher();
|
var dispatcher:Dispatcher = new Dispatcher();
|
||||||
dispatcher.dispatchEvent(new WebRTCEchoTestEvent(WebRTCEchoTestEvent.WEBRTC_ECHO_TEST_NO_AUDIO));
|
dispatcher.dispatchEvent(new WebRTCEchoTestEvent(WebRTCEchoTestEvent.WEBRTC_ECHO_TEST_NO_AUDIO));
|
||||||
onCancelClicked();
|
onCancelClicked();
|
||||||
|
@ -28,6 +28,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
import mx.events.FlexEvent;
|
import mx.events.FlexEvent;
|
||||||
import org.bigbluebutton.common.events.OpenWindowEvent;
|
import org.bigbluebutton.common.events.OpenWindowEvent;
|
||||||
import org.bigbluebutton.core.EventConstants;
|
import org.bigbluebutton.core.EventConstants;
|
||||||
|
import org.bigbluebutton.main.events.BBBEvent;
|
||||||
import org.bigbluebutton.main.events.ModuleStartedEvent;
|
import org.bigbluebutton.main.events.ModuleStartedEvent;
|
||||||
import org.bigbluebutton.modules.chat.events.ChatEvent;
|
import org.bigbluebutton.modules.chat.events.ChatEvent;
|
||||||
import org.bigbluebutton.modules.chat.events.SendPrivateChatMessageEvent;
|
import org.bigbluebutton.modules.chat.events.SendPrivateChatMessageEvent;
|
||||||
@ -79,6 +80,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
<EventHandlers type="{TranscriptEvent.TRANSCRIPT_EVENT}" >
|
<EventHandlers type="{TranscriptEvent.TRANSCRIPT_EVENT}" >
|
||||||
<MethodInvoker generator="{ChatMessageService}" method="sendWelcomeMessage"/>
|
<MethodInvoker generator="{ChatMessageService}" method="sendWelcomeMessage"/>
|
||||||
</EventHandlers>
|
</EventHandlers>
|
||||||
|
|
||||||
|
<EventHandlers type="{BBBEvent.RECONNECT_BIGBLUEBUTTON_SUCCEEDED_EVENT}" >
|
||||||
|
<EventAnnouncer generator="{TranscriptEvent}" type="{TranscriptEvent.LOAD_TRANSCRIPT}"/>
|
||||||
|
</EventHandlers>
|
||||||
|
|
||||||
<Injectors target="{ChatMessageService}">
|
<Injectors target="{ChatMessageService}">
|
||||||
<PropertyInjector targetKey="dispatcher" source="{scope.dispatcher}"/>
|
<PropertyInjector targetKey="dispatcher" source="{scope.dispatcher}"/>
|
||||||
|
@ -35,6 +35,8 @@ package org.bigbluebutton.modules.chat.services
|
|||||||
{
|
{
|
||||||
|
|
||||||
private static const LOGGER:ILogger = getClassLogger(MessageReceiver);
|
private static const LOGGER:ILogger = getClassLogger(MessageReceiver);
|
||||||
|
|
||||||
|
private var welcomed:Boolean = false;
|
||||||
|
|
||||||
public var dispatcher:IEventDispatcher;
|
public var dispatcher:IEventDispatcher;
|
||||||
|
|
||||||
@ -67,9 +69,12 @@ package org.bigbluebutton.modules.chat.services
|
|||||||
for (var i:int = 0; i < chats.length; i++) {
|
for (var i:int = 0; i < chats.length; i++) {
|
||||||
handleChatReceivePublicMessageCommand(chats[i], true);
|
handleChatReceivePublicMessageCommand(chats[i], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
var pcEvent:TranscriptEvent = new TranscriptEvent(TranscriptEvent.TRANSCRIPT_EVENT);
|
if (!welcomed) {
|
||||||
dispatcher.dispatchEvent(pcEvent);
|
var pcEvent:TranscriptEvent = new TranscriptEvent(TranscriptEvent.TRANSCRIPT_EVENT);
|
||||||
|
dispatcher.dispatchEvent(pcEvent);
|
||||||
|
welcomed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleChatReceivePublicMessageCommand(message:Object, history:Boolean = false):void {
|
private function handleChatReceivePublicMessageCommand(message:Object, history:Boolean = false):void {
|
||||||
|
@ -62,6 +62,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
<mate:Listener type="{ShortcutEvent.CHANGE_FONT_COLOUR}" method="focusColourPicker" />
|
<mate:Listener type="{ShortcutEvent.CHANGE_FONT_COLOUR}" method="focusColourPicker" />
|
||||||
<mate:Listener type="{ShortcutEvent.SEND_MESSAGE}" method="remoteSendMessage" />
|
<mate:Listener type="{ShortcutEvent.SEND_MESSAGE}" method="remoteSendMessage" />
|
||||||
<mate:Listener type="{ShortcutEvent.CHAT_DEBUG}" method="chatDebugInfo" />
|
<mate:Listener type="{ShortcutEvent.CHAT_DEBUG}" method="chatDebugInfo" />
|
||||||
|
<mate:Listener type="{BBBEvent.RECONNECT_DISCONNECTED_EVENT}" receive="refreshChat(event)"/>
|
||||||
|
|
||||||
<mate:Listener type="{LockControlEvent.CHANGED_LOCK_SETTINGS}" method="lockSettingsChanged" />
|
<mate:Listener type="{LockControlEvent.CHANGED_LOCK_SETTINGS}" method="lockSettingsChanged" />
|
||||||
|
|
||||||
@ -83,6 +84,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
import org.bigbluebutton.main.events.ShortcutEvent;
|
import org.bigbluebutton.main.events.ShortcutEvent;
|
||||||
import org.bigbluebutton.main.events.UserJoinedEvent;
|
import org.bigbluebutton.main.events.UserJoinedEvent;
|
||||||
import org.bigbluebutton.main.events.UserLeftEvent;
|
import org.bigbluebutton.main.events.UserLeftEvent;
|
||||||
|
import org.bigbluebutton.main.events.BBBEvent;
|
||||||
import org.bigbluebutton.main.model.users.BBBUser;
|
import org.bigbluebutton.main.model.users.BBBUser;
|
||||||
import org.bigbluebutton.main.model.users.Conference;
|
import org.bigbluebutton.main.model.users.Conference;
|
||||||
import org.bigbluebutton.modules.chat.ChatConstants;
|
import org.bigbluebutton.modules.chat.ChatConstants;
|
||||||
@ -232,6 +234,13 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
scrollToEndOfMessage();
|
scrollToEndOfMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function refreshChat(e:BBBEvent):void {
|
||||||
|
if (e.payload.type == "BIGBLUEBUTTON_CONNECTION") {
|
||||||
|
if (publicChat) chatMessages = new ChatConversation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private function handleUserJoinedEvent(event:UserJoinedEvent):void {
|
private function handleUserJoinedEvent(event:UserJoinedEvent):void {
|
||||||
// Handle user joining so that the user can start to talk if the person rejoins
|
// Handle user joining so that the user can start to talk if the person rejoins
|
||||||
if (!publicChat && event.userID == chatWithUserID) {
|
if (!publicChat && event.userID == chatWithUserID) {
|
||||||
|
34
bigbluebutton-client/src/org/bigbluebutton/modules/classyaudio/managers/ConnectionManager.as
Executable file → Normal file
34
bigbluebutton-client/src/org/bigbluebutton/modules/classyaudio/managers/ConnectionManager.as
Executable file → Normal file
@ -27,12 +27,16 @@ package org.bigbluebutton.modules.classyaudio.managers {
|
|||||||
import flash.net.NetConnection;
|
import flash.net.NetConnection;
|
||||||
import flash.net.ObjectEncoding;
|
import flash.net.ObjectEncoding;
|
||||||
|
|
||||||
|
import org.as3commons.logging.api.ILogger;
|
||||||
|
import org.as3commons.logging.api.getClassLogger;
|
||||||
|
import org.bigbluebutton.common.LogUtil;
|
||||||
import org.bigbluebutton.modules.classyaudio.events.CallConnectedEvent;
|
import org.bigbluebutton.modules.classyaudio.events.CallConnectedEvent;
|
||||||
import org.bigbluebutton.modules.classyaudio.events.CallDisconnectedEvent;
|
import org.bigbluebutton.modules.classyaudio.events.CallDisconnectedEvent;
|
||||||
import org.bigbluebutton.modules.classyaudio.events.ConnectionStatusEvent;
|
import org.bigbluebutton.modules.classyaudio.events.ConnectionStatusEvent;
|
||||||
|
|
||||||
public class ConnectionManager {
|
public class ConnectionManager {
|
||||||
|
private static const LOGGER:ILogger = getClassLogger(ConnectionManager);
|
||||||
|
|
||||||
private var netConnection:NetConnection = null;
|
private var netConnection:NetConnection = null;
|
||||||
private var username:String;
|
private var username:String;
|
||||||
private var uri:String;
|
private var uri:String;
|
||||||
@ -82,42 +86,42 @@ package org.bigbluebutton.modules.classyaudio.managers {
|
|||||||
|
|
||||||
switch(evt.info.code) {
|
switch(evt.info.code) {
|
||||||
case "NetConnection.Connect.Success":
|
case "NetConnection.Connect.Success":
|
||||||
LogUtil.debug("Successfully connected to SIP application.");
|
LOGGER.debug("Successfully connected to SIP application.");
|
||||||
event.status = ConnectionStatusEvent.SUCCESS;
|
event.status = ConnectionStatusEvent.SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "NetConnection.Connect.Failed":
|
case "NetConnection.Connect.Failed":
|
||||||
LogUtil.debug("Failed to connect to SIP application.");
|
LOGGER.debug("Failed to connect to SIP application.");
|
||||||
event.status = ConnectionStatusEvent.FAILED;
|
event.status = ConnectionStatusEvent.FAILED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "NetConnection.Connect.Closed":
|
case "NetConnection.Connect.Closed":
|
||||||
LogUtil.debug("Connection to SIP application has closed.");
|
LOGGER.debug("Connection to SIP application has closed.");
|
||||||
event.status = ConnectionStatusEvent.CLOSED;
|
event.status = ConnectionStatusEvent.CLOSED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "NetConnection.Connect.Rejected":
|
case "NetConnection.Connect.Rejected":
|
||||||
LogUtil.debug("Connection to SIP application was rejected.");
|
LOGGER.debug("Connection to SIP application was rejected.");
|
||||||
event.status = ConnectionStatusEvent.REJECTED;
|
event.status = ConnectionStatusEvent.REJECTED;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
LogUtil.debug("Phone Module Connection Status: " + event.status);
|
LOGGER.debug("Phone Module Connection Status: {0}", [event.status]);
|
||||||
LogUtil.debug("Dispatching " + event.status);
|
LOGGER.debug("Dispatching " + event.status);
|
||||||
dispatcher.dispatchEvent(event);
|
dispatcher.dispatchEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function asyncErrorHandler(event:AsyncErrorEvent):void {
|
private function asyncErrorHandler(event:AsyncErrorEvent):void {
|
||||||
LogUtil.debug("AsyncErrorEvent: " + event);
|
LOGGER.debug("AsyncErrorEvent: {0}", [event]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function securityErrorHandler(event:SecurityErrorEvent):void {
|
private function securityErrorHandler(event:SecurityErrorEvent):void {
|
||||||
LogUtil.debug("securityErrorHandler: " + event);
|
LOGGER.debug("securityErrorHandler: {0}", [event]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function call():void {
|
public function call():void {
|
||||||
LogUtil.debug("Calling " + room);
|
LOGGER.debug("Calling {0}", [room]);
|
||||||
doCall(room);
|
doCall(room);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,21 +131,21 @@ package org.bigbluebutton.modules.classyaudio.managers {
|
|||||||
//
|
//
|
||||||
//********************************************************************************************
|
//********************************************************************************************
|
||||||
public function failedToJoinVoiceConferenceCallback(msg:String):* {
|
public function failedToJoinVoiceConferenceCallback(msg:String):* {
|
||||||
LogUtil.debug("failedToJoinVoiceConferenceCallback " + msg);
|
LOGGER.debug("failedToJoinVoiceConferenceCallback {0}", [msg]);
|
||||||
var event:CallDisconnectedEvent = new CallDisconnectedEvent();
|
var event:CallDisconnectedEvent = new CallDisconnectedEvent();
|
||||||
dispatcher.dispatchEvent(event);
|
dispatcher.dispatchEvent(event);
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function disconnectedFromJoinVoiceConferenceCallback(msg:String):* {
|
public function disconnectedFromJoinVoiceConferenceCallback(msg:String):* {
|
||||||
LogUtil.debug("disconnectedFromJoinVoiceConferenceCallback " + msg);
|
LOGGER.debug("disconnectedFromJoinVoiceConferenceCallback {0}", [msg]);
|
||||||
var event:CallDisconnectedEvent = new CallDisconnectedEvent();
|
var event:CallDisconnectedEvent = new CallDisconnectedEvent();
|
||||||
dispatcher.dispatchEvent(event);
|
dispatcher.dispatchEvent(event);
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function successfullyJoinedVoiceConferenceCallback(publishName:String, playName:String, codec:String):* {
|
public function successfullyJoinedVoiceConferenceCallback(publishName:String, playName:String, codec:String):* {
|
||||||
LogUtil.debug("successfullyJoinedVoiceConferenceCallback " + publishName + " : " + playName + " : " + codec);
|
LOGGER.debug("successfullyJoinedVoiceConferenceCallback {0} : {1} : {2}", [publishName, playName, codec]);
|
||||||
isConnected = true;
|
isConnected = true;
|
||||||
var event:CallConnectedEvent = new CallConnectedEvent();
|
var event:CallConnectedEvent = new CallConnectedEvent();
|
||||||
event.publishStreamName = publishName;
|
event.publishStreamName = publishName;
|
||||||
@ -156,7 +160,7 @@ package org.bigbluebutton.modules.classyaudio.managers {
|
|||||||
//
|
//
|
||||||
//********************************************************************************************
|
//********************************************************************************************
|
||||||
public function doCall(dialStr:String):void {
|
public function doCall(dialStr:String):void {
|
||||||
LogUtil.debug("Calling " + dialStr);
|
LOGGER.debug("Calling ", [dialStr]);
|
||||||
netConnection.call("voiceconf.call", null, "default", username, dialStr);
|
netConnection.call("voiceconf.call", null, "default", username, dialStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@ package org.bigbluebutton.modules.deskshare.managers
|
|||||||
|
|
||||||
public function startSharing(uri:String , useTLS:Boolean , room:String, autoStart:Boolean, autoFullScreen:Boolean):void {
|
public function startSharing(uri:String , useTLS:Boolean , room:String, autoStart:Boolean, autoFullScreen:Boolean):void {
|
||||||
LOGGER.debug("DS:PublishWindowManager::opening desk share window, autostart={0} autoFullScreen={1}", [autoStart, autoFullScreen]);
|
LOGGER.debug("DS:PublishWindowManager::opening desk share window, autostart={0} autoFullScreen={1}", [autoStart, autoFullScreen]);
|
||||||
|
|
||||||
shareWindow = new DesktopPublishWindow();
|
shareWindow = new DesktopPublishWindow();
|
||||||
shareWindow.initWindow(service.getConnection(), uri , useTLS , room, autoStart, autoFullScreen);
|
shareWindow.initWindow(service.getConnection(), uri , useTLS , room, autoStart, autoFullScreen);
|
||||||
shareWindow.visible = true;
|
shareWindow.visible = true;
|
||||||
|
@ -83,7 +83,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
</EventHandlers>
|
</EventHandlers>
|
||||||
|
|
||||||
<EventHandlers type="{ViewWindowEvent.CLOSE}">
|
<EventHandlers type="{ViewWindowEvent.CLOSE}">
|
||||||
<MethodInvoker generator="{DeskshareManager}" method="handleViewWindowCloseEvent"/>
|
<MethodInvoker generator="{DeskshareManager}" method="handleViewWindowCloseEvent"/>
|
||||||
</EventHandlers>
|
</EventHandlers>
|
||||||
|
|
||||||
<EventHandlers type="{ModuleEvent.STOP}">
|
<EventHandlers type="{ModuleEvent.STOP}">
|
||||||
|
@ -21,6 +21,7 @@ package org.bigbluebutton.modules.deskshare.services.red5
|
|||||||
{
|
{
|
||||||
import com.asfusion.mate.events.Dispatcher;
|
import com.asfusion.mate.events.Dispatcher;
|
||||||
|
|
||||||
|
import flash.events.AsyncErrorEvent;
|
||||||
import flash.events.NetStatusEvent;
|
import flash.events.NetStatusEvent;
|
||||||
import flash.events.SecurityErrorEvent;
|
import flash.events.SecurityErrorEvent;
|
||||||
import flash.events.TimerEvent;
|
import flash.events.TimerEvent;
|
||||||
@ -30,20 +31,23 @@ package org.bigbluebutton.modules.deskshare.services.red5
|
|||||||
import flash.net.SharedObject;
|
import flash.net.SharedObject;
|
||||||
import flash.utils.Timer;
|
import flash.utils.Timer;
|
||||||
|
|
||||||
|
import mx.utils.ObjectUtil;
|
||||||
|
|
||||||
import org.as3commons.logging.api.ILogger;
|
import org.as3commons.logging.api.ILogger;
|
||||||
import org.as3commons.logging.api.getClassLogger;
|
import org.as3commons.logging.api.getClassLogger;
|
||||||
import org.bigbluebutton.core.UsersUtil;
|
import org.bigbluebutton.core.UsersUtil;
|
||||||
|
import org.bigbluebutton.core.managers.ReconnectionManager;
|
||||||
|
import org.bigbluebutton.main.events.BBBEvent;
|
||||||
import org.bigbluebutton.modules.deskshare.events.AppletStartedEvent;
|
import org.bigbluebutton.modules.deskshare.events.AppletStartedEvent;
|
||||||
import org.bigbluebutton.modules.deskshare.events.CursorEvent;
|
import org.bigbluebutton.modules.deskshare.events.CursorEvent;
|
||||||
import org.bigbluebutton.modules.deskshare.events.ViewStreamEvent;
|
import org.bigbluebutton.modules.deskshare.events.ViewStreamEvent;
|
||||||
|
|
||||||
|
|
||||||
public class Connection {
|
public class Connection {
|
||||||
private static const LOGGER:ILogger = getClassLogger(Connection);
|
private static const LOGGER:ILogger = getClassLogger(Connection);
|
||||||
|
|
||||||
private var nc:NetConnection;
|
private var nc:NetConnection;
|
||||||
private var uri:String;
|
private var uri:String;
|
||||||
private const connectionTimeout:int = 5000;
|
|
||||||
private var retryTimer:Timer = null;
|
private var retryTimer:Timer = null;
|
||||||
private var retryCount:int = 0;
|
private var retryCount:int = 0;
|
||||||
private const MAX_RETRIES:int = 5;
|
private const MAX_RETRIES:int = 5;
|
||||||
@ -52,7 +56,10 @@ package org.bigbluebutton.modules.deskshare.services.red5
|
|||||||
private var width:Number;
|
private var width:Number;
|
||||||
private var height:Number;
|
private var height:Number;
|
||||||
private var room:String;
|
private var room:String;
|
||||||
|
private var logoutOnUserCommand:Boolean = false;
|
||||||
|
private var reconnecting:Boolean = false;
|
||||||
|
private var wasPresenterBeforeDisconnect:Boolean = false;
|
||||||
|
|
||||||
private var dispatcher:Dispatcher = new Dispatcher();
|
private var dispatcher:Dispatcher = new Dispatcher();
|
||||||
|
|
||||||
public function Connection(room:String) {
|
public function Connection(room:String) {
|
||||||
@ -90,6 +97,8 @@ package org.bigbluebutton.modules.deskshare.services.red5
|
|||||||
nc.objectEncoding = ObjectEncoding.AMF0;
|
nc.objectEncoding = ObjectEncoding.AMF0;
|
||||||
nc.client = this;
|
nc.client = this;
|
||||||
|
|
||||||
|
nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, debugAsyncErrorHandler);
|
||||||
|
nc.addEventListener(NetStatusEvent.NET_STATUS, debugNetStatusHandler);
|
||||||
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
|
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
|
||||||
nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
|
nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
|
||||||
|
|
||||||
@ -110,12 +119,6 @@ package org.bigbluebutton.modules.deskshare.services.red5
|
|||||||
}
|
}
|
||||||
|
|
||||||
nc.connect(getURI(), UsersUtil.getInternalMeetingID());
|
nc.connect(getURI(), UsersUtil.getInternalMeetingID());
|
||||||
|
|
||||||
if (!retry) {
|
|
||||||
retryTimer = new Timer(connectionTimeout, 1);
|
|
||||||
retryTimer.addEventListener(TimerEvent.TIMER_COMPLETE, connectTimeoutHandler);
|
|
||||||
retryTimer.start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function connectTimeoutHandler(e:TimerEvent):void {
|
private function connectTimeoutHandler(e:TimerEvent):void {
|
||||||
@ -180,6 +183,11 @@ package org.bigbluebutton.modules.deskshare.services.red5
|
|||||||
|
|
||||||
switch(event.info.code){
|
switch(event.info.code){
|
||||||
case "NetConnection.Connect.Failed":
|
case "NetConnection.Connect.Failed":
|
||||||
|
if (reconnecting) {
|
||||||
|
var attemptFailedEvent:BBBEvent = new BBBEvent(BBBEvent.RECONNECT_CONNECTION_ATTEMPT_FAILED_EVENT);
|
||||||
|
attemptFailedEvent.payload.type = ReconnectionManager.DESKSHARE_CONNECTION;
|
||||||
|
dispatcher.dispatchEvent(attemptFailedEvent);
|
||||||
|
}
|
||||||
ce.status = ConnectionEvent.FAILED;
|
ce.status = ConnectionEvent.FAILED;
|
||||||
|
|
||||||
dispatcher.dispatchEvent(ce);
|
dispatcher.dispatchEvent(ce);
|
||||||
@ -187,6 +195,17 @@ package org.bigbluebutton.modules.deskshare.services.red5
|
|||||||
|
|
||||||
case "NetConnection.Connect.Success":
|
case "NetConnection.Connect.Success":
|
||||||
ce.status = ConnectionEvent.SUCCESS;
|
ce.status = ConnectionEvent.SUCCESS;
|
||||||
|
if (reconnecting) {
|
||||||
|
reconnecting = false;
|
||||||
|
if (wasPresenterBeforeDisconnect) {
|
||||||
|
wasPresenterBeforeDisconnect = false;
|
||||||
|
stopSharingDesktop(room, room)
|
||||||
|
}
|
||||||
|
|
||||||
|
var attemptSucceeded:BBBEvent = new BBBEvent(BBBEvent.RECONNECT_CONNECTION_ATTEMPT_SUCCEEDED_EVENT);
|
||||||
|
attemptSucceeded.payload.type = ReconnectionManager.DESKSHARE_CONNECTION;
|
||||||
|
dispatcher.dispatchEvent(attemptSucceeded);
|
||||||
|
}
|
||||||
dispatcher.dispatchEvent(ce);
|
dispatcher.dispatchEvent(ce);
|
||||||
connectionSuccessHandler();
|
connectionSuccessHandler();
|
||||||
break;
|
break;
|
||||||
@ -199,7 +218,24 @@ package org.bigbluebutton.modules.deskshare.services.red5
|
|||||||
case "NetConnection.Connect.Closed":
|
case "NetConnection.Connect.Closed":
|
||||||
LOGGER.debug("Deskshare connection closed.");
|
LOGGER.debug("Deskshare connection closed.");
|
||||||
ce.status = ConnectionEvent.CLOSED;
|
ce.status = ConnectionEvent.CLOSED;
|
||||||
// dispatcher.dispatchEvent(ce);
|
if (UsersUtil.amIPresenter()) {
|
||||||
|
// Let's keep our presenter status before disconnected. We can't
|
||||||
|
// tell the other user's to stop desktop sharing as our connection is broken. (ralam july 24, 2015)
|
||||||
|
wasPresenterBeforeDisconnect = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
stopViewing();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!logoutOnUserCommand) {
|
||||||
|
reconnecting = true;
|
||||||
|
|
||||||
|
var disconnectedEvent:BBBEvent = new BBBEvent(BBBEvent.RECONNECT_DISCONNECTED_EVENT);
|
||||||
|
disconnectedEvent.payload.type = ReconnectionManager.DESKSHARE_CONNECTION;
|
||||||
|
disconnectedEvent.payload.callback = connect;
|
||||||
|
disconnectedEvent.payload.callbackParameters = [];
|
||||||
|
dispatcher.dispatchEvent(disconnectedEvent);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "NetConnection.Connect.InvalidApp":
|
case "NetConnection.Connect.InvalidApp":
|
||||||
@ -253,6 +289,7 @@ package org.bigbluebutton.modules.deskshare.services.red5
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function disconnect():void{
|
public function disconnect():void{
|
||||||
|
logoutOnUserCommand = true;
|
||||||
if (nc != null) nc.close();
|
if (nc != null) nc.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,10 +298,20 @@ package org.bigbluebutton.modules.deskshare.services.red5
|
|||||||
var deskSOName:String = room + "-deskSO";
|
var deskSOName:String = room + "-deskSO";
|
||||||
deskSO = SharedObject.getRemote(deskSOName, uri, false);
|
deskSO = SharedObject.getRemote(deskSOName, uri, false);
|
||||||
deskSO.client = this;
|
deskSO.client = this;
|
||||||
|
deskSO.addEventListener(AsyncErrorEvent.ASYNC_ERROR, debugAsyncErrorHandler);
|
||||||
|
deskSO.addEventListener(NetStatusEvent.NET_STATUS, debugNetStatusHandler);
|
||||||
deskSO.connect(nc);
|
deskSO.connect(nc);
|
||||||
|
|
||||||
checkIfStreamIsPublishing(room);
|
checkIfStreamIsPublishing(room);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function debugNetStatusHandler(e:NetStatusEvent):void {
|
||||||
|
LOGGER.debug("netStatusHandler target={0} info={1}", [e.target, ObjectUtil.toString(e.info)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function debugAsyncErrorHandler(e:AsyncErrorEvent):void {
|
||||||
|
LOGGER.debug("asyncErrorHandler target={0} info={1}", [e.target, e.text]);
|
||||||
|
}
|
||||||
|
|
||||||
public function getConnection():NetConnection{
|
public function getConnection():NetConnection{
|
||||||
return nc;
|
return nc;
|
||||||
@ -285,10 +332,13 @@ package org.bigbluebutton.modules.deskshare.services.red5
|
|||||||
*/
|
*/
|
||||||
public function appletStarted(videoWidth:Number, videoHeight:Number):void{
|
public function appletStarted(videoWidth:Number, videoHeight:Number):void{
|
||||||
LOGGER.debug("Got applet started");
|
LOGGER.debug("Got applet started");
|
||||||
var event:AppletStartedEvent = new AppletStartedEvent();
|
if (nc != null && nc.connected) {
|
||||||
event.videoWidth = videoWidth;
|
var event:AppletStartedEvent = new AppletStartedEvent();
|
||||||
event.videoHeight = videoHeight;
|
event.videoWidth = videoWidth;
|
||||||
dispatcher.dispatchEvent(event);
|
event.videoHeight = videoHeight;
|
||||||
|
dispatcher.dispatchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -103,6 +103,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
[Bindable] private var baseIndex:int;
|
[Bindable] private var baseIndex:int;
|
||||||
[Bindable] private var dsOptions:DeskshareOptions;
|
[Bindable] private var dsOptions:DeskshareOptions;
|
||||||
|
|
||||||
|
private var calledStopApplet:Boolean = false;
|
||||||
|
|
||||||
private function init():void {
|
private function init():void {
|
||||||
dsOptions = new DeskshareOptions();
|
dsOptions = new DeskshareOptions();
|
||||||
baseIndex = dsOptions.baseTabIndex;
|
baseIndex = dsOptions.baseTabIndex;
|
||||||
@ -246,6 +248,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function onAppletStart(event:AppletStartedEvent):void{
|
private function onAppletStart(event:AppletStartedEvent):void{
|
||||||
|
if (!connection.connected) return;
|
||||||
|
|
||||||
LOGGER.debug("DeskShareWindow::onAppletStart");
|
LOGGER.debug("DeskShareWindow::onAppletStart");
|
||||||
startPreviewStream(connection, room, event.videoWidth, event.videoHeight);
|
startPreviewStream(connection, room, event.videoWidth, event.videoHeight);
|
||||||
var streamEvent:StreamEvent = new StreamEvent(StreamEvent.START);
|
var streamEvent:StreamEvent = new StreamEvent(StreamEvent.START);
|
||||||
@ -343,15 +347,24 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
closeWindow();
|
closeWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function closeWindow():void {
|
private function callStopApplet():void {
|
||||||
ExternalInterface.call("stopApplet");
|
if (!calledStopApplet) {
|
||||||
dispatchEvent(new ShareWindowEvent(ShareWindowEvent.CLOSE));
|
calledStopApplet = true;
|
||||||
}
|
LOGGER.debug("Calling stopApplet in callStopApplet()");
|
||||||
|
ExternalInterface.call("stopApplet");
|
||||||
private function restartJava():void {
|
}
|
||||||
ExternalInterface.call("stopApplet");
|
}
|
||||||
shareScreen(sharingFullScreen);
|
private function closeWindow():void {
|
||||||
}
|
LOGGER.debug("Calling stopApplet in closeWindow()");
|
||||||
|
callStopApplet();
|
||||||
|
dispatchEvent(new ShareWindowEvent(ShareWindowEvent.CLOSE));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function restartJava():void {
|
||||||
|
LOGGER.debug("Calling stopApplet in restartJava()");
|
||||||
|
callStopApplet();
|
||||||
|
shareScreen(sharingFullScreen);
|
||||||
|
}
|
||||||
|
|
||||||
private function handleDeskshareAppletLaunchedEvent(e:DeskshareAppletLaunchedEvent):void {
|
private function handleDeskshareAppletLaunchedEvent(e:DeskshareAppletLaunchedEvent):void {
|
||||||
if (javaTimer && javaTimer.running) {
|
if (javaTimer && javaTimer.running) {
|
||||||
|
@ -187,6 +187,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function onNetStatus(e:NetStatusEvent):void{
|
private function onNetStatus(e:NetStatusEvent):void{
|
||||||
|
LOGGER.debug("onNetStatus info={0}", [e.info.text]);
|
||||||
|
|
||||||
switch(e.info.code){
|
switch(e.info.code){
|
||||||
case "NetStream.Play.Start":
|
case "NetStream.Play.Start":
|
||||||
LOGGER.debug("NetStream.Publish.Start for broadcast stream {0}", [stream]);
|
LOGGER.debug("NetStream.Publish.Start for broadcast stream {0}", [stream]);
|
||||||
|
@ -12,11 +12,13 @@ package org.bigbluebutton.modules.phone.events
|
|||||||
public static const NETWORK_CHANGE:String = "flash voice connection status network change event";
|
public static const NETWORK_CHANGE:String = "flash voice connection status network change event";
|
||||||
|
|
||||||
public var status:String;
|
public var status:String;
|
||||||
|
public var reconnecting:Boolean;
|
||||||
|
|
||||||
public function FlashVoiceConnectionStatusEvent(connStatus:String)
|
public function FlashVoiceConnectionStatusEvent(connStatus:String, isReconnecting:Boolean = false)
|
||||||
{
|
{
|
||||||
super(CONN_STATUS, true, false);
|
super(CONN_STATUS, true, false);
|
||||||
status = connStatus;
|
status = connStatus;
|
||||||
|
reconnecting = isReconnecting;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,7 +30,9 @@ package org.bigbluebutton.modules.phone.managers {
|
|||||||
import org.as3commons.logging.api.getClassLogger;
|
import org.as3commons.logging.api.getClassLogger;
|
||||||
import org.bigbluebutton.core.BBB;
|
import org.bigbluebutton.core.BBB;
|
||||||
import org.bigbluebutton.core.UsersUtil;
|
import org.bigbluebutton.core.UsersUtil;
|
||||||
|
import org.bigbluebutton.core.managers.ReconnectionManager;
|
||||||
import org.bigbluebutton.main.api.JSLog;
|
import org.bigbluebutton.main.api.JSLog;
|
||||||
|
import org.bigbluebutton.main.events.BBBEvent;
|
||||||
import org.bigbluebutton.modules.phone.events.FlashCallConnectedEvent;
|
import org.bigbluebutton.modules.phone.events.FlashCallConnectedEvent;
|
||||||
import org.bigbluebutton.modules.phone.events.FlashCallDisconnectedEvent;
|
import org.bigbluebutton.modules.phone.events.FlashCallDisconnectedEvent;
|
||||||
import org.bigbluebutton.modules.phone.events.FlashVoiceConnectionStatusEvent;
|
import org.bigbluebutton.modules.phone.events.FlashVoiceConnectionStatusEvent;
|
||||||
@ -49,6 +51,8 @@ package org.bigbluebutton.modules.phone.managers {
|
|||||||
|
|
||||||
private var registered:Boolean = false;
|
private var registered:Boolean = false;
|
||||||
private var closedByUser:Boolean = false;
|
private var closedByUser:Boolean = false;
|
||||||
|
|
||||||
|
private var reconnecting:Boolean = false;
|
||||||
|
|
||||||
private var dispatcher:Dispatcher;
|
private var dispatcher:Dispatcher;
|
||||||
|
|
||||||
@ -99,11 +103,39 @@ package org.bigbluebutton.modules.phone.managers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function handleConnectionSuccess():void {
|
||||||
|
if (reconnecting) {
|
||||||
|
var attemptSucceeded:BBBEvent = new BBBEvent(BBBEvent.RECONNECT_CONNECTION_ATTEMPT_SUCCEEDED_EVENT);
|
||||||
|
attemptSucceeded.payload.type = ReconnectionManager.SIP_CONNECTION;
|
||||||
|
dispatcher.dispatchEvent(attemptSucceeded);
|
||||||
|
}
|
||||||
|
dispatcher.dispatchEvent(new FlashVoiceConnectionStatusEvent(FlashVoiceConnectionStatusEvent.CONNECTED));
|
||||||
|
reconnecting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleConnectionFailed():void {
|
||||||
|
if (reconnecting) {
|
||||||
|
var attemptFailedEvent:BBBEvent = new BBBEvent(BBBEvent.RECONNECT_CONNECTION_ATTEMPT_FAILED_EVENT);
|
||||||
|
attemptFailedEvent.payload.type = ReconnectionManager.SIP_CONNECTION;
|
||||||
|
dispatcher.dispatchEvent(attemptFailedEvent);
|
||||||
|
}
|
||||||
|
dispatcher.dispatchEvent(new FlashVoiceConnectionStatusEvent(FlashVoiceConnectionStatusEvent.FAILED, reconnecting));
|
||||||
|
}
|
||||||
|
|
||||||
private function handleConnectionClosed():void {
|
private function handleConnectionClosed():void {
|
||||||
if (!closedByUser) {
|
if (!closedByUser) {
|
||||||
|
reconnecting = true;
|
||||||
|
|
||||||
|
var disconnectedEvent:BBBEvent = new BBBEvent(BBBEvent.RECONNECT_DISCONNECTED_EVENT);
|
||||||
|
disconnectedEvent.payload.type = ReconnectionManager.SIP_CONNECTION;
|
||||||
|
disconnectedEvent.payload.callback = connect;
|
||||||
|
disconnectedEvent.payload.callbackParameters = [];
|
||||||
|
dispatcher.dispatchEvent(disconnectedEvent);
|
||||||
|
|
||||||
dispatcher.dispatchEvent(new FlashVoiceConnectionStatusEvent(FlashVoiceConnectionStatusEvent.DISCONNECTED));
|
dispatcher.dispatchEvent(new FlashVoiceConnectionStatusEvent(FlashVoiceConnectionStatusEvent.DISCONNECTED));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function netStatus (event:NetStatusEvent ):void {
|
private function netStatus (event:NetStatusEvent ):void {
|
||||||
var info : Object = event.info;
|
var info : Object = event.info;
|
||||||
var statusCode : String = info.code;
|
var statusCode : String = info.code;
|
||||||
@ -115,12 +147,12 @@ package org.bigbluebutton.modules.phone.managers {
|
|||||||
case "NetConnection.Connect.Success":
|
case "NetConnection.Connect.Success":
|
||||||
LOGGER.debug("Connection success");
|
LOGGER.debug("Connection success");
|
||||||
JSLog.debug("Successfully connected to BBB Voice", logData);
|
JSLog.debug("Successfully connected to BBB Voice", logData);
|
||||||
dispatcher.dispatchEvent(new FlashVoiceConnectionStatusEvent(FlashVoiceConnectionStatusEvent.CONNECTED));
|
handleConnectionSuccess();
|
||||||
break;
|
break;
|
||||||
case "NetConnection.Connect.Failed":
|
case "NetConnection.Connect.Failed":
|
||||||
LOGGER.debug("Connection failed");
|
LOGGER.debug("Connection failed");
|
||||||
JSLog.error("Failed to connect to BBB Voice", logData);
|
JSLog.error("Failed to connect to BBB Voice", logData);
|
||||||
dispatcher.dispatchEvent(new FlashVoiceConnectionStatusEvent(FlashVoiceConnectionStatusEvent.FAILED));
|
handleConnectionFailed();
|
||||||
break;
|
break;
|
||||||
case "NetConnection.Connect.NetworkChange":
|
case "NetConnection.Connect.NetworkChange":
|
||||||
LOGGER.debug("Detected network change. User might be on a wireless and temporarily dropped connection. Doing nothing. Just making a note.");
|
LOGGER.debug("Detected network change. User might be on a wireless and temporarily dropped connection. Doing nothing. Just making a note.");
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
import org.as3commons.logging.util.jsonXify;
|
import org.as3commons.logging.util.jsonXify;
|
||||||
import org.bigbluebutton.core.UsersUtil;
|
import org.bigbluebutton.core.UsersUtil;
|
||||||
import org.bigbluebutton.main.api.JSLog;
|
import org.bigbluebutton.main.api.JSLog;
|
||||||
|
import org.bigbluebutton.main.events.ClientStatusEvent;
|
||||||
import org.bigbluebutton.modules.phone.PhoneOptions;
|
import org.bigbluebutton.modules.phone.PhoneOptions;
|
||||||
import org.bigbluebutton.modules.phone.events.FlashCallConnectedEvent;
|
import org.bigbluebutton.modules.phone.events.FlashCallConnectedEvent;
|
||||||
import org.bigbluebutton.modules.phone.events.FlashCallDisconnectedEvent;
|
import org.bigbluebutton.modules.phone.events.FlashCallDisconnectedEvent;
|
||||||
@ -368,23 +369,49 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function handleFlashVoiceConnected():void {
|
||||||
|
switch (state) {
|
||||||
|
case JOIN_VOICE_CONFERENCE:
|
||||||
|
callIntoVoiceConference();
|
||||||
|
break;
|
||||||
|
case DO_ECHO_TEST:
|
||||||
|
callIntoEchoTest();
|
||||||
|
break;
|
||||||
|
case CALL_TO_LISTEN_ONLY_STREAM:
|
||||||
|
callToListenOnlyStream();
|
||||||
|
break;
|
||||||
|
case ON_LISTEN_ONLY_STREAM:
|
||||||
|
callToListenOnlyStream();
|
||||||
|
break;
|
||||||
|
case IN_CONFERENCE:
|
||||||
|
LOGGER.debug("Reconnected while transmiting mic. Automatic retransmission not implemented.");
|
||||||
|
state = INITED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
LOGGER.debug("unhandled state: {0}", [state]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function handleFlashVoiceConnectionStatusEvent(event:FlashVoiceConnectionStatusEvent):void {
|
public function handleFlashVoiceConnectionStatusEvent(event:FlashVoiceConnectionStatusEvent):void {
|
||||||
LOGGER.debug("Connection status event. status=[{0}]", [event.status]);
|
LOGGER.debug("Connection status event. status=[{0}]", [event.status]);
|
||||||
if (event.status == FlashVoiceConnectionStatusEvent.CONNECTED) {
|
switch (event.status) {
|
||||||
switch (state) {
|
case FlashVoiceConnectionStatusEvent.CONNECTED:
|
||||||
case JOIN_VOICE_CONFERENCE:
|
handleFlashVoiceConnected();
|
||||||
callIntoVoiceConference();
|
break;
|
||||||
break;
|
|
||||||
case DO_ECHO_TEST:
|
case FlashVoiceConnectionStatusEvent.FAILED:
|
||||||
callIntoEchoTest();
|
case FlashVoiceConnectionStatusEvent.DISCONNECTED:
|
||||||
break;
|
// If reconnection is under way the state should de kept
|
||||||
case CALL_TO_LISTEN_ONLY_STREAM:
|
if(!event.reconnecting) {
|
||||||
callToListenOnlyStream();
|
state = INITED;
|
||||||
break;
|
}
|
||||||
default:
|
dispatcher.dispatchEvent(new FlashLeftVoiceConferenceEvent());
|
||||||
LOGGER.debug("unhandled state: {0}", [state]);
|
break;
|
||||||
break;
|
|
||||||
}
|
default:
|
||||||
|
LOGGER.debug("unhandled state: {0}", [state]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,5 +419,12 @@
|
|||||||
usingFlash = true;
|
usingFlash = true;
|
||||||
startCall(true);
|
startCall(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function handleFlashLeftVoiceConference():void {
|
||||||
|
if (isConnected()) {
|
||||||
|
streamManager.stopStreams();
|
||||||
|
connectionManager.disconnect(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ package org.bigbluebutton.modules.phone.managers
|
|||||||
import org.as3commons.logging.api.getClassLogger;
|
import org.as3commons.logging.api.getClassLogger;
|
||||||
import org.bigbluebutton.core.UsersUtil;
|
import org.bigbluebutton.core.UsersUtil;
|
||||||
import org.bigbluebutton.main.api.JSAPI;
|
import org.bigbluebutton.main.api.JSAPI;
|
||||||
|
import org.bigbluebutton.main.api.JSLog;
|
||||||
import org.bigbluebutton.main.events.ClientStatusEvent;
|
import org.bigbluebutton.main.events.ClientStatusEvent;
|
||||||
import org.bigbluebutton.modules.phone.PhoneModel;
|
import org.bigbluebutton.modules.phone.PhoneModel;
|
||||||
import org.bigbluebutton.modules.phone.PhoneOptions;
|
import org.bigbluebutton.modules.phone.PhoneOptions;
|
||||||
@ -188,6 +189,11 @@ package org.bigbluebutton.modules.phone.managers
|
|||||||
errorString = ResourceUtil.getInstance().getString("bbb.webrtcWarning.failedError.unknown", [event.errorCode]);
|
errorString = ResourceUtil.getInstance().getString("bbb.webrtcWarning.failedError.unknown", [event.errorCode]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var logData:Object = new Object();
|
||||||
|
logData.reason = errorString;
|
||||||
|
logData.user = UsersUtil.getUserData();
|
||||||
|
JSLog.warn("WebRtc Echo test failed.", logData);
|
||||||
|
|
||||||
sendWebRTCAlert(ResourceUtil.getInstance().getString("bbb.webrtcWarning.title"), ResourceUtil.getInstance().getString("bbb.webrtcWarning.message", [errorString]), errorString);
|
sendWebRTCAlert(ResourceUtil.getInstance().getString("bbb.webrtcWarning.title"), ResourceUtil.getInstance().getString("bbb.webrtcWarning.message", [errorString]), errorString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
import org.bigbluebutton.modules.phone.events.FlashCallDisconnectedEvent;
|
import org.bigbluebutton.modules.phone.events.FlashCallDisconnectedEvent;
|
||||||
import org.bigbluebutton.modules.phone.events.FlashEchoTestHasAudioEvent;
|
import org.bigbluebutton.modules.phone.events.FlashEchoTestHasAudioEvent;
|
||||||
import org.bigbluebutton.modules.phone.events.FlashEchoTestNoAudioEvent;
|
import org.bigbluebutton.modules.phone.events.FlashEchoTestNoAudioEvent;
|
||||||
|
import org.bigbluebutton.modules.phone.events.FlashLeftVoiceConferenceEvent;
|
||||||
import org.bigbluebutton.modules.phone.events.FlashStartEchoTestCommand;
|
import org.bigbluebutton.modules.phone.events.FlashStartEchoTestCommand;
|
||||||
import org.bigbluebutton.modules.phone.events.FlashStopEchoTestCommand;
|
import org.bigbluebutton.modules.phone.events.FlashStopEchoTestCommand;
|
||||||
import org.bigbluebutton.modules.phone.events.FlashVoiceConnectionStatusEvent;
|
import org.bigbluebutton.modules.phone.events.FlashVoiceConnectionStatusEvent;
|
||||||
@ -106,7 +107,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
<EventHandlers type="{LeaveVoiceConferenceCommand.LEAVE_VOICE_CONF}">
|
<EventHandlers type="{LeaveVoiceConferenceCommand.LEAVE_VOICE_CONF}">
|
||||||
<MethodInvoker generator="{FlashCallManager}" method="handleLeaveVoiceConferenceCommand" arguments="{event}"/>
|
<MethodInvoker generator="{FlashCallManager}" method="handleLeaveVoiceConferenceCommand" arguments="{event}"/>
|
||||||
</EventHandlers>
|
</EventHandlers>
|
||||||
|
|
||||||
|
<EventHandlers type="{FlashLeftVoiceConferenceEvent.LEFT_VOICE_CONFERENCE}">
|
||||||
|
<MethodInvoker generator="{FlashCallManager}" method="handleFlashLeftVoiceConference"/>
|
||||||
|
</EventHandlers>
|
||||||
|
|
||||||
<EventHandlers type="{UseFlashModeCommand.USE_FLASH_MODE}">
|
<EventHandlers type="{UseFlashModeCommand.USE_FLASH_MODE}">
|
||||||
<MethodInvoker generator="{FlashCallManager}" method="handleUseFlashModeCommand"/>
|
<MethodInvoker generator="{FlashCallManager}" method="handleUseFlashModeCommand"/>
|
||||||
</EventHandlers>
|
</EventHandlers>
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
package org.bigbluebutton.modules.polling.model
|
package org.bigbluebutton.modules.polling.model
|
||||||
{
|
{
|
||||||
import mx.collections.ArrayCollection;
|
|
||||||
|
|
||||||
public class SimplePollResult
|
public class SimplePollResult
|
||||||
{
|
{
|
||||||
private var _id:String;
|
private var _id:String;
|
||||||
private var _answers: Array;
|
private var _answers: Array;
|
||||||
|
private var _numRespondents: int;
|
||||||
public function SimplePollResult(id:String, answers:Array)
|
private var _numResponders: int;
|
||||||
|
|
||||||
|
public function SimplePollResult(id:String, answers:Array, numRespondents: int, numResponders: int)
|
||||||
{
|
{
|
||||||
_id = id;
|
_id = id;
|
||||||
_answers = answers;
|
_answers = answers;
|
||||||
|
_numRespondents = numRespondents;
|
||||||
|
_numResponders = numResponders;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get id():String {
|
public function get id():String {
|
||||||
@ -22,5 +25,12 @@ package org.bigbluebutton.modules.polling.model
|
|||||||
return _answers;
|
return _answers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function get numRespondents():int {
|
||||||
|
return _numRespondents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get numResponders():int {
|
||||||
|
return _numResponders;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,8 +2,13 @@ package org.bigbluebutton.modules.polling.service
|
|||||||
{
|
{
|
||||||
import com.asfusion.mate.events.Dispatcher;
|
import com.asfusion.mate.events.Dispatcher;
|
||||||
|
|
||||||
|
import flash.accessibility.Accessibility;
|
||||||
|
|
||||||
import org.as3commons.logging.api.ILogger;
|
import org.as3commons.logging.api.ILogger;
|
||||||
import org.as3commons.logging.api.getClassLogger;
|
import org.as3commons.logging.api.getClassLogger;
|
||||||
|
import org.bigbluebutton.modules.chat.ChatConstants;
|
||||||
|
import org.bigbluebutton.modules.chat.events.PublicChatMessageEvent;
|
||||||
|
import org.bigbluebutton.modules.chat.vo.ChatMessageVO;
|
||||||
import org.bigbluebutton.modules.polling.events.PollShowResultEvent;
|
import org.bigbluebutton.modules.polling.events.PollShowResultEvent;
|
||||||
import org.bigbluebutton.modules.polling.events.PollStartedEvent;
|
import org.bigbluebutton.modules.polling.events.PollStartedEvent;
|
||||||
import org.bigbluebutton.modules.polling.events.PollStoppedEvent;
|
import org.bigbluebutton.modules.polling.events.PollStoppedEvent;
|
||||||
@ -13,6 +18,7 @@ package org.bigbluebutton.modules.polling.service
|
|||||||
import org.bigbluebutton.modules.polling.model.SimpleAnswerResult;
|
import org.bigbluebutton.modules.polling.model.SimpleAnswerResult;
|
||||||
import org.bigbluebutton.modules.polling.model.SimplePoll;
|
import org.bigbluebutton.modules.polling.model.SimplePoll;
|
||||||
import org.bigbluebutton.modules.polling.model.SimplePollResult;
|
import org.bigbluebutton.modules.polling.model.SimplePollResult;
|
||||||
|
import org.bigbluebutton.util.i18n.ResourceUtil;
|
||||||
|
|
||||||
public class PollDataProcessor
|
public class PollDataProcessor
|
||||||
{
|
{
|
||||||
@ -61,19 +67,43 @@ package org.bigbluebutton.modules.polling.service
|
|||||||
var map:Object = JSON.parse(msg.msg);
|
var map:Object = JSON.parse(msg.msg);
|
||||||
if (map.hasOwnProperty("poll")) {
|
if (map.hasOwnProperty("poll")) {
|
||||||
var poll:Object = map.poll;
|
var poll:Object = map.poll;
|
||||||
if (poll.hasOwnProperty("id") && poll.hasOwnProperty("answers")) {
|
if (poll.hasOwnProperty("id") && poll.hasOwnProperty("answers")
|
||||||
|
&& poll.hasOwnProperty("num_responders") && poll.hasOwnProperty("num_respondents")) {
|
||||||
var pollId:String = poll.id;
|
var pollId:String = poll.id;
|
||||||
|
|
||||||
var answers:Array = poll.answers as Array;
|
var answers:Array = poll.answers as Array;
|
||||||
|
var accessibleAnswers:String = ResourceUtil.getInstance().getString("bbb.polling.results.accessible.header") + "<br />";
|
||||||
|
|
||||||
var ans:Array = new Array();
|
var ans:Array = new Array();
|
||||||
|
|
||||||
for (var j:int = 0; j < answers.length; j++) {
|
for (var j:int = 0; j < answers.length; j++) {
|
||||||
var a:Object = answers[j];
|
var a:Object = answers[j];
|
||||||
ans.push(new SimpleAnswerResult(a.id as Number, a.key, a.num_votes as Number));
|
ans.push(new SimpleAnswerResult(a.id as Number, a.key, a.num_votes as Number));
|
||||||
|
accessibleAnswers += ResourceUtil.getInstance().getString("bbb.polling.results.accessible.answer", [ResourceUtil.getInstance().getString("bbb.polling.answer."+a.key), a.num_votes]) + "<br />";
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatcher.dispatchEvent(new PollShowResultEvent(new SimplePollResult(pollId, ans)));
|
var numRespondents:Number = poll.num_respondents;
|
||||||
|
var numResponders:Number = poll.num_responders;
|
||||||
|
|
||||||
|
dispatcher.dispatchEvent(new PollShowResultEvent(new SimplePollResult(pollId, ans, numRespondents, numResponders)));
|
||||||
|
|
||||||
|
if (Accessibility.active) {
|
||||||
|
var pollResultMessage:ChatMessageVO = new ChatMessageVO();
|
||||||
|
pollResultMessage.chatType = ChatConstants.PUBLIC_CHAT;
|
||||||
|
pollResultMessage.fromUserID = ResourceUtil.getInstance().getString("bbb.chat.chatMessage.systemMessage");
|
||||||
|
pollResultMessage.fromUsername = ResourceUtil.getInstance().getString("bbb.chat.chatMessage.systemMessage");
|
||||||
|
pollResultMessage.fromColor = "86187";
|
||||||
|
pollResultMessage.fromTime = new Date().getTime();
|
||||||
|
pollResultMessage.fromTimezoneOffset = new Date().getTimezoneOffset();
|
||||||
|
pollResultMessage.toUserID = ResourceUtil.getInstance().getString("bbb.chat.chatMessage.systemMessage");
|
||||||
|
pollResultMessage.toUsername = ResourceUtil.getInstance().getString("bbb.chat.chatMessage.systemMessage");
|
||||||
|
pollResultMessage.message = accessibleAnswers;
|
||||||
|
|
||||||
|
var pollResultMessageEvent:PublicChatMessageEvent = new PublicChatMessageEvent(PublicChatMessageEvent.PUBLIC_CHAT_MESSAGE_EVENT);
|
||||||
|
pollResultMessageEvent.message = pollResultMessage;
|
||||||
|
pollResultMessageEvent.history = false;
|
||||||
|
dispatcher.dispatchEvent(pollResultMessageEvent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,7 +113,8 @@ package org.bigbluebutton.modules.polling.service
|
|||||||
var map:Object = JSON.parse(msg.msg);
|
var map:Object = JSON.parse(msg.msg);
|
||||||
if (map.hasOwnProperty("poll")) {
|
if (map.hasOwnProperty("poll")) {
|
||||||
var poll:Object = map.poll;
|
var poll:Object = map.poll;
|
||||||
if (poll.hasOwnProperty("id") && poll.hasOwnProperty("answers")) {
|
if (poll.hasOwnProperty("id") && poll.hasOwnProperty("answers")
|
||||||
|
&& poll.hasOwnProperty("num_responders") && poll.hasOwnProperty("num_respondents")) {
|
||||||
var pollId:String = poll.id;
|
var pollId:String = poll.id;
|
||||||
|
|
||||||
var answers:Array = poll.answers as Array;
|
var answers:Array = poll.answers as Array;
|
||||||
@ -95,7 +126,10 @@ package org.bigbluebutton.modules.polling.service
|
|||||||
ans.push(new SimpleAnswerResult(a.id as Number, a.key, a.num_votes as Number));
|
ans.push(new SimpleAnswerResult(a.id as Number, a.key, a.num_votes as Number));
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatcher.dispatchEvent(new PollVotedEvent(new SimplePollResult(pollId, ans)));
|
var numRespondents:Number = poll.num_respondents;
|
||||||
|
var numResponders:Number = poll.num_responders;
|
||||||
|
|
||||||
|
dispatcher.dispatchEvent(new PollVotedEvent(new SimplePollResult(pollId, ans, numRespondents, numResponders)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,6 +233,7 @@ package org.bigbluebutton.modules.polling.views
|
|||||||
private function findFontSize(textField:TextField, defaultSize:Number):int {
|
private function findFontSize(textField:TextField, defaultSize:Number):int {
|
||||||
var tFormat:TextFormat = new TextFormat();
|
var tFormat:TextFormat = new TextFormat();
|
||||||
tFormat.size = defaultSize;
|
tFormat.size = defaultSize;
|
||||||
|
tFormat.font = "arial";
|
||||||
tFormat.align = TextFormatAlign.CENTER;
|
tFormat.align = TextFormatAlign.CENTER;
|
||||||
textField.setTextFormat(tFormat);
|
textField.setTextFormat(tFormat);
|
||||||
var size:Number = defaultSize;
|
var size:Number = defaultSize;
|
||||||
|
@ -8,6 +8,10 @@ package org.bigbluebutton.modules.polling.views
|
|||||||
import mx.containers.HBox;
|
import mx.containers.HBox;
|
||||||
import mx.containers.TitleWindow;
|
import mx.containers.TitleWindow;
|
||||||
import mx.controls.Button;
|
import mx.controls.Button;
|
||||||
|
import mx.controls.HRule;
|
||||||
|
import mx.controls.Label;
|
||||||
|
import mx.controls.TextArea;
|
||||||
|
import mx.core.ScrollPolicy;
|
||||||
import mx.managers.PopUpManager;
|
import mx.managers.PopUpManager;
|
||||||
|
|
||||||
import org.bigbluebutton.modules.polling.events.PollVotedEvent;
|
import org.bigbluebutton.modules.polling.events.PollVotedEvent;
|
||||||
@ -21,6 +25,7 @@ package org.bigbluebutton.modules.polling.views
|
|||||||
public class PollResultsModal extends TitleWindow {
|
public class PollResultsModal extends TitleWindow {
|
||||||
private var _voteListener:Listener;
|
private var _voteListener:Listener;
|
||||||
|
|
||||||
|
private var _respondersLabel:Label;
|
||||||
private var _pollGraphic:PollGraphic;
|
private var _pollGraphic:PollGraphic;
|
||||||
private var _publishBtn:Button;
|
private var _publishBtn:Button;
|
||||||
private var _closeBtn:Button;
|
private var _closeBtn:Button;
|
||||||
@ -28,23 +33,33 @@ package org.bigbluebutton.modules.polling.views
|
|||||||
public function PollResultsModal() {
|
public function PollResultsModal() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
styleName = "micSettingsWindowStyle";
|
||||||
width = 300;
|
width = 300;
|
||||||
height = 300;
|
height = 300;
|
||||||
|
setStyle("verticalGap", 15);
|
||||||
showCloseButton = false;
|
showCloseButton = false;
|
||||||
layout = "vertical";
|
layout = "vertical";
|
||||||
setStyle("horizontalAlign", "center");
|
setStyle("horizontalAlign", "center");
|
||||||
setStyle("verticalAlign", "middle");
|
setStyle("verticalAlign", "middle");
|
||||||
|
|
||||||
|
var modalTitle:TextArea = new TextArea();
|
||||||
|
modalTitle.setStyle("borderSkin", null);
|
||||||
|
modalTitle.verticalScrollPolicy = ScrollPolicy.OFF;
|
||||||
|
modalTitle.editable = false;
|
||||||
|
modalTitle.text = ResourceUtil.getInstance().getString('bbb.polling.pollModal.title');
|
||||||
|
modalTitle.styleName = "micSettingsWindowTitleStyle";
|
||||||
|
modalTitle.percentWidth = 100;
|
||||||
|
modalTitle.height = 25;
|
||||||
|
addChild(modalTitle);
|
||||||
|
|
||||||
var topBox:HBox = new HBox();
|
var hrule:HRule = new HRule();
|
||||||
_publishBtn = new Button();
|
hrule.percentWidth = 100;
|
||||||
_publishBtn.label = ResourceUtil.getInstance().getString('bbb.polling.publishButton.label');
|
addChild(hrule);
|
||||||
_publishBtn.addEventListener(MouseEvent.CLICK, handlePublishClick);
|
|
||||||
topBox.addChild(_publishBtn);
|
_respondersLabel = new Label();
|
||||||
_closeBtn = new Button();
|
_respondersLabel.styleName = "pollResondersLabelStyle";
|
||||||
_closeBtn.label = ResourceUtil.getInstance().getString('bbb.polling.closeButton.label');
|
_respondersLabel.text = " ";// ResourceUtil.getInstance().getString('bbb.polling.respondersLabel.novotes');
|
||||||
_closeBtn.addEventListener(MouseEvent.CLICK, handleCloseClick);
|
addChild(_respondersLabel);
|
||||||
topBox.addChild(_closeBtn);
|
|
||||||
addChild(topBox);
|
|
||||||
|
|
||||||
_pollGraphic = new PollGraphic();
|
_pollGraphic = new PollGraphic();
|
||||||
_pollGraphic.data = null;
|
_pollGraphic.data = null;
|
||||||
@ -52,6 +67,23 @@ package org.bigbluebutton.modules.polling.views
|
|||||||
_pollGraphic.minWidth = 130;
|
_pollGraphic.minWidth = 130;
|
||||||
addChild(_pollGraphic);
|
addChild(_pollGraphic);
|
||||||
|
|
||||||
|
hrule = new HRule();
|
||||||
|
hrule.percentWidth = 100;
|
||||||
|
addChild(hrule);
|
||||||
|
|
||||||
|
var botBox:HBox = new HBox();
|
||||||
|
botBox.setStyle("gap", 10);
|
||||||
|
|
||||||
|
_publishBtn = new Button();
|
||||||
|
_publishBtn.label = ResourceUtil.getInstance().getString('bbb.polling.publishButton.label');
|
||||||
|
_publishBtn.addEventListener(MouseEvent.CLICK, handlePublishClick);
|
||||||
|
botBox.addChild(_publishBtn);
|
||||||
|
_closeBtn = new Button();
|
||||||
|
_closeBtn.label = ResourceUtil.getInstance().getString('bbb.polling.closeButton.label');
|
||||||
|
_closeBtn.addEventListener(MouseEvent.CLICK, handleCloseClick);
|
||||||
|
botBox.addChild(_closeBtn);
|
||||||
|
addChild(botBox);
|
||||||
|
|
||||||
_voteListener = new Listener();
|
_voteListener = new Listener();
|
||||||
_voteListener.type = PollVotedEvent.POLL_VOTED;
|
_voteListener.type = PollVotedEvent.POLL_VOTED;
|
||||||
_voteListener.method = handlePollVotedEvent;
|
_voteListener.method = handlePollVotedEvent;
|
||||||
@ -62,14 +94,14 @@ package org.bigbluebutton.modules.polling.views
|
|||||||
var answers:Array = poll.answers;
|
var answers:Array = poll.answers;
|
||||||
for (var j:int = 0; j < answers.length; j++) {
|
for (var j:int = 0; j < answers.length; j++) {
|
||||||
var a:SimpleAnswer = answers[j] as SimpleAnswer;
|
var a:SimpleAnswer = answers[j] as SimpleAnswer;
|
||||||
resultData.push({a:a.key, v:0});
|
resultData.push({a:ResourceUtil.getInstance().getString('bbb.polling.answer.' + a.key), v:0});
|
||||||
}
|
}
|
||||||
|
|
||||||
_pollGraphic.data = resultData;
|
_pollGraphic.data = resultData;
|
||||||
_pollGraphic.height = ((23+10)*_pollGraphic.data.length+10);
|
_pollGraphic.height = ((23+10)*_pollGraphic.data.length+10);
|
||||||
_pollGraphic.minHeight = ((16+10)*_pollGraphic.data.length+10);
|
_pollGraphic.minHeight = ((16+10)*_pollGraphic.data.length+10);
|
||||||
|
|
||||||
height = _pollGraphic.height + 140;
|
height = _pollGraphic.height + 220;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handlePollVotedEvent(e:PollVotedEvent):void {
|
private function handlePollVotedEvent(e:PollVotedEvent):void {
|
||||||
@ -77,10 +109,11 @@ package org.bigbluebutton.modules.polling.views
|
|||||||
var answers:Array = e.result.answers;
|
var answers:Array = e.result.answers;
|
||||||
for (var j:int = 0; j < answers.length; j++) {
|
for (var j:int = 0; j < answers.length; j++) {
|
||||||
var a:SimpleAnswerResult = answers[j] as SimpleAnswerResult;
|
var a:SimpleAnswerResult = answers[j] as SimpleAnswerResult;
|
||||||
resultData.push({a:a.key, v:a.numVotes});
|
resultData.push({a:ResourceUtil.getInstance().getString('bbb.polling.answer.' + a.key), v:a.numVotes});
|
||||||
}
|
}
|
||||||
|
|
||||||
_pollGraphic.data = resultData;
|
_pollGraphic.data = resultData;
|
||||||
|
_respondersLabel.text = ResourceUtil.getInstance().getString('bbb.polling.respondersLabel.text', [e.result.numResponders + "/" + e.result.numRespondents]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handlePublishClick(e:MouseEvent):void {
|
private function handlePublishClick(e:MouseEvent):void {
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
package org.bigbluebutton.modules.polling.views {
|
||||||
|
import com.asfusion.mate.events.Listener;
|
||||||
|
|
||||||
|
import mx.controls.Button;
|
||||||
|
|
||||||
|
import org.as3commons.logging.api.ILogger;
|
||||||
|
import org.as3commons.logging.api.getClassLogger;
|
||||||
|
import org.bigbluebutton.modules.present.events.PageLoadedEvent;
|
||||||
|
import org.bigbluebutton.modules.present.model.Page;
|
||||||
|
import org.bigbluebutton.modules.present.model.PresentationModel;
|
||||||
|
|
||||||
|
public class QuickPollButton extends Button {
|
||||||
|
private static const LOGGER:ILogger = getClassLogger(QuickPollButton);
|
||||||
|
|
||||||
|
public function QuickPollButton() {
|
||||||
|
super();
|
||||||
|
visible = false;
|
||||||
|
|
||||||
|
var listener:Listener = new Listener();
|
||||||
|
listener.type = PageLoadedEvent.PAGE_LOADED_EVENT;
|
||||||
|
listener.method = handlePageLoadedEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handlePageLoadedEvent(e:PageLoadedEvent):void {
|
||||||
|
var page:Page = PresentationModel.getInstance().getPage(e.pageId);
|
||||||
|
if (page != null) {
|
||||||
|
parseSlideText(page.txtData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseSlideText(text:String):void {
|
||||||
|
var regEx:RegExp = new RegExp("\n[^\s]+[\.\)]", "g");
|
||||||
|
var matchedArray:Array = text.match(regEx);
|
||||||
|
LOGGER.debug("Parse Result: {0} {1}", [matchedArray.length, matchedArray.join(" ")]);
|
||||||
|
if (matchedArray.length > 2) {
|
||||||
|
label = "A-" + (matchedArray.length < 8 ? matchedArray.length : 7);
|
||||||
|
visible = true;
|
||||||
|
} else {
|
||||||
|
visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -24,6 +24,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
<![CDATA[
|
<![CDATA[
|
||||||
import mx.events.FlexEvent;
|
import mx.events.FlexEvent;
|
||||||
|
|
||||||
|
import org.bigbluebutton.main.events.BBBEvent;
|
||||||
import org.bigbluebutton.main.model.users.events.RoleChangeEvent;
|
import org.bigbluebutton.main.model.users.events.RoleChangeEvent;
|
||||||
import org.bigbluebutton.modules.present.api.PresentationAPI;
|
import org.bigbluebutton.modules.present.api.PresentationAPI;
|
||||||
import org.bigbluebutton.modules.present.business.PresentProxy;
|
import org.bigbluebutton.modules.present.business.PresentProxy;
|
||||||
@ -71,6 +72,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
<MethodInvoker generator="{PresentManager}" method="handleStopModuleEvent" />
|
<MethodInvoker generator="{PresentManager}" method="handleStopModuleEvent" />
|
||||||
</EventHandlers>
|
</EventHandlers>
|
||||||
|
|
||||||
|
<EventHandlers type="{BBBEvent.RECONNECT_BIGBLUEBUTTON_SUCCEEDED_EVENT}" >
|
||||||
|
<MethodInvoker generator="{PresentProxy}" method="getCurrentPresentationInfo" />
|
||||||
|
</EventHandlers>
|
||||||
|
|
||||||
<EventHandlers type="{UploadEvent.OPEN_UPLOAD_WINDOW}" >
|
<EventHandlers type="{UploadEvent.OPEN_UPLOAD_WINDOW}" >
|
||||||
<MethodInvoker generator="{PresentManager}" method="handleOpenUploadWindow" arguments="{event}" />
|
<MethodInvoker generator="{PresentManager}" method="handleOpenUploadWindow" arguments="{event}" />
|
||||||
</EventHandlers>
|
</EventHandlers>
|
||||||
|
@ -11,7 +11,6 @@ package org.bigbluebutton.modules.present.model
|
|||||||
|
|
||||||
private static var instance:PresentationModel = null;
|
private static var instance:PresentationModel = null;
|
||||||
|
|
||||||
private var _pages:ArrayCollection = new ArrayCollection();
|
|
||||||
private var _presentations:ArrayCollection = new ArrayCollection();
|
private var _presentations:ArrayCollection = new ArrayCollection();
|
||||||
private var _presenter: Presenter;
|
private var _presenter: Presenter;
|
||||||
|
|
||||||
@ -48,10 +47,6 @@ package org.bigbluebutton.modules.present.model
|
|||||||
return _presenter;
|
return _presenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addPage(page: Page):void {
|
|
||||||
_pages.addItem(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addPresentation(p: Presentation):void {
|
public function addPresentation(p: Presentation):void {
|
||||||
_presentations.addItem(p);
|
_presentations.addItem(p);
|
||||||
}
|
}
|
||||||
@ -68,6 +63,10 @@ package org.bigbluebutton.modules.present.model
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function removeAllPresentations():void {
|
||||||
|
_presentations.removeAll();
|
||||||
|
}
|
||||||
|
|
||||||
public function replacePresentation(p: Presentation):void {
|
public function replacePresentation(p: Presentation):void {
|
||||||
var oldPres:Presentation = removePresentation(p.id);
|
var oldPres:Presentation = removePresentation(p.id);
|
||||||
if (oldPres == null) {
|
if (oldPres == null) {
|
||||||
|
@ -150,6 +150,10 @@ package org.bigbluebutton.modules.present.services
|
|||||||
LOGGER.debug("Switching presentation but presentation [{0}] is not current [{0}]", [presVO.id, presVO.isCurrent()]);
|
LOGGER.debug("Switching presentation but presentation [{0}] is not current [{0}]", [presVO.id, presVO.isCurrent()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function removeAllPresentations():void {
|
||||||
|
model.removeAllPresentations();
|
||||||
|
}
|
||||||
|
|
||||||
public function removePresentation(presentationID:String):void {
|
public function removePresentation(presentationID:String):void {
|
||||||
var removedEvent:RemovePresentationEvent = new RemovePresentationEvent(RemovePresentationEvent.PRESENTATION_REMOVED_EVENT);
|
var removedEvent:RemovePresentationEvent = new RemovePresentationEvent(RemovePresentationEvent.PRESENTATION_REMOVED_EVENT);
|
||||||
|
@ -294,6 +294,7 @@ package org.bigbluebutton.modules.present.services.messaging
|
|||||||
presos.addItem(presVO);
|
presos.addItem(presVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
service.removeAllPresentations();
|
||||||
service.addPresentations(presos);
|
service.addPresentations(presos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
width="{DEFAULT_WINDOW_WIDTH}" height="{DEFAULT_WINDOW_HEIGHT}"
|
width="{DEFAULT_WINDOW_WIDTH}" height="{DEFAULT_WINDOW_HEIGHT}"
|
||||||
x="{DEFAULT_X_POSITION}" y="{DEFAULT_Y_POSITION}"
|
x="{DEFAULT_X_POSITION}" y="{DEFAULT_Y_POSITION}"
|
||||||
title="{ResourceUtil.getInstance().getString('bbb.presentation.titleWithPres',[currentPresentation])}"
|
title="{ResourceUtil.getInstance().getString('bbb.presentation.titleWithPres',[currentPresentation])}"
|
||||||
xmlns:views="org.bigbluebutton.modules.present.ui.views.*"
|
xmlns:views="org.bigbluebutton.modules.present.ui.views.*"
|
||||||
|
xmlns:poll="org.bigbluebutton.modules.polling.views.*"
|
||||||
>
|
>
|
||||||
|
|
||||||
<mate:Dispatcher id="globalDispatcher" />
|
<mate:Dispatcher id="globalDispatcher" />
|
||||||
@ -616,6 +617,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function quickPollClicked(e:MouseEvent):void {
|
||||||
|
sendStartPollEvent(Button(e.target).label);
|
||||||
|
}
|
||||||
|
|
||||||
private function onPollStartButtonClicked():void {
|
private function onPollStartButtonClicked():void {
|
||||||
openPollTypeMenu();
|
openPollTypeMenu();
|
||||||
}
|
}
|
||||||
@ -640,39 +645,45 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function sendStartPollEvent(pollType:String):void {
|
||||||
|
// Let's reset the page to display full size so we can display the result
|
||||||
|
// on the bottom right-corner.
|
||||||
|
onResetZoom();
|
||||||
|
var dispatcher:Dispatcher = new Dispatcher();
|
||||||
|
dispatchEvent(new StartPollEvent(pollType));
|
||||||
|
}
|
||||||
|
|
||||||
private function menuClickHandler(e:MenuEvent):void {
|
private function menuClickHandler(e:MenuEvent):void {
|
||||||
if(pollMenuData[e.index] != undefined) {
|
if(pollMenuData[e.index] != undefined) {
|
||||||
// start the requested poll
|
// start the requested poll
|
||||||
var pollEvent:StartPollEvent = null;
|
var pollEvent:StartPollEvent = null;
|
||||||
switch (e.index) {
|
switch (e.index) {
|
||||||
case 0:
|
case 0:
|
||||||
pollEvent = new StartPollEvent("YN");
|
sendStartPollEvent("YN");
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
pollEvent = new StartPollEvent("TF");
|
sendStartPollEvent("TF");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
pollEvent = new StartPollEvent("A-2");
|
sendStartPollEvent("A-2");
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
pollEvent = new StartPollEvent("A-3");
|
sendStartPollEvent("A-3");
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
pollEvent = new StartPollEvent("A-4");
|
sendStartPollEvent("A-4");
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
pollEvent = new StartPollEvent("A-5");
|
sendStartPollEvent("A-5");
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
pollEvent = new StartPollEvent("A-6");
|
sendStartPollEvent("A-6");
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
pollEvent = new StartPollEvent("A-7");
|
sendStartPollEvent("A-7");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var dispatcher:Dispatcher = new Dispatcher();
|
|
||||||
//dispatcher.
|
|
||||||
dispatchEvent(pollEvent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -759,30 +770,32 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
<mx:Button id="pollStartBtn" visible="false" height="30" styleName="pollStartButtonStyle"
|
<mx:Button id="pollStartBtn" visible="false" height="30" styleName="pollStartButtonStyle"
|
||||||
toolTip="{ResourceUtil.getInstance().getString('bbb.polling.startButton.tooltip')}"
|
toolTip="{ResourceUtil.getInstance().getString('bbb.polling.startButton.tooltip')}"
|
||||||
click="onPollStartButtonClicked()" tabIndex="{baseIndex+6}"/>
|
click="onPollStartButtonClicked()" tabIndex="{baseIndex+6}"/>
|
||||||
|
<poll:QuickPollButton id="quickPollBtn" height="30" tabIndex="{baseIndex+7}"
|
||||||
|
click="quickPollClicked(event)" />
|
||||||
<mx:Spacer width="100%" id="spacer1"/>
|
<mx:Spacer width="100%" id="spacer1"/>
|
||||||
<mx:Button id="backButton" visible="false" width="45" height="30" styleName="presentationBackButtonStyle"
|
<mx:Button id="backButton" visible="false" width="45" height="30" styleName="presentationBackButtonStyle"
|
||||||
toolTip="{ResourceUtil.getInstance().getString('bbb.presentation.backBtn.toolTip')}" click="gotoPreviousSlide()"
|
toolTip="{ResourceUtil.getInstance().getString('bbb.presentation.backBtn.toolTip')}" click="gotoPreviousSlide()"
|
||||||
tabIndex="{baseIndex+7}"/>
|
tabIndex="{baseIndex+8}"/>
|
||||||
<mx:Button id="btnSlideNum" visible="false" label="" click="showThumbnails()"
|
<mx:Button id="btnSlideNum" visible="false" label="" click="showThumbnails()"
|
||||||
toolTip="{ResourceUtil.getInstance().getString('bbb.presentation.btnSlideNum.toolTip')}"
|
toolTip="{ResourceUtil.getInstance().getString('bbb.presentation.btnSlideNum.toolTip')}"
|
||||||
tabIndex="{baseIndex+8}"/>
|
tabIndex="{baseIndex+9}"/>
|
||||||
<mx:Button id="forwardButton" visible="false" width="45" height="30" styleName="presentationForwardButtonStyle"
|
<mx:Button id="forwardButton" visible="false" width="45" height="30" styleName="presentationForwardButtonStyle"
|
||||||
toolTip="{ResourceUtil.getInstance().getString('bbb.presentation.forwardBtn.toolTip')}" click="gotoNextSlide()"
|
toolTip="{ResourceUtil.getInstance().getString('bbb.presentation.forwardBtn.toolTip')}" click="gotoNextSlide()"
|
||||||
tabIndex="{baseIndex+9}"/>
|
tabIndex="{baseIndex+10}"/>
|
||||||
<mx:Spacer width="50%" id="spacer3"/>
|
<mx:Spacer width="50%" id="spacer3"/>
|
||||||
<mx:HSlider id="zoomSlider" visible="false" value="{slideView.zoomPercentage}" styleName="presentationZoomSliderStyle"
|
<mx:HSlider id="zoomSlider" visible="false" value="{slideView.zoomPercentage}" styleName="presentationZoomSliderStyle"
|
||||||
minimum="100" maximum="400" dataTipPlacement="top" labels="['100%','400%']"
|
minimum="100" maximum="400" dataTipPlacement="top" labels="['100%','400%']"
|
||||||
useHandCursor="true" snapInterval="5" allowTrackClick="true" liveDragging="true"
|
useHandCursor="true" snapInterval="5" allowTrackClick="true" liveDragging="true"
|
||||||
dataTipFormatFunction="removeDecimalFromDataTip" change="onSliderZoom()" width="100"
|
dataTipFormatFunction="removeDecimalFromDataTip" change="onSliderZoom()" width="100"
|
||||||
tabIndex="{baseIndex+10}" accessibilityName="{ResourceUtil.getInstance().getString('bbb.presentation.slider')}"/>
|
tabIndex="{baseIndex+11}" accessibilityName="{ResourceUtil.getInstance().getString('bbb.presentation.slider')}"/>
|
||||||
<mx:Button id="btnFitToWidth" visible="false" width="30" height="30" styleName="presentationFitToWidthButtonStyle"
|
<mx:Button id="btnFitToWidth" visible="false" width="30" height="30" styleName="presentationFitToWidthButtonStyle"
|
||||||
toolTip="{ResourceUtil.getInstance().getString('bbb.presentation.fitToWidth.toolTip')}"
|
toolTip="{ResourceUtil.getInstance().getString('bbb.presentation.fitToWidth.toolTip')}"
|
||||||
click="onFitToPage(false)"
|
click="onFitToPage(false)"
|
||||||
tabIndex="{baseIndex+11}"/>
|
tabIndex="{baseIndex+12}"/>
|
||||||
<mx:Button id="btnFitToPage" visible="false" width="30" height="30" styleName="presentationFitToPageButtonStyle"
|
<mx:Button id="btnFitToPage" visible="false" width="30" height="30" styleName="presentationFitToPageButtonStyle"
|
||||||
toolTip="{ResourceUtil.getInstance().getString('bbb.presentation.fitToPage.toolTip')}"
|
toolTip="{ResourceUtil.getInstance().getString('bbb.presentation.fitToPage.toolTip')}"
|
||||||
click="onFitToPage(true)"
|
click="onFitToPage(true)"
|
||||||
tabIndex="{baseIndex+12}"/>
|
tabIndex="{baseIndex+13}"/>
|
||||||
<!-- This spacer is to prevent the whiteboard toolbar from overlapping the fit-ot-page button -->
|
<!-- This spacer is to prevent the whiteboard toolbar from overlapping the fit-ot-page button -->
|
||||||
<mx:Spacer width="30" height="30" id="spacer4"/>
|
<mx:Spacer width="30" height="30" id="spacer4"/>
|
||||||
</mx:HBox>
|
</mx:HBox>
|
||||||
|
@ -179,6 +179,14 @@ package org.bigbluebutton.modules.users.services
|
|||||||
var e:UsersConnectionEvent = new UsersConnectionEvent(UsersConnectionEvent.CONNECTION_SUCCESS);
|
var e:UsersConnectionEvent = new UsersConnectionEvent(UsersConnectionEvent.CONNECTION_SUCCESS);
|
||||||
e.userid = userid;
|
e.userid = userid;
|
||||||
dispatcher.dispatchEvent(e);
|
dispatcher.dispatchEvent(e);
|
||||||
|
|
||||||
|
// If the user was the presenter he's reconnecting and must become viewer
|
||||||
|
if (UserManager.getInstance().getConference().amIPresenter) {
|
||||||
|
sendSwitchedPresenterEvent(false, UsersUtil.getPresenterUserID());
|
||||||
|
UserManager.getInstance().getConference().amIPresenter = false;
|
||||||
|
var viewerEvent:MadePresenterEvent = new MadePresenterEvent(MadePresenterEvent.SWITCH_TO_VIEWER_MODE);
|
||||||
|
dispatcher.dispatchEvent(viewerEvent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleMeetingMuted(msg:Object):void {
|
private function handleMeetingMuted(msg:Object):void {
|
||||||
@ -346,6 +354,7 @@ package org.bigbluebutton.modules.users.services
|
|||||||
|
|
||||||
if (UsersUtil.hasUser(internUserID)) {
|
if (UsersUtil.hasUser(internUserID)) {
|
||||||
var bu:BBBUser = UsersUtil.getUser(internUserID);
|
var bu:BBBUser = UsersUtil.getUser(internUserID);
|
||||||
|
bu.talking = voiceUser.talking;
|
||||||
bu.voiceMuted = voiceUser.muted;
|
bu.voiceMuted = voiceUser.muted;
|
||||||
bu.voiceJoined = true;
|
bu.voiceJoined = true;
|
||||||
|
|
||||||
@ -409,6 +418,9 @@ package org.bigbluebutton.modules.users.services
|
|||||||
LOGGER.debug("*** handleGetUsersReply {0} **** \n", [msg.msg]);
|
LOGGER.debug("*** handleGetUsersReply {0} **** \n", [msg.msg]);
|
||||||
var map:Object = JSON.parse(msg.msg);
|
var map:Object = JSON.parse(msg.msg);
|
||||||
var users:Object = map.users as Array;
|
var users:Object = map.users as Array;
|
||||||
|
|
||||||
|
// since might be a reconnection, clean up users list
|
||||||
|
UserManager.getInstance().getConference().removeAllParticipants();
|
||||||
|
|
||||||
if (map.count > 0) {
|
if (map.count > 0) {
|
||||||
LOGGER.debug("number of users = [{0}]", [users.length]);
|
LOGGER.debug("number of users = [{0}]", [users.length]);
|
||||||
@ -555,6 +567,10 @@ package org.bigbluebutton.modules.users.services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (joinedUser.voiceUser.joined) {
|
||||||
|
userJoinedVoice(joinedUser);
|
||||||
|
}
|
||||||
|
|
||||||
UserManager.getInstance().getConference().presenterStatusChanged(user.userID, joinedUser.presenter);
|
UserManager.getInstance().getConference().presenterStatusChanged(user.userID, joinedUser.presenter);
|
||||||
UserManager.getInstance().getConference().raiseHand(user.userID, joinedUser.raiseHand);
|
UserManager.getInstance().getConference().raiseHand(user.userID, joinedUser.raiseHand);
|
||||||
|
|
||||||
@ -582,4 +598,4 @@ package org.bigbluebutton.modules.users.services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,9 +36,13 @@ package org.bigbluebutton.modules.videoconf.business
|
|||||||
import org.as3commons.logging.api.getClassLogger;
|
import org.as3commons.logging.api.getClassLogger;
|
||||||
import org.bigbluebutton.core.BBB;
|
import org.bigbluebutton.core.BBB;
|
||||||
import org.bigbluebutton.core.UsersUtil;
|
import org.bigbluebutton.core.UsersUtil;
|
||||||
|
import org.bigbluebutton.core.managers.ReconnectionManager;
|
||||||
|
import org.bigbluebutton.main.events.BBBEvent;
|
||||||
import org.bigbluebutton.modules.videoconf.events.ConnectedEvent;
|
import org.bigbluebutton.modules.videoconf.events.ConnectedEvent;
|
||||||
import org.bigbluebutton.modules.videoconf.events.StartBroadcastEvent;
|
import org.bigbluebutton.modules.videoconf.events.StartBroadcastEvent;
|
||||||
|
import org.bigbluebutton.modules.videoconf.events.StopBroadcastEvent;
|
||||||
import org.bigbluebutton.modules.videoconf.model.VideoConfOptions;
|
import org.bigbluebutton.modules.videoconf.model.VideoConfOptions;
|
||||||
|
import org.bigbluebutton.main.api.JSLog;
|
||||||
|
|
||||||
|
|
||||||
public class VideoProxy
|
public class VideoProxy
|
||||||
@ -48,15 +52,12 @@ package org.bigbluebutton.modules.videoconf.business
|
|||||||
public var videoOptions:VideoConfOptions;
|
public var videoOptions:VideoConfOptions;
|
||||||
|
|
||||||
private var nc:NetConnection;
|
private var nc:NetConnection;
|
||||||
private var ns:NetStream;
|
|
||||||
private var _url:String;
|
private var _url:String;
|
||||||
private var camerasPublishing:Object = new Object();
|
private var camerasPublishing:Object = new Object();
|
||||||
private var connected:Boolean = false;
|
private var reconnect:Boolean = false;
|
||||||
private var reconnect:Boolean = false;
|
|
||||||
private var reconnecting:Boolean = false;
|
private var reconnecting:Boolean = false;
|
||||||
|
private var dispatcher:Dispatcher = new Dispatcher();
|
||||||
private var autoReconnectTimer:Timer = new Timer(1000, 1);
|
|
||||||
|
|
||||||
private function parseOptions():void {
|
private function parseOptions():void {
|
||||||
videoOptions = new VideoConfOptions();
|
videoOptions = new VideoConfOptions();
|
||||||
videoOptions.parseOptions();
|
videoOptions.parseOptions();
|
||||||
@ -91,32 +92,70 @@ package org.bigbluebutton.modules.videoconf.business
|
|||||||
LOGGER.debug("VIDEO WEBCAM onIOError");
|
LOGGER.debug("VIDEO WEBCAM onIOError");
|
||||||
}
|
}
|
||||||
|
|
||||||
private function onConnectedToVideoApp():void{
|
private function onConnectedToVideoApp():void{
|
||||||
var dispatcher:Dispatcher = new Dispatcher();
|
dispatcher.dispatchEvent(new ConnectedEvent(reconnecting));
|
||||||
dispatcher.dispatchEvent(new ConnectedEvent(reconnecting));
|
if (reconnecting) {
|
||||||
reconnecting = false;
|
reconnecting = false;
|
||||||
}
|
|
||||||
|
var attemptSucceeded:BBBEvent = new BBBEvent(BBBEvent.RECONNECT_CONNECTION_ATTEMPT_SUCCEEDED_EVENT);
|
||||||
|
attemptSucceeded.payload.type = ReconnectionManager.VIDEO_CONNECTION;
|
||||||
|
dispatcher.dispatchEvent(attemptSucceeded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private function onNetStatus(event:NetStatusEvent):void{
|
private function onNetStatus(event:NetStatusEvent):void{
|
||||||
|
|
||||||
LOGGER.debug("[{0}] for [{1}]", [event.info.code, _url]);
|
LOGGER.debug("[{0}] for [{1}]", [event.info.code, _url]);
|
||||||
|
var logData:Object = new Object();
|
||||||
|
logData.user = UsersUtil.getUserData();
|
||||||
switch(event.info.code){
|
switch(event.info.code){
|
||||||
case "NetConnection.Connect.Success":
|
case "NetConnection.Connect.Success":
|
||||||
connected = true;
|
|
||||||
//ns = new NetStream(nc);
|
|
||||||
onConnectedToVideoApp();
|
onConnectedToVideoApp();
|
||||||
break;
|
break;
|
||||||
case "NetStream.Play.Failed":
|
case "NetStream.Play.Failed":
|
||||||
disconnect();
|
if (reconnect) {
|
||||||
|
JSLog.warn("NetStream.Play.Failed from bbb-video", logData);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "NetStream.Play.Stop":
|
case "NetStream.Play.Stop":
|
||||||
disconnect();
|
if (reconnect) {
|
||||||
|
JSLog.warn("NetStream.Play.Stop from bbb-video", logData);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "NetConnection.Connect.Closed":
|
case "NetConnection.Connect.Closed":
|
||||||
|
dispatcher.dispatchEvent(new StopBroadcastEvent());
|
||||||
|
|
||||||
|
if (reconnect) {
|
||||||
|
reconnecting = true;
|
||||||
|
|
||||||
|
var disconnectedEvent:BBBEvent = new BBBEvent(BBBEvent.RECONNECT_DISCONNECTED_EVENT);
|
||||||
|
disconnectedEvent.payload.type = ReconnectionManager.VIDEO_CONNECTION;
|
||||||
|
disconnectedEvent.payload.callback = connect;
|
||||||
|
disconnectedEvent.payload.callbackParameters = [];
|
||||||
|
dispatcher.dispatchEvent(disconnectedEvent);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "NetConnection.Connect.Failed":
|
||||||
|
if (reconnecting) {
|
||||||
|
var attemptFailedEvent:BBBEvent = new BBBEvent(BBBEvent.RECONNECT_CONNECTION_ATTEMPT_FAILED_EVENT);
|
||||||
|
attemptFailedEvent.payload.type = ReconnectionManager.VIDEO_CONNECTION;
|
||||||
|
dispatcher.dispatchEvent(attemptFailedEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reconnect) {
|
||||||
|
JSLog.warn("Disconnected from bbb-video", logData);
|
||||||
|
}
|
||||||
|
|
||||||
disconnect();
|
disconnect();
|
||||||
break;
|
break;
|
||||||
|
case "NetConnection.Connect.NetworkChange":
|
||||||
|
JSLog.warn("Detected network change on bbb-video", logData);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LOGGER.debug("[{0}] for [{1}]", [event.info.code, _url]);
|
LOGGER.debug("[{0}] for [{1}]", [event.info.code, _url]);
|
||||||
connected = false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,17 +168,14 @@ package org.bigbluebutton.modules.videoconf.business
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function startPublishing(e:StartBroadcastEvent):void{
|
public function startPublishing(e:StartBroadcastEvent):void{
|
||||||
ns = new NetStream(nc);
|
var ns:NetStream = new NetStream(nc);
|
||||||
ns.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
|
ns.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
|
||||||
ns.addEventListener( IOErrorEvent.IO_ERROR, onIOError );
|
ns.addEventListener( IOErrorEvent.IO_ERROR, onIOError );
|
||||||
ns.addEventListener( AsyncErrorEvent.ASYNC_ERROR, onAsyncError );
|
ns.addEventListener( AsyncErrorEvent.ASYNC_ERROR, onAsyncError );
|
||||||
ns.client = this;
|
ns.client = this;
|
||||||
ns.attachCamera(e.camera);
|
ns.attachCamera(e.camera);
|
||||||
// Uncomment if you want to build support for H264. But you need at least FP 11. (ralam july 23, 2011)
|
|
||||||
// if (Capabilities.version.search("11,0") != -1) {
|
|
||||||
if ((BBB.getFlashPlayerVersion() >= 11) && e.videoProfile.enableH264) {
|
if ((BBB.getFlashPlayerVersion() >= 11) && e.videoProfile.enableH264) {
|
||||||
// if (BBB.getFlashPlayerVersion() >= 11) {
|
|
||||||
LOGGER.info("Using H264 codec for video.");
|
|
||||||
var h264:H264VideoStreamSettings = new H264VideoStreamSettings();
|
var h264:H264VideoStreamSettings = new H264VideoStreamSettings();
|
||||||
var h264profile:String = H264Profile.MAIN;
|
var h264profile:String = H264Profile.MAIN;
|
||||||
if (e.videoProfile.h264Profile != "main") {
|
if (e.videoProfile.h264Profile != "main") {
|
||||||
@ -165,7 +201,6 @@ package org.bigbluebutton.modules.videoconf.business
|
|||||||
case "5.1": h264Level = H264Level.LEVEL_5_1; break;
|
case "5.1": h264Level = H264Level.LEVEL_5_1; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.info("Codec used: {0}", [h264Level]);
|
|
||||||
|
|
||||||
h264.setProfileLevel(h264profile, h264Level);
|
h264.setProfileLevel(h264profile, h264Level);
|
||||||
ns.videoStreamSettings = h264;
|
ns.videoStreamSettings = h264;
|
||||||
@ -200,18 +235,6 @@ package org.bigbluebutton.modules.videoconf.business
|
|||||||
LOGGER.debug("VideoProxy:: disconnecting from Video application");
|
LOGGER.debug("VideoProxy:: disconnecting from Video application");
|
||||||
stopAllBroadcasting();
|
stopAllBroadcasting();
|
||||||
if (nc != null) nc.close();
|
if (nc != null) nc.close();
|
||||||
|
|
||||||
if (reconnect) {
|
|
||||||
var reconnectTimer:Timer = new Timer(1000, 1);
|
|
||||||
reconnectTimer.addEventListener("timer", reconnectTimerHandler);
|
|
||||||
reconnectTimer.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function reconnectTimerHandler(event:TimerEvent):void {
|
|
||||||
LOGGER.debug("rtmptRetryTimerHandler: {0}", [event]);
|
|
||||||
reconnecting = true;
|
|
||||||
connect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onBWCheck(... rest):Number {
|
public function onBWCheck(... rest):Number {
|
||||||
|
@ -23,7 +23,7 @@ package org.bigbluebutton.modules.videoconf.events
|
|||||||
public class ConnectedEvent extends Event
|
public class ConnectedEvent extends Event
|
||||||
{
|
{
|
||||||
public static const VIDEO_CONNECTED:String = "connected to video app event";
|
public static const VIDEO_CONNECTED:String = "connected to video app event";
|
||||||
|
|
||||||
public var reconnection:Boolean = false;
|
public var reconnection:Boolean = false;
|
||||||
|
|
||||||
public function ConnectedEvent(reconnection:Boolean)
|
public function ConnectedEvent(reconnection:Boolean)
|
||||||
|
@ -129,7 +129,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
<EventHandlers type="{BBBEvent.CAM_SETTINGS_CLOSED}">
|
<EventHandlers type="{BBBEvent.CAM_SETTINGS_CLOSED}">
|
||||||
<MethodInvoker generator="{VideoEventMapDelegate}" method="handleCamSettingsClosedEvent" arguments="{event}"/>
|
<MethodInvoker generator="{VideoEventMapDelegate}" method="handleCamSettingsClosedEvent" arguments="{event}"/>
|
||||||
</EventHandlers>
|
</EventHandlers>
|
||||||
|
|
||||||
|
<EventHandlers type="{BBBEvent.RECONNECT_DISCONNECTED_EVENT}">
|
||||||
|
<MethodInvoker generator="{VideoEventMapDelegate}" method="closeAllWindows"/>
|
||||||
|
</EventHandlers>
|
||||||
<!-- ~~~~~~~~~~~~~~~~~~ INJECTORS ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
|
<!-- ~~~~~~~~~~~~~~~~~~ INJECTORS ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
|
||||||
|
|
||||||
</EventMap>
|
</EventMap>
|
||||||
|
@ -110,7 +110,7 @@ package org.bigbluebutton.modules.videoconf.maps
|
|||||||
|
|
||||||
public function handleStreamStoppedEvent(event:StreamStoppedEvent):void {
|
public function handleStreamStoppedEvent(event:StreamStoppedEvent):void {
|
||||||
if (UserManager.getInstance().getConference().amIThisUser(event.userId)) {
|
if (UserManager.getInstance().getConference().amIThisUser(event.userId)) {
|
||||||
closePublishWindowWithStream(event.userId, event.streamId);
|
closePublishWindowByStream(event.streamId);
|
||||||
} else {
|
} else {
|
||||||
closeViewWindowWithStream(event.userId, event.streamId);
|
closeViewWindowWithStream(event.userId, event.streamId);
|
||||||
}
|
}
|
||||||
@ -262,11 +262,19 @@ package org.bigbluebutton.modules.videoconf.maps
|
|||||||
_graphics.removeGraphicsFor(userID);
|
_graphics.removeGraphicsFor(userID);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function closePublishWindowWithStream(userID:String, stream:String):int {
|
private function closePublishWindowByStream(stream:String):int {
|
||||||
return _graphics.removeVideoByStreamName(userID, stream);
|
return _graphics.removeVideoByStreamName(UsersUtil.getMyUserID(), stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function closePublishWindow():void {
|
||||||
|
closeWindow(UsersUtil.getMyUserID());
|
||||||
}
|
}
|
||||||
|
|
||||||
private function openViewWindowFor(userID:String):void {
|
private function openViewWindowFor(userID:String):void {
|
||||||
|
if (!proxy.connection.connected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LOGGER.debug("VideoEventMapDelegate:: [{0}] openViewWindowFor:: Opening VIEW window for [{1}] [{2}]", [me, userID, UsersUtil.getUserName(userID)]);
|
LOGGER.debug("VideoEventMapDelegate:: [{0}] openViewWindowFor:: Opening VIEW window for [{1}] [{2}]", [me, userID, UsersUtil.getUserName(userID)]);
|
||||||
|
|
||||||
var bbbUser:BBBUser = UsersUtil.getUser(userID);
|
var bbbUser:BBBUser = UsersUtil.getUser(userID);
|
||||||
@ -305,49 +313,21 @@ package org.bigbluebutton.modules.videoconf.maps
|
|||||||
|
|
||||||
public function stopPublishing(e:StopBroadcastEvent):void{
|
public function stopPublishing(e:StopBroadcastEvent):void{
|
||||||
LOGGER.debug("VideoEventMapDelegate:: [{0}] Stop publishing. ready = [{1}]", [me, _ready]);
|
LOGGER.debug("VideoEventMapDelegate:: [{0}] Stop publishing. ready = [{1}]", [me, _ready]);
|
||||||
if(streamList.length <= 1) {
|
checkLastBroadcasting();
|
||||||
setStopLastBroadcasting();
|
|
||||||
} else {
|
|
||||||
UsersUtil.setIAmPublishing(true);
|
|
||||||
}
|
|
||||||
streamList.removeItem(e.stream);
|
streamList.removeItem(e.stream);
|
||||||
stopBroadcasting(e.stream);
|
stopBroadcasting(e.stream);
|
||||||
button.setCamAsInactive(e.camId);
|
button.setCamAsInactive(e.camId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function stopAllBroadcasting():void {
|
private function checkLastBroadcasting():void {
|
||||||
LOGGER.debug("[VideoEventMapDelegate:stopAllBroadcasting]");
|
LOGGER.debug("[VideoEventMapDelegate:checkLastBroadcasting]");
|
||||||
setStopLastBroadcasting();
|
_isPublishing = streamList.length > 0;
|
||||||
streamList = new ArrayList();
|
UsersUtil.setIAmPublishing(streamList.length > 0);
|
||||||
proxy.stopAllBroadcasting();
|
|
||||||
|
|
||||||
var userID:String = UsersUtil.getMyUserID();
|
|
||||||
_graphics.removeGraphicsFor(userID);
|
|
||||||
|
|
||||||
var broadcastEvent:BroadcastStoppedEvent = new BroadcastStoppedEvent();
|
|
||||||
broadcastEvent.stream = "";
|
|
||||||
broadcastEvent.userid = UsersUtil.getMyUserID();
|
|
||||||
broadcastEvent.avatarURL = UsersUtil.getAvatarURL();
|
|
||||||
_dispatcher.dispatchEvent(broadcastEvent);
|
|
||||||
|
|
||||||
if (proxy.videoOptions.showButton) {
|
|
||||||
//Make toolbar button enabled again
|
|
||||||
button.setAllCamAsInactive();
|
|
||||||
}
|
|
||||||
if (options.displayAvatar) {
|
|
||||||
LOGGER.debug("VideoEventMapDelegate:: [{0}] Opening avatar", [me]);
|
|
||||||
openAvatarWindowFor(UsersUtil.getMyUserID());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function setStopLastBroadcasting():void {
|
private function stopBroadcasting(stream:String = ""):void {
|
||||||
LOGGER.debug("[VideoEventMapDelegate:setStopLastBroadcasting]");
|
if (stream == null) stream = "";
|
||||||
_isPublishing = false;
|
LOGGER.debug("Stopping broadcast{0}", [(stream.length > 0? " of stream [" + stream + "]": "")]);
|
||||||
UsersUtil.setIAmPublishing(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function stopBroadcasting(stream:String):void {
|
|
||||||
LOGGER.debug("Stopping broadcast of stream [{0}]", [stream]);
|
|
||||||
|
|
||||||
proxy.stopBroadcasting(stream);
|
proxy.stopBroadcasting(stream);
|
||||||
|
|
||||||
@ -357,11 +337,20 @@ package org.bigbluebutton.modules.videoconf.maps
|
|||||||
broadcastEvent.avatarURL = UsersUtil.getAvatarURL();
|
broadcastEvent.avatarURL = UsersUtil.getAvatarURL();
|
||||||
_dispatcher.dispatchEvent(broadcastEvent);
|
_dispatcher.dispatchEvent(broadcastEvent);
|
||||||
|
|
||||||
var camId:int = closePublishWindowWithStream(UsersUtil.getMyUserID(), stream);
|
if (stream.length > 0) {
|
||||||
|
var camId:int = closePublishWindowByStream(stream);
|
||||||
|
|
||||||
if (proxy.videoOptions.showButton) {
|
if (proxy.videoOptions.showButton) {
|
||||||
//Make toolbar button enabled again
|
//Make toolbar button enabled again
|
||||||
button.publishingStatus(button.STOP_PUBLISHING, camId);
|
button.publishingStatus(button.STOP_PUBLISHING, camId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
closePublishWindow();
|
||||||
|
|
||||||
|
if (proxy.videoOptions.showButton) {
|
||||||
|
// make toolbar button enabled again
|
||||||
|
button.setAllCamAsInactive();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (streamList.length == 0 && options.displayAvatar) {
|
if (streamList.length == 0 && options.displayAvatar) {
|
||||||
@ -373,7 +362,7 @@ package org.bigbluebutton.modules.videoconf.maps
|
|||||||
public function handleClosePublishWindowEvent(event:ClosePublishWindowEvent):void {
|
public function handleClosePublishWindowEvent(event:ClosePublishWindowEvent):void {
|
||||||
LOGGER.debug("Closing publish window");
|
LOGGER.debug("Closing publish window");
|
||||||
if (_isPublishing || _chromeWebcamPermissionDenied) {
|
if (_isPublishing || _chromeWebcamPermissionDenied) {
|
||||||
stopAllBroadcasting();
|
stopBroadcasting();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,7 +377,7 @@ package org.bigbluebutton.modules.videoconf.maps
|
|||||||
|
|
||||||
public function handleStopAllShareCameraRequestEvent(event:StopShareCameraRequestEvent):void {
|
public function handleStopAllShareCameraRequestEvent(event:StopShareCameraRequestEvent):void {
|
||||||
LOGGER.debug("[VideoEventMapDelegate:handleStopAllShareCameraRequestEvent]");
|
LOGGER.debug("[VideoEventMapDelegate:handleStopAllShareCameraRequestEvent]");
|
||||||
stopAllBroadcasting();
|
stopBroadcasting();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleStopShareCameraRequestEvent(event:StopShareCameraRequestEvent):void {
|
public function handleStopShareCameraRequestEvent(event:StopShareCameraRequestEvent):void {
|
||||||
@ -425,7 +414,7 @@ package org.bigbluebutton.modules.videoconf.maps
|
|||||||
public function closeAllWindows():void{
|
public function closeAllWindows():void{
|
||||||
LOGGER.debug("VideoEventMapDelegate:: closing all windows");
|
LOGGER.debug("VideoEventMapDelegate:: closing all windows");
|
||||||
if (_isPublishing) {
|
if (_isPublishing) {
|
||||||
stopAllBroadcasting();
|
stopBroadcasting();
|
||||||
}
|
}
|
||||||
|
|
||||||
_graphics.shutdown();
|
_graphics.shutdown();
|
||||||
@ -446,7 +435,7 @@ package org.bigbluebutton.modules.videoconf.maps
|
|||||||
LOGGER.debug("****************** Switching to viewer. Show video button?=[{0}]", [UsersUtil.amIPresenter()]);
|
LOGGER.debug("****************** Switching to viewer. Show video button?=[{0}]", [UsersUtil.amIPresenter()]);
|
||||||
displayToolbarButton();
|
displayToolbarButton();
|
||||||
if (_isPublishing && options.presenterShareOnly) {
|
if (_isPublishing && options.presenterShareOnly) {
|
||||||
stopAllBroadcasting();
|
stopBroadcasting();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -454,17 +443,13 @@ package org.bigbluebutton.modules.videoconf.maps
|
|||||||
public function connectedToVideoApp(event: ConnectedEvent):void{
|
public function connectedToVideoApp(event: ConnectedEvent):void{
|
||||||
LOGGER.debug("VideoEventMapDelegate:: [{0}] Connected to video application.", [me]);
|
LOGGER.debug("VideoEventMapDelegate:: [{0}] Connected to video application.", [me]);
|
||||||
_ready = true;
|
_ready = true;
|
||||||
if (event.reconnection) {
|
if (event.reconnection) {
|
||||||
LOGGER.debug("VideoEventMapDelegate:: Got reconnected event.");
|
closeAllWindows()
|
||||||
stopAllBroadcasting();
|
} else {
|
||||||
LOGGER.debug("VideoEventMapDelegate:: Closing all webcam windows.");
|
addToolbarButton();
|
||||||
closeAllWindows()
|
}
|
||||||
openWebcamWindows();
|
openWebcamWindows();
|
||||||
} else {
|
|
||||||
addToolbarButton();
|
|
||||||
openWebcamWindows();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleCameraSetting(event:BBBEvent):void {
|
public function handleCameraSetting(event:BBBEvent):void {
|
||||||
|
@ -233,17 +233,6 @@ package org.bigbluebutton.modules.videoconf.views
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
override public function validateDisplayList():void {
|
|
||||||
super.validateDisplayList();
|
|
||||||
|
|
||||||
if (priorityMode) {
|
|
||||||
updateDisplayListHelperByPriority(this.width, this.height);
|
|
||||||
} else {
|
|
||||||
updateDisplayListHelper(this.width, this.height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
public function addAvatarFor(userId:String):void {
|
public function addAvatarFor(userId:String):void {
|
||||||
if (! UsersUtil.hasUser(userId)) return;
|
if (! UsersUtil.hasUser(userId)) return;
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function updateTalkingStatus() : void{
|
private function updateTalkingStatus():void {
|
||||||
if (user.talking) {
|
if (user.talking) {
|
||||||
titleBox.setStyle("styleName", "videoToolbarBackgroundTalkingStyle");
|
titleBox.setStyle("styleName", "videoToolbarBackgroundTalkingStyle");
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,287 +1,289 @@
|
|||||||
/**
|
/**
|
||||||
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
|
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
|
* 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
|
* 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
|
* 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
|
* Foundation; either version 3.0 of the License, or (at your option) any later
|
||||||
* version.
|
* version.
|
||||||
*
|
*
|
||||||
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
* 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
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
* 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
|
* You should have received a copy of the GNU Lesser General Public License along
|
||||||
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.bigbluebutton.modules.whiteboard.business.shapes
|
package org.bigbluebutton.modules.whiteboard.business.shapes
|
||||||
{
|
{
|
||||||
import flash.text.TextField;
|
import flash.text.TextField;
|
||||||
import flash.text.TextFormat;
|
import flash.text.TextFormat;
|
||||||
import flash.text.TextFormatAlign;
|
import flash.text.TextFormatAlign;
|
||||||
|
|
||||||
import org.as3commons.logging.api.ILogger;
|
import org.as3commons.logging.api.ILogger;
|
||||||
import org.as3commons.logging.api.getClassLogger;
|
import org.as3commons.logging.api.getClassLogger;
|
||||||
import org.as3commons.logging.util.jsonXify;
|
import org.as3commons.logging.util.jsonXify;
|
||||||
import org.bigbluebutton.modules.whiteboard.models.Annotation;
|
import org.bigbluebutton.modules.whiteboard.models.Annotation;
|
||||||
|
import org.bigbluebutton.util.i18n.ResourceUtil;
|
||||||
public class PollResultObject extends DrawObject {
|
|
||||||
private static const LOGGER:ILogger = getClassLogger(PollResultObject);
|
public class PollResultObject extends DrawObject {
|
||||||
|
private static const LOGGER:ILogger = getClassLogger(PollResultObject);
|
||||||
//private const h:uint = 100;
|
|
||||||
//private const w:uint = 280;
|
//private const h:uint = 100;
|
||||||
private const bgFill:uint = 0XCECECE; //0xFFFFFF;
|
//private const w:uint = 280;
|
||||||
private const colFill:uint = 0x000000;
|
private const bgFill:uint = 0xFFFFFF;
|
||||||
private const vpadding:Number = 10;
|
private const colFill:uint = 0x000000;
|
||||||
private const hpadding:Number = 5;
|
private const vpadding:Number = 10;
|
||||||
private const labelStartWidth:int = 40;
|
private const hpadding:Number = 5;
|
||||||
private const percentStartWidth:int = 40;
|
private const labelStartWidth:int = 40;
|
||||||
|
private const percentStartWidth:int = 40;
|
||||||
private var sampledata:Array = [{a:"A", v:3}, {a:"B", v:1}, {a:"C", v:5}, {a:"D", v:8}];
|
|
||||||
private var _data:Array;
|
private var sampledata:Array = [{a:"A", v:3}, {a:"B", v:1}, {a:"C", v:5}, {a:"D", v:8}];
|
||||||
private var _textFields:Array;
|
private var _data:Array;
|
||||||
|
private var _textFields:Array;
|
||||||
public function PollResultObject(id:String, type:String, status:String) {
|
|
||||||
super(id, type, status)
|
public function PollResultObject(id:String, type:String, status:String) {
|
||||||
|
super(id, type, status)
|
||||||
_textFields = new Array();
|
|
||||||
data = null;
|
_textFields = new Array();
|
||||||
// temp setter for testing purposes
|
data = null;
|
||||||
//data = sampledata;
|
// temp setter for testing purposes
|
||||||
|
//data = sampledata;
|
||||||
}
|
|
||||||
|
}
|
||||||
public function set data(d:Array):void {
|
|
||||||
_data = d;
|
public function set data(d:Array):void {
|
||||||
}
|
_data = d;
|
||||||
|
}
|
||||||
public function get data():Array {
|
|
||||||
return _data;
|
public function get data():Array {
|
||||||
}
|
return _data;
|
||||||
|
}
|
||||||
private function makeTextFields(num:int):void {
|
|
||||||
if (num > _textFields.length) {
|
private function makeTextFields(num:int):void {
|
||||||
var textField:TextField;
|
if (num > _textFields.length) {
|
||||||
for (var i:int=_textFields.length; i < num; i++) {
|
var textField:TextField;
|
||||||
textField = new TextField();
|
for (var i:int=_textFields.length; i < num; i++) {
|
||||||
addChild(textField);
|
textField = new TextField();
|
||||||
_textFields.push(textField);
|
addChild(textField);
|
||||||
}
|
_textFields.push(textField);
|
||||||
} else if (num < _textFields.length) {
|
}
|
||||||
for (var j:int=_textFields.length; i > num; i--) {
|
} else if (num < _textFields.length) {
|
||||||
removeChild(_textFields.pop());
|
for (var j:int=_textFields.length; i > num; i--) {
|
||||||
}
|
removeChild(_textFields.pop());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
|
|
||||||
// graphics.clear();
|
private function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
|
||||||
|
// graphics.clear();
|
||||||
if (_data != null && _data.length > 0) {
|
|
||||||
graphics.lineStyle(2);
|
if (_data != null && _data.length > 0) {
|
||||||
graphics.beginFill(bgFill, 1.0);
|
graphics.lineStyle(2);
|
||||||
graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
|
graphics.beginFill(bgFill, 1.0);
|
||||||
graphics.endFill();
|
graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
|
||||||
|
graphics.endFill();
|
||||||
var actualRH:Number = (unscaledHeight-vpadding*(_data.length+1)) / _data.length;
|
|
||||||
LOGGER.debug("PollGraphic - as raw {0} int {1}", [actualRH, int(actualRH)]);
|
var actualRH:Number = (unscaledHeight-vpadding*(_data.length+1)) / _data.length;
|
||||||
// Current problem is that the rowHeight is truncated. It would be nice if the extra pixels
|
LOGGER.debug("PollGraphic - as raw {0} int {1}", [actualRH, int(actualRH)]);
|
||||||
// could be distributed for a more even look.
|
// Current problem is that the rowHeight is truncated. It would be nice if the extra pixels
|
||||||
var avgRowHeight:int = (unscaledHeight-vpadding*(_data.length+1)) / _data.length;
|
// could be distributed for a more even look.
|
||||||
var extraVPixels:int = unscaledHeight - (_data.length * (avgRowHeight+vpadding) + vpadding);
|
var avgRowHeight:int = (unscaledHeight-vpadding*(_data.length+1)) / _data.length;
|
||||||
LOGGER.debug("PollGraphic - extraVPixels {0}", [extraVPixels]);
|
var extraVPixels:int = unscaledHeight - (_data.length * (avgRowHeight+vpadding) + vpadding);
|
||||||
var largestVal:int = -1;
|
LOGGER.debug("PollGraphic - extraVPixels {0}", [extraVPixels]);
|
||||||
var totalCount:Number = 0;
|
var largestVal:int = -1;
|
||||||
//find largest value
|
var totalCount:Number = 0;
|
||||||
for (var i:int=0; i<_data.length; i++) {
|
//find largest value
|
||||||
if (_data[i].v > largestVal) largestVal = _data[i].v;
|
for (var i:int=0; i<_data.length; i++) {
|
||||||
totalCount += _data[i].v;
|
if (_data[i].v > largestVal) largestVal = _data[i].v;
|
||||||
}
|
totalCount += _data[i].v;
|
||||||
|
}
|
||||||
var currTFIdx:int = 0;
|
|
||||||
var answerText:TextField;
|
var currTFIdx:int = 0;
|
||||||
var percentText:TextField;
|
var answerText:TextField;
|
||||||
var answerArray:Array = new Array();
|
var percentText:TextField;
|
||||||
var percentArray:Array = new Array();
|
var answerArray:Array = new Array();
|
||||||
var minFontSize:int = 20;
|
var percentArray:Array = new Array();
|
||||||
var currFontSize:int;
|
var minFontSize:int = 20;
|
||||||
|
var currFontSize:int;
|
||||||
graphics.lineStyle(2);
|
|
||||||
graphics.beginFill(colFill, 1.0);
|
graphics.lineStyle(2);
|
||||||
for (var j:int=0, vp:int=extraVPixels, ry:int=0, curRowHeight:int=0; j<_data.length; j++) {
|
graphics.beginFill(colFill, 1.0);
|
||||||
ry += Math.round(curRowHeight/2)+vpadding; // add the last row's height plus padding
|
for (var j:int=0, vp:int=extraVPixels, ry:int=0, curRowHeight:int=0; j<_data.length; j++) {
|
||||||
|
ry += Math.round(curRowHeight/2)+vpadding; // add the last row's height plus padding
|
||||||
curRowHeight = avgRowHeight;
|
|
||||||
if (j%2==0 && vp > 0) {
|
curRowHeight = avgRowHeight;
|
||||||
curRowHeight += 1;
|
if (j%2==0 && vp > 0) {
|
||||||
vp--;
|
curRowHeight += 1;
|
||||||
}
|
vp--;
|
||||||
ry += curRowHeight/2;
|
}
|
||||||
|
ry += curRowHeight/2;
|
||||||
//ry += curRowHeight * (j+0.5) + vpadding*(j+1);
|
|
||||||
// add row label
|
//ry += curRowHeight * (j+0.5) + vpadding*(j+1);
|
||||||
answerText = _textFields[currTFIdx++];
|
// add row label
|
||||||
answerText.text = _data[j].a;
|
answerText = _textFields[currTFIdx++];
|
||||||
answerText.width = labelStartWidth;
|
answerText.text = _data[j].a;
|
||||||
answerText.height = curRowHeight;
|
answerText.width = labelStartWidth;
|
||||||
answerText.selectable = false;
|
answerText.height = curRowHeight;
|
||||||
//addChild(answerText);
|
answerText.selectable = false;
|
||||||
answerArray.push(answerText);
|
//addChild(answerText);
|
||||||
currFontSize = findFontSize(answerText, 20);
|
answerArray.push(answerText);
|
||||||
if (currFontSize < minFontSize) minFontSize = currFontSize;
|
currFontSize = findFontSize(answerText, 20);
|
||||||
//rowText.height = rowText.textHeight;
|
if (currFontSize < minFontSize) minFontSize = currFontSize;
|
||||||
answerText.x = hpadding;
|
//rowText.height = rowText.textHeight;
|
||||||
//rowText.y = ry-rowText.height/2;
|
answerText.x = hpadding;
|
||||||
|
//rowText.y = ry-rowText.height/2;
|
||||||
// add percentage
|
|
||||||
percentText = _textFields[currTFIdx++];;// new TextField();
|
// add percentage
|
||||||
var percentNum:Number = (totalCount == 0 ? 0 : ((_data[j].v/totalCount)*100));
|
percentText = _textFields[currTFIdx++];;// new TextField();
|
||||||
percentText.text = Math.round(percentNum).toString() + "%";
|
var percentNum:Number = (totalCount == 0 ? 0 : ((_data[j].v/totalCount)*100));
|
||||||
percentText.width = percentStartWidth;
|
percentText.text = Math.round(percentNum).toString() + "%";
|
||||||
percentText.height = curRowHeight;
|
percentText.width = percentStartWidth;
|
||||||
percentText.selectable = false;
|
percentText.height = curRowHeight;
|
||||||
//addChild(percentText);
|
percentText.selectable = false;
|
||||||
percentArray.push(percentText);
|
//addChild(percentText);
|
||||||
currFontSize = findFontSize(percentText, 20);
|
percentArray.push(percentText);
|
||||||
if (currFontSize < minFontSize) minFontSize = currFontSize;
|
currFontSize = findFontSize(percentText, 20);
|
||||||
//percentText.height = percentText.textHeight;
|
if (currFontSize < minFontSize) minFontSize = currFontSize;
|
||||||
//percentText.x = unscaledWidth-percentStartWidth/2-percentText.width/2;
|
//percentText.height = percentText.textHeight;
|
||||||
//percentText.y = ry-percentText.height/2;
|
//percentText.x = unscaledWidth-percentStartWidth/2-percentText.width/2;
|
||||||
}
|
//percentText.y = ry-percentText.height/2;
|
||||||
|
}
|
||||||
var maxAnswerWidth:int = 0;
|
|
||||||
var maxPercentWidth:int = 0;
|
var maxAnswerWidth:int = 0;
|
||||||
|
var maxPercentWidth:int = 0;
|
||||||
for (j=0, vp=extraVPixels, ry=0, curRowHeight=0; j<_data.length; j++) {
|
|
||||||
ry += Math.round(curRowHeight/2)+vpadding; // add the last row's height plus padding
|
for (j=0, vp=extraVPixels, ry=0, curRowHeight=0; j<_data.length; j++) {
|
||||||
|
ry += Math.round(curRowHeight/2)+vpadding; // add the last row's height plus padding
|
||||||
curRowHeight = avgRowHeight;
|
|
||||||
if (j%2==0 && vp > 0) {
|
curRowHeight = avgRowHeight;
|
||||||
curRowHeight += 1;
|
if (j%2==0 && vp > 0) {
|
||||||
vp--;
|
curRowHeight += 1;
|
||||||
}
|
vp--;
|
||||||
ry += curRowHeight/2;
|
}
|
||||||
|
ry += curRowHeight/2;
|
||||||
//ry = curRowHeight * (j+0.5) + vpadding*(j+1);
|
|
||||||
|
//ry = curRowHeight * (j+0.5) + vpadding*(j+1);
|
||||||
answerText = TextField(answerArray[j]);
|
|
||||||
findFontSize(answerText, minFontSize);
|
answerText = TextField(answerArray[j]);
|
||||||
answerText.width = answerText.textWidth+4;
|
findFontSize(answerText, minFontSize);
|
||||||
answerText.height = answerText.textHeight+4;
|
answerText.width = answerText.textWidth+4;
|
||||||
answerText.y = ry-answerText.height/2;
|
answerText.height = answerText.textHeight+4;
|
||||||
if (answerText.width > maxAnswerWidth) maxAnswerWidth = answerText.width;
|
answerText.y = ry-answerText.height/2;
|
||||||
|
if (answerText.width > maxAnswerWidth) maxAnswerWidth = answerText.width;
|
||||||
percentText = TextField(percentArray[j]);
|
|
||||||
findFontSize(percentText, minFontSize);
|
percentText = TextField(percentArray[j]);
|
||||||
percentText.width = percentText.textWidth+4;
|
findFontSize(percentText, minFontSize);
|
||||||
percentText.height = percentText.textHeight+4;
|
percentText.width = percentText.textWidth+4;
|
||||||
percentText.x = unscaledWidth - hpadding - percentText.width;
|
percentText.height = percentText.textHeight+4;
|
||||||
percentText.y = ry-percentText.height/2;
|
percentText.x = unscaledWidth - hpadding - percentText.width;
|
||||||
if (percentText.width > maxPercentWidth) maxPercentWidth = percentText.width;
|
percentText.y = ry-percentText.height/2;
|
||||||
|
if (percentText.width > maxPercentWidth) maxPercentWidth = percentText.width;
|
||||||
}
|
|
||||||
|
}
|
||||||
var countText:TextField;
|
|
||||||
var maxBarWidth:int = unscaledWidth - (hpadding*4) - maxAnswerWidth - maxPercentWidth;
|
var countText:TextField;
|
||||||
var barStartX:int = maxAnswerWidth + (hpadding*2);
|
var maxBarWidth:int = unscaledWidth - (hpadding*4) - maxAnswerWidth - maxPercentWidth;
|
||||||
|
var barStartX:int = maxAnswerWidth + (hpadding*2);
|
||||||
for (j=0, vp=extraVPixels, ry=0, curRowHeight=0; j<_data.length; j++) {
|
|
||||||
ry += Math.round(curRowHeight/2)+vpadding; // add the last row's height plus padding
|
for (j=0, vp=extraVPixels, ry=0, curRowHeight=0; j<_data.length; j++) {
|
||||||
|
ry += Math.round(curRowHeight/2)+vpadding; // add the last row's height plus padding
|
||||||
curRowHeight = avgRowHeight;
|
|
||||||
if (j%2==0 && vp > 0) {
|
curRowHeight = avgRowHeight;
|
||||||
curRowHeight += 1;
|
if (j%2==0 && vp > 0) {
|
||||||
vp--;
|
curRowHeight += 1;
|
||||||
}
|
vp--;
|
||||||
ry += curRowHeight/2;
|
}
|
||||||
|
ry += curRowHeight/2;
|
||||||
//ry = curRowHeight * (j+0.5) + vpadding*(j+1);
|
|
||||||
|
//ry = curRowHeight * (j+0.5) + vpadding*(j+1);
|
||||||
// draw rect
|
|
||||||
var rectWidth:int = maxBarWidth*(_data[j].v/largestVal);
|
// draw rect
|
||||||
graphics.drawRect(barStartX, ry-curRowHeight/2, rectWidth, curRowHeight);
|
var rectWidth:int = maxBarWidth*(_data[j].v/largestVal);
|
||||||
// add vote count in middle of rect
|
graphics.drawRect(barStartX, ry-curRowHeight/2, rectWidth, curRowHeight);
|
||||||
countText = _textFields[currTFIdx++]; // new TextField();
|
// add vote count in middle of rect
|
||||||
countText.text = _data[j].v;
|
countText = _textFields[currTFIdx++]; // new TextField();
|
||||||
countText.width = rectWidth;
|
countText.text = _data[j].v;
|
||||||
countText.height = curRowHeight;
|
countText.width = rectWidth;
|
||||||
countText.textColor = 0xFFFFFF;
|
countText.height = curRowHeight;
|
||||||
countText.selectable = false;
|
countText.textColor = 0xFFFFFF;
|
||||||
//addChild(countText);
|
countText.selectable = false;
|
||||||
findFontSize(countText, minFontSize);
|
//addChild(countText);
|
||||||
countText.width = countText.textWidth+4;
|
findFontSize(countText, minFontSize);
|
||||||
countText.height = countText.textHeight+4;
|
countText.width = countText.textWidth+4;
|
||||||
countText.x = barStartX+rectWidth/2-countText.width/2;
|
countText.height = countText.textHeight+4;
|
||||||
countText.y = ry-countText.height/2;
|
countText.x = barStartX+rectWidth/2-countText.width/2;
|
||||||
}
|
countText.y = ry-countText.height/2;
|
||||||
|
}
|
||||||
graphics.endFill();
|
|
||||||
}
|
graphics.endFill();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private function findFontSize(textField:TextField, defaultSize:Number):int {
|
|
||||||
var tFormat:TextFormat = new TextFormat();
|
private function findFontSize(textField:TextField, defaultSize:Number):int {
|
||||||
tFormat.size = defaultSize;
|
var tFormat:TextFormat = new TextFormat();
|
||||||
tFormat.align = TextFormatAlign.CENTER;
|
tFormat.size = defaultSize;
|
||||||
textField.setTextFormat(tFormat);
|
tFormat.font = "arial";
|
||||||
var size:Number = defaultSize;
|
tFormat.align = TextFormatAlign.CENTER;
|
||||||
while((textField.textWidth+4 > textField.width || textField.textHeight+4 > textField.height) && size > 0) {
|
textField.setTextFormat(tFormat);
|
||||||
size = size - 1;
|
var size:Number = defaultSize;
|
||||||
tFormat.size = size;
|
while((textField.textWidth+4 > textField.width || textField.textHeight+4 > textField.height) && size > 0) {
|
||||||
textField.setTextFormat(tFormat);
|
size = size - 1;
|
||||||
}
|
tFormat.size = size;
|
||||||
|
textField.setTextFormat(tFormat);
|
||||||
return size;
|
}
|
||||||
}
|
|
||||||
|
return size;
|
||||||
private function drawRect(a:Annotation, parentWidth:Number, parentHeight:Number, zoom:Number):void {
|
}
|
||||||
var ao:Object = a.annotation;
|
|
||||||
this.graphics.lineStyle(1 * zoom, 0);
|
private function drawRect(a:Annotation, parentWidth:Number, parentHeight:Number, zoom:Number):void {
|
||||||
|
var ao:Object = a.annotation;
|
||||||
var arrayEnd:Number = (ao.points as Array).length;
|
this.graphics.lineStyle(1 * zoom, 0);
|
||||||
var startX:Number = denormalize(21.845575, parentWidth);
|
|
||||||
var startY:Number = denormalize(23.145401, parentHeight);
|
var arrayEnd:Number = (ao.points as Array).length;
|
||||||
var width:Number = denormalize(46.516006, parentWidth) - startX;
|
var startX:Number = denormalize(21.845575, parentWidth);
|
||||||
var height:Number = denormalize(61.42433, parentHeight) - startY;
|
var startY:Number = denormalize(23.145401, parentHeight);
|
||||||
|
var width:Number = denormalize(46.516006, parentWidth) - startX;
|
||||||
this.graphics.drawRect(startX, startY, width, height);
|
var height:Number = denormalize(61.42433, parentHeight) - startY;
|
||||||
|
|
||||||
}
|
this.graphics.drawRect(startX, startY, width, height);
|
||||||
|
|
||||||
override public function draw(a:Annotation, parentWidth:Number, parentHeight:Number, zoom:Number):void {
|
}
|
||||||
var ao:Object = a.annotation;
|
|
||||||
LOGGER.debug("RESULT = {0}", [jsonXify(a)]);
|
override public function draw(a:Annotation, parentWidth:Number, parentHeight:Number, zoom:Number):void {
|
||||||
|
var ao:Object = a.annotation;
|
||||||
var arrayEnd:Number = (ao.points as Array).length;
|
LOGGER.debug("RESULT = {0}", [jsonXify(a)]);
|
||||||
var startX:Number = denormalize((ao.points as Array)[0], parentWidth);
|
|
||||||
var startY:Number = denormalize((ao.points as Array)[1], parentHeight);
|
var arrayEnd:Number = (ao.points as Array).length;
|
||||||
var pwidth:Number = denormalize((ao.points as Array)[2], parentWidth) - startX;
|
var startX:Number = denormalize((ao.points as Array)[0], parentWidth);
|
||||||
var pheight:Number = denormalize((ao.points as Array)[3], parentHeight) - startY;
|
var startY:Number = denormalize((ao.points as Array)[1], parentHeight);
|
||||||
|
var pwidth:Number = denormalize((ao.points as Array)[2], parentWidth);
|
||||||
var answers:Array = ao.result as Array;
|
var pheight:Number = denormalize((ao.points as Array)[3], parentHeight);
|
||||||
var ans:Array = new Array();
|
|
||||||
for (var j:int = 0; j < answers.length; j++) {
|
var answers:Array = ao.result as Array;
|
||||||
var ar:Object = answers[j];
|
var ans:Array = new Array();
|
||||||
var rs:Object = {a: ar.key, v: ar.num_votes as Number};
|
for (var j:int = 0; j < answers.length; j++) {
|
||||||
LOGGER.debug("poll result a=[{0}] v=[{1}]", [ar.key, ar.num_votes]);
|
var ar:Object = answers[j];
|
||||||
ans.push(rs);
|
var rs:Object = {a: ResourceUtil.getInstance().getString('bbb.polling.answer.' + ar.key), v: ar.num_votes as Number};
|
||||||
}
|
LOGGER.debug("poll result a=[{0}] v=[{1}]", [ar.key, ar.num_votes]);
|
||||||
|
ans.push(rs);
|
||||||
data = ans;
|
}
|
||||||
makeTextFields((answers != null ? answers.length*3 : 0));
|
|
||||||
|
data = ans;
|
||||||
this.x = startX;
|
makeTextFields((answers != null ? answers.length*3 : 0));
|
||||||
this.y = startY;
|
|
||||||
|
this.x = startX;
|
||||||
updateDisplayList(pwidth, pheight);
|
this.y = startY;
|
||||||
|
|
||||||
}
|
updateDisplayList(pwidth, pheight);
|
||||||
|
|
||||||
override public function redraw(a:Annotation, parentWidth:Number, parentHeight:Number, zoom:Number):void {
|
}
|
||||||
draw(a, parentWidth, parentHeight, zoom);
|
|
||||||
}
|
override public function redraw(a:Annotation, parentWidth:Number, parentHeight:Number, zoom:Number):void {
|
||||||
}
|
draw(a, parentWidth, parentHeight, zoom);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -138,5 +138,10 @@ package org.bigbluebutton.modules.whiteboard.managers
|
|||||||
public function handlePageChangedEvent(e:PageLoadedEvent):void {
|
public function handlePageChangedEvent(e:PageLoadedEvent):void {
|
||||||
displayModel.changePage(e.pageId);
|
displayModel.changePage(e.pageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function removeAnnotationsHistory():void {
|
||||||
|
// it will dispatch the cleanAnnotations in the displayModel later
|
||||||
|
whiteboardModel.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
<EventMap xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="http://mate.asfusion.com/" xmlns:mate="org.bigbluebutton.common.mate.*">
|
<EventMap xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="http://mate.asfusion.com/" xmlns:mate="org.bigbluebutton.common.mate.*">
|
||||||
<mx:Script>
|
<mx:Script>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
|
import org.bigbluebutton.main.events.BBBEvent;
|
||||||
import org.bigbluebutton.main.events.ModuleStartedEvent;
|
import org.bigbluebutton.main.events.ModuleStartedEvent;
|
||||||
import org.bigbluebutton.modules.present.events.AddOverlayCanvasEvent;
|
import org.bigbluebutton.modules.present.events.AddOverlayCanvasEvent;
|
||||||
import org.bigbluebutton.modules.present.events.NavigationEvent;
|
import org.bigbluebutton.modules.present.events.NavigationEvent;
|
||||||
@ -122,6 +123,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
<MethodInvoker generator="{WhiteboardManager}" method="handlePageChangedEvent" arguments="{event}" />
|
<MethodInvoker generator="{WhiteboardManager}" method="handlePageChangedEvent" arguments="{event}" />
|
||||||
</EventHandlers>
|
</EventHandlers>
|
||||||
|
|
||||||
|
<EventHandlers type="{BBBEvent.RECONNECT_BIGBLUEBUTTON_SUCCEEDED_EVENT}" >
|
||||||
|
<MethodInvoker generator="{WhiteboardManager}" method="removeAnnotationsHistory" />
|
||||||
|
</EventHandlers>
|
||||||
|
|
||||||
<Injectors target="{WhiteboardManager}">
|
<Injectors target="{WhiteboardManager}">
|
||||||
<ObjectBuilder generator="{WhiteboardModel}" cache="global" constructorArguments="{scope.dispatcher}"/>
|
<ObjectBuilder generator="{WhiteboardModel}" cache="global" constructorArguments="{scope.dispatcher}"/>
|
||||||
<PropertyInjector targetKey="whiteboardModel" source="{WhiteboardModel}"/>
|
<PropertyInjector targetKey="whiteboardModel" source="{WhiteboardModel}"/>
|
||||||
|
@ -135,11 +135,16 @@ package org.bigbluebutton.modules.whiteboard.models
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function clear(wbId:String):void {
|
public function clear(wbId:String = null):void {
|
||||||
LOGGER.debug("Clearing whiteboard");
|
LOGGER.debug("Clearing whiteboard");
|
||||||
var wb:Whiteboard = getWhiteboard(wbId);
|
if (wbId != null) {
|
||||||
if (wb != null) {
|
var wb:Whiteboard = getWhiteboard(wbId);
|
||||||
wb.clear();
|
if (wb != null) {
|
||||||
|
wb.clear();
|
||||||
|
_dispatcher.dispatchEvent(new WhiteboardUpdate(WhiteboardUpdate.CLEAR_ANNOTATIONS));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_whiteboards.removeAll();
|
||||||
_dispatcher.dispatchEvent(new WhiteboardUpdate(WhiteboardUpdate.CLEAR_ANNOTATIONS));
|
_dispatcher.dispatchEvent(new WhiteboardUpdate(WhiteboardUpdate.CLEAR_ANNOTATIONS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ package org.bigbluebutton.modules.whiteboard.services
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onMessage(messageName:String, message:Object):void {
|
public function onMessage(messageName:String, message:Object):void {
|
||||||
// LogUtil.debug("WB: received message " + messageName);
|
// trace("WB: received message " + messageName);
|
||||||
|
|
||||||
switch (messageName) {
|
switch (messageName) {
|
||||||
case "WhiteboardRequestAnnotationHistoryReply":
|
case "WhiteboardRequestAnnotationHistoryReply":
|
||||||
|
@ -26,3 +26,5 @@ pagebakers:ionicons
|
|||||||
ewall:foundation
|
ewall:foundation
|
||||||
maibaum:foundation-icons
|
maibaum:foundation-icons
|
||||||
gthacoder:sled
|
gthacoder:sled
|
||||||
|
chriswessels:hammer@3.1.1
|
||||||
|
fastclick
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
agnito:raphael@0.1.0
|
agnito:raphael@0.1.0
|
||||||
aldeed:simple-schema@1.3.2
|
aldeed:simple-schema@1.3.2
|
||||||
|
aldeed:template-extension@3.4.3
|
||||||
amplify@1.0.0
|
amplify@1.0.0
|
||||||
arunoda:npm@0.2.6
|
arunoda:npm@0.2.6
|
||||||
autoupdate@1.2.1
|
autoupdate@1.2.1
|
||||||
@ -12,6 +13,7 @@ brentjanderson:winston-client@0.2.1
|
|||||||
callback-hook@1.0.3
|
callback-hook@1.0.3
|
||||||
cfs:http-methods@0.0.27
|
cfs:http-methods@0.0.27
|
||||||
check@1.0.5
|
check@1.0.5
|
||||||
|
chriswessels:hammer@3.1.1
|
||||||
clinical:nightwatch@2.0.1
|
clinical:nightwatch@2.0.1
|
||||||
coffeescript@1.0.6
|
coffeescript@1.0.6
|
||||||
ddp@1.1.0
|
ddp@1.1.0
|
||||||
|
@ -15,9 +15,9 @@
|
|||||||
|
|
||||||
# Convert a color `value` as integer to a hex color (e.g. 255 to #0000ff)
|
# Convert a color `value` as integer to a hex color (e.g. 255 to #0000ff)
|
||||||
@colourToHex = (value) ->
|
@colourToHex = (value) ->
|
||||||
hex = parseInt(value).toString(16)
|
hex = parseInt(value).toString(16)
|
||||||
hex = "0" + hex while hex.length < 6
|
hex = "0" + hex while hex.length < 6
|
||||||
"##{hex}"
|
"##{hex}"
|
||||||
|
|
||||||
# color can be a number (a hex converted to int) or a string (e.g. "#ffff00")
|
# color can be a number (a hex converted to int) or a string (e.g. "#ffff00")
|
||||||
@formatColor = (color) ->
|
@formatColor = (color) ->
|
||||||
@ -34,6 +34,10 @@
|
|||||||
@getTime = -> # returns epoch in ms
|
@getTime = -> # returns epoch in ms
|
||||||
(new Date).valueOf()
|
(new Date).valueOf()
|
||||||
|
|
||||||
|
# checks if the pan gesture is mostly horizontal
|
||||||
|
@isPanHorizontal = (event) ->
|
||||||
|
Math.abs(event.deltaX) > Math.abs(event.deltaY)
|
||||||
|
|
||||||
# helper to determine whether user has joined any type of audio
|
# helper to determine whether user has joined any type of audio
|
||||||
Handlebars.registerHelper "amIInAudio", ->
|
Handlebars.registerHelper "amIInAudio", ->
|
||||||
BBB.amIInAudio()
|
BBB.amIInAudio()
|
||||||
@ -212,11 +216,55 @@ Handlebars.registerHelper 'whiteboardSize', (section) ->
|
|||||||
$('.sl-left-drawer').addClass('hiddenInLandscape')
|
$('.sl-left-drawer').addClass('hiddenInLandscape')
|
||||||
setTimeout(redrawWhiteboard, 0)
|
setTimeout(redrawWhiteboard, 0)
|
||||||
|
|
||||||
|
@populateNotifications = (msg) ->
|
||||||
|
myUserId = getInSession "userId"
|
||||||
|
users = Meteor.Users.find().fetch()
|
||||||
|
|
||||||
|
# assuming that I only have access only to private messages where I am the sender or the recipient
|
||||||
|
myPrivateChats = Meteor.Chat.find({'message.chat_type': 'PRIVATE_CHAT'}).fetch()
|
||||||
|
|
||||||
|
uniqueArray = []
|
||||||
|
for chat in myPrivateChats
|
||||||
|
if chat.message.to_userid is myUserId
|
||||||
|
uniqueArray.push({userId: chat.message.from_userid, username: chat.message.from_username})
|
||||||
|
if chat.message.from_userid is myUserId
|
||||||
|
uniqueArray.push({userId: chat.message.to_userid, username: chat.message.to_username})
|
||||||
|
|
||||||
|
#keep unique entries only
|
||||||
|
uniqueArray = uniqueArray.filter((itm, i, a) ->
|
||||||
|
i is a.indexOf(itm)
|
||||||
|
)
|
||||||
|
|
||||||
|
if msg.message.to_userid is myUserId
|
||||||
|
new_msg_userid = msg.message.from_userid
|
||||||
|
if msg.message.from_userid is myUserId
|
||||||
|
new_msg_userid = msg.message.to_userid
|
||||||
|
|
||||||
|
chats = getInSession('chats')
|
||||||
|
if chats is undefined
|
||||||
|
initChats = [
|
||||||
|
userId: "PUBLIC_CHAT"
|
||||||
|
gotMail: false
|
||||||
|
number: 0;
|
||||||
|
]
|
||||||
|
setInSession 'chats', initChats
|
||||||
|
|
||||||
|
#insert the unique entries in the collection
|
||||||
|
for u in uniqueArray
|
||||||
|
chats = getInSession('chats')
|
||||||
|
if chats.filter((chat) -> chat.userId == u.userId).length is 0 and u.userId is new_msg_userid
|
||||||
|
chats.push {userId: u.userId, gotMail: false, number: 0}
|
||||||
|
setInSession 'chats', chats
|
||||||
|
|
||||||
@toggleShield = ->
|
@toggleShield = ->
|
||||||
if $('.shield').hasClass('darken')
|
if parseFloat($('.shield').css('opacity')) is 0.5 # triggered during a pan gesture
|
||||||
$('.shield').removeClass('darken')
|
$('.shield').css('opacity', '')
|
||||||
else
|
|
||||||
|
if !$('.shield').hasClass('darken') and !$('.shield').hasClass('animatedShield')
|
||||||
$('.shield').addClass('darken')
|
$('.shield').addClass('darken')
|
||||||
|
else
|
||||||
|
$('.shield').removeClass('darken')
|
||||||
|
$('.shield').removeClass('animatedShield')
|
||||||
|
|
||||||
@removeFullscreenStyles = ->
|
@removeFullscreenStyles = ->
|
||||||
$('#whiteboard-paper').removeClass('verticallyCentered')
|
$('#whiteboard-paper').removeClass('verticallyCentered')
|
||||||
@ -327,7 +375,7 @@ Handlebars.registerHelper 'whiteboardSize', (section) ->
|
|||||||
@clearSessionVar = (callback) ->
|
@clearSessionVar = (callback) ->
|
||||||
amplify.store('authToken', null)
|
amplify.store('authToken', null)
|
||||||
amplify.store('bbbServerVersion', null)
|
amplify.store('bbbServerVersion', null)
|
||||||
amplify.store('chatTabs', null)
|
amplify.store('chats', null)
|
||||||
amplify.store('dateOfBuild', null)
|
amplify.store('dateOfBuild', null)
|
||||||
amplify.store('display_chatPane', null)
|
amplify.store('display_chatPane', null)
|
||||||
amplify.store('display_chatbar', null)
|
amplify.store('display_chatbar', null)
|
||||||
@ -351,9 +399,11 @@ Handlebars.registerHelper 'whiteboardSize', (section) ->
|
|||||||
setInSession "display_chatbar", true
|
setInSession "display_chatbar", true
|
||||||
setInSession "display_whiteboard", true
|
setInSession "display_whiteboard", true
|
||||||
setInSession "display_chatPane", true
|
setInSession "display_chatPane", true
|
||||||
if not getInSession "inChatWith" then setInSession "inChatWith", 'PUBLIC_CHAT'
|
|
||||||
|
#if it is a desktop version of the client
|
||||||
if isPortraitMobile() or isLandscapeMobile()
|
if isPortraitMobile() or isLandscapeMobile()
|
||||||
setInSession "messageFontSize", Meteor.config.app.mobileFont
|
setInSession "messageFontSize", Meteor.config.app.mobileFont
|
||||||
|
#if this is a mobile version of the client
|
||||||
else
|
else
|
||||||
setInSession "messageFontSize", Meteor.config.app.desktopFont
|
setInSession "messageFontSize", Meteor.config.app.desktopFont
|
||||||
setInSession 'display_slidingMenu', false
|
setInSession 'display_slidingMenu', false
|
||||||
@ -363,8 +413,34 @@ Handlebars.registerHelper 'whiteboardSize', (section) ->
|
|||||||
else
|
else
|
||||||
setInSession 'display_usersList', false
|
setInSession 'display_usersList', false
|
||||||
setInSession 'display_menu', false
|
setInSession 'display_menu', false
|
||||||
|
setInSession 'chatInputMinHeight', 0
|
||||||
|
|
||||||
|
#keep notifications and an opened private chat tab if page was refreshed
|
||||||
|
#reset to default if that's a new user
|
||||||
|
if loginOrRefresh()
|
||||||
|
initChats = [
|
||||||
|
userId: "PUBLIC_CHAT"
|
||||||
|
gotMail: false
|
||||||
|
number: 0
|
||||||
|
]
|
||||||
|
setInSession 'chats', initChats
|
||||||
|
setInSession "inChatWith", 'PUBLIC_CHAT'
|
||||||
|
|
||||||
TimeSync.loggingEnabled = false # suppresses the log messages from timesync
|
TimeSync.loggingEnabled = false # suppresses the log messages from timesync
|
||||||
|
|
||||||
|
#true if it is a new user, false if the client was just refreshed
|
||||||
|
@loginOrRefresh = ->
|
||||||
|
userId = getInSession 'userId'
|
||||||
|
checkId = getInSession 'checkId'
|
||||||
|
if checkId is undefined
|
||||||
|
setInSession 'checkId', userId
|
||||||
|
return true
|
||||||
|
else if userId isnt checkId
|
||||||
|
setInSession 'checkId', userId
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
|
||||||
@onLoadComplete = ->
|
@onLoadComplete = ->
|
||||||
document.title = "BigBlueButton #{BBB.getMeetingName() ? 'HTML5'}"
|
document.title = "BigBlueButton #{BBB.getMeetingName() ? 'HTML5'}"
|
||||||
setDefaultSettings()
|
setDefaultSettings()
|
||||||
@ -386,7 +462,14 @@ Handlebars.registerHelper 'whiteboardSize', (section) ->
|
|||||||
navigator.userAgent.match(/webOS/i)
|
navigator.userAgent.match(/webOS/i)
|
||||||
|
|
||||||
@isLandscape = ->
|
@isLandscape = ->
|
||||||
window.matchMedia('(orientation: landscape)').matches
|
not isMobile() and
|
||||||
|
window.matchMedia('(orientation: landscape)').matches and # browser is landscape
|
||||||
|
window.matchMedia('(min-device-aspect-ratio: 1/1)').matches # device is landscape
|
||||||
|
|
||||||
|
@isPortrait = ->
|
||||||
|
not isMobile() and
|
||||||
|
window.matchMedia('(orientation: portrait)').matches and # browser is portrait
|
||||||
|
window.matchMedia('(min-device-aspect-ratio: 1/1)').matches # device is landscape
|
||||||
|
|
||||||
# Checks if the view is portrait and a mobile device is being used
|
# Checks if the view is portrait and a mobile device is being used
|
||||||
@isPortraitMobile = () ->
|
@isPortraitMobile = () ->
|
||||||
@ -397,8 +480,8 @@ Handlebars.registerHelper 'whiteboardSize', (section) ->
|
|||||||
# Checks if the view is landscape and mobile device is being used
|
# Checks if the view is landscape and mobile device is being used
|
||||||
@isLandscapeMobile = () ->
|
@isLandscapeMobile = () ->
|
||||||
isMobile() and
|
isMobile() and
|
||||||
window.matchMedia('(orientation: landscape)').matches and # browser is landscape
|
window.matchMedia('(orientation: landscape)').matches and # browser is landscape
|
||||||
window.matchMedia('(min-device-aspect-ratio: 1/1)').matches # device is landscape
|
window.matchMedia('(min-device-aspect-ratio: 1/1)').matches # device is landscape
|
||||||
|
|
||||||
# Checks if only one panel (userlist/whiteboard/chatbar) is currently open
|
# Checks if only one panel (userlist/whiteboard/chatbar) is currently open
|
||||||
@isOnlyOnePanelOpen = () ->
|
@isOnlyOnePanelOpen = () ->
|
||||||
@ -417,3 +500,22 @@ Handlebars.registerHelper 'whiteboardSize', (section) ->
|
|||||||
return 'IE'
|
return 'IE'
|
||||||
else
|
else
|
||||||
return null
|
return null
|
||||||
|
|
||||||
|
# changes the height of the chat input area if needed (based on the textarea content)
|
||||||
|
@adjustChatInputHeight = () ->
|
||||||
|
$('#newMessageInput').css('height', 'auto')
|
||||||
|
projectedHeight = $('#newMessageInput')[0].scrollHeight + 23
|
||||||
|
if projectedHeight isnt $('.panel-footer').height() and
|
||||||
|
projectedHeight >= getInSession('chatInputMinHeight')
|
||||||
|
$('#newMessageInput').css('overflow', 'hidden') # prevents a scroll bar
|
||||||
|
|
||||||
|
# resizes the chat input area
|
||||||
|
$('.panel-footer').css('top', - (projectedHeight - 70) + 'px')
|
||||||
|
$('.panel-footer').css('height', projectedHeight + 'px')
|
||||||
|
|
||||||
|
$('#newMessageInput').height($('#newMessageInput')[0].scrollHeight)
|
||||||
|
|
||||||
|
# resizes the chat messages container
|
||||||
|
$('#chatbody').height($('#chat').height() - projectedHeight - 45)
|
||||||
|
$('#chatbody').scrollTop($('#chatbody')[0]?.scrollHeight)
|
||||||
|
$('#newMessageInput').css('height', '')
|
||||||
|
@ -141,5 +141,177 @@ Template.main.events
|
|||||||
$('.signOutIcon').blur()
|
$('.signOutIcon').blur()
|
||||||
$("#logoutModal").foundation('reveal', 'open');
|
$("#logoutModal").foundation('reveal', 'open');
|
||||||
|
|
||||||
|
Template.main.gestures
|
||||||
|
'panstart #container': (event, template) ->
|
||||||
|
if isPortraitMobile() and isPanHorizontal(event)
|
||||||
|
panIsValid = getInSession('panIsValid')
|
||||||
|
initTransformValue = getInSession('initTransform')
|
||||||
|
menuPanned = getInSession('menuPanned')
|
||||||
|
screenWidth = $('#container').width()
|
||||||
|
|
||||||
|
setInSession 'panStarted', true
|
||||||
|
|
||||||
|
if panIsValid and
|
||||||
|
menuPanned is 'left' and
|
||||||
|
initTransformValue + event.deltaX >= 0 and
|
||||||
|
initTransformValue + event.deltaX <= $('.left-drawer').width()
|
||||||
|
$('.left-drawer').css('transform', 'translateX(' + (initTransformValue + event.deltaX) + 'px)')
|
||||||
|
|
||||||
|
else if panIsValid and
|
||||||
|
menuPanned is 'right' and
|
||||||
|
initTransformValue + event.deltaX >= screenWidth - $('.right-drawer').width() and
|
||||||
|
initTransformValue + event.deltaX <= screenWidth
|
||||||
|
$('.right-drawer').css('transform', 'translateX(' + (initTransformValue + event.deltaX) + 'px)')
|
||||||
|
|
||||||
|
'panend #container': (event, template) ->
|
||||||
|
if isPortraitMobile()
|
||||||
|
panIsValid = getInSession('panIsValid')
|
||||||
|
menuPanned = getInSession('menuPanned')
|
||||||
|
leftDrawerWidth = $('.left-drawer').width()
|
||||||
|
screenWidth = $('#container').width()
|
||||||
|
|
||||||
|
setInSession 'panStarted', false
|
||||||
|
|
||||||
|
if panIsValid and
|
||||||
|
menuPanned is 'left' and
|
||||||
|
$('.left-drawer').css('transform') isnt 'none'
|
||||||
|
|
||||||
|
if parseInt($('.left-drawer').css('transform').split(',')[4]) < leftDrawerWidth / 2
|
||||||
|
$('.shield').removeClass('animatedShield')
|
||||||
|
$('.shield').css('opacity', '')
|
||||||
|
$('.left-drawer').removeClass('sl-left-drawer-out')
|
||||||
|
$('.left-drawer').css('transform', '')
|
||||||
|
$('.toggleUserlistButton').removeClass('sl-toggled-on')
|
||||||
|
$('.shield').removeClass('darken') # in case it was opened by clicking a button
|
||||||
|
else
|
||||||
|
$('.left-drawer').css('transform', 'translateX(' + leftDrawerWidth + 'px)')
|
||||||
|
$('.shield').css('opacity', 0.5)
|
||||||
|
$('.left-drawer').addClass('sl-left-drawer-out')
|
||||||
|
$('.left-drawer').css('transform', '')
|
||||||
|
$('.toggleUserlistButton').addClass('sl-toggled-on')
|
||||||
|
|
||||||
|
if panIsValid and
|
||||||
|
menuPanned is 'right' and
|
||||||
|
parseInt($('.right-drawer').css('transform').split(',')[4]) isnt leftDrawerWidth
|
||||||
|
|
||||||
|
if parseInt($('.right-drawer').css('transform').split(',')[4]) > screenWidth - $('.right-drawer').width() / 2
|
||||||
|
$('.shield').removeClass('animatedShield')
|
||||||
|
$('.shield').css('opacity', '')
|
||||||
|
$('.right-drawer').css('transform', 'translateX(' + screenWidth + 'px)')
|
||||||
|
$('.right-drawer').removeClass('sl-right-drawer-out')
|
||||||
|
$('.right-drawer').css('transform', '')
|
||||||
|
$('.toggleMenuButton').removeClass('sl-toggled-on')
|
||||||
|
$('.shield').removeClass('darken') # in case it was opened by clicking a button
|
||||||
|
else
|
||||||
|
$('.shield').css('opacity', 0.5)
|
||||||
|
$('.right-drawer').css('transform', 'translateX(' + (screenWidth - $('.right-drawer').width()) + 'px)')
|
||||||
|
$('.right-drawer').addClass('sl-right-drawer-out')
|
||||||
|
$('.right-drawer').css('transform', '')
|
||||||
|
$('.toggleMenuButton').addClass('sl-toggled-on')
|
||||||
|
|
||||||
|
$('.left-drawer').addClass('sl-left-drawer')
|
||||||
|
$('.sl-left-drawer').removeClass('left-drawer')
|
||||||
|
|
||||||
|
$('.right-drawer').addClass('sl-right-drawer')
|
||||||
|
$('.sl-right-drawer').removeClass('right-drawer')
|
||||||
|
|
||||||
|
'panright #container, panleft #container': (event, template) ->
|
||||||
|
if isPortraitMobile() and isPanHorizontal(event)
|
||||||
|
|
||||||
|
# panright/panleft is always triggered once right before panstart
|
||||||
|
if !getInSession('panStarted')
|
||||||
|
|
||||||
|
# opening the left-hand menu
|
||||||
|
if event.type is 'panright' and
|
||||||
|
event.center.x <= $('#container').width() * 0.1
|
||||||
|
setInSession 'panIsValid', true
|
||||||
|
setInSession 'menuPanned', 'left'
|
||||||
|
|
||||||
|
# closing the left-hand menu
|
||||||
|
else if event.type is 'panleft' and
|
||||||
|
event.center.x < $('#container').width() * 0.9
|
||||||
|
setInSession 'panIsValid', true
|
||||||
|
setInSession 'menuPanned', 'left'
|
||||||
|
|
||||||
|
# opening the right-hand menu
|
||||||
|
else if event.type is 'panleft' and
|
||||||
|
event.center.x >= $('#container').width() * 0.9
|
||||||
|
setInSession 'panIsValid', true
|
||||||
|
setInSession 'menuPanned', 'right'
|
||||||
|
|
||||||
|
# closing the right-hand menu
|
||||||
|
else if event.type is 'panright' and
|
||||||
|
event.center.x > $('#container').width() * 0.1
|
||||||
|
setInSession 'panIsValid', true
|
||||||
|
setInSession 'menuPanned', 'right'
|
||||||
|
|
||||||
|
else
|
||||||
|
setInSession 'panIsValid', false
|
||||||
|
|
||||||
|
setInSession 'eventType', event.type
|
||||||
|
|
||||||
|
if getInSession('menuPanned') is 'left'
|
||||||
|
if $('.sl-left-drawer').css('transform') isnt 'none' # menu is already transformed
|
||||||
|
setInSession 'initTransform', parseInt($('.sl-left-drawer').css('transform').split(',')[4]) # translateX value
|
||||||
|
else if $('.sl-left-drawer').hasClass('sl-left-drawer-out')
|
||||||
|
setInSession 'initTransform', $('.sl-left-drawer').width()
|
||||||
|
else
|
||||||
|
setInSession 'initTransform', 0
|
||||||
|
$('.sl-left-drawer').addClass('left-drawer')
|
||||||
|
$('.left-drawer').removeClass('sl-left-drawer') # to prevent animations from Sled library
|
||||||
|
$('.left-drawer').removeClass('sl-left-drawer-content-delay') # makes the menu content movable too
|
||||||
|
|
||||||
|
else if getInSession('menuPanned') is 'right'
|
||||||
|
if $('.sl-right-drawer').css('transform') isnt 'none' # menu is already transformed
|
||||||
|
setInSession 'initTransform', parseInt($('.sl-right-drawer').css('transform').split(',')[4]) # translateX value
|
||||||
|
else if $('.sl-right-drawer').hasClass('sl-right-drawer-out')
|
||||||
|
setInSession 'initTransform', $('.sl-right-drawer').width()
|
||||||
|
else
|
||||||
|
setInSession 'initTransform', 0
|
||||||
|
$('.sl-right-drawer').addClass('right-drawer')
|
||||||
|
$('.right-drawer').removeClass('sl-right-drawer') # to prevent animations from Sled library
|
||||||
|
$('.right-drawer').removeClass('sl-right-drawer-content-delay') # makes the menu content movable too
|
||||||
|
|
||||||
|
initTransformValue = getInSession('initTransform')
|
||||||
|
panIsValid = getInSession('panIsValid')
|
||||||
|
menuPanned = getInSession('menuPanned')
|
||||||
|
leftDrawerWidth = $('.left-drawer').width()
|
||||||
|
rightDrawerWidth = $('.right-drawer').width()
|
||||||
|
screenWidth = $('#container').width()
|
||||||
|
|
||||||
|
# moving the left-hand menu
|
||||||
|
if panIsValid and
|
||||||
|
menuPanned is 'left' and
|
||||||
|
initTransformValue + event.deltaX >= 0 and
|
||||||
|
initTransformValue + event.deltaX <= leftDrawerWidth
|
||||||
|
|
||||||
|
if $('.sl-right-drawer').hasClass('sl-right-drawer-out')
|
||||||
|
toggleRightDrawer()
|
||||||
|
toggleRightArrowClockwise()
|
||||||
|
|
||||||
|
$('.left-drawer').css('transform', 'translateX(' + (initTransformValue + event.deltaX) + 'px)')
|
||||||
|
|
||||||
|
if !getInSession('panStarted')
|
||||||
|
$('.shield').addClass('animatedShield')
|
||||||
|
$('.shield').css('opacity',
|
||||||
|
0.5 * (initTransformValue + event.deltaX) / leftDrawerWidth)
|
||||||
|
|
||||||
|
# moving the right-hand menu
|
||||||
|
else if panIsValid and
|
||||||
|
menuPanned is 'right' and
|
||||||
|
initTransformValue + event.deltaX >= screenWidth - rightDrawerWidth and
|
||||||
|
initTransformValue + event.deltaX <= screenWidth
|
||||||
|
|
||||||
|
if $('.sl-left-drawer').hasClass('sl-left-drawer-out')
|
||||||
|
toggleLeftDrawer()
|
||||||
|
toggleLeftArrowClockwise()
|
||||||
|
|
||||||
|
$('.right-drawer').css('transform', 'translateX(' + (initTransformValue + event.deltaX) + 'px)')
|
||||||
|
|
||||||
|
if !getInSession('panStarted')
|
||||||
|
$('.shield').addClass('animatedShield')
|
||||||
|
$('.shield').css('opacity',
|
||||||
|
0.5 * (screenWidth - initTransformValue - event.deltaX) / rightDrawerWidth)
|
||||||
|
|
||||||
Template.makeButton.rendered = ->
|
Template.makeButton.rendered = ->
|
||||||
$('button[rel=tooltip]').tooltip()
|
$('button[rel=tooltip]').tooltip()
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
<template name="header">
|
<template name="header">
|
||||||
<nav id="navbar" class="myNavbar gradientBar top-bar" role="navigation">
|
<nav id="navbar" class="myNavbar top-bar" role="navigation">
|
||||||
<button class="btn toggleUserlistButton navbarButton sl-hamburger sl-ham-la-cw sl-portrait-mobile sl-portrait-keyboard">
|
{{> makeButton btn_class="btn toggleUserlistButton navbarButton sl-hamburger sl-ham-la-cw sl-portrait-mobile sl-portrait-keyboard" rel="tooltip" title="Toggle Userlist" span=true notification="all_chats"}}
|
||||||
<span></span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{{#if amIInAudio}}
|
{{#if amIInAudio}}
|
||||||
{{#if amIListenOnlyAudio}}
|
{{#if amIListenOnlyAudio}}
|
||||||
{{> makeButton btn_class="navbarButton leaveAudioButton" i_class="icon fi-volume-none" rel="tooltip" title="Exit Audio"}}
|
{{> makeButton btn_class="navbarButton leaveAudioButton" i_class="icon fi-volume-none" rel="tooltip" title="Exit Audio"}}
|
||||||
|
@ -11,9 +11,21 @@
|
|||||||
height: 45px;
|
height: 45px;
|
||||||
min-height: 45px;
|
min-height: 45px;
|
||||||
.btn {
|
.btn {
|
||||||
|
&:hover {
|
||||||
|
color: #3896D3;
|
||||||
|
background-color:white;
|
||||||
|
border-bottom: 1px solid #E5E5E5;
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
background-color:white;
|
||||||
|
border-bottom: 1px solid #E5E5E5;
|
||||||
|
}
|
||||||
|
padding: 0.625rem 0.5rem 0.6875rem 0.5rem;
|
||||||
background-color: inherit;
|
background-color: inherit;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: 45px;
|
height: 45px;
|
||||||
|
outline: none;
|
||||||
|
min-width: 50px;
|
||||||
}
|
}
|
||||||
span {
|
span {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -29,23 +41,40 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.privateChatName {
|
.privateChatName {
|
||||||
|
width: calc(~'100% - 105px');
|
||||||
|
min-width: 101px;
|
||||||
|
text-align: right;
|
||||||
float: right;
|
float: right;
|
||||||
padding: 0.65rem 1.25rem 0.6rem 0.3rem;
|
padding: 0.65rem 1.25rem 0.6rem 0.3rem;
|
||||||
font-family: "Helvetica Neue",Helvetica,Roboto,Arial,sans-serif;
|
font-family: "Helvetica Neue",Helvetica,Roboto,Arial,sans-serif;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.toPublic .unreadChatNumber {
|
||||||
|
@media @desktop-portrait, @landscape {
|
||||||
|
padding: 2px;
|
||||||
|
position: absolute;
|
||||||
|
top: 31%;
|
||||||
|
left: 100%;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#chat {
|
#chat {
|
||||||
@media @landscape {
|
@media @landscape {
|
||||||
-webkit-flex: 3 3 30%;
|
-webkit-flex: 1 1;
|
||||||
-moz-flex: 3 3 30%;
|
-moz-flex: 1 1;
|
||||||
-ms-flex: 3 3 30%;
|
-ms-flex: 1 1;
|
||||||
flex: 3 3 30%;
|
flex: 1 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border-top: 0px;
|
border-top: 0px;
|
||||||
border-right: 0px;
|
border-right: 0px;
|
||||||
border-top-left-radius: 0px;
|
border-top-left-radius: 0px;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
order: 3;
|
order: 3;
|
||||||
}
|
}
|
||||||
@ -136,23 +165,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.gotUnreadMail {
|
|
||||||
background: extract(@yellow, 2) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#newMessageInput {
|
#newMessageInput {
|
||||||
display: block;
|
display: block;
|
||||||
float: left;
|
float: left;
|
||||||
width: 75%;
|
width: 75%;
|
||||||
resize: none;
|
resize: none;
|
||||||
padding-top: 5px;
|
padding-top: 0px;
|
||||||
padding-bottom: 0px;
|
padding-bottom: 0px;
|
||||||
|
|
||||||
border:1px solid extract(@lightGrey, 3);
|
border:1px solid extract(@lightGrey, 3);
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
|
|
||||||
@media @landscape {
|
@media @landscape {
|
||||||
height: 40px; /* same height as send button */
|
height: 100%; /* same height as send button */
|
||||||
}
|
}
|
||||||
@media @mobile-portrait {
|
@media @mobile-portrait {
|
||||||
font-size: 4vw;
|
font-size: 4vw;
|
||||||
@ -173,22 +198,24 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
background: extract(@white, 1);
|
background: extract(@white, 1);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border-top: 1px solid #E5E5E5;
|
border-top: 1px solid extract(@lightGrey, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#sendMessageButton {
|
#sendMessageButton {
|
||||||
width: 20%; /* 75% for the message input, 5% margin between the two */
|
width: 20%; /* 75% for the message input, 5% margin between the two */
|
||||||
color: extract(@black, 1);
|
color: extract(@black, 1);
|
||||||
background-color: extract(@white, 1);
|
background-color: #3896D3;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
border: 1px solid extract(@lightGrey, 3);
|
border: 1px solid extract(@lightGrey, 3);
|
||||||
|
|
||||||
@media @desktop-portrait {
|
@media @desktop-portrait {
|
||||||
width: 20%; /* 75% for the message input, 5% margin between the two */
|
width: 20%; /* 75% for the message input, 5% margin between the two */
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
|
&:hover {
|
||||||
|
background: #3A82D4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@media @mobile-portrait {
|
@media @mobile-portrait {
|
||||||
width: 15vw;
|
width: 15vw;
|
||||||
@ -203,6 +230,11 @@
|
|||||||
@media @landscape {
|
@media @landscape {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
&:hover {
|
||||||
|
background: #3A82D4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,3 +247,16 @@
|
|||||||
min-width: 140px;
|
min-width: 140px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
@media @landscape {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#chatInput {
|
||||||
|
@media @landscape {
|
||||||
|
height: 100%;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -33,9 +33,42 @@ body {
|
|||||||
margin-left:5px
|
margin-left:5px
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media @mobile-portrait {
|
||||||
|
.sl-toggled-on .unreadChat {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbarButton {
|
||||||
|
color: #469DCF;
|
||||||
|
.unreadChat {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
background:red;
|
||||||
|
border-radius:80%;
|
||||||
|
@media @desktop-portrait, @landscape {
|
||||||
|
top: 20%;
|
||||||
|
left: 65%;
|
||||||
|
width:19%;
|
||||||
|
height:20%;
|
||||||
|
}
|
||||||
|
@media @mobile-portrait {
|
||||||
|
top: 14%;
|
||||||
|
left: 70%;
|
||||||
|
width:25%;
|
||||||
|
height:25%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.myNavbar {
|
.myNavbar {
|
||||||
border-bottom: 0px;
|
border-bottom: 1px;
|
||||||
&.gradientBar {
|
@media @desktop-portrait, @landscape {
|
||||||
|
background-color: white;
|
||||||
|
border-bottom: 1px solid extract(@lightGrey, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media @mobile-portrait-with-keyboard, @mobile-portrait {
|
||||||
.linear-gradient(rgb(72,76,85), rgb(65,68,77));
|
.linear-gradient(rgb(72,76,85), rgb(65,68,77));
|
||||||
}
|
}
|
||||||
.btn {
|
.btn {
|
||||||
@ -45,13 +78,15 @@ body {
|
|||||||
top: 0 !important;
|
top: 0 !important;
|
||||||
padding-left: 1% !important;
|
padding-left: 1% !important;
|
||||||
padding-right: 1% !important;
|
padding-right: 1% !important;
|
||||||
|
background-color: white;
|
||||||
|
border-bottom: 1px solid extract(@lightGrey, 1);
|
||||||
}
|
}
|
||||||
@media @mobile-portrait-with-keyboard, @mobile-portrait {
|
@media @mobile-portrait-with-keyboard, @mobile-portrait {
|
||||||
height: 100px !important;
|
height: 100px !important;
|
||||||
width: 10%;
|
width: 10%;
|
||||||
min-width: 60px;
|
min-width: 60px;
|
||||||
|
.linear-gradient(rgb(72,76,85), rgb(65,68,77));
|
||||||
}
|
}
|
||||||
.linear-gradient(rgb(72,76,85), rgb(65,68,77));
|
|
||||||
.push-menu-icon {
|
.push-menu-icon {
|
||||||
.icon-bar {
|
.icon-bar {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
@ -71,10 +106,9 @@ body {
|
|||||||
&.toggleUserlistButton, &.toggleMenuButton {
|
&.toggleUserlistButton, &.toggleMenuButton {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
span { background-color: white; }
|
span { background-color: #469DCF; }
|
||||||
}
|
}
|
||||||
@media @landscape {
|
@media @landscape {
|
||||||
min-width: 768px;
|
|
||||||
height: 50px;
|
height: 50px;
|
||||||
}
|
}
|
||||||
@media @mobile-portrait-with-keyboard, @mobile-portrait {
|
@media @mobile-portrait-with-keyboard, @mobile-portrait {
|
||||||
@ -87,28 +121,35 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.navbarTitle {
|
.navbarTitle {
|
||||||
color: extract(@white, 1);
|
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@media @landscape {
|
position: absolute;
|
||||||
font-size: 16px;
|
|
||||||
width: 30% !important;
|
|
||||||
}
|
|
||||||
@media @mobile-portrait-with-keyboard, @mobile-portrait {
|
@media @mobile-portrait-with-keyboard, @mobile-portrait {
|
||||||
font-size: 30px;
|
color: extract(@white, 1);
|
||||||
padding-top: 30px;
|
font-size: 35px;
|
||||||
padding-left: 5px;
|
|
||||||
height: 72px;
|
height: 72px;
|
||||||
width: 70%;
|
max-width: 70%;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
|
height: 110px;
|
||||||
|
padding-top: 55px; // half the height
|
||||||
|
padding-left: 30px;
|
||||||
}
|
}
|
||||||
@media @desktop-portrait {
|
@media @desktop-portrait {
|
||||||
|
max-width: calc(~'100% - 155px'); // navbar width minus the space for 3 buttons
|
||||||
|
}
|
||||||
|
@media @landscape {
|
||||||
|
max-width: calc(~'100% - 125px'); // navbar width minus the space for 4 buttons
|
||||||
|
}
|
||||||
|
@media @landscape, @desktop-portrait {
|
||||||
|
color: extract(@darkGrey, 1);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
width: calc(~'100% - 102.4px');
|
height: 50px;
|
||||||
|
padding-top: 25px; // half the height
|
||||||
|
padding-left: 15px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,30 +182,32 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.meetingTitle {
|
.meetingTitle {
|
||||||
|
text-align: center;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
line-height: 2em;
|
line-height: 2em;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@media @mobile-portrait, @mobile-portrait-with-keyboard, @desktop-portrait {
|
@media @mobile-portrait, @mobile-portrait-with-keyboard {
|
||||||
.linear-gradient(rgb(72,76,85), rgb(65,68,77));
|
.linear-gradient(rgb(72,76,85), rgb(65,68,77));
|
||||||
padding-left: 140px;
|
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
color: white;
|
color: white;
|
||||||
|
font-size: 4vw;
|
||||||
|
height: 110px;
|
||||||
|
}
|
||||||
|
@media @desktop-portrait {
|
||||||
|
.linear-gradient(rgb(72,76,85), rgb(65,68,77));
|
||||||
|
padding-top: 10px;
|
||||||
|
color: white;
|
||||||
}
|
}
|
||||||
@media @landscape {
|
@media @landscape {
|
||||||
border-bottom: 1px solid extract(@lightGrey, 1);
|
border-bottom: 1px solid extract(@lightGrey, 1);
|
||||||
color: extract(@darkGrey, 1);
|
color: extract(@darkGrey, 1);
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
padding-left: 10px;
|
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
}
|
}
|
||||||
@media @desktop-portrait, @landscape {
|
@media @desktop-portrait, @landscape {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
}
|
}
|
||||||
@media @mobile-portrait, @mobile-portrait-with-keyboard {
|
|
||||||
font-size: 4vw;
|
|
||||||
height: 110px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#container {
|
#container {
|
||||||
@ -272,10 +315,10 @@ body {
|
|||||||
|
|
||||||
#main {
|
#main {
|
||||||
@media @landscape {
|
@media @landscape {
|
||||||
-webkit-flex: 4 4 80%;
|
-webkit-flex: 1 1;
|
||||||
-moz-flex: 4 4 80%;
|
-moz-flex: 1 1;
|
||||||
-ms-flex: 4 4 80%;
|
-ms-flex: 1 1;
|
||||||
flex: 4 4 80%;
|
flex: 1 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
@media @mobile-portrait-with-keyboard, @desktop-portrait, @mobile-portrait {
|
@media @mobile-portrait-with-keyboard, @desktop-portrait, @mobile-portrait {
|
||||||
@ -303,6 +346,12 @@ body {
|
|||||||
|
|
||||||
.signOutIcon {
|
.signOutIcon {
|
||||||
@media @landscape {
|
@media @landscape {
|
||||||
|
&:hover {
|
||||||
|
color: #2A5E7C;
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
color: #2A5E7C;
|
||||||
|
}
|
||||||
height: 28px;
|
height: 28px;
|
||||||
width: 75px;
|
width: 75px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
@ -333,8 +382,18 @@ body {
|
|||||||
z-index: 1001;
|
z-index: 1001;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.toggleUserlistButton {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
.settingsIcon {
|
.settingsIcon {
|
||||||
@media @landscape {
|
@media @landscape {
|
||||||
|
&:hover {
|
||||||
|
color: #2A5E7C;
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
color: #2A5E7C;
|
||||||
|
}
|
||||||
width: 57px;
|
width: 57px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
@ -459,7 +518,7 @@ body {
|
|||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: -400px;
|
left: -400px;
|
||||||
width: 400px;
|
width: 400px !important; // overrides any width value set manually in landscape
|
||||||
&.sl-left-drawer-out {
|
&.sl-left-drawer-out {
|
||||||
left: 0px;
|
left: 0px;
|
||||||
}
|
}
|
||||||
@ -478,10 +537,7 @@ body {
|
|||||||
.sl-left-drawer {
|
.sl-left-drawer {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@media @landscape {
|
@media @landscape {
|
||||||
-webkit-flex: 1 1 20%;
|
width: 300px;
|
||||||
-moz-flex: 1 1 20%;
|
|
||||||
-ms-flex: 1 1 20%;
|
|
||||||
flex: 1 1 20%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,7 +570,7 @@ body {
|
|||||||
@media @landscape {
|
@media @landscape {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
&:not(.darken) {
|
&:not(.darken):not(.animatedShield) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -532,3 +588,28 @@ body {
|
|||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui-resizable-handle {
|
||||||
|
@media @mobile-portrait, @desktop-portrait, @mobile-portrait-with-keyboard {
|
||||||
|
display: none; // hides the sizing handle everywhere except the landscape mode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// same as Sled's left drawer except for animations
|
||||||
|
.left-drawer {
|
||||||
|
z-index: 1000;
|
||||||
|
position: fixed;
|
||||||
|
width: 60vw;
|
||||||
|
left: -60vw;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
// same as Sled's right drawer except for animations
|
||||||
|
.right-drawer {
|
||||||
|
z-index: 1000;
|
||||||
|
position: fixed;
|
||||||
|
transform: translateX(100vw);
|
||||||
|
height: 100%;
|
||||||
|
.linear-gradient(rgb(65,68,77), rgb(58,60,69));
|
||||||
|
width: 60vw;
|
||||||
|
}
|
||||||
|
@ -1,26 +1,48 @@
|
|||||||
@import "variables";
|
@import "variables";
|
||||||
@import "mixins";
|
@import "mixins";
|
||||||
|
|
||||||
.usericon {
|
.statusIcon {
|
||||||
font-size: 16px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#usericons {
|
#usericons {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
color: white;
|
||||||
|
span i {
|
||||||
|
@media @landscape, @desktop-portrait {
|
||||||
|
margin-right: 10px;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.unreadChatNumber {
|
||||||
|
@media @landscape, @desktop-portrait{
|
||||||
|
float: left;
|
||||||
|
margin-top: 5px;
|
||||||
|
width: 28px;
|
||||||
|
height: 18px;
|
||||||
|
border-radius: 41%;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
background: #3896D3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.usernameEntry {
|
.usernameEntry {
|
||||||
|
cursor: pointer;
|
||||||
|
line-height: 1.1;
|
||||||
float:left;
|
float:left;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
width: 60%;
|
width: calc(~'100% - 130px');
|
||||||
@media @landscape {
|
@media @landscape {
|
||||||
height: 20px;
|
height: 27px;
|
||||||
font-size: 4.5mm;
|
font-size: 4.5mm;
|
||||||
}
|
}
|
||||||
@media @desktop-portrait {
|
@media @desktop-portrait {
|
||||||
height: 25px;
|
height: 27px;
|
||||||
font-size: 4.5mm;
|
font-size: 4.5mm;
|
||||||
}
|
}
|
||||||
@media @mobile-portrait, @mobile-portrait-with-keyboard {
|
@media @mobile-portrait, @mobile-portrait-with-keyboard {
|
||||||
@ -34,7 +56,6 @@
|
|||||||
border-left: 0px;
|
border-left: 0px;
|
||||||
border-top: 0px;
|
border-top: 0px;
|
||||||
border-top-right-radius: 0px;
|
border-top-right-radius: 0px;
|
||||||
background-color: #FAFAFA;
|
|
||||||
}
|
}
|
||||||
@media @mobile-portrait-with-keyboard, @desktop-portrait, @mobile-portrait {
|
@media @mobile-portrait-with-keyboard, @desktop-portrait, @mobile-portrait {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -62,15 +83,24 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#user-contents {
|
#user-contents {
|
||||||
height: 83vh; /* for the inside scrolling list to utilize as much room as possible, this surrounding window must also take up as much room as possible */
|
height: calc(~'100% - 50px'); /* user-contents = user-contens - meetingTitle */
|
||||||
|
@media @landscape, @desktop-portrait{
|
||||||
|
background-color: #34495E;
|
||||||
|
}
|
||||||
.userlist {
|
.userlist {
|
||||||
height: calc(~'100% - 29px'); /* height of user contents - user list */
|
max-height: 100% !important;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
#content:hover {
|
||||||
|
@media @landscape, @desktop-portrait {
|
||||||
|
background-color: #2C4155;
|
||||||
|
}
|
||||||
|
}
|
||||||
#content {
|
#content {
|
||||||
span:hover {
|
span:hover {
|
||||||
/*background-color: #EEEEEE;*/
|
@media @mobile-portrait-with-keyboard, @desktop-portrait, @mobile-portrait {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
&:first-child { margin-top: 0px; }
|
&:first-child { margin-top: 0px; }
|
||||||
@ -103,17 +133,13 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.closeUserlistIcon {
|
.toggleUserlistButton, .toggleMenuButton {
|
||||||
float: right;
|
span {
|
||||||
margin-right: 5px;
|
@media @landscape, @desktop-portrait {
|
||||||
@media @mobile-portrait-with-keyboard, @desktop-portrait, @mobile-portrait {
|
width: 26px;
|
||||||
display: none;
|
margin-left: auto;
|
||||||
}
|
margin-right: auto;
|
||||||
.closeSettings {
|
height: 8%;
|
||||||
@media @landscape {
|
|
||||||
color: #aaa;
|
|
||||||
font-style: normal;
|
|
||||||
font-size: 30px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,3 +154,18 @@
|
|||||||
.muteIcon .ion-ios-mic-off:hover:before {
|
.muteIcon .ion-ios-mic-off:hover:before {
|
||||||
content: "\f461";
|
content: "\f461";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.userName {
|
||||||
|
color: #E6E6E6;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status {
|
||||||
|
float: left;
|
||||||
|
width: 15px;
|
||||||
|
min-width: 15px;
|
||||||
|
height: 27px;
|
||||||
|
margin-right: 10px;
|
||||||
|
font-size: 18px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
@ -7,19 +7,15 @@
|
|||||||
border-top: 0px;
|
border-top: 0px;
|
||||||
border-left: 0px;
|
border-left: 0px;
|
||||||
border-right: 0px;
|
border-right: 0px;
|
||||||
-webkit-order: 2;
|
border-top-left-radius: 0;
|
||||||
order: 2;
|
border-top-right-radius: 0;
|
||||||
-webkit-flex: 7 7 70%;
|
width: 70%;
|
||||||
-moz-flex: 7 7 70%;
|
|
||||||
-ms-flex: 7 7 70%;
|
|
||||||
flex: 7 7 70%;
|
|
||||||
min-width: 50%;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
@media @mobile-portrait-with-keyboard, @desktop-portrait, @mobile-portrait {
|
@media @mobile-portrait-with-keyboard, @desktop-portrait, @mobile-portrait {
|
||||||
-webkit-order: 1;
|
-webkit-order: 1;
|
||||||
order: 1;
|
order: 1;
|
||||||
width: 100%;
|
width: 100% !important; // overrides any width value set manually in landscape
|
||||||
}
|
}
|
||||||
&:-webkit-full-screen {
|
&:-webkit-full-screen {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -126,6 +122,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.switchSlideButton {
|
.switchSlideButton {
|
||||||
|
outline: none;
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
@ -200,11 +197,12 @@
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: rgba(0, 0, 0, 0.2);
|
background: #3896D3;
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(0, 0, 0, 0.4);
|
background: #3A82D4;
|
||||||
}
|
}
|
||||||
&:focus {
|
&:focus {
|
||||||
|
background: #3896D3;
|
||||||
outline:0;
|
outline:0;
|
||||||
}
|
}
|
||||||
i {
|
i {
|
||||||
|
@ -22,13 +22,15 @@
|
|||||||
else
|
else
|
||||||
chatMessage.message?.from_userid
|
chatMessage.message?.from_userid
|
||||||
Tracker.autorun (comp) ->
|
Tracker.autorun (comp) ->
|
||||||
tabsTime = getInSession('tabsRenderedTime')
|
tabsTime = getInSession('userListRenderedTime')
|
||||||
if tabsTime? and chatMessage.message.from_userid isnt "SYSTEM_MESSAGE" and chatMessage.message.from_time - tabsTime > 0
|
if tabsTime? and chatMessage.message.from_userid isnt "SYSTEM_MESSAGE" and chatMessage.message.from_time - tabsTime > 0
|
||||||
populateChatTabs(chatMessage) # check if we need to open a new tab
|
populateNotifications(chatMessage) # check if we need to show a new notification
|
||||||
destinationTab = findDestinationTab()
|
destinationTab = findDestinationTab()
|
||||||
if destinationTab isnt getInSession "inChatWith"
|
if destinationTab isnt getInSession "inChatWith"
|
||||||
setInSession 'chatTabs', getInSession('chatTabs').map((tab) ->
|
setInSession 'chats', getInSession('chats').map((tab) ->
|
||||||
tab.gotMail = true if tab.userId is destinationTab
|
if tab.userId is destinationTab
|
||||||
|
tab.gotMail = true
|
||||||
|
tab.number++
|
||||||
tab
|
tab
|
||||||
)
|
)
|
||||||
comp.stop()
|
comp.stop()
|
||||||
@ -120,22 +122,51 @@ Template.chatbar.helpers
|
|||||||
return Meteor.Users.findOne({userId: getInSession('inChatWith')})?
|
return Meteor.Users.findOne({userId: getInSession('inChatWith')})?
|
||||||
|
|
||||||
# When chatbar gets rendered, launch the auto-check for unread chat
|
# When chatbar gets rendered, launch the auto-check for unread chat
|
||||||
Template.chatbar.rendered = -> detectUnreadChat()
|
Template.chatbar.rendered = ->
|
||||||
|
detectUnreadChat()
|
||||||
|
|
||||||
# When "< Public" is clicked, go to public chat
|
# When "< Public" is clicked, go to public chat
|
||||||
Template.chatbar.events
|
Template.chatbar.events
|
||||||
'click .toPublic': (event) ->
|
'click .toPublic': (event) ->
|
||||||
setInSession 'inChatWith', 'PUBLIC_CHAT'
|
setInSession 'inChatWith', 'PUBLIC_CHAT'
|
||||||
|
setInSession 'chats', getInSession('chats').map((chat) ->
|
||||||
|
if chat.userId is "PUBLIC_CHAT"
|
||||||
|
chat.gotMail = false
|
||||||
|
chat.number = 0
|
||||||
|
chat
|
||||||
|
)
|
||||||
|
|
||||||
|
Template.privateChatTab.rendered = ->
|
||||||
|
if isLandscape() or isPortrait()
|
||||||
|
$("#newMessageInput").focus()
|
||||||
|
|
||||||
# When message gets rendered, scroll to the bottom
|
# When message gets rendered, scroll to the bottom
|
||||||
Template.message.rendered = ->
|
Template.message.rendered = ->
|
||||||
$('#chatbody').scrollTop($('#chatbody')[0]?.scrollHeight)
|
$('#chatbody').scrollTop($('#chatbody')[0]?.scrollHeight)
|
||||||
false
|
false
|
||||||
|
|
||||||
|
Template.chatInput.rendered = ->
|
||||||
|
$('.panel-footer').resizable
|
||||||
|
handles: 'n'
|
||||||
|
minHeight: 70
|
||||||
|
resize: (event, ui) ->
|
||||||
|
if $('.panel-footer').css('top') is '0px'
|
||||||
|
$('.panel-footer').height(70) # prevents the element from shrinking vertically for 1-2 px
|
||||||
|
else
|
||||||
|
$('.panel-footer').css('top', parseInt($('.panel-footer').css('top')) + 1 + 'px')
|
||||||
|
$('#chatbody').height($('#chat').height() - $('.panel-footer').height() - 45)
|
||||||
|
$('#chatbody').scrollTop($('#chatbody')[0]?.scrollHeight)
|
||||||
|
start: (event, ui) ->
|
||||||
|
$('#newMessageInput').css('overflow', '')
|
||||||
|
$('.panel-footer').resizable('option', 'maxHeight', Math.max($('.panel-footer').height(), $('#chat').height() / 2))
|
||||||
|
stop: (event, ui) ->
|
||||||
|
setInSession 'chatInputMinHeight', $('.panel-footer').height() + 1
|
||||||
|
|
||||||
Template.chatInput.events
|
Template.chatInput.events
|
||||||
'click #sendMessageButton': (event) ->
|
'click #sendMessageButton': (event) ->
|
||||||
$('#sendMessageButton').blur()
|
$('#sendMessageButton').blur()
|
||||||
sendMessage()
|
sendMessage()
|
||||||
|
adjustChatInputHeight()
|
||||||
|
|
||||||
'keypress #newMessageInput': (event) -> # user pressed a button inside the chatbox
|
'keypress #newMessageInput': (event) -> # user pressed a button inside the chatbox
|
||||||
key = (if event.charCode then event.charCode else (if event.keyCode then event.keyCode else 0))
|
key = (if event.charCode then event.charCode else (if event.keyCode then event.keyCode else 0))
|
||||||
@ -152,6 +183,11 @@ Template.chatInput.events
|
|||||||
$('#newMessageInput').val("")
|
$('#newMessageInput').val("")
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
Template.chatInputControls.rendered = ->
|
||||||
|
$('#newMessageInput').on('keydown paste cut', () -> setTimeout(() ->
|
||||||
|
adjustChatInputHeight()
|
||||||
|
, 0))
|
||||||
|
|
||||||
Template.message.helpers
|
Template.message.helpers
|
||||||
sanitizeAndFormat: (str) ->
|
sanitizeAndFormat: (str) ->
|
||||||
if typeof str is 'string'
|
if typeof str is 'string'
|
||||||
|
@ -2,13 +2,7 @@
|
|||||||
<div id="{{id}}" {{visibility name}} class="component">
|
<div id="{{id}}" {{visibility name}} class="component">
|
||||||
<div class="chatBodyContainer">
|
<div class="chatBodyContainer">
|
||||||
{{#if inPrivateChat}}
|
{{#if inPrivateChat}}
|
||||||
<div class="privateChatTab">
|
{{> privateChatTab}}
|
||||||
{{> makeButton id="close" btn_class="secondary tiny round toPublic " i_class="ion-ios-arrow-left" rel="tooltip"
|
|
||||||
data_placement="bottom" title="Back to public" label="Public"}}
|
|
||||||
<div class="privateChatName">
|
|
||||||
{{privateChatName}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<div id="chatbody">
|
<div id="chatbody">
|
||||||
<ul class="chat" {{messageFontSize}}>
|
<ul class="chat" {{messageFontSize}}>
|
||||||
@ -27,6 +21,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template name="privateChatTab">
|
||||||
|
<div class="privateChatTab">
|
||||||
|
{{> makeButton id="close" btn_class="secondary tiny toPublic " i_class="ion-ios-arrow-left" rel="tooltip"
|
||||||
|
data_placement="bottom" title="Back to public" label="Public" notification="PUBLIC_CHAT"}}
|
||||||
|
<div class="privateChatName">
|
||||||
|
{{privateChatName}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template name="chatInput">
|
<template name="chatInput">
|
||||||
<div id="chatInput" class="chat-input-wrapper">
|
<div id="chatInput" class="chat-input-wrapper">
|
||||||
{{#if inPrivateChat}}
|
{{#if inPrivateChat}}
|
||||||
|
@ -46,12 +46,12 @@
|
|||||||
|
|
||||||
<div class="bar bottomBar">
|
<div class="bar bottomBar">
|
||||||
<a href="#" class="closeSettings close-reveal-modal"><u>Cancel</u></a>
|
<a href="#" class="closeSettings close-reveal-modal"><u>Cancel</u></a>
|
||||||
{{> makeButton id="saveSettings" btn_class="settingsButton" rel="tooltip" title="Save Changes" text="Save"}}
|
{{> makeButton id="saveSettings" btn_class="settingsButton" rel="tooltip" title="Save Changes" label="Save"}}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template name="logoutModal">
|
<template name="logoutModal">
|
||||||
<p>Are you sure you want to logout?</p>
|
<p>Are you sure you want to logout?</p>
|
||||||
{{> makeButton id="yes" btn_class="logoutButton" rel="tooltip" title="Logout" text="Yes"}}
|
{{> makeButton id="yes" btn_class="logoutButton" rel="tooltip" title="Logout" label="Yes"}}
|
||||||
{{> makeButton id="no" btn_class="logoutButton" rel="tooltip" title="Logout" text="No"}}
|
{{> makeButton id="no" btn_class="logoutButton" rel="tooltip" title="Logout" label="No"}}
|
||||||
</template>
|
</template>
|
||||||
|
33
bigbluebutton-html5/app/client/views/sharedTemplates.coffee
Executable file
33
bigbluebutton-html5/app/client/views/sharedTemplates.coffee
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
Template.makeButton.helpers
|
||||||
|
hasGotUnreadMail: (userId) ->
|
||||||
|
chats = getInSession('chats')
|
||||||
|
if chats isnt undefined
|
||||||
|
if userId is "all_chats"
|
||||||
|
for tabs in chats
|
||||||
|
if tabs.gotMail is true
|
||||||
|
return true
|
||||||
|
else if userId is "PUBLIC_CHAT"
|
||||||
|
for tabs in chats
|
||||||
|
if tabs.userId is userId and tabs.gotMail is true
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
|
||||||
|
getNumberOfUnreadMessages: (userId) ->
|
||||||
|
if userId is "all_chats"
|
||||||
|
return
|
||||||
|
else
|
||||||
|
chats = getInSession('chats')
|
||||||
|
if chats isnt undefined
|
||||||
|
for chat in chats
|
||||||
|
if chat.userId is userId and chat.gotMail
|
||||||
|
if chat.number > 9
|
||||||
|
return "9+"
|
||||||
|
else
|
||||||
|
return chat.number
|
||||||
|
return
|
||||||
|
|
||||||
|
getNotificationClass: (userId) ->
|
||||||
|
if userId is "all_chats"
|
||||||
|
return "unreadChat"
|
||||||
|
if userId is "PUBLIC_CHAT"
|
||||||
|
return "unreadChatNumber"
|
@ -1,11 +1,18 @@
|
|||||||
<template name="makeButton">
|
<template name="makeButton">
|
||||||
<button type="submit" id="{{id}}" class="btn {{btn_class}}" {{isDisabled}} rel="{{rel}}" data-placement="{{data_placement}}" title="{{title}}" style="{{style}}">
|
<button type="submit" id="{{id}}" class="btn {{btn_class}}" {{isDisabled}} rel="{{rel}}" data-placement="{{data_placement}}" title="{{title}}" style="{{style}}">
|
||||||
{{#if text}}
|
{{#if notification}}
|
||||||
<span>{{text}}</span>
|
{{#if hasGotUnreadMail notification }}
|
||||||
{{else}}
|
<div class="{{getNotificationClass notification}}">{{getNumberOfUnreadMessages notification}}</div>
|
||||||
{{#if i_class}}
|
|
||||||
<i class="{{i_class}}"></i><span>{{label}}</span>
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</button>
|
{{/if}}
|
||||||
|
{{#if i_class}}
|
||||||
|
<i class="{{i_class}}"></i>
|
||||||
|
{{/if}}
|
||||||
|
{{#if label}}
|
||||||
|
<span>{{label}}</span>
|
||||||
|
{{/if}}
|
||||||
|
{{#if span}}
|
||||||
|
<span></span>
|
||||||
|
{{/if}}
|
||||||
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
@ -26,5 +26,49 @@ Template.displayUserIcons.helpers
|
|||||||
Template.usernameEntry.events
|
Template.usernameEntry.events
|
||||||
'click .usernameEntry': (event) ->
|
'click .usernameEntry': (event) ->
|
||||||
userIdSelected = @.userId
|
userIdSelected = @.userId
|
||||||
unless userIdSelected is null or userIdSelected is BBB.getCurrentUser()?.userId
|
unless userIdSelected is null
|
||||||
setInSession "inChatWith", userIdSelected
|
if userIdSelected is BBB.getCurrentUser()?.userId
|
||||||
|
setInSession "inChatWith", "PUBLIC_CHAT"
|
||||||
|
else
|
||||||
|
setInSession "inChatWith", userIdSelected
|
||||||
|
if isLandscape()
|
||||||
|
$("#newMessageInput").focus()
|
||||||
|
if isPortrait() or isPortraitMobile()
|
||||||
|
toggleUsersList()
|
||||||
|
$("#newMessageInput").focus()
|
||||||
|
|
||||||
|
'click .gotUnreadMail': (event) ->
|
||||||
|
_this = @
|
||||||
|
currentId = getInSession('userId')
|
||||||
|
if currentId isnt undefined and currentId is _this.userId
|
||||||
|
_id = "PUBLIC_CHAT"
|
||||||
|
else
|
||||||
|
_id = _this.userId
|
||||||
|
chats = getInSession('chats')
|
||||||
|
if chats isnt undefined
|
||||||
|
for chat in chats
|
||||||
|
if chat.userId is _id
|
||||||
|
chat.gotMail = false
|
||||||
|
chat.number = 0
|
||||||
|
break
|
||||||
|
setInSession 'chats', chats
|
||||||
|
|
||||||
|
Template.usernameEntry.helpers
|
||||||
|
hasGotUnreadMailClass: (userId) ->
|
||||||
|
chats = getInSession('chats')
|
||||||
|
if chats isnt undefined
|
||||||
|
for chat in chats
|
||||||
|
if chat.userId is userId and chat.gotMail
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
|
||||||
|
getNumberOfUnreadMessages: (userId) ->
|
||||||
|
chats = getInSession('chats')
|
||||||
|
if chats isnt undefined
|
||||||
|
for chat in chats
|
||||||
|
if chat.userId is userId and chat.gotMail
|
||||||
|
if chat.number > 9
|
||||||
|
return "9+"
|
||||||
|
else
|
||||||
|
return chat.number
|
||||||
|
return
|
||||||
|
@ -54,38 +54,50 @@
|
|||||||
<i class="icon fi-lock usericon"></i>
|
<i class="icon fi-lock usericon"></i>
|
||||||
</span>
|
</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if user.presenter}}
|
|
||||||
<span rel="tooltip" data-placement="bottom" title="{{user.name}} is the presenter">
|
|
||||||
<i class="icon fi-projection-screen usericon"></i>
|
|
||||||
</span>
|
|
||||||
{{else}}
|
|
||||||
{{#if equals user.role "MODERATOR"}}
|
|
||||||
<span rel="tooltip" data-placement="bottom" title="{{user.name}} is a moderator">
|
|
||||||
<i class="icon fi-torso usericon"></i>
|
|
||||||
</span>
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{#if user.raise_hand}}
|
|
||||||
{{#if isCurrentUser userId}}
|
|
||||||
<span class="ion-android-hand usericon" rel="tooltip" data-placement="bottom" title="Lower your hand"></span>
|
|
||||||
{{else}}
|
|
||||||
<span class="ion-android-hand usericon" rel="tooltip" data-placement="bottom" title="{{user.name}} has raised their hand"></span>
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template name="usernameEntry">
|
<template name="usernameEntry">
|
||||||
{{#if isCurrentUser userId}}
|
<div class="status">
|
||||||
<span class="userCurrent usernameEntry" rel="tooltip" data-placement="bottom" title="{{user.name}} (you)">
|
{{#if user.raise_hand}}
|
||||||
{{user.name}} {{#if user.presenter}} (presenter) {{/if}} (you)
|
{{#if isCurrentUser userId}}
|
||||||
</span>
|
<span rel="tooltip" data-placement="bottom" title="Lower your hand">
|
||||||
{{else}}
|
<i class="icon ion-android-hand statusIcon"></i>
|
||||||
<span class="usernameEntry" rel="tooltip" data-placement="bottom" title="{{user.name}}">
|
</span>
|
||||||
{{user.name}} {{#if user.presenter}} (presenter) {{/if}}
|
{{else}}
|
||||||
</span>
|
<span rel="tooltip" data-placement="bottom" title="{{user.name}} has raised their hand">
|
||||||
{{/if}}
|
<i class="icon ion-android-hand statusIcon"></i>
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
{{#if user.presenter}}
|
||||||
|
<span rel="tooltip" data-placement="bottom" title="{{user.name}} is the presenter">
|
||||||
|
<i class="icon fi-projection-screen statusIcon"></i>
|
||||||
|
</span>
|
||||||
|
{{else}}
|
||||||
|
{{#if equals user.role "MODERATOR"}}
|
||||||
|
<span rel="tooltip" data-placement="bottom" title="{{user.name}} is a moderator">
|
||||||
|
<i class="icon fi-torso statusIcon"></i>
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if isCurrentUser userId}}
|
||||||
|
<span class="userCurrent usernameEntry {{#if hasGotUnreadMailClass 'PUBLIC_CHAT'}}gotUnreadMail{{/if}}" rel="tooltip" data-placement="bottom" title="{{user.name}} (you)">
|
||||||
|
<span class="userName">{{user.name}} {{#if user.presenter}} (presenter) {{/if}} (you)</span>
|
||||||
|
</span>
|
||||||
|
{{#if hasGotUnreadMailClass 'PUBLIC_CHAT' }}
|
||||||
|
<div class="unreadChatNumber">{{getNumberOfUnreadMessages 'PUBLIC_CHAT'}}</div>
|
||||||
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
<span class="usernameEntry {{#if hasGotUnreadMailClass user.userid}}gotUnreadMail{{/if}}" rel="tooltip" data-placement="bottom" title="{{user.name}}">
|
||||||
|
<span class="userName"> {{user.name}} {{#if user.presenter}} (presenter) {{/if}}</span>
|
||||||
|
</span>
|
||||||
|
{{#if hasGotUnreadMailClass user.userid }}
|
||||||
|
<div class="unreadChatNumber">{{getNumberOfUnreadMessages user.userid}}</div>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template name="userItem">
|
<template name="userItem">
|
||||||
|
@ -5,6 +5,14 @@ Template.usersList.helpers
|
|||||||
return "Users: #{numberUsers}"
|
return "Users: #{numberUsers}"
|
||||||
# do not display the label if there are just a few users
|
# do not display the label if there are just a few users
|
||||||
|
|
||||||
Template.usersList.events
|
Template.usersList.rendered = ->
|
||||||
"click .closeUserlistIcon": (event, template) ->
|
$('.sl-left-drawer').resizable
|
||||||
toggleUsersList()
|
handles: 'e'
|
||||||
|
maxWidth: 600
|
||||||
|
minWidth: 200
|
||||||
|
resize: () ->
|
||||||
|
adjustChatInputHeight()
|
||||||
|
Tracker.autorun (comp) ->
|
||||||
|
setInSession 'userListRenderedTime', TimeSync.serverTime()
|
||||||
|
if getInSession('userListRenderedTime') isnt undefined
|
||||||
|
comp.stop()
|
||||||
|
@ -2,11 +2,6 @@
|
|||||||
<div id="{{id}}" {{visibility name}} class="component {{class}}">
|
<div id="{{id}}" {{visibility name}} class="component {{class}}">
|
||||||
<h3 class="meetingTitle">
|
<h3 class="meetingTitle">
|
||||||
{{getMeetingName}}
|
{{getMeetingName}}
|
||||||
<span class="closeUserlistIcon">
|
|
||||||
<a href="#">
|
|
||||||
<i class="closeSettings close-reveal-modal">×</i>
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
</h3>
|
</h3>
|
||||||
<div id="user-contents">
|
<div id="user-contents">
|
||||||
<div class="userlist ScrollableWindowY">
|
<div class="userlist ScrollableWindowY">
|
||||||
|
@ -6,7 +6,8 @@ Template.slide.rendered = ->
|
|||||||
setInSession 'slideOriginalHeight', this.height
|
setInSession 'slideOriginalHeight', this.height
|
||||||
$(window).resize( ->
|
$(window).resize( ->
|
||||||
# redraw the whiteboard to adapt to the resized window
|
# redraw the whiteboard to adapt to the resized window
|
||||||
redrawWhiteboard()
|
if !$('.panel-footer').hasClass('ui-resizable-resizing') # not in the middle of resizing the message input
|
||||||
|
redrawWhiteboard()
|
||||||
)
|
)
|
||||||
if currentSlide?.slide?.png_uri?
|
if currentSlide?.slide?.png_uri?
|
||||||
createWhiteboardPaper (wpm) ->
|
createWhiteboardPaper (wpm) ->
|
||||||
|
@ -46,3 +46,18 @@ Template.whiteboard.events
|
|||||||
|
|
||||||
'click .lowerHand': (event) ->
|
'click .lowerHand': (event) ->
|
||||||
BBB.lowerHand(BBB.getMeetingId(), getInSession('userId'), getInSession('userId'), getInSession('authToken'))
|
BBB.lowerHand(BBB.getMeetingId(), getInSession('userId'), getInSession('userId'), getInSession('authToken'))
|
||||||
|
|
||||||
|
Template.whiteboard.rendered = ->
|
||||||
|
$('#whiteboard').resizable
|
||||||
|
handles: 'e'
|
||||||
|
minWidth: 150
|
||||||
|
resize: () ->
|
||||||
|
adjustChatInputHeight()
|
||||||
|
start: () ->
|
||||||
|
if $('#chat').width() / $('#panels').width() > 0.2 # chat shrinking can't make it smaller than one fifth of the whiteboard-chat area
|
||||||
|
$('#whiteboard').resizable('option', 'maxWidth', $('#panels').width() - 200) # gives the chat enough space (200px)
|
||||||
|
else
|
||||||
|
$('#whiteboard').resizable('option', 'maxWidth', $('#whiteboard').width())
|
||||||
|
stop: () ->
|
||||||
|
$('#whiteboard').css('width', 100 * $('#whiteboard').width() / $('#panels').width() + '%') # transforms width to %
|
||||||
|
$('#whiteboard').resizable('option', 'maxWidth', null)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template name="whiteboard">
|
<template name="whiteboard">
|
||||||
<div id="{{id}}" {{visibility name}} class="component gradientBar">
|
<div id="{{id}}" {{visibility name}} class="component">
|
||||||
{{#each getCurrentSlide}}
|
{{#each getCurrentSlide}}
|
||||||
{{> slide}}
|
{{> slide}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
@ -103,8 +103,12 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper {
|
|||||||
r.setPlaybackFormat(rec.playback.format.text());
|
r.setPlaybackFormat(rec.playback.format.text());
|
||||||
r.setPlaybackLink(rec.playback.link.text());
|
r.setPlaybackLink(rec.playback.link.text());
|
||||||
r.setPlaybackDuration(rec.playback.duration.text());
|
r.setPlaybackDuration(rec.playback.duration.text());
|
||||||
r.setPlaybackExtensions(rec.playback.extension.children());
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Commenting this out to see if this is causing memory to hang around resulting in
|
||||||
|
OOM in tomcat7 (ralam july 23, 2015)
|
||||||
|
r.setPlaybackExtensions(rec.playback.extension.children());
|
||||||
|
*/
|
||||||
Map<String, String> meta = new HashMap<String, String>();
|
Map<String, String> meta = new HashMap<String, String>();
|
||||||
rec.meta.children().each { anode ->
|
rec.meta.children().each { anode ->
|
||||||
log.debug("metadata: "+anode.name()+" "+anode.text())
|
log.debug("metadata: "+anode.name()+" "+anode.text())
|
||||||
|
@ -201,7 +201,9 @@ public class DeskShareApplet extends JApplet implements ClientListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onClientStop(ExitCode reason) {
|
public void onClientStop(ExitCode reason) {
|
||||||
// determine if client is disconnected _PTS_272_
|
client.stop();
|
||||||
|
|
||||||
|
/*
|
||||||
if ( ExitCode.CONNECTION_TO_DESKSHARE_SERVER_DROPPED == reason ){
|
if ( ExitCode.CONNECTION_TO_DESKSHARE_SERVER_DROPPED == reason ){
|
||||||
JFrame pframe = new JFrame("Desktop Sharing Disconneted");
|
JFrame pframe = new JFrame("Desktop Sharing Disconneted");
|
||||||
if ( null != pframe ){
|
if ( null != pframe ){
|
||||||
@ -215,6 +217,7 @@ public class DeskShareApplet extends JApplet implements ClientListener {
|
|||||||
}else{
|
}else{
|
||||||
client.stop();
|
client.stop();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user