private chat

git-svn-id: http://bigbluebutton.googlecode.com/svn/trunk@1876 af16638f-c34d-0410-8cfa-b39d5352b314
This commit is contained in:
Denis Zgonjanin 2009-07-13 19:53:21 +00:00
parent b73165bc22
commit 71dc224eef
16 changed files with 376 additions and 33 deletions

View File

@ -69,5 +69,8 @@ package org.bigbluebutton.common.messaging
public static const STARTED_BROADCAST:String = 'STARTED_BROADCAST';
public static const STOPPED_BROADCAST:String = 'STOPPED_BROADCAST';
public static const VIEW_CAMERA:String = 'VIEW_CAMERA';
public static const NEW_PARTICIPANT:String = 'NEW_PARTICIPANT';
public static const PARTICIPANT_LEFT:String = 'PARTICIPANT_LEFT';
}
}

View File

@ -28,8 +28,6 @@ package org.bigbluebutton.main
import org.puremvc.as3.multicore.patterns.mediator.Mediator;
import org.puremvc.as3.multicore.utilities.pipes.interfaces.IPipeMessage;
import mx.logging.Log;
public class MainEndpointMediator extends Mediator implements IMediator
{
public static const NAME:String = "MainEndpointMediator";

View File

@ -108,6 +108,14 @@ package org.bigbluebutton.modules.chat
//LogUtil.debug('Received OPEN_WINDOW message from ' + message.getHeader().SRC);
//facade.sendNotification(ChatModuleConstants.OPEN_WINDOW);
break;
case EndpointMessageConstants.NEW_PARTICIPANT:
var userToAdd:Object = message.getBody(); //Has username, userid, userrole parameters
facade.sendNotification(ChatModuleConstants.ADD_PARTICIPANT, userToAdd.username as String);
break;
case EndpointMessageConstants.PARTICIPANT_LEFT:
var userToRemove:Object = message.getBody();
facade.sendNotification(ChatModuleConstants.REMOVE_PARTICIPANT, userToRemove.username as String);
break;
}
}

View File

@ -20,6 +20,7 @@
package org.bigbluebutton.modules.chat
{
import org.bigbluebutton.common.IBigBlueButtonModule;
import org.bigbluebutton.modules.chat.controller.OpenChatBoxCommand;
import org.bigbluebutton.modules.chat.controller.StartupCommand;
import org.bigbluebutton.modules.chat.controller.StopCommand;
import org.puremvc.as3.multicore.interfaces.IFacade;
@ -52,6 +53,7 @@ package org.bigbluebutton.modules.chat
super.initializeController();
registerCommand(STARTUP, StartupCommand);
registerCommand(STOP, StopCommand);
registerCommand(ChatModuleConstants.OPEN_CHAT_BOX, OpenChatBoxCommand);
}

View File

@ -32,5 +32,10 @@ package org.bigbluebutton.modules.chat
public static const CLOSE_WINDOW:String = 'CLOSE_WINDOW';
public static const ADD_WINDOW:String = 'ADD_WINDOW';
public static const REMOVE_WINDOW:String = 'REMOVE_WINDOW';
public static const OPEN_CHAT_BOX:String = "OPEN_CHAT_BOX";
public static const ADD_PARTICIPANT:String = "ADD_PARTICIPANT";
public static const REMOVE_PARTICIPANT:String = "REMOVE_PARTICIPANT";
public static const NEW_PRIVATE_MESSAGE:String = "NEW_PRIVATE_MESSAGE";
}
}

View File

@ -0,0 +1,17 @@
package org.bigbluebutton.modules.chat.controller
{
import org.bigbluebutton.modules.chat.view.ChatBoxMediator;
import org.bigbluebutton.modules.chat.view.components.ChatBox;
import org.puremvc.as3.multicore.interfaces.INotification;
import org.puremvc.as3.multicore.patterns.command.SimpleCommand;
public class OpenChatBoxCommand extends SimpleCommand
{
override public function execute(notification:INotification):void{
var box:ChatBox = notification.getBody() as ChatBox;
facade.registerMediator(new ChatBoxMediator(box));
}
}
}

View File

@ -23,6 +23,7 @@ package org.bigbluebutton.modules.chat.controller
import org.bigbluebutton.modules.chat.ChatModuleConstants;
import org.bigbluebutton.modules.chat.ChatModuleMediator;
import org.bigbluebutton.modules.chat.model.business.ChatProxy;
import org.bigbluebutton.modules.chat.model.business.PrivateProxy;
import org.bigbluebutton.modules.chat.view.ChatWindowMediator;
import org.puremvc.as3.multicore.interfaces.ICommand;
import org.puremvc.as3.multicore.interfaces.INotification;
@ -37,6 +38,7 @@ package org.bigbluebutton.modules.chat.controller
facade.registerMediator(new ChatEndpointMediator(m));
facade.registerMediator( new ChatWindowMediator(m) );
facade.registerProxy(new ChatProxy(m));
facade.registerProxy(new PrivateProxy(m));
sendNotification(ChatModuleConstants.CONNECTED);
}
}

View File

@ -0,0 +1,17 @@
package org.bigbluebutton.modules.chat.model
{
public class MessageVO
{
public var message:String;
public var recepient:String;
public var sender:String;
public function MessageVO(message:String, sender:String, recepient:String)
{
this.message = message;
this.recepient = recepient;
this.sender = sender;
}
}
}

View File

@ -0,0 +1,118 @@
package org.bigbluebutton.modules.chat.model.business
{
import flash.events.SyncEvent;
import flash.net.NetConnection;
import flash.net.Responder;
import flash.net.SharedObject;
import mx.controls.Alert;
import org.bigbluebutton.common.red5.ConnectionEvent;
import org.bigbluebutton.modules.chat.ChatModuleConstants;
import org.bigbluebutton.modules.chat.model.MessageVO;
import org.bigbluebutton.modules.chat.view.ChatBoxMediator;
import org.bigbluebutton.modules.chat.view.components.ChatBox;
import org.puremvc.as3.multicore.interfaces.IProxy;
import org.puremvc.as3.multicore.patterns.proxy.Proxy;
public class PrivateProxy extends Proxy implements IProxy
{
public static const NAME:String = "PrivateProxy";
private var _module:ChatModule;
private var nc:NetConnection;
private var chatSO:SharedObject;
private var participantsSO:SharedObject;
private var privateResponder:Responder;
private var participantsResponder:Responder;
public function PrivateProxy(module:ChatModule)
{
super(NAME);
this._module = module;
nc = _module.connection;
chatSO = SharedObject.getRemote(_module.username, _module.uri, false);
chatSO.addEventListener(SyncEvent.SYNC, sharedObjectSyncHandler);
chatSO.client = this;
chatSO.connect(nc);
//participantsSO = SharedObject.getRemote("participantsSO", _module.uri, false);
//participantsSO.client = this;
//participantsSO.connect(nc);
privateResponder = new Responder(
function(result:Object):void{
LogUtil.debug("Successfully called chat server private message");
},
function(status:Object):void{
LogUtil.error("Error while trying to call privateMessage on server");
}
);
participantsResponder = new Responder(
// participants - On successful result
function(result:Object):void {
LogUtil.debug("Successfully queried participants: " + result.count);
if (result.count > 0) {
for(var p:Object in result.participants)
{
participantJoined(result.participants[p]);
}
}
},
// status - On error occurred
function(status:Object):void {
LogUtil.error("Error occurred:");
for (var x:Object in status) {
LogUtil.error(x + " : " + status[x]);
}
LogUtil.error("Error in participantsResponder call");
}
)
queryForParticipants();
}
private function onConnectionSuccess(e:ConnectionEvent):void{
}
private function onConnectionFailed(e:ConnectionEvent):void{
Alert.show("connection failed to " + _module.uri + " with message " + e.toString());
}
private function onConnectionRejected(e:ConnectionEvent):void{
Alert.show("connection rejected to " + _module.uri + " with message " + e.toString());
}
private function sharedObjectSyncHandler(e:SyncEvent):void{
}
public function sendMessage(message:MessageVO):void{
nc.call("chat.privateMessage", privateResponder, message.message, message.sender , message.recepient);
}
public function messageReceived(from:String, message:String):void{
sendNotification(ChatModuleConstants.NEW_PRIVATE_MESSAGE, new MessageVO(message, from, _module.username));
}
public function participantJoined(joinedUser:Object):void {
//Alert.show("new participant joined");
var userName:String = joinedUser.name;
var userid:String = joinedUser.userid;
var userRole:String = joinedUser.userRole;
LogUtil.info("Joined as [" + userid + "," + userName + "," + userRole + "]");
sendNotification(ChatModuleConstants.ADD_PARTICIPANT, userName);
}
private function queryForParticipants():void {
nc.call("participants.getParticipants",participantsResponder);
}
}
}

View File

@ -0,0 +1,35 @@
package org.bigbluebutton.modules.chat.view
{
import org.bigbluebutton.modules.chat.view.components.ChatBox;
import org.puremvc.as3.multicore.interfaces.IMediator;
import org.puremvc.as3.multicore.interfaces.INotification;
import org.puremvc.as3.multicore.patterns.mediator.Mediator;
public class ChatBoxMediator extends Mediator implements IMediator
{
public function ChatBoxMediator(chatBox:ChatBox)
{
super(chatBox.id, chatBox);
chatBox.label = chatBox.id;
}
public function get chatBox():ChatBox{
return viewComponent as ChatBox;
}
override public function listNotificationInterests():Array{
return [];
}
override public function handleNotification(notification:INotification):void{
}
public function showMessage(message:String):void{
chatBox.showNewMessage(message);
chatBox.setMessageUnread();
}
}
}

View File

@ -21,8 +21,13 @@ package org.bigbluebutton.modules.chat.view
{
import flash.events.Event;
import mx.core.Container;
import org.bigbluebutton.modules.chat.ChatModuleConstants;
import org.bigbluebutton.modules.chat.model.MessageVO;
import org.bigbluebutton.modules.chat.model.business.ChatProxy;
import org.bigbluebutton.modules.chat.model.business.PrivateProxy;
import org.bigbluebutton.modules.chat.view.components.ChatBox;
import org.bigbluebutton.modules.chat.view.components.ChatWindow;
import org.puremvc.as3.multicore.interfaces.IMediator;
import org.puremvc.as3.multicore.interfaces.INotification;
@ -45,6 +50,7 @@ package org.bigbluebutton.modules.chat.view
_chatWindow = new ChatWindow();
_chatWindow.name = _module.username;
_chatWindow.addEventListener(ChatWindow.SEND_MESSAGE, onSendChatMessage);
_chatWindow.addEventListener(ChatModuleConstants.OPEN_CHAT_BOX, onOpenChatBox);
}
private function time() : String
@ -59,16 +65,43 @@ package org.bigbluebutton.modules.chat.view
var newMessage:String;
newMessage = "<font color=\"#" + _chatWindow.cmpColorPicker.selectedColor.toString(16) + "\"><b>[" +
_module.username +" - "+ time()+ "]</b> " + _chatWindow.txtMsg.text + "</font><br/>";
proxy.sendMessage(newMessage);
if (_chatWindow.tabNav.selectedChild.id == "Public") proxy.sendMessage(newMessage);
else{
var privateMessage:MessageVO = new MessageVO(newMessage, _module.username as String, _chatWindow.tabNav.selectedChild.id);
privateProxy.sendMessage(privateMessage);
(_chatWindow.tabNav.selectedChild as ChatBox).showNewMessage(newMessage);
}
_chatWindow.txtMsg.text = "";
}
public function onOpenChatBox(e:Event):void{
var name:String = _chatWindow.participantList.selectedItem.label;
if (_chatWindow.tabNav.getChildByName(name) != null){
_chatWindow.tabNav.selectedChild = _chatWindow.tabNav.getChildByName(name) as Container;
return;
}
var chatBox:ChatBox = new ChatBox();
chatBox.id = name;
chatBox.name = name;
sendNotification(ChatModuleConstants.OPEN_CHAT_BOX, chatBox);
_chatWindow.tabNav.selectedChild = chatBox;
//chatBox.boxButton = _chatWindow.tabNav.getTabAt(_chatWindow.tabNav.getChildIndex(_chatWindow.tabNav.getChildByName(name)));
}
override public function listNotificationInterests():Array
{
return [
ChatModuleConstants.NEW_MESSAGE,
ChatModuleConstants.CLOSE_WINDOW,
ChatModuleConstants.OPEN_WINDOW
ChatModuleConstants.OPEN_WINDOW,
ChatModuleConstants.ADD_PARTICIPANT,
ChatModuleConstants.OPEN_CHAT_BOX,
ChatModuleConstants.REMOVE_PARTICIPANT,
ChatModuleConstants.NEW_PRIVATE_MESSAGE
];
}
@ -82,7 +115,8 @@ package org.bigbluebutton.modules.chat.view
switch(notification.getName())
{
case ChatModuleConstants.NEW_MESSAGE:
_chatWindow.showNewMessage(notification.getBody() as String);
var publicChat:ChatBox = _chatWindow.tabNav.getChildByName("Public") as ChatBox;
publicChat.showNewMessage(notification.getBody() as String);
break;
case ChatModuleConstants.CLOSE_WINDOW:
if (_chatWindowOpen) {
@ -91,8 +125,6 @@ package org.bigbluebutton.modules.chat.view
}
break;
case ChatModuleConstants.OPEN_WINDOW:
_chatWindow.width = 250;
_chatWindow.height = 220;
_chatWindow.title = "Group Chat";
_chatWindow.showCloseButton = false;
_chatWindow.xPosition = 675;
@ -100,12 +132,42 @@ package org.bigbluebutton.modules.chat.view
facade.sendNotification(ChatModuleConstants.ADD_WINDOW, _chatWindow);
_chatWindowOpen = true;
break;
case ChatModuleConstants.ADD_PARTICIPANT:
_chatWindow.addParticipant(notification.getBody() as String);
break;
case ChatModuleConstants.OPEN_CHAT_BOX:
_chatWindow.tabNav.addChild(notification.getBody() as ChatBox);
break;
case ChatModuleConstants.REMOVE_PARTICIPANT:
_chatWindow.removeParticipant(notification.getName() as String);
break;
case ChatModuleConstants.NEW_PRIVATE_MESSAGE:
showPrivateMessage(notification.getBody() as MessageVO);
break;
}
}
public function get proxy():ChatProxy
{
return facade.retrieveProxy(ChatProxy.NAME) as ChatProxy;
}
}
public function get privateProxy():PrivateProxy{
return facade.retrieveProxy(PrivateProxy.NAME) as PrivateProxy;
}
public function showPrivateMessage(message:MessageVO):void{
var privateBox:ChatBoxMediator = facade.retrieveMediator(message.sender) as ChatBoxMediator;
if (privateBox == null) {
var chatBox:ChatBox = new ChatBox();
chatBox.id = message.sender;
chatBox.name = message.sender;
sendNotification(ChatModuleConstants.OPEN_CHAT_BOX, chatBox);
chatBox.boxButton = _chatWindow.tabNav.getTabAt(_chatWindow.tabNav.numChildren-1);
privateBox = facade.retrieveMediator(message.sender) as ChatBoxMediator;
}
if (_chatWindow.tabNav.selectedChild.name != message.sender) _chatWindow.setMessageUnread(message.sender);
privateBox.showMessage(message.message);
}
}
}

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" click="setMessageRead()">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.controls.Button;
public var read:Boolean = true;
[Bindable]
private var backgroundColor:uint = 0x000000;
private var _boxButton:Button;
private function updateScroll():void{
txtChatBox.verticalScrollPosition = txtChatBox.maxVerticalScrollPosition;
}
public function showNewMessage(message:String):void
{
txtChatBox.htmlText += message;
}
public function setMessageUnread():void{
this.read = false;
backgroundColor = 0xFFFF00;
}
public function setMessageRead():void{
this.read = true;
backgroundColor = 0x000000;
}
public function set boxButton(button:Button):void{
this._boxButton = button;
}
]]>
</mx:Script>
<mx:TextArea id="txtChatBox" editable="false" width="100%" height="100%" focusEnabled="false" updateComplete="updateScroll()" />
</mx:VBox>

View File

@ -15,21 +15,23 @@
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, If not, see <http://www.gnu.org/licenses/>.
with BigBlueButton; If not, see <http://www.gnu.org/licenses/>.
$Id: $
-->
<MDIWindow xmlns="flexlib.mdi.containers.*"
xmlns:mx="http://www.adobe.com/2006/mxml"
width="300" height="300" showCloseButton="false"
click="setFocusOn(this.txtMsg || this.txtChatBox)"
width="600" height="300" showCloseButton="false"
focusEnd="setFocusOff()"
creationComplete="init()"
implements="org.bigbluebutton.common.IBbbModuleWindow">
implements="org.bigbluebutton.common.IBbbModuleWindow" xmlns:components="org.bigbluebutton.modules.chat.view.components.*">
<mx:Script>
<![CDATA[
import org.bigbluebutton.modules.chat.ChatModuleConstants;
import org.bigbluebutton.modules.chat.view.ChatWindowMediator;
import mx.collections.ArrayCollection;
import org.bigbluebutton.modules.chat.view.SendMessageEvent;
import mx.core.Application;
import mx.events.MenuEvent;
@ -42,14 +44,13 @@
private var _xPosition:int;
private var _yPosition:int;
[Bindable]
private var participants:ArrayCollection = new ArrayCollection();
private function init():void{
}
public function showNewMessage(message:String):void
{
txtChatBox.htmlText += message;
addParticipant("Public");
dispatchEvent(new Event(ChatModuleConstants.OPEN_CHAT_BOX));
}
public function setFocusOn(component:UIComponent):void
@ -77,20 +78,10 @@
public function sendMessages():void
{
if (txtMsg.text.length > 1000)
{
txtChatBox.htmlText += "Your message is too long!" +
" There is a limit of maximum 1000 character per message." + "\n";
return;
} else if (txtMsg.text != ""){
if (txtMsg.text != ""){
dispatchEvent(new SendMessageEvent(SEND_MESSAGE));
}
}
private function updateScroll():void
{
txtChatBox.verticalScrollPosition = txtChatBox.maxVerticalScrollPosition;
}
public function get xPosition():int {
@ -108,13 +99,39 @@
public function set yPosition(y:int):void {
_yPosition = y;
}
public function addParticipant(name:String):void{
var item:Object = new Object();
item.label = name;
participants.addItem(item);
}
public function removeParticipant(name:String):void{
tabNav.removeChild(tabNav.getChildByName(name));
var item:Object = new Object();
item.label = name;
participants.removeItemAt(participants.getItemIndex(item));
}
public function setMessageUnread(name:String):void{
var tab:Button = tabNav.getTabAt(tabNav.getChildIndex(tabNav.getChildByName(name)));
tab.setStyle("fillColors", new Array(0xFFFF00, 0xcccc66));
}
private function setMessageRead():void{
var tab:Button = tabNav.getTabAt(tabNav.selectedIndex);
tab.setStyle("fillColors", new Array(0xFFFFFF, 0xCCCCCC));
}
]]>
</mx:Script>
<mx:TextArea id="txtChatBox" editable="false" width="100%" height="100%" focusEnabled="false" updateComplete="updateScroll()"/>
<mx:TabNavigator id="tabNav" width="100%" height="100%" change="setMessageRead()"/>
<mx:ApplicationControlBar id="chatCtrlBar" width="100%" height="10%">
<mx:TextInput id="txtMsg" width="100%" enter="sendMessages()"/>
<mx:ColorPicker id="cmpColorPicker" showTextField="false" toolTip="Text Color" selectedColor="0x000000"/>
<mx:Button label="Send" id="sendBtn" toolTip="Send Message" click="sendMessages()"/>
<mx:Button label="Send" id="sendBtn" toolTip="Send Message" click="sendMessages()"/>
<mx:ComboBox id="participantList" dataProvider="{participants}" close="dispatchEvent(new Event(ChatModuleConstants.OPEN_CHAT_BOX))" />
</mx:ApplicationControlBar>
</MDIWindow>

View File

@ -19,7 +19,6 @@
*/
package org.bigbluebutton.modules.viewers
{
import org.bigbluebutton.common.IBigBlueButtonModule;
import org.bigbluebutton.common.messaging.Endpoint;
import org.bigbluebutton.common.messaging.EndpointMessageConstants;
import org.bigbluebutton.common.messaging.Router;
@ -68,7 +67,9 @@ package org.bigbluebutton.modules.viewers
ViewersModuleConstants.REMOVE_WINDOW,
ViewersModuleConstants.ASSIGN_PRESENTER,
ViewersModuleConstants.BECOME_VIEWER,
ViewersModuleConstants.VIEW_CAMERA
ViewersModuleConstants.VIEW_CAMERA,
ViewersModuleConstants.USER_JOINED,
ViewersModuleConstants.USER_LEFT
];
}
@ -127,6 +128,12 @@ package org.bigbluebutton.modules.viewers
EndpointMessageConstants.TO_VIDEO_MODULE,
{viewerName:_module.username, streamName:notification.getBody().stream, viewedName:notification.getBody().viewedName});
break;
case ViewersModuleConstants.USER_JOINED:
_endpoint.sendMessage(EndpointMessageConstants.NEW_PARTICIPANT, EndpointMessageConstants.TO_CHAT_MODULE, notification.getBody());
break;
case ViewersModuleConstants.USER_LEFT:
_endpoint.sendMessage(EndpointMessageConstants.PARTICIPANT_LEFT, EndpointMessageConstants.TO_CHAT_MODULE, notification.getBody());
break;
}
}

View File

@ -71,5 +71,8 @@ package org.bigbluebutton.modules.viewers
public static const APP_SHUTDOWN:String = "APP_SHUTDOWN";
public static const CONNECT_REJECTED:String = "CONNECT_REJECTED";
public static const UNKNOWN_REASON:String = "UNKNOWN_REASON";
public static const USER_JOINED:String = "USER_JOINED";
public static const USER_LEFT:String = "USER_LEFT";
}
}

View File

@ -25,6 +25,8 @@ package org.bigbluebutton.modules.viewers.model.services
import flash.net.Responder;
import flash.net.SharedObject;
import org.bigbluebutton.modules.viewers.ViewersFacade;
import org.bigbluebutton.modules.viewers.ViewersModuleConstants;
import org.bigbluebutton.modules.viewers.model.business.IViewers;
import org.bigbluebutton.modules.viewers.model.vo.User;
@ -170,6 +172,10 @@ package org.bigbluebutton.modules.viewers.model.services
public function participantLeft(user:Object):void {
_participants.removeParticipant(Number(user));
//This sends a notification that a user has left. Another dirty hack, brought to you by Denis Inc. - Code when YOU need it.
var userObj:Object = {username:user.name, userid:user.userid, userrole:user.role};
ViewersFacade.getInstance().sendNotification(ViewersModuleConstants.USER_LEFT, userObj);
}
public function participantJoined(joinedUser:Object):void {
@ -187,6 +193,10 @@ package org.bigbluebutton.modules.viewers.model.services
participantStatusChange(user.userid, "streamName", joinedUser.status.streamName);
participantStatusChange(user.userid, "presenter", joinedUser.status.presenter);
participantStatusChange(user.userid, "raiseHand", joinedUser.status.raiseHand);
//This sends a notification that a new user has joined to other modules. Right now a dirty, dirty hack - Denis
var userObj:Object = {username:user.name, userid:user.userid, userrole:user.role};
ViewersFacade.getInstance().sendNotification(ViewersModuleConstants.USER_JOINED, userObj);
}
public function participantStatusChange(userid:Number, status:String, value:Object):void {