Added chat to the new Flex 4 UI
This commit is contained in:
parent
73ddb24c92
commit
2edfdf450c
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
|
||||
xmlns:s="library://ns.adobe.com/flex/spark"
|
||||
xmlns:mx="library://ns.adobe.com/flex/mx"
|
||||
xmlns:views="org.bigbluebutton.lib.common.views.*"
|
||||
width="100%"
|
||||
styleName="chatMessageStyle">
|
||||
|
||||
<fx:Script>
|
||||
<![CDATA[
|
||||
import flashx.textLayout.conversion.TextConverter;
|
||||
|
||||
import org.bigbluebutton.lib.chat.models.ChatMessage;
|
||||
|
||||
override public function set data(obj:Object):void {
|
||||
super.data = obj;
|
||||
var m:ChatMessage = obj as ChatMessage;
|
||||
if (m) {
|
||||
time.text = m.time
|
||||
if (!isHTMLString(m.senderText)) {
|
||||
message.text = m.senderText;
|
||||
} else {
|
||||
message.textFlow = TextConverter.importToFlow(m.senderText, TextConverter.TEXT_FIELD_HTML_FORMAT);
|
||||
}
|
||||
var sameUser:Boolean = (m.lastSenderId == m.senderId);
|
||||
var sameTime:Boolean = (m.lastTime == m.time);
|
||||
if (sameUser && sameTime) {
|
||||
nameTimeGroup.includeInLayout = false;
|
||||
nameTimeGroup.visible = false;
|
||||
participantIcon.visible = false;
|
||||
} else {
|
||||
nameTimeGroup.includeInLayout = true;
|
||||
nameTimeGroup.visible = true;
|
||||
if (m.name == " ") {
|
||||
participantIcon.visible = false;
|
||||
username.visible = false;
|
||||
username.includeInLayout = false;
|
||||
} else {
|
||||
username.text = m.name;
|
||||
participantIcon.setFirstLetters(m.name);
|
||||
participantIcon.visible = true;
|
||||
username.visible = true;
|
||||
username.includeInLayout = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if message string contains opening and closing HTML tag e.g. <....>
|
||||
**/
|
||||
public function isHTMLString(str:String):Boolean {
|
||||
var pattern:RegExp = new RegExp("(\<+.*\>+)");
|
||||
var result:Object = pattern.exec(str);
|
||||
if (result == null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
]]>
|
||||
</fx:Script>
|
||||
<s:states>
|
||||
<s:State name="others_state" />
|
||||
<s:State name="me_state" />
|
||||
</s:states>
|
||||
<s:VGroup width="100%">
|
||||
<s:HGroup width="100%">
|
||||
<views:ParticipantIcon id="participantIcon"
|
||||
height="100%" />
|
||||
<s:VGroup width="100%">
|
||||
<s:Spacer height="10%" />
|
||||
<s:Group id="nameTimeGroup"
|
||||
width="100%"
|
||||
height="100%">
|
||||
<s:layout>
|
||||
<s:HorizontalLayout verticalAlign="bottom" />
|
||||
</s:layout>
|
||||
<s:Label id="username"
|
||||
visible="true"
|
||||
fontSize="{getStyle('nameFontSize')}" />
|
||||
<s:Label id="time"
|
||||
fontSize="{getStyle('timeFontSize')}" />
|
||||
</s:Group>
|
||||
<s:HGroup width="100%">
|
||||
<s:RichEditableText editable="false"
|
||||
selectable="false"
|
||||
id="message"
|
||||
width="100%"
|
||||
fontSize="{getStyle('messageFontSize')}" />
|
||||
</s:HGroup>
|
||||
</s:VGroup>
|
||||
</s:HGroup>
|
||||
</s:VGroup>
|
||||
</s:ItemRenderer>
|
@ -0,0 +1,88 @@
|
||||
package org.bigbluebutton.lib.chat.views {
|
||||
import mx.core.ClassFactory;
|
||||
import mx.core.ScrollPolicy;
|
||||
|
||||
import spark.components.Button;
|
||||
import spark.components.Group;
|
||||
import spark.components.HGroup;
|
||||
import spark.components.List;
|
||||
import spark.components.Scroller;
|
||||
import spark.components.TextInput;
|
||||
import spark.components.VGroup;
|
||||
|
||||
public class ChatViewBase extends VGroup {
|
||||
private var _chatList:List;
|
||||
|
||||
public function get chatList():List {
|
||||
return _chatList;
|
||||
}
|
||||
|
||||
private var _inputGroup:HGroup;
|
||||
|
||||
private var _sendButton:Button;
|
||||
|
||||
public function get sendButton():Button {
|
||||
return _sendButton;
|
||||
}
|
||||
|
||||
private var _textInput:TextInput;
|
||||
|
||||
public function get textInput():TextInput {
|
||||
return _textInput;
|
||||
}
|
||||
|
||||
public function ChatViewBase() {
|
||||
super();
|
||||
|
||||
var scroller:Scroller = new Scroller();
|
||||
scroller.percentWidth = 100;
|
||||
scroller.percentHeight = 100;
|
||||
scroller.setStyle("horizontalScrollPolicy", "off");
|
||||
|
||||
var sGroup:VGroup = new VGroup();
|
||||
sGroup.percentWidth = 100;
|
||||
sGroup.percentHeight = 100;
|
||||
sGroup.setStyle("horizontalScrollPolicy", "off");
|
||||
scroller.viewport = sGroup;
|
||||
|
||||
_chatList = new List();
|
||||
_chatList.percentWidth = 100;
|
||||
_chatList.percentHeight = 100;
|
||||
_chatList.setStyle("horizontalScrollPolicy", "off");
|
||||
var itemRendererClass:ClassFactory = new ClassFactory(ChatItemRenderer);
|
||||
_chatList.itemRenderer = itemRendererClass; //org.bigbluebutton.air.chat.views.chat.ChatItemRenderer
|
||||
sGroup.addElement(_chatList);
|
||||
|
||||
addElement(scroller);
|
||||
|
||||
_inputGroup = new HGroup();
|
||||
_inputGroup.percentWidth = 100;
|
||||
_inputGroup.verticalAlign = "middle";
|
||||
_inputGroup.horizontalAlign = "center";
|
||||
|
||||
_textInput = new TextInput();
|
||||
_textInput.percentWidth = 100;
|
||||
_textInput.percentHeight = 100;
|
||||
//_textInput.showPromptWhenFocused = false;
|
||||
_textInput.prompt = "Type message here";
|
||||
_textInput.styleName = "contentFontSize msgInputBoxStyle";
|
||||
_inputGroup.addElement(_textInput);
|
||||
|
||||
_sendButton = new Button();
|
||||
_sendButton.percentHeight = 100;
|
||||
_sendButton.label = "Send";
|
||||
//enabled="{inputMessage0.text!=''}"
|
||||
_sendButton.styleName = "sendButtonStyle";
|
||||
_inputGroup.addElement(_sendButton);
|
||||
|
||||
addElement(_inputGroup);
|
||||
}
|
||||
|
||||
override protected function updateDisplayList(w:Number, h:Number):void {
|
||||
_inputGroup.height = getStyle('chatInputTextHeight');
|
||||
_sendButton.width = getStyle('btnWidth');
|
||||
|
||||
super.updateDisplayList(w, h);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
package org.bigbluebutton.lib.chat.views {
|
||||
import flash.events.KeyboardEvent;
|
||||
import flash.events.MouseEvent;
|
||||
import flash.ui.Keyboard;
|
||||
|
||||
import mx.utils.StringUtil;
|
||||
|
||||
import org.bigbluebutton.lib.chat.models.ChatMessage;
|
||||
import org.bigbluebutton.lib.chat.models.ChatMessageVO;
|
||||
import org.bigbluebutton.lib.chat.models.ChatMessages;
|
||||
import org.bigbluebutton.lib.chat.models.IChatMessagesSession;
|
||||
import org.bigbluebutton.lib.chat.services.IChatMessageService;
|
||||
import org.bigbluebutton.lib.main.models.IUserSession;
|
||||
import org.bigbluebutton.lib.user.models.User;
|
||||
|
||||
import robotlegs.bender.bundles.mvcs.Mediator;
|
||||
|
||||
public class ChatViewMediatorBase extends Mediator {
|
||||
|
||||
[Inject]
|
||||
public var view:ChatViewBase;
|
||||
|
||||
[Inject]
|
||||
public var chatMessageService:IChatMessageService;
|
||||
|
||||
[Inject]
|
||||
public var chatMessagesSession:IChatMessagesSession;
|
||||
|
||||
[Inject]
|
||||
public var userSession:IUserSession;
|
||||
|
||||
protected var _publicChat:Boolean = true;
|
||||
|
||||
protected var _user:User;
|
||||
|
||||
override public function initialize():void {
|
||||
chatMessageService.sendMessageOnSuccessSignal.add(onSendSuccess);
|
||||
chatMessageService.sendMessageOnFailureSignal.add(onSendFailure);
|
||||
chatMessagesSession.newChatMessageSignal.add(scrollUpdate);
|
||||
userSession.userList.userRemovedSignal.add(userRemoved);
|
||||
userSession.userList.userAddedSignal.add(userAdded);
|
||||
|
||||
view.textInput.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
|
||||
view.sendButton.addEventListener(MouseEvent.CLICK, sendButtonClickHandler);
|
||||
|
||||
// TEMP CODE NEED TO REMOVE SOMEHOW
|
||||
_publicChat = true;
|
||||
chatMessagesSession.publicChat
|
||||
openChat(chatMessagesSession.publicChat);
|
||||
// END OF TEMP CODE
|
||||
}
|
||||
|
||||
protected function openChat(chatMessages:ChatMessages):void {
|
||||
chatMessages.resetNewMessages();
|
||||
view.chatList.dataProvider = chatMessages.messages;
|
||||
}
|
||||
|
||||
private function onSendSuccess(result:String):void {
|
||||
view.textInput.enabled = true;
|
||||
view.textInput.text = "";
|
||||
}
|
||||
|
||||
private function onSendFailure(status:String):void {
|
||||
view.textInput.enabled = true;
|
||||
}
|
||||
|
||||
private function scrollUpdate(userId:String = null, publicChat:Boolean = true):void {
|
||||
if ((_publicChat && publicChat) || (!_publicChat && !publicChat && _user && userId == _user.userID)) {
|
||||
if (isIndexVisible(view.chatList.dataProvider.length - 2)) {
|
||||
view.chatList.ensureIndexIsVisible(view.chatList.dataProvider.length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function isIndexVisible(itemIndex:int):Boolean {
|
||||
return view.chatList.dataGroup.getItemIndicesInView().indexOf(itemIndex) > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* When user left the conference, add '[Offline]' to the username
|
||||
* and disable text input
|
||||
*/
|
||||
protected function userRemoved(userID:String):void {
|
||||
if (view != null && _user && _user.userID == userID) {
|
||||
view.textInput.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When user returned(refreshed the page) to the conference, remove '[Offline]' from the username
|
||||
* and enable text input
|
||||
*/
|
||||
protected function userAdded(newuser:User):void {
|
||||
if ((view != null) && (_user != null) && (_user.userID == newuser.userID)) {
|
||||
view.textInput.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private function keyDownHandler(e:KeyboardEvent):void {
|
||||
if (e.keyCode == Keyboard.ENTER && !e.shiftKey) {
|
||||
sendButtonClickHandler(null);
|
||||
}
|
||||
}
|
||||
|
||||
private function sendButtonClickHandler(e:MouseEvent):void {
|
||||
view.textInput.enabled = false;
|
||||
|
||||
var message:String = StringUtil.trim(view.textInput.text);
|
||||
|
||||
if (message) {
|
||||
var currentDate:Date = new Date();
|
||||
//TODO get info from the right source
|
||||
var m:ChatMessageVO = new ChatMessageVO();
|
||||
m.fromUserID = userSession.userId;
|
||||
m.fromUsername = userSession.userList.getUser(userSession.userId).name;
|
||||
m.fromColor = "0";
|
||||
m.fromTime = currentDate.time;
|
||||
m.fromTimezoneOffset = currentDate.timezoneOffset;
|
||||
m.fromLang = "en";
|
||||
m.message = message;
|
||||
m.toUserID = _publicChat ? "public_chat_userid" : _user.userID;
|
||||
m.toUsername = _publicChat ? "public_chat_username" : _user.name;
|
||||
if (_publicChat) {
|
||||
m.chatType = "PUBLIC_CHAT";
|
||||
chatMessageService.sendPublicMessage(m);
|
||||
} else {
|
||||
m.chatType = "PRIVATE_CHAT";
|
||||
chatMessageService.sendPrivateMessage(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override public function destroy():void {
|
||||
chatMessageService.sendMessageOnSuccessSignal.remove(onSendSuccess);
|
||||
chatMessageService.sendMessageOnFailureSignal.remove(onSendFailure);
|
||||
chatMessagesSession.newChatMessageSignal.remove(scrollUpdate);
|
||||
userSession.userList.userRemovedSignal.remove(userRemoved);
|
||||
userSession.userList.userAddedSignal.remove(userAdded);
|
||||
|
||||
view.textInput.removeEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
|
||||
view.sendButton.removeEventListener(MouseEvent.CLICK, sendButtonClickHandler);
|
||||
|
||||
super.destroy();
|
||||
view = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
|
||||
xmlns:s="library://ns.adobe.com/flex/spark"
|
||||
xmlns:mx="library://ns.adobe.com/flex/mx"
|
||||
styleName="participantIconStyle">
|
||||
|
||||
<fx:Script>
|
||||
<![CDATA[
|
||||
public function setFirstLetters(participantName:String):void {
|
||||
var names:Array = participantName.split(" ");
|
||||
var firstLettersText:String = names[0].charAt(0);
|
||||
if (names[1]) {
|
||||
firstLettersText += names[1].charAt(0);
|
||||
}
|
||||
firstLetters.text = firstLettersText.toUpperCase();
|
||||
}
|
||||
]]>
|
||||
</fx:Script>
|
||||
|
||||
<s:Label id="firstLetters"
|
||||
fontSize="{getStyle('fontSize')}"
|
||||
verticalCenter="0"
|
||||
horizontalCenter="0" />
|
||||
|
||||
<s:Ellipse id="circle"
|
||||
height="25"
|
||||
width="25"
|
||||
verticalCenter="0"
|
||||
horizontalCenter="0">
|
||||
<s:stroke>
|
||||
<s:SolidColorStroke id="circleColor"
|
||||
color="{getStyle('circleColor')}"
|
||||
weight="1" />
|
||||
</s:stroke>
|
||||
</s:Ellipse>
|
||||
|
||||
|
||||
</s:Group>
|
||||
|
@ -104,4 +104,19 @@ s|Application
|
||||
.handStatusButtonStyle
|
||||
{
|
||||
backgroundImage : Embed(source="../../air-client/src/assets/res/drawable-mdpi/hand.png");
|
||||
}
|
||||
}
|
||||
|
||||
.participantIconStyle
|
||||
{
|
||||
circleColor : #8898A5;
|
||||
width : 32;
|
||||
height : 32;
|
||||
fontSize : 12;
|
||||
}
|
||||
|
||||
.chatMessageStyle
|
||||
{
|
||||
nameFontSize: 16;
|
||||
timeFontSize: 16;
|
||||
messageFontSize: 14;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
import org.bigbluebutton.lib.whiteboard.views.WhiteboardConfig;
|
||||
import org.bigbluebutton.web.AppConfig;
|
||||
import org.bigbluebutton.web.chat.ChatConfig;
|
||||
import org.bigbluebutton.web.main.MainConfig;
|
||||
import org.bigbluebutton.web.presentation.views.PresentationConfig;
|
||||
|
||||
@ -36,6 +37,7 @@
|
||||
.configure(MainConfig)
|
||||
.configure(PresentationConfig)
|
||||
.configure(WhiteboardConfig)
|
||||
.configure(ChatConfig)
|
||||
.configure(new ContextView(this));
|
||||
|
||||
// If you wish to change the log level then uncomment the line below and set
|
||||
|
@ -1,4 +1,6 @@
|
||||
package org.bigbluebutton.web.chat {
|
||||
import org.bigbluebutton.lib.chat.views.ChatViewBase;
|
||||
import org.bigbluebutton.lib.chat.views.ChatViewMediatorBase;
|
||||
import org.bigbluebutton.web.chat.views.ChatView;
|
||||
import org.bigbluebutton.web.chat.views.ChatViewMediator;
|
||||
import org.bigbluebutton.web.chat.views.ChatWindow;
|
||||
@ -39,8 +41,7 @@ package org.bigbluebutton.web.chat {
|
||||
* Maps view mediators to views.
|
||||
*/
|
||||
private function mediators():void {
|
||||
mediatorMap.map(ChatWindow).toMediator(ChatWindowMediator);
|
||||
mediatorMap.map(ChatView).toMediator(ChatViewMediator);
|
||||
mediatorMap.map(ChatViewBase).toMediator(ChatViewMediatorBase);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.bigbluebutton.web.chat.views {
|
||||
import mx.graphics.SolidColor;
|
||||
|
||||
import org.bigbluebutton.lib.chat.views.ChatViewBase;
|
||||
import org.bigbluebutton.web.common.views.IPanelAdjustable;
|
||||
|
||||
import spark.components.Group;
|
||||
@ -20,15 +21,10 @@ package org.bigbluebutton.web.chat.views {
|
||||
public function ChatPanel() {
|
||||
super();
|
||||
|
||||
var fillerRect:Rect = new Rect();
|
||||
fillerRect.percentWidth = 100;
|
||||
fillerRect.percentHeight = 100;
|
||||
var fill:SolidColor = new SolidColor();
|
||||
fill.color = 0x00FF00;
|
||||
fillerRect.fill = fill;
|
||||
addElement(fillerRect);
|
||||
|
||||
|
||||
var _chatView:ChatViewBase = new ChatViewBase();
|
||||
_chatView.percentWidth = 100;
|
||||
_chatView.percentHeight = 100;
|
||||
addElement(_chatView);
|
||||
}
|
||||
}
|
||||
}
|
@ -22,7 +22,9 @@ package org.bigbluebutton.web.main.views {
|
||||
|
||||
//this.setStyle("gap", 0);
|
||||
this.direction = "horizontal";
|
||||
|
||||
}
|
||||
|
||||
public function createPanels():void {
|
||||
var appWidth:Number = FlexGlobals.topLevelApplication.width;
|
||||
var appHeight:Number = FlexGlobals.topLevelApplication.height;
|
||||
|
||||
|
@ -12,8 +12,15 @@ package org.bigbluebutton.web.main.views {
|
||||
public var uiSession:IUISession;
|
||||
|
||||
override public function initialize():void {
|
||||
uiSession.loadingChangeSignal.add(onLoadingChangeSignal);
|
||||
uiSession.participantsOpenSignal.add(onParticipantsOpenSignal);
|
||||
onParticipantsOpenSignal();
|
||||
}
|
||||
|
||||
private function onLoadingChangeSignal(val:Boolean, message:String):void {
|
||||
if (!val) {
|
||||
view.createPanels();
|
||||
onParticipantsOpenSignal();
|
||||
}
|
||||
}
|
||||
|
||||
private function onParticipantsOpenSignal():void {
|
||||
@ -21,6 +28,7 @@ package org.bigbluebutton.web.main.views {
|
||||
}
|
||||
|
||||
override public function destroy():void {
|
||||
uiSession.loadingChangeSignal.remove(onLoadingChangeSignal);
|
||||
uiSession.participantsOpenSignal.remove(onParticipantsOpenSignal);
|
||||
|
||||
super.destroy();
|
||||
|
Loading…
Reference in New Issue
Block a user