- Updated top and bottom menus.

- Updated presentation and participants views.
This commit is contained in:
Ghaz Triki 2016-04-03 11:30:38 +01:00
parent df6045e368
commit f81ba4c9bd
61 changed files with 2613 additions and 805 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
chat.item.privateChat=New private chat
chat.item.publicChat=Public chat
chat.public.title=Public chat
chat.item.publicChat=Public Chat
chat.public.title=Public Chat
chat.sendBtn.text=Send
chat.title=Chat Rooms
chat.textInput.text=Type message here
@ -19,11 +19,16 @@ notification.title=BigBlueButton
notification.message=A meeting is running
participants.guests=Guests
participants.title=Participants
participants.status.presenter=Presenter
participants.conversations=Conversations
participants.online=Online
participants.status.presenter=Currently Presenting
participants.status.moderator=Moderator
profile.title=User Settings
presentation.sharedWebcams=Shared webcams
presentation.sharedWebcam=Shared webcam
profile.title=Settings
profile.subtitle=Session Settings
profile.participant=Participant
profile.logout=Log out
profile.logout=Leave session
profile.status.title=Change status
profile.status.current=Current status
profile.settings=Settings
@ -35,19 +40,24 @@ profile.settings.cameraQuality.selectquality = Select camera quality:
profile.settings.mic=Audio
profile.settings.mic.on=Leave audio
profile.settings.mic.off=Join audio
profile.settings.handRaise=Raise hand
profile.settings.handRaise=Raise
profile.settings.agree=Agree
profile.settings.disagree=Disagree
profile.settings.speakLouder = Could you please speak louder?
profile.settings.speakSofter = Could you please speak softer?
profile.settings.speakFaster = Could you please speak faster?
profile.settings.speakSlower = Could you please speak slower?
profile.settings.beRightBack = I'll be right back
profile.settings.laughter=:)
profile.settings.sad=:(
profile.settings.clearStatus=Clear my status
profile.settings.beRightBack = Time
profile.settings.laughter=Happy
profile.settings.sad=Sad
profile.settings.neutral=Undecided
profile.settings.confused=Confused
profile.settings.clearStatus=Clear
profile.settings.handLower=Lower hand
selectParticipant.title=Select a Participant
selectStream.title=Active Webcams
selectStream.viewWebcam=Start viewing webcam
selectStream.hideWebcam=Stop viewing webcams
userDetail.title=Participant
userDetail.name=Name
userDetail.role=Role
@ -87,20 +97,24 @@ management.muteAll = Mute all users
management.unmuteAll = Unmute all users
management.muteAllExceptPresenter = Mute all users except presenter
management.lockViewers = Lock viewers
menuButtons.camOff = Cam Off
menuButtons.camOn = Cam On
menuButtons.micOff = Mic Off
menuButtons.micOn = Mic On
lockSettings.title = Lock Viewers
lockSettings.cam = Webcam
lockSettings.mic = Microphone
lockSettings.publicChat = Public chat
lockSettings.privateChat = Private chat
lockSettings.publicChat = Public Chat
lockSettings.privateChat = Private Chat
lockSettings.layout = Web layout
lockSettings.apply = Apply
guest.waitMessage=You are a guest, please wait moderator approval.
deskshare.noDeskshare = No desktop stream to display
deskshare.title = Desktop Sharing
cameraSettings.title=Camera Settings
cameraSettings.title=Video
cameraSettings.rotate=Rotate Camera
cameraSettings.swap=Swap Camera
audioSettings.title=Audio Settings
audioSettings.title=Audio
audioSettings.enableMic=Enable microphone
audioSettings.enableAudio=Enable audio
audioSettings.pushToTalk=Push to talk

View File

@ -1,7 +1,8 @@
<?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:mx="library://ns.adobe.com/flex/mx"
xmlns:participanticon="org.bigbluebutton.air.common.views.*">
<fx:Script>
<![CDATA[
@ -14,6 +15,12 @@
var m:ChatMessage = obj as ChatMessage;
if (m) {
username.text = m.name;
participantIcon.participantName = m.name;
if (m.name == " ") {
participantIcon.visible = false;
username.visible = false;
username.includeInLayout = false;
}
time.text = m.time
if (!isHTMLString(m.senderText)) {
message.text = m.senderText;
@ -54,29 +61,30 @@
<s:State name="others_state" />
<s:State name="me_state" />
</s:states>
<s:Group width="100%">
<s:layout>
<s:VerticalLayout verticalAlign="middle" />
</s:layout>
<s:Group id="nameTimeGroup"
width="100%">
<s:layout>
<s:HorizontalLayout />
</s:layout>
<s:Label id="username"
width="50%"
styleName="chatNameTimeStyle subContentFontSize" />
<s:Label id="time"
width="50%"
textAlign="right"
styleName="chatTimeColor chatNameTimeStyle subContentFontSize" />
</s:Group>
<s:Group width="100%">
<s:RichEditableText editable="false"
selectable="false"
id="message"
width="100%"
styleName="msgTextStyle contentFontSize" />
</s:Group>
</s:Group>
<s:HGroup width="100%">
<participanticon: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"
styleName="contentFontSize" />
<s:Label id="time"
styleName="chatTimeColor subContentFontSize" />
</s:Group>
<s:HGroup width="100%">
<s:RichEditableText editable="false"
selectable="false"
id="message"
width="100%"
styleName="msgTextStyle contentFontSize" />
</s:HGroup>
<s:Spacer height="{nameTimeGroup.height}" />
</s:VGroup>
</s:HGroup>
</s:ItemRenderer>

View File

@ -21,7 +21,7 @@ package org.bigbluebutton.air.chat.views.chat {
}
public function get pageName():Label {
return FlexGlobals.topLevelApplication.pageName;
return FlexGlobals.topLevelApplication.topActionBar.pageName;
}
override protected function childrenCreated():void {

View File

@ -21,22 +21,27 @@
</s:VGroup>
</s:Scroller>
<s:Group width="100%"
height="{getStyle('chatInputTextHeight')}">
<s:HGroup width="100%"
height="{getStyle('chatInputTextHeight')}"
verticalAlign="middle"
horizontalAlign="center">
<!-- soft keyboard fix: http://stackoverflow.com/a/14337230/4793308 -->
<s:TextInput showPromptWhenFocused="false"
skinClass="spark.skins.mobile.TextInputSkin"
id="inputMessage0"
width="100%"
height="100%"
prompt="{resourceManager.getString('resources','chat.textInput.text')}"
styleName="contentFontSize msgInputBoxStyle" />
<s:Button id="sendButton0"
width="{getStyle('btnWidth')}"
height="100%"
right="0"
enabled="{inputMessage0.text!=''}"
styleName="sendButtonStyle" />
</s:Group>
<s:TextInput showPromptWhenFocused="false"
skinClass="spark.skins.mobile.TextInputSkin"
id="inputMessage0"
width="90%"
height="90%"
prompt="{resourceManager.getString('resources','chat.textInput.text')}"
styleName="contentFontSize msgInputBoxStyle" />
</s:HGroup>
</s:Group>
</common:NoTabView>

View File

@ -2,6 +2,7 @@
<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:participanticon="org.bigbluebutton.air.common.views.*"
styleName="chatRoomItemStyle">
<fx:Script>
@ -13,6 +14,14 @@
if (obj) {
if (!obj.hasOwnProperty("button")) {
title.text = obj.name;
if (obj.name == resourceManager.getString('resources', 'chat.item.publicChat')) {
publicChatIcon.visible = true;
publicChatIcon.includeInLayout = true;
} else {
participantIcon.participantName = obj.name;
participantIcon.visible = true;
participantIcon.includeInLayout = true;
}
if (obj.online == false) {
title.text += resourceManager.getString('resources', 'userDetail.userOffline');
}
@ -23,6 +32,7 @@
} else {
newMessages.visible = false;
}
} else {
newMessages.visible = false;
title.text = "+" + resourceManager.getString('resources', 'chat.item.privateChat');
@ -31,21 +41,28 @@
}
]]>
</fx:Script>
<s:Group width="100%">
<s:Group width="100%"
height="{getStyle('itemHeight')}">
<s:layout>
<s:HorizontalLayout verticalAlign="middle" />
<s:HorizontalLayout verticalAlign="middle"
horizontalAlign="center"
paddingLeft="{getStyle('itemPaddingLeft')}"
paddingRight="{getStyle('itemPaddingRight')}" />
</s:layout>
<s:Image id="publicChatIcon"
visible="false"
includeInLayout="false"
styleName="iconStyle publicChatIconStyle" />
<participanticon:ParticipantIcon id="participantIcon"
visible="false"
includeInLayout="false" />
<s:Label id="title"
width="100%"
styleName="contentFontSize chatRoomLabelStyle"
verticalCenter="0"
horizontalCenter="0" />
height="100%"
styleName="contentFontSize" />
<s:Button id="newMessages"
buttonMode="false"
styleName="newMessagesButtonStyle" />
<s:Image styleName="iconStyle arrowRightStyle"
horizontalCenter="0"
verticalCenter="0" />
</s:Group>
<s:Line width="100%">
<s:stroke>

View File

@ -1,9 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<s:List xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
useVirtualLayout="false"
itemRenderer="org.bigbluebutton.air.chat.views.chatrooms.ChatRoomsItemRenderer">
itemRenderer="org.bigbluebutton.air.chat.views.chatrooms.ChatRoomsItemRenderer"
verticalScrollPolicy="off">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:layout>
<s:VerticalLayout horizontalAlign="contentJustify"
requestedRowCount="-1" />
</s:layout>
</s:List>

View File

@ -17,7 +17,6 @@ package org.bigbluebutton.air.common.views {
import org.bigbluebutton.air.settings.views.audio.AudioSettingsView;
import org.bigbluebutton.air.settings.views.camera.CameraSettingsView;
import org.bigbluebutton.air.settings.views.lock.LockSettingsView;
import org.bigbluebutton.air.settings.views.status.StatusView;
import org.bigbluebutton.air.users.views.participants.ParticipantsView;
import org.bigbluebutton.air.users.views.userdetails.UserDetailsView;
import org.bigbluebutton.air.video.views.videochat.VideoChatView;
@ -77,7 +76,6 @@ package org.bigbluebutton.air.common.views {
dic[PRESENTATION] = PresentationView;
dic[LOGIN] = LoginPageView;
dic[PROFILE] = ProfileView;
dic[STATUS] = StatusView;
dic[USER_DETAILS] = UserDetailsView;
dic[VIDEO_CHAT] = VideoChatView;
dic[CHATROOMS] = ChatRoomsView;

View File

@ -0,0 +1,45 @@
<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"
creationComplete="init()">
<fx:Script>
<![CDATA[
public var participantName:String;
public function init():void {
//create first letters icon
if (participantName) {
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:HGroup horizontalAlign="center"
verticalAlign="middle"
width="{getStyle('width')}"
height="{getStyle('height')}">
<s:Label id="firstLetters"
styleName="nameIconText" />
</s:HGroup>
<s:Ellipse id="circle"
height="{firstLetters.height * 2.5}"
width="{circle.height}"
x="{firstLetters.x - (circle.width - firstLetters.width)/2}"
y="{firstLetters.y - (circle.height - firstLetters.height)/2}">
<s:stroke>
<s:SolidColorStroke id="circleColor"
color="{getStyle('circleColor')}"
weight="1" />
</s:stroke>
</s:Ellipse>
</s:Group>

View File

@ -0,0 +1,16 @@
<s:HGroup xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="100%"
height="100%"
horizontalAlign="right"
verticalAlign="middle">
<s:states>
<s:State name="normal" />
<s:State name="selected" />
</s:states>
<s:Image styleName.selected="iconStyle selectedIconStyle"
styleName.normal="iconStyle unselectedIconStyle" />
</s:HGroup>

View File

@ -22,9 +22,9 @@ package org.bigbluebutton.air.deskshare.views {
public override function initialize():void {
showDeskshare(userSession.deskshareConnection.streamWidth, userSession.deskshareConnection.streamHeight);
FlexGlobals.topLevelApplication.stage.addEventListener(ResizeEvent.RESIZE, stageOrientationChangingHandler);
FlexGlobals.topLevelApplication.pageName.text = ResourceManager.getInstance().getString('resources', 'deskshare.title');
FlexGlobals.topLevelApplication.backBtn.visible = false;
FlexGlobals.topLevelApplication.profileBtn.visible = true;
FlexGlobals.topLevelApplication.topActionBar.pageName.text = ResourceManager.getInstance().getString('resources', 'deskshare.title');
FlexGlobals.topLevelApplication.topActionBar.backBtn.visible = false;
FlexGlobals.topLevelApplication.topActionBar.profileBtn.visible = true;
super.initialize();
}

View File

@ -36,7 +36,7 @@ package org.bigbluebutton.air.main.views.disconnectpage {
view.reconnectButton.addEventListener(MouseEvent.CLICK, reconnect);
changeConnectionStatus(userUISession.currentPageDetails as int);
if (FlexGlobals.topLevelApplication.hasOwnProperty("pageName")) {
FlexGlobals.topLevelApplication.pageName.text = "";
FlexGlobals.topLevelApplication.topActionBar.pageName.text = "";
FlexGlobals.topLevelApplication.topActionBar.visible = false;
FlexGlobals.topLevelApplication.bottomMenu.visible = false;
}

View File

@ -45,7 +45,7 @@ package org.bigbluebutton.air.main.views.exit {
view.yesButton.addEventListener(MouseEvent.CLICK, applicationExit);
view.noButton.addEventListener(MouseEvent.CLICK, backToApplication);
changeConnectionStatus(userUISession.currentPageDetails as int);
FlexGlobals.topLevelApplication.pageName.text = "";
FlexGlobals.topLevelApplication.topActionBar.pageName.text = "";
_topBar = FlexGlobals.topLevelApplication.topActionBar.visible;
FlexGlobals.topLevelApplication.topActionBar.visible = false;
_bottomMenu = FlexGlobals.topLevelApplication.bottomMenu.visible;

View File

@ -26,7 +26,7 @@ package org.bigbluebutton.air.main.views.guest {
} else {
view.exitButton.addEventListener(MouseEvent.CLICK, applicationExit);
}
FlexGlobals.topLevelApplication.pageName.text = "";
FlexGlobals.topLevelApplication.topActionBar.pageName.text = "";
FlexGlobals.topLevelApplication.topActionBar.visible = false;
FlexGlobals.topLevelApplication.bottomMenu.visible = false;
}

View File

@ -34,8 +34,8 @@ package org.bigbluebutton.air.main.views.loginpage.openroom {
public var userUISession:IUserUISession;
override public function initialize():void {
FlexGlobals.topLevelApplication.profileBtn.visible = false;
FlexGlobals.topLevelApplication.backBtn.visible = false;
FlexGlobals.topLevelApplication.topActionBar.profileBtn.visible = false;
FlexGlobals.topLevelApplication.topActionBar.backBtn.visible = false;
FlexGlobals.topLevelApplication.bottomMenu.includeInLayout = false;
FlexGlobals.topLevelApplication.topActionBar.visible = false;
(view as View).addEventListener(KeyboardEvent.KEY_DOWN, KeyHandler);

View File

@ -45,13 +45,6 @@ package org.bigbluebutton.air.main.views.loginpage.openroom.recentrooms {
}
view.roomsList.dataProvider = dataProvider;
view.roomsList.addEventListener(MouseEvent.CLICK, selectRoom);
FlexGlobals.topLevelApplication.profileBtn.visible = false;
FlexGlobals.topLevelApplication.backBtn.visible = false;
FlexGlobals.topLevelApplication.pageName.text = ResourceManager.getInstance().getString('resources', 'recentRooms.title');
FlexGlobals.topLevelApplication.topActionBar.visible = true;
FlexGlobals.topLevelApplication.bottomMenu.includeInLayout = false;
FlexGlobals.topLevelApplication.backBtn.includeInLayout = true;
FlexGlobals.topLevelApplication.backBtn.visible = true;
}
protected function selectRoom(event:MouseEvent):void {

View File

@ -1,15 +1,11 @@
package org.bigbluebutton.air.main.views.menubuttons {
import org.bigbluebutton.air.main.views.ui.navigationbutton.NavigationButton;
import spark.components.Button;
public interface IMenuButtonsView {
function get menuDeskshareButton():NavigationButton
function get menuVideoChatButton():NavigationButton
function get menuPresentationButton():NavigationButton
function get menuChatButton():NavigationButton
function get menuParticipantsButton():NavigationButton
function get pushToTalkButton():Button;
function get camButton():Button
function get micButton():Button
function get statusButton():Button
}
}

View File

@ -5,57 +5,57 @@
xmlns:navigationbutton="org.bigbluebutton.air.main.views.ui.navigationbutton.*"
xmlns:common="org.bigbluebutton.view.navigation.pages.common.*"
width="100%"
height="100%">
height="100%"
styleName="bottomMenuStyle">
<fx:Script>
<![CDATA[
import mx.core.FlexGlobals;
import org.bigbluebutton.air.common.views.PagesENUM;
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:layout>
<s:HorizontalLayout gap="0" />
</s:layout>
<s:Rect left="0"
right="0"
top="0"
bottom="0">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry alpha="0"
color="{getStyle('gradientColor')}" />
<s:GradientEntry color="{getStyle('gradientColor')}" />
</s:LinearGradient>
</s:fill>
</s:Rect>
<s:Spacer id="pushToTalkSpacer"
width="{pushToTalkButton0.getStyle('EllipseWidth')}" />
<s:Group width="50%"
height="100%"
id="buttons"
x="{(this.width - buttons.width)/2}"
y="{(this.height - buttons.height * 1.1)}">
<s:Button id="pushToTalkButton0"
width="100%"
height="100"
includeInLayout="false"
creationComplete="{pushToTalkButton0.y=participantsBtn0.height}"
styleName="pushToTalkStyle" />
<s:layout>
<s:HorizontalLayout gap="0"
horizontalAlign="center" />
</s:layout>
<navigationbutton:NavigationButton id="deskshareBtn0"
navigateTo="{[PagesENUM.DESKSHARE]}"
width="100%"
height="100%"
visible="false"
includeInLayout="false"
styleName="deskshareBtnStyle" />
<navigationbutton:NavigationButton id="presentationBtn0"
width="100%"
height="100%"
navigateTo="{[PagesENUM.PRESENTATION]}"
styleName="presentationBtnStyle" />
<navigationbutton:NavigationButton id="videochatBtn0"
navigateTo="{[PagesENUM.VIDEO_CHAT]}"
width="100%"
height="100%"
styleName="videochatBtnStyle" />
<navigationbutton:NavigationButton id="chatBtn0"
navigateTo="{FlexGlobals.topLevelApplication.isTabletLandscape() ? [PagesENUM.SPLITCHAT] : [PagesENUM.CHATROOMS,PagesENUM.CHAT,PagesENUM.SELECT_PARTICIPANT]}"
width="100%"
height="100%"
styleName="chatBtnStyle" />
<navigationbutton:NavigationButton id="participantsBtn0"
navigateTo="{FlexGlobals.topLevelApplication.isTabletLandscape() ? [PagesENUM.SPLITPARTICIPANTS] : [PagesENUM.PARTICIPANTS,PagesENUM.USER_DETAILS]}"
width="100%"
height="100%"
styleName="participantsBtnStyle" />
<s:Button id="micBtn0"
width="100%"
height="100%"
label="Mic on"
styleName="micOnButtonStyle bottomPresentationBtnStyle" />
<s:Button id="camBtn0"
width="100%"
height="100%"
label="Cam off"
styleName="camOnButtonStyle bottomPresentationBtnStyle" />
<s:Button id="statusBtn0"
width="100%"
height="100%"
label="Raise"
styleName="handStatusButtonStyle bottomPresentationBtnStyle" />
</s:Group>
</s:Group>

View File

@ -1,5 +1,10 @@
package org.bigbluebutton.air.main.views.menubuttons {
import org.bigbluebutton.air.video.commands.ShareCameraCommand;
import org.bigbluebutton.lib.video.commands.ShareCameraSignal;
import org.bigbluebutton.lib.voice.commands.ShareMicrophoneCommand;
import org.bigbluebutton.lib.voice.commands.ShareMicrophoneSignal;
import robotlegs.bender.extensions.mediatorMap.api.IMediatorMap;
import robotlegs.bender.extensions.signalCommandMap.api.ISignalCommandMap;
import robotlegs.bender.framework.api.IConfig;
@ -41,6 +46,8 @@ package org.bigbluebutton.air.main.views.menubuttons {
* Maps signals to commands using the signalCommandMap.
*/
private function signals():void {
signalCommandMap.map(ShareCameraSignal).toCommand(ShareCameraCommand);
signalCommandMap.map(ShareMicrophoneSignal).toCommand(ShareMicrophoneCommand);
}
}
}

View File

@ -1,32 +1,19 @@
package org.bigbluebutton.air.main.views.menubuttons {
import org.bigbluebutton.air.main.views.ui.navigationbutton.NavigationButton;
import spark.components.Button;
public class MenuButtonsView extends MenuButtons implements IMenuButtonsView {
public function get menuDeskshareButton():NavigationButton {
return deskshareBtn0;
public function get camButton():Button {
return camBtn0;
}
public function get menuVideoChatButton():NavigationButton {
return videochatBtn0;
public function get micButton():Button {
return micBtn0;
}
public function get menuPresentationButton():NavigationButton {
return presentationBtn0;
}
public function get pushToTalkButton():Button {
return pushToTalkButton0;
}
public function get menuChatButton():NavigationButton {
return chatBtn0;
}
public function get menuParticipantsButton():NavigationButton {
return participantsBtn0;
public function get statusButton():Button {
return statusBtn0;
}
}
}

View File

@ -5,6 +5,7 @@ package org.bigbluebutton.air.main.views.menubuttons {
import flash.desktop.NativeApplication;
import flash.desktop.SystemIdleMode;
import flash.display.DisplayObjectContainer;
import flash.events.Event;
import flash.events.InvokeEvent;
import flash.events.MouseEvent;
@ -16,21 +17,29 @@ package org.bigbluebutton.air.main.views.menubuttons {
import mx.core.mx_internal;
import mx.events.FlexEvent;
import mx.events.ResizeEvent;
import mx.managers.PopUpManager;
import mx.resources.ResourceManager;
import org.bigbluebutton.air.common.views.PagesENUM;
import org.bigbluebutton.air.common.views.TransitionAnimationENUM;
import org.bigbluebutton.air.main.models.IUserUISession;
import org.bigbluebutton.air.main.views.menubuttons.changestatus.ChangeStatusPopUp;
import org.bigbluebutton.air.main.views.menubuttons.changestatus.StatusItemRenderer;
import org.bigbluebutton.air.main.views.skins.NavigationButtonSkin;
import org.bigbluebutton.air.main.views.skins.PresentationButtonSkin;
import org.bigbluebutton.lib.chat.models.IChatMessagesSession;
import org.bigbluebutton.lib.main.commands.DisconnectUserSignal;
import org.bigbluebutton.lib.main.models.IUserSession;
import org.bigbluebutton.lib.user.models.User;
import org.bigbluebutton.lib.user.models.UserList;
import org.bigbluebutton.lib.user.services.IUsersService;
import org.bigbluebutton.lib.video.commands.ShareCameraSignal;
import org.bigbluebutton.lib.voice.commands.ShareMicrophoneSignal;
import robotlegs.bender.bundles.mvcs.Mediator;
import robotlegs.bender.extensions.mediatorMap.api.IMediatorMap;
import spark.events.PopUpEvent;
import spark.transitions.ViewTransitionBase;
public class MenuButtonsViewMediator extends Mediator {
@ -53,6 +62,15 @@ package org.bigbluebutton.air.main.views.menubuttons {
[Inject]
public var disconnectUserSignal:DisconnectUserSignal;
[Inject]
public var shareCameraSignal:ShareCameraSignal;
[Inject]
public var shareMicrophoneSignal:ShareMicrophoneSignal;
[Inject]
public var mediatorMap:IMediatorMap;
private var notificationManager:NotificationManager = new NotificationManager();
private var loggingOut:Boolean = false;
@ -61,52 +79,43 @@ package org.bigbluebutton.air.main.views.menubuttons {
NativeApplication.nativeApplication.addEventListener(Event.ACTIVATE, fl_Activate);
NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, fl_Deactivate);
NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, onInvokeEvent);
view.pushToTalkButton.addEventListener(FlexEvent.BUTTON_DOWN, pushToTalkOn);
view.pushToTalkButton.addEventListener(MouseEvent.MOUSE_UP, pushToTalkOff);
view.pushToTalkButton.addEventListener(MouseEvent.MOUSE_OUT, pushToTalkOff);
userUISession.loadingSignal.add(loadingFinished);
userUISession.pageChangedSignal.add(pageChanged);
userSession.guestList.userAddedSignal.add(guestAdded);
userSession.guestList.userRemovedSignal.add(guestRemoved);
userSession.userList.userChangeSignal.add(userChanged);
chatMessagesSession.newChatMessageSignal.add(updateMessagesNotification);
userSession.presentationList.presentationChangeSignal.add(presentationChanged);
userSession.userList.userChangeSignal.add(userChangeHandler);
userSession.logoutSignal.add(loggingOutHandler);
userSession.assignedDeskshareSignal.add(configDeskshare);
userSession.pushToTalkSignal.add(pushToTalkChange);
pushToTalkChange();
view.camButton.addEventListener(MouseEvent.CLICK, camOnOff);
view.micButton.addEventListener(MouseEvent.CLICK, micOnOff);
view.statusButton.addEventListener(MouseEvent.CLICK, changeStatus);
}
private function isPushToTalkOn() {
var micEnabled:Boolean = (userSession.voiceStreamManager && userSession.voiceStreamManager.mic && userSession.voiceConnection.callActive) ? true : false;
return userSession.pushToTalk && micEnabled;
}
private function pushToTalkChange():void {
if (userSession.voiceConnection && userSession.voiceConnection.callActive) {
userSession.voiceStreamManager.muteMicGain(userSession.pushToTalk);
private function changeStatus(e:MouseEvent):void {
var changeStatusPopUp:ChangeStatusPopUp = new ChangeStatusPopUp();
mediatorMap.mediate(changeStatusPopUp);
changeStatusPopUp.width = view.width;
changeStatusPopUp.height = view.height;
changeStatusPopUp.open(view as DisplayObjectContainer, true);
if (FlexGlobals.topLevelApplication.aspectRatio == "landscape") {
changeStatusPopUp.x = view.x + view.statusButton.x;
changeStatusPopUp.y = view.y - changeStatusPopUp.height * 2;
} else {
//(changeStatusPopUp.statusList.dataProvider.getItemAt(0) as StatusItemRenderer).icon;
//var popUpButtonPadding = ((changeStatusPopUp.statusList.itemRenderer as StatusItemRenderer).icon.width - (changeStatusPopUp.statusList.itemRenderer as StatusItemRenderer).clearStatusIcon.width) / 2;
//trace("++ isso " + ((changeStatusPopUp.statusList.itemRenderer as StatusItemRenderer).icon.width - (changeStatusPopUp.statusList.itemRenderer as StatusItemRenderer).clearStatusIcon.width) / 2);
changeStatusPopUp.x = -(view.width - view.statusButton.x - view.statusButton.width) / 2 - (view.statusButton.width - (view.statusButton.skin as PresentationButtonSkin).backgroundEllipse.width) / 2 + 6;
changeStatusPopUp.y = view.y - changeStatusPopUp.height * changeStatusPopUp.statusList.dataProvider.length;
}
view.pushToTalkButton.visible = isPushToTalkOn();
view.pushToTalkSpacer.includeInLayout = isPushToTalkOn();
}
/**
* Update the view when there is a chenge in the model
*/
private function userChangeHandler(user:User, type:int):void {
if (user && user.me && type == UserList.MUTE) {
view.pushToTalkButton.enabled = !user.muted;
}
private function micOnOff(e:MouseEvent):void {
var audioOptions:Object = new Object();
audioOptions.shareMic = !userSession.userList.me.voiceJoined;
audioOptions.listenOnly = false;
shareMicrophoneSignal.dispatch(audioOptions);
}
private function pushToTalkOn(e:FlexEvent):void {
userSession.voiceStreamManager.muteMicGain(false);
}
private function pushToTalkOff(e:MouseEvent):void {
userSession.voiceStreamManager.muteMicGain(true);
private function camOnOff(e:MouseEvent):void {
shareCameraSignal.dispatch(!userSession.userList.me.hasStream, userSession.videoConnection.cameraPosition);
}
private function onInvokeEvent(invocation:InvokeEvent):void {
@ -133,123 +142,32 @@ package org.bigbluebutton.air.main.views.menubuttons {
loggingOut = true;
}
private function presentationChanged():void {
userSession.presentationList.currentPresentation.slideChangeSignal.add(updatePresentationNotification);
}
private function updatePresentationNotification() {
if (userUISession.currentPage != PagesENUM.PRESENTATION) {
(view.menuPresentationButton.skin as NavigationButtonSkin).notification.visible = true;
} else {
(view.menuPresentationButton.skin as NavigationButtonSkin).notification.visible = false;
}
}
private function updateMessagesNotification(userID:String, publicChat:Boolean):void {
var notification = (view.menuChatButton.skin as NavigationButtonSkin).notification;
if (userUISession.currentPage == PagesENUM.SPLITCHAT) {
notification.visible = false;
} else {
var data = userUISession.currentPageDetails;
var currentPageIsPublicChat:Boolean = data && data.hasOwnProperty("user") && !data.user;
var currentPageIsPrivateChatOfTheSender:Boolean = (data is User && userID == data.userID) || (data && data.hasOwnProperty("user") && data.user && data.user.userID == userID);
var iAmSender = (userID == userSession.userId);
if (!iAmSender) {
if (userUISession.currentPage != PagesENUM.CHATROOMS && !(currentPageIsPrivateChatOfTheSender && !publicChat) && !(currentPageIsPublicChat && publicChat)) {
notification.visible = true;
} else {
notification.visible = false;
}
}
}
}
private function pageChanged(pageName:String, pageRemoved:Boolean = false, animation:int = TransitionAnimationENUM.APPEAR, transition:ViewTransitionBase = null):void {
if (pageName == PagesENUM.PARTICIPANTS) {
updateGuestsNotification();
}
if (pageName == PagesENUM.PRESENTATION) {
updatePresentationNotification();
}
if (pageName == PagesENUM.CHATROOMS || pageName == PagesENUM.SPLITCHAT) {
(view.menuChatButton.skin as NavigationButtonSkin).notification.visible = false;
}
}
private function updateGuestsNotification():void {
var numberOfGuests:int = userSession.guestList.users.length;
if (numberOfGuests > 0 && userSession.userList.me.role == User.MODERATOR && userUISession.currentPage != PagesENUM.PARTICIPANTS) {
(view.menuParticipantsButton.skin as NavigationButtonSkin).notification.visible = true;
} else {
(view.menuParticipantsButton.skin as NavigationButtonSkin).notification.visible = false;
}
}
private function guestAdded(guest:Object):void {
updateGuestsNotification();
}
private function guestRemoved(guest:Object):void {
if (userSession.guestList.users.length == 0) {
(view.menuParticipantsButton.skin as NavigationButtonSkin).notification.visible = false;
}
}
private function userChanged(user:User, property:String = null):void {
if (user && user.me) {
updateGuestsNotification();
if (user.hasStream) {
view.camButton.label = ResourceManager.getInstance().getString('resources', 'menuButtons.camOff');
view.camButton.styleName = "camOffButtonStyle bottomPresentationBtnStyle"
} else {
view.camButton.label = ResourceManager.getInstance().getString('resources', 'menuButtons.camOn');
view.camButton.styleName = "camOnButtonStyle bottomPresentationBtnStyle"
}
if (userSession.userList.me.voiceJoined) {
view.micButton.label = ResourceManager.getInstance().getString('resources', 'menuButtons.micOff');
view.micButton.styleName = "micOffButtonStyle bottomPresentationBtnStyle"
} else {
view.micButton.label = ResourceManager.getInstance().getString('resources', 'menuButtons.micOn');
view.micButton.styleName = "micOnButtonStyle bottomPresentationBtnStyle"
}
}
}
private function loadingFinished(loading:Boolean):void {
if (!loading) {
updateGuestsNotification();
userUISession.loadingSignal.remove(loadingFinished);
}
}
private function configDeskshare() {
view.menuDeskshareButton.visible = view.menuDeskshareButton.includeInLayout = userSession.deskshareConnection.isStreaming;
userSession.deskshareConnection.isStreamingSignal.add(onDeskshareStreamChange);
}
/**
* If we recieve signal that deskshare stream is on - include Deskshare button to the layout
*/
public function onDeskshareStreamChange(isDeskshareStreaming:Boolean):void {
view.menuDeskshareButton.visible = view.menuDeskshareButton.includeInLayout = isDeskshareStreaming;
}
/*private function userChangeHandler(user:User, property:int):void
{
var users:ArrayCollection = userSession.userList.users;
var hasStream : Boolean = false;
if (property == UserList.HAS_STREAM )
{
if(user.hasStream)
{
hasStream = true;
}
else
{
for each(var u:User in users)
{
if(u.hasStream)
{
hasStream = true;
break;
}
}
}
view.menuVideoChatButton.visible = view.menuVideoChatButton.includeInLayout = hasStream;
}
}*/
/**
* Unsubscribe from listening for Deskshare Streaming Signal
*/
public override function destroy():void {
userSession.deskshareConnection.isStreamingSignal.remove(onDeskshareStreamChange);
/*userSession.userList.userChangeSignal.remove(userChangeHandler);*/
}
private function fl_Activate(event:Event = null):void {

View File

@ -1,4 +1,4 @@
package org.bigbluebutton.air.settings.views.status {
package org.bigbluebutton.air.main.views.menubuttons.changestatus {
import org.bigbluebutton.lib.main.commands.EmojiCommand;
import org.bigbluebutton.lib.main.commands.EmojiSignal;
@ -8,7 +8,7 @@ package org.bigbluebutton.air.settings.views.status {
import robotlegs.bender.framework.api.IConfig;
import robotlegs.bender.framework.api.IInjector;
public class StatusConfig implements IConfig {
public class ChangeStatusConfig implements IConfig {
[Inject]
public var injector:IInjector;
@ -37,7 +37,7 @@ package org.bigbluebutton.air.settings.views.status {
* Maps view mediators to views.
*/
private function mediators():void {
mediatorMap.map(IStatusView).toMediator(StatusViewMediator);
mediatorMap.map(IChangeStatusPopUp).toMediator(ChangeStatusPopUpMediator);
}
/**

View File

@ -0,0 +1,13 @@
package org.bigbluebutton.air.main.views.menubuttons.changestatus {
import spark.components.List;
public class ChangeStatusPopUp extends ChangeStatusPopUpBase implements IChangeStatusPopUp {
public function get statusList():List {
return statusList0;
}
public function dispose():void {
}
}
}

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<s:SkinnablePopUpContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="100%"
height="100%"
styleName="changeStatusPopUp">
<s:VGroup width="100%"
horizontalAlign="center"
verticalAlign="middle">
<s:List id="statusList0"
width="100%"
contentBackgroundAlpha="0"
itemRenderer="org.bigbluebutton.air.main.views.menubuttons.changestatus.StatusItemRenderer"
height="100%"
labelField="data"
verticalScrollPolicy="off"
horizontalScrollPolicy="off">
<s:ArrayList>
<fx:Object data="{resourceManager.getString('resources', 'profile.settings.beRightBack')}"
signal="away" />
<fx:Object data="{resourceManager.getString('resources', 'profile.settings.handRaise')}"
signal="raiseHand" />
<fx:Object data="{resourceManager.getString('resources', 'profile.settings.neutral')}"
signal="neutral" />
<fx:Object data="{resourceManager.getString('resources', 'profile.settings.confused')}"
signal="confused" />
<fx:Object data="{resourceManager.getString('resources', 'profile.settings.sad')}"
signal="sad" />
<fx:Object data="{resourceManager.getString('resources', 'profile.settings.laughter')}"
signal="happy" />
<fx:Object data="{resourceManager.getString('resources', 'profile.settings.clearStatus')}"
signal="none" />
</s:ArrayList>
</s:List>
</s:VGroup>
</s:SkinnablePopUpContainer>

View File

@ -0,0 +1,77 @@
package org.bigbluebutton.air.main.views.menubuttons.changestatus {
import flash.events.MouseEvent;
import flashx.textLayout.container.ScrollPolicy;
import mx.collections.ArrayCollection;
import mx.core.ClassFactory;
import mx.core.FlexGlobals;
import mx.events.FlexMouseEvent;
import org.bigbluebutton.air.main.models.IUserUISession;
import org.bigbluebutton.lib.main.commands.EmojiSignal;
import org.bigbluebutton.lib.main.models.IUserSession;
import robotlegs.bender.bundles.mvcs.Mediator;
import spark.components.SkinnablePopUpContainer;
import spark.layouts.HorizontalLayout;
import spark.layouts.VerticalLayout;
public class ChangeStatusPopUpMediator extends Mediator {
[Inject]
public var userSession:IUserSession;
[Inject]
public var view:IChangeStatusPopUp;
[Inject]
public var emojiSignal:EmojiSignal;
protected var dataProvider:ArrayCollection;
override public function initialize():void {
view.statusList.addEventListener(MouseEvent.CLICK, onSelectStatus);
for (var i:Number = 0; i < view.statusList.dataProvider.length; i++) {
if (userSession.userList.me.status == view.statusList.dataProvider.getItemAt(i).signal) {
view.statusList.setSelectedIndex(i);
break;
}
}
updateListOrientation();
(view as SkinnablePopUpContainer).addEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE, closePopUp);
}
private function closePopUp(e:FlexMouseEvent):void {
(view as SkinnablePopUpContainer).close(false);
}
private function updateListOrientation():void {
if (FlexGlobals.topLevelApplication.aspectRatio == "landscape") {
view.statusList.layout = new HorizontalLayout();
view.statusList.width = FlexGlobals.topLevelApplication.width;
view.statusList.setStyle('verticalScrollPolicy', ScrollPolicy.OFF);
view.statusList.itemRenderer = new ClassFactory(HorizontalStatusItemRenderer);
} else {
}
}
private function onSelectStatus(event:MouseEvent):void {
var obj:Object;
obj = view.statusList.selectedItem;
emojiSignal.dispatch(view.statusList.selectedItem.signal);
(view as SkinnablePopUpContainer).close();
}
override public function destroy():void {
view.statusList.addEventListener(MouseEvent.CLICK, onSelectStatus);
view.dispose();
view = null;
super.destroy();
}
}
}

View File

@ -0,0 +1,106 @@
<?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"
autoDrawBackground="false"
styleName="statusItemStyle">
<s:states>
<s:State name="normal" />
<s:State name="selected" />
</s:states>
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import org.bigbluebutton.lib.user.models.User;
override public function set data(obj:Object):void {
super.data = obj;
if (obj) {
profileIcon.visible = profileIcon.includeInLayout = obj.signal == User.NO_STATUS;
handIcon.visible = handIcon.includeInLayout = obj.signal == User.RAISE_HAND;
beRightBackIcon.visible = beRightBackIcon.includeInLayout = obj.signal == User.AWAY;
laughterIcon.visible = laughterIcon.includeInLayout = obj.signal == User.HAPPY;
sadIcon.visible = sadIcon.includeInLayout = obj.signal == User.SAD;
}
}
]]>
</fx:Script>
<s:Group id="content">
<s:layout>
<s:VerticalLayout horizontalAlign="center"
verticalAlign="middle" />
</s:layout>
<s:Label id="labelDisplay"
width="{icon.width * 2}"
textAlign="center"
lineBreak="explicit"
styleName="contentFontSize" />
<s:Group id="icon">
<s:Button id="profileIcon"
styleName="bottomPresentationBtnStyle noStatusButtonStyle"
height="100%" />
<s:Button id="handIcon"
styleName="bottomPresentationBtnStyle handStatusButtonStyle"
height="100%" />
<s:Button id="beRightBackIcon"
styleName="bottomPresentationBtnStyle beRightBackStatusButtonStyle"
height="100%" />
<s:Button id="laughterIcon"
styleName="bottomPresentationBtnStyle laughterStatusButtonStyle"
height="100%" />
<s:Button id="sadIcon"
styleName="bottomPresentationBtnStyle sadStatusButtonStyle"
height="100%" />
</s:Group>
</s:Group>
<s:Group visible.normal="false"
width="100%"
x="{icon.x + icon.width - selectionCircle.width/1.5}"
y="{icon.y + icon.height/4}"
height="100%">
<s:Ellipse id="selectionCircle"
height="25%"
width="{selectionCircle.height}">
<s:fill>
<s:SolidColor color="{getStyle('selectedColor')}" />
</s:fill>
</s:Ellipse>
<s:Ellipse id="innerSelectionCircle"
height="{selectionCircle.height * 0.7}"
width="{innerSelectionCircle.height}"
x="{selectionCircle.x + (selectionCircle.width - innerSelectionCircle.width)/2}"
y="{selectionCircle.y + (selectionCircle.height - innerSelectionCircle.height)/2}">
<s:stroke>
<s:SolidColorStroke color="{getStyle('strokeColor')}" />
</s:stroke>
</s:Ellipse>
<s:Line id="selectedLine1"
xFrom="{innerSelectionCircle.x + innerSelectionCircle.width / 3.2}"
xTo="{innerSelectionCircle.x + innerSelectionCircle.width / 2.3}"
yFrom="{innerSelectionCircle.y + innerSelectionCircle.height / 2}"
yTo="{innerSelectionCircle.y + innerSelectionCircle.height / 1.5}">
<s:stroke>
<s:SolidColorStroke color="{getStyle('strokeColor')}" />
</s:stroke>
</s:Line>
<s:Line id="selectedLine2"
xFrom="{innerSelectionCircle.x + innerSelectionCircle.width / 1.4}"
xTo="{innerSelectionCircle.x + innerSelectionCircle.width / 2.3}"
yFrom="{innerSelectionCircle.y + innerSelectionCircle.height / 2.5}"
yTo="{innerSelectionCircle.y + innerSelectionCircle.height / 1.5}">
<s:stroke>
<s:SolidColorStroke color="{getStyle('strokeColor')}" />
</s:stroke>
</s:Line>
</s:Group>
</s:ItemRenderer>

View File

@ -0,0 +1,10 @@
package org.bigbluebutton.air.main.views.menubuttons.changestatus {
import org.bigbluebutton.air.common.views.IView;
import spark.components.List;
public interface IChangeStatusPopUp extends IView {
function get statusList():List;
}
}

View File

@ -0,0 +1,118 @@
<?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"
autoDrawBackground="false"
styleName="statusItemStyle">
<s:states>
<s:State name="normal" />
<s:State name="selected" />
</s:states>
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import org.bigbluebutton.lib.user.models.User;
override public function set data(obj:Object):void {
super.data = obj;
if (obj) {
clearStatusIcon.visible = clearStatusIcon.includeInLayout = obj.signal == User.NO_STATUS;
handIcon.visible = handIcon.includeInLayout = obj.signal == User.RAISE_HAND;
beRightBackIcon.visible = beRightBackIcon.includeInLayout = obj.signal == User.AWAY;
happyIcon.visible = happyIcon.includeInLayout = obj.signal == User.HAPPY;
sadIcon.visible = sadIcon.includeInLayout = obj.signal == User.SAD;
confusedIcon.visible = confusedIcon.includeInLayout = obj.signal == User.CONFUSED;
undecidedIcon.visible = undecidedIcon.includeInLayout = obj.signal == User.NEUTRAL;
}
}
]]>
</fx:Script>
<s:Group id="content"
width="100%"
height="{getStyle('itemHeight')}">
<s:layout>
<s:HorizontalLayout verticalAlign="middle"
horizontalAlign="right"
paddingLeft="{getStyle('itemPaddingLeft')}"
paddingRight="{getStyle('itemPaddingRight')}" />
</s:layout>
<s:Label id="labelDisplay"
textAlign="right"
width="100%"
height="100%"
styleName="contentFontSize" />
<s:Group id="icon">
<s:Button id="beRightBackIcon"
styleName="bottomPresentationBtnStyle beRightBackStatusButtonStyle"
height="100%" />
<s:Button id="handIcon"
styleName="bottomPresentationBtnStyle handStatusButtonStyle"
height="100%" />
<s:Button id="undecidedIcon"
styleName="bottomPresentationBtnStyle undecidedStatusButtonStyle"
height="100%" />
<s:Button id="confusedIcon"
styleName="bottomPresentationBtnStyle confusedStatusButtonStyle"
height="100%" />
<s:Button id="sadIcon"
styleName="bottomPresentationBtnStyle sadStatusButtonStyle"
height="100%" />
<s:Button id="happyIcon"
styleName="bottomPresentationBtnStyle happyStatusButtonStyle"
height="100%" />
<s:Button id="clearStatusIcon"
styleName="bottomPresentationBtnStyle clearStatusButtonStyle"
height="100%" />
</s:Group>
</s:Group>
<s:Group visible.normal="false"
width="100%"
x="{icon.x + icon.width - selectionCircle.width/1.5}"
y="{icon.y + icon.height/4}"
height="100%">
<s:Ellipse id="selectionCircle"
height="30%"
width="{selectionCircle.height}">
<s:fill>
<s:SolidColor color="{getStyle('selectedColor')}" />
</s:fill>
</s:Ellipse>
<s:Ellipse id="innerSelectionCircle"
height="{selectionCircle.height * 0.7}"
width="{innerSelectionCircle.height}"
x="{selectionCircle.x + (selectionCircle.width - innerSelectionCircle.width)/2}"
y="{selectionCircle.y + (selectionCircle.height - innerSelectionCircle.height)/2}">
<s:stroke>
<s:SolidColorStroke color="{getStyle('strokeColor')}" />
</s:stroke>
</s:Ellipse>
<s:Line id="selectedLine1"
xFrom="{innerSelectionCircle.x + innerSelectionCircle.width / 3.2}"
xTo="{innerSelectionCircle.x + innerSelectionCircle.width / 2.3}"
yFrom="{innerSelectionCircle.y + innerSelectionCircle.height / 2}"
yTo="{innerSelectionCircle.y + innerSelectionCircle.height / 1.5}">
<s:stroke>
<s:SolidColorStroke color="{getStyle('strokeColor')}" />
</s:stroke>
</s:Line>
<s:Line id="selectedLine2"
xFrom="{innerSelectionCircle.x + innerSelectionCircle.width / 1.4}"
xTo="{innerSelectionCircle.x + innerSelectionCircle.width / 2.3}"
yFrom="{innerSelectionCircle.y + innerSelectionCircle.height / 2.5}"
yTo="{innerSelectionCircle.y + innerSelectionCircle.height / 1.5}">
<s:stroke>
<s:SolidColorStroke color="{getStyle('strokeColor')}" />
</s:stroke>
</s:Line>
</s:Group>
</s:ItemRenderer>

View File

@ -1,15 +1,16 @@
package org.bigbluebutton.air.main.views.profile {
import org.bigbluebutton.air.common.views.IView;
import spark.components.Button;
import spark.components.Label;
public interface IProfileView extends IView {
function get firstLetters():Label;
function get userName():Label;
function get shareCameraButton():Button;
function get shareCameraBtnLabel():String;
function get shareMicButton():Button;
function get shareMicBtnLabel():String;
function get statusButton():Button;
function get logoutButton():Button;
function get currentState():String;
function set currentState(value:String):void;

View File

@ -1,6 +1,7 @@
package org.bigbluebutton.air.main.views.profile {
import spark.components.Button;
import spark.components.Label;
public class ProfileView extends ProfileViewBase implements IProfileView {
override protected function childrenCreated():void {
@ -10,6 +11,14 @@ package org.bigbluebutton.air.main.views.profile {
public function dispose():void {
}
public function get firstLetters():Label {
return firstLetters0;
}
public function get userName():Label {
return userName0;
}
public function get shareCameraButton():Button {
return shareCameraBtn0;
}
@ -22,10 +31,6 @@ package org.bigbluebutton.air.main.views.profile {
return shareMicBtn0;
}
public function get statusButton():Button {
return statusBtn0;
}
public function get shareMicBtnLabel():String {
return shareMicBtn0.label;
}

View File

@ -3,54 +3,111 @@
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:view="org.bigbluebutton.air.common.views.*"
styleName="audioSettingsStyle">
styleName="settingsStyle">
<fx:Script>
<![CDATA[
import mx.core.FlexGlobals;
import mx.events.FlexEvent;
import org.bigbluebutton.air.common.views.PagesENUM
import org.bigbluebutton.air.common.views.TransitionAnimationENUM;
]]>
</fx:Script>
<s:Scroller width="100%"
height="100%">
<s:VGroup width="100%"
height="100%"
horizontalAlign="center"
gap="1">
<s:Button id="statusBtn0"
visible="false"
includeInLayout="false"
width="100%"
label="{resourceManager.getString('resources', 'profile.status.title')}"
styleName="videoAudioSettingStyle contentFontSize" />
<s:Group>
<s:Button id="shareCameraBtn0"
width="100%"
label="{resourceManager.getString('resources', 'cameraSettings.title')}"
styleName="cameraSettingsButtonStyle profileSettingsButtonStyle videoAudioSettingStyle contentFontSize" />
<s:Button id="shareMicBtn0"
width="100%"
label="{resourceManager.getString('resources', 'audioSettings.title')}"
styleName="audioSettingsButtonStyle profileSettingsButtonStyle videoAudioSettingStyle contentFontSize" />
<s:Button id="lockViewersBtn"
width="100%"
label="{resourceManager.getString('resources', 'management.lockViewers')}"
styleName="lockParticipantsButtonStyle profileSettingsButtonStyle videoAudioSettingStyle contentFontSize" />
<s:Button id="clearAllStatusBtn"
width="100%"
label="{resourceManager.getString('resources', 'management.clearAllStatus')}"
styleName="clearButtonStyle videoAudioSettingStyle contentFontSize" />
<s:Button id="unmuteAllBtn"
width="100%"
label="{resourceManager.getString('resources', 'management.unmuteAll')}"
styleName="audioSettingsShareMicButtonStyle videoAudioSettingStyle contentFontSize" />
<s:Button id="muteAllBtn"
width="100%"
label="{resourceManager.getString('resources', 'management.muteAll')}"
styleName="MuteButtonStyle videoAudioSettingStyle contentFontSize" />
<s:Button id="muteAllExceptPresenterBtn"
width="100%"
label="{resourceManager.getString('resources', 'management.muteAllExceptPresenter')}"
styleName="MuteButtonStyle videoAudioSettingStyle contentFontSize" />
<s:VGroup width="100%"
height="100%"
horizontalAlign="center"
gap="0">
<s:Button id="logoutButton0"
width="100%"
label="{resourceManager.getString('resources', 'profile.logout')}"
styleName="QuitButtonStyle videoAudioSettingStyle contentFontSize" />
</s:VGroup>
<s:Group height="{getStyle('topRectHeight')}"
width="100%">
<s:Rect width="100%"
height="100%">
<s:fill>
<s:SolidColor color="{getStyle('rectangleColor')}" />
</s:fill>
</s:Rect>
<s:VGroup horizontalAlign="center"
verticalAlign="middle"
width="100%"
height="100%">
<s:Label id="firstLetters0"
styleName="settingsUserFirstLettersStyle" />
<s:Spacer height="25%" />
<s:Label id="userName0"
styleName="settingsUserNameStyle contentFontSize" />
</s:VGroup>
</s:Group>
<s:Group width="100%"
height="{getStyle('itemHeight')}">
<s:Rect width="100%"
height="100%">
<s:fill>
<s:SolidColor color="{getStyle('subRectangleColor')}" />
</s:fill>
</s:Rect>
<s:HGroup height="100%">
<s:Spacer width="2%" />
<s:Label text="{resourceManager.getString('resources', 'profile.subtitle')}"
styleName="settingsSubtitleStyle subContentFontSize"
height="100%" />
</s:HGroup>
</s:Group>
<s:Button id="shareMicBtn0"
width="100%"
label="{resourceManager.getString('resources', 'audioSettings.title')}"
styleName="audioSettingsButtonStyle profileSettingsButtonStyle videoAudioSettingStyle contentFontSize" />
<s:Button id="shareCameraBtn0"
width="100%"
label="{resourceManager.getString('resources', 'cameraSettings.title')}"
styleName="cameraSettingsButtonStyle profileSettingsButtonStyle videoAudioSettingStyle contentFontSize" />
<s:Button id="lockViewersBtn"
width="100%"
label="{resourceManager.getString('resources', 'management.lockViewers')}"
styleName="lockParticipantsButtonStyle profileSettingsButtonStyle videoAudioSettingStyle contentFontSize" />
<s:Button id="clearAllStatusBtn"
width="100%"
label="{resourceManager.getString('resources', 'management.clearAllStatus')}"
styleName="clearButtonStyle videoAudioSettingStyle contentFontSize" />
<s:Button id="unmuteAllBtn"
width="100%"
label="{resourceManager.getString('resources', 'management.unmuteAll')}"
styleName="audioSettingsShareMicButtonStyle videoAudioSettingStyle contentFontSize" />
<s:Button id="muteAllBtn"
width="100%"
label="{resourceManager.getString('resources', 'management.muteAll')}"
styleName="MuteButtonStyle videoAudioSettingStyle contentFontSize" />
<s:Button id="muteAllExceptPresenterBtn"
width="100%"
label="{resourceManager.getString('resources', 'management.muteAllExceptPresenter')}"
styleName="MuteButtonStyle videoAudioSettingStyle contentFontSize" />
<s:Button id="logoutButton0"
width="100%"
label="{resourceManager.getString('resources', 'profile.logout')}"
styleName="QuitButtonStyle videoAudioSettingStyle contentFontSize" />
</s:VGroup>
</s:Group>
</s:Scroller>
<s:Ellipse id="circle"
height="{firstLetters0.height * 3}"
width="{circle.height}"
x="{firstLetters0.x - (circle.width - firstLetters0.width)/2}"
y="{firstLetters0.y - (circle.height - firstLetters0.height)/2}">
<s:stroke>
<s:SolidColorStroke id="circleColor"
color="{getStyle('circleColor')}"
weight="1" />
</s:stroke>
</s:Ellipse>
</view:NoTabView>

View File

@ -2,11 +2,9 @@ package org.bigbluebutton.air.main.views.profile {
import flash.events.Event;
import flash.events.MouseEvent;
import mx.core.FlexGlobals;
import mx.events.ResizeEvent;
import mx.resources.ResourceManager;
import org.bigbluebutton.air.common.views.PagesENUM;
import org.bigbluebutton.air.common.views.SplitViewEvent;
import org.bigbluebutton.air.main.models.IUserUISession;
@ -18,7 +16,6 @@ package org.bigbluebutton.air.main.views.profile {
import org.bigbluebutton.lib.main.models.IUserSession;
import org.bigbluebutton.lib.user.models.User;
import org.bigbluebutton.lib.user.services.IUsersService;
import robotlegs.bender.bundles.mvcs.Mediator;
public class ProfileViewMediator extends Mediator {
@ -54,7 +51,6 @@ package org.bigbluebutton.air.main.views.profile {
override public function initialize():void {
var userMe:User = userSession.userList.me;
changeStatusIcon(userMe.status);
disableCamButton(userSession.lockSettings.disableCam && !userMe.presenter && userMe.locked && userMe.role != User.MODERATOR);
userSession.lockSettings.disableCamSignal.add(disableCamButton);
if (userMe.role != User.MODERATOR) {
@ -68,42 +64,28 @@ package org.bigbluebutton.air.main.views.profile {
}
userSession.userList.userChangeSignal.add(userChanged);
view.logoutButton.addEventListener(MouseEvent.CLICK, logoutClick);
FlexGlobals.topLevelApplication.pageName.text = ResourceManager.getInstance().getString('resources', 'profile.title');
FlexGlobals.topLevelApplication.profileBtn.visible = false;
FlexGlobals.topLevelApplication.backBtn.visible = true;
FlexGlobals.topLevelApplication.topActionBar.pageName.text = ResourceManager.getInstance().getString('resources', 'profile.title');
addNavigationListeners();
setNameLabels();
}
private function changeStatusIcon(status:String) {
switch (status) {
case User.RAISE_HAND:
view.statusButton.styleName = "handStatusButtonStyle videoAudioSettingStyle contentFontSize";
break;
case User.AWAY:
view.statusButton.styleName = "beRightBackStatusButtonStyle";
break;
case User.HAPPY:
view.statusButton.styleName = "laughterStatusButtonStyle";
break;
case User.SAD:
view.statusButton.styleName = "sadStatusButtonStyle";
break;
case User.NO_STATUS:
view.statusButton.styleName = "noStatusButtonStyle";
break;
private function setNameLabels():void {
view.userName.text = userSession.userList.me.name;
var names:Array = view.userName.text.split(" ");
var firstLetters:String = names[0].charAt(0);
if (names[1]) {
firstLetters += names[1].charAt(0);
}
view.statusButton.styleName += " profileSettingsButtonStyle videoAudioSettingStyle contentFontSize";
view.firstLetters.text = firstLetters.toUpperCase();
}
private function addNavigationListeners():void {
view.statusButton.addEventListener(MouseEvent.CLICK, navigateToStatus);
view.shareCameraButton.addEventListener(MouseEvent.CLICK, navigateToCameraSettings);
view.shareMicButton.addEventListener(MouseEvent.CLICK, navigateToAudioSettings);
view.lockViewersButton.addEventListener(MouseEvent.CLICK, navigateToLockSettings);
}
private function removeNavigationListeners():void {
view.statusButton.removeEventListener(MouseEvent.CLICK, navigateToStatus);
view.shareCameraButton.removeEventListener(MouseEvent.CLICK, navigateToCameraSettings);
view.shareMicButton.removeEventListener(MouseEvent.CLICK, navigateToAudioSettings);
view.lockViewersButton.removeEventListener(MouseEvent.CLICK, navigateToLockSettings);
@ -191,7 +173,6 @@ package org.bigbluebutton.air.main.views.profile {
private function userChanged(user:User, type:int):void {
if (userSession.userList.me.userID == user.userID) {
changeStatusIcon(user.status);
if (userSession.userList.me.role == User.MODERATOR) {
displayManagementButtons(true);
setMuteState(userSession.meetingMuted);

View File

@ -14,24 +14,20 @@
<s:State name="up" />
</s:states>
<s:Rect top="0"
bottom="0"
right="0"
left="0">
<s:stroke>
<s:SolidColorStroke color="{hostComponent.getStyle('strokeColor')}"
weight="{hostComponent.getStyle('strokeWeight')}"
alpha="0.5" />
</s:stroke>
<s:Ellipse id="backgroundEllipse" height="{image.height * 3/2}" width="{backgroundEllipse.height}"
x="{(this.width - backgroundEllipse.width)/2}"
y="{(this.height - backgroundEllipse.height)/2}">
<s:fill>
<s:SolidColor color="{hostComponent.getStyle('backgroundColor')}"
color.down="{hostComponent.getStyle('selectedBackgroundColor')}" />
</s:fill>
</s:Rect>
</s:Ellipse>
<s:BitmapImage id="image"
source="{getStyle('backgroundImage')}"
horizontalCenter="0"
verticalCenter="0" />
<s:Label id="iconLabel" text="{hostComponent.label}" x="{(this.width - iconLabel.width)/2}" y="{backgroundEllipse.y + backgroundEllipse.height * 9/8}" />
<s:Ellipse id="notification"
visible="false"

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<!-- host component -->
<fx:Metadata>
[HostComponent("spark.components.Button")]
</fx:Metadata>
<!-- states -->
<s:states>
<s:State name="disabled" />
<s:State name="down" />
<s:State name="over" />
<s:State name="up" />
</s:states>
<s:Ellipse id="backgroundEllipse"
height="{image.height * 3/2}"
width="{backgroundEllipse.height}"
x="{(this.width - backgroundEllipse.width)/2}"
y="{(this.height - backgroundEllipse.height)/2}">
<s:fill>
<s:SolidColor color="{hostComponent.getStyle('backgroundColor')}"
color.down="{hostComponent.getStyle('selectedBackgroundColor')}" />
</s:fill>
</s:Ellipse>
<s:BitmapImage id="image"
source="{getStyle('backgroundImage')}"
horizontalCenter="0"
verticalCenter="0" />
<s:Label id="iconLabel"
text="{hostComponent.label}"
x="{(this.width - iconLabel.width)/2}"
y="{backgroundEllipse.y + backgroundEllipse.height * 9/8}" />
</s:Skin>

View File

@ -20,7 +20,8 @@
width="100%">
<s:fill>
<s:SolidColor color="{hostComponent.getStyle('backgroundColor')}"
color.down="{hostComponent.getStyle('onClickBackgroundColor')}" />
color.down="{hostComponent.getStyle('onClickBackgroundColor')}"
color.disabled="{hostComponent.getStyle('disabledBackgroundColor')}" />
</s:fill>
</s:Rect>
<s:Label width="100%"

View File

@ -16,9 +16,7 @@
<s:State name="upAndSelected" />
<s:State name="downAndSelected" />
</s:states>
<s:Rect radiusX="{getStyle('radiusX')}"
radiusY="{getStyle('radiusY')}"
height="{hostComponent.getStyle('height')}"
<s:Rect height="{hostComponent.getStyle('height')}"
width="100%">
<s:fill>
<s:SolidColor color="{hostComponent.getStyle('backgroundColor')}"

View File

@ -1,16 +1,25 @@
package org.bigbluebutton.air.presentation.views {
import flash.media.Video;
import flash.net.NetConnection;
import mx.controls.SWFLoader;
import org.bigbluebutton.air.common.views.IView;
import org.bigbluebutton.lib.presentation.models.Slide;
import org.bigbluebutton.lib.presentation.views.IPresentationView;
import org.bigbluebutton.lib.whiteboard.views.WhiteboardCanvas;
import spark.components.Group;
import spark.components.Label;
import spark.components.VideoDisplay;
public interface IPresentationViewAir extends IPresentationView {
function get videoStream():VideoDisplay;
function rotationHandler(rotation:String):void;
function dispose():void;
function get showSharedCams():Label;
function get showSharedCamsGroup():Group;
function get videoGroup():Group
function get video():Video;
function stopStream():void
function startStream(connection:NetConnection, name:String, streamName:String, userID:String, width:Number, height:Number, screenHeight:Number, screenWidth:Number):void
}
}

View File

@ -3,23 +3,39 @@ package org.bigbluebutton.air.presentation.views {
import flash.display.StageOrientation;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.media.Video;
import flash.net.NetConnection;
import flash.system.ApplicationDomain;
import flash.system.LoaderContext;
import mx.controls.SWFLoader;
import mx.core.FlexGlobals;
import org.bigbluebutton.air.video.views.videochat.VideoChatVideoView;
import org.bigbluebutton.lib.presentation.models.Slide;
import org.bigbluebutton.lib.presentation.views.IPresentationView;
import org.bigbluebutton.lib.whiteboard.views.WhiteboardCanvas;
import spark.components.Group;
import spark.components.Label;
import spark.components.VideoDisplay;
public class PresentationView extends PresentationViewBase implements IPresentationViewAir {
private var webcam:VideoChatVideoView;
override protected function childrenCreated():void {
super.childrenCreated();
}
public function get videoStream():VideoDisplay {
return videostream;
}
public function get showSharedCams():Label {
return showSharedCams0;
}
public function get showSharedCamsGroup():Group {
return showSharedCamsGroup0;
}
public function get content():Group {
return content0;
}
@ -37,7 +53,7 @@ package org.bigbluebutton.air.presentation.views {
}
public function setPresentationName(name:String):void {
FlexGlobals.topLevelApplication.pageName.text = name;
FlexGlobals.topLevelApplication.topActionBar.pageName.text = name;
}
public function setSlide(s:Slide):void {
@ -73,7 +89,45 @@ package org.bigbluebutton.air.presentation.views {
}
}
public function startStream(connection:NetConnection, name:String, streamName:String, userID:String, width:Number, height:Number, screenHeight:Number, screenWidth:Number):void {
if (webcam)
stopStream();
webcam = new VideoChatVideoView();
webcam.percentWidth = 100;
webcam.percentHeight = 100;
videoStream.addChild(webcam.videoViewVideo);
this.videoGroup.addElement(webcam);
var topActionBarHeight:Number = FlexGlobals.topLevelApplication.topActionBar.height;
var bottomMenuHeight:Number = FlexGlobals.topLevelApplication.bottomMenu.height;
webcam.initializeScreenSizeValues(width, height, screenHeight, screenWidth, topActionBarHeight, bottomMenuHeight);
webcam.startStream(connection, name, streamName, userID);
webcam.setVideoPosition(name);
}
public function stopStream():void {
if (webcam) {
webcam.close();
if (this.videoGroup.containsElement(webcam)) {
this.videoGroup.removeElement(webcam);
}
webcam = null;
}
}
public function get video():Video {
if (webcam) {
return webcam.videoViewVideo;
} else {
return null;
}
}
public function get videoGroup():Group {
return videoGroup0;
}
public function dispose():void {
stopStream();
}
}
}

View File

@ -3,7 +3,8 @@
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:common="org.bigbluebutton.air.common.views.*"
xmlns:whiteboard="org.bigbluebutton.lib.whiteboard.views.*">
xmlns:whiteboard="org.bigbluebutton.lib.whiteboard.views.*"
styleName="presentationStyle">
<s:Group id="content0"
width="100%"
@ -26,5 +27,38 @@
height="100%" />
<whiteboard:WhiteboardCanvas id="whiteboardCanvas0" />
</s:Group>
<s:Spacer height="2%" />
<s:Group id="videoGroup0"
width="{videostream.width}">
<s:filters>
<s:DropShadowFilter distance="0"
quality="1"
strength="1"
blurX="14"
blurY="14"
alpha="0.8" />
</s:filters>
<s:VideoDisplay id="videostream"
width="100%"
styleName="videoTextFieldStyle" />
</s:Group>
<s:HGroup id="showSharedCamsGroup0"
horizontalAlign="center"
visible="false"
includeInLayout="false">
<s:Image id="cameraIcon"
height="100%"
styleName="iconStyle cameraIconStyle" />
<s:Label id="showSharedCams0"
height="100%"
styleName="showSharedCamsLabel" />
</s:HGroup>
</s:Group>
</common:NoTabView>

View File

@ -1,13 +1,25 @@
package org.bigbluebutton.air.presentation.views {
import flash.display.DisplayObjectContainer;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.events.TouchEvent;
import flash.events.TransformGestureEvent;
import flash.utils.Timer;
import mx.collections.ArrayCollection;
import mx.core.DragSource;
import mx.core.FlexGlobals;
import mx.events.ResizeEvent;
import mx.managers.DragManager;
import mx.managers.PopUpManager;
import mx.resources.ResourceManager;
import org.bigbluebutton.air.common.views.PagesENUM;
import org.bigbluebutton.air.main.models.IUserUISession;
import org.bigbluebutton.air.presentation.views.selectWebcam.SelectStreamPopUp;
import org.bigbluebutton.air.presentation.views.selectWebcam.SelectStreamPopUpBase;
import org.bigbluebutton.lib.main.models.IUserSession;
import org.bigbluebutton.lib.presentation.commands.LoadSlideSignal;
import org.bigbluebutton.lib.presentation.models.Presentation;
@ -16,6 +28,16 @@ package org.bigbluebutton.air.presentation.views {
import org.bigbluebutton.lib.presentation.services.IPresentationService;
import org.bigbluebutton.lib.presentation.utils.CursorIndicator;
import org.bigbluebutton.lib.presentation.views.PresentationMediator;
import org.bigbluebutton.lib.user.models.User;
import org.bigbluebutton.lib.user.models.UserList;
import org.bigbluebutton.lib.video.models.UserStreamName;
import org.bigbluebutton.lib.video.models.VideoProfile;
import robotlegs.bender.extensions.mediatorMap.api.IMediatorMap;
import spark.components.SkinnablePopUpContainer;
import spark.components.VideoDisplay;
import spark.events.PopUpEvent;
public class PresentationViewMediator extends PresentationMediator {
@ -25,12 +47,435 @@ package org.bigbluebutton.air.presentation.views {
[Inject]
public var userUISession:IUserUISession;
[Inject]
public var mediatorMap:IMediatorMap;
private var speaker:User = null;
protected var dataProvider:ArrayCollection;
private var manualSelection:Boolean = false;
private var changeStream:Boolean = true;
private var camerasHidden:Boolean = false;
private var videoOffsetX:Number;
private var videoOffsetY:Number;
private var originalVideoX:Number;
private var originalVideoY:Number;
private var videoMovedDistanceX:Number = 0;
private var videoMovedDistanceY:Number = 0;
var overlayTimer:Timer = new Timer(3.5 * 1000, 1);
override public function initialize():void {
super.initialize();
view.slide.addEventListener(TransformGestureEvent.GESTURE_SWIPE, swipehandler);
userSession.userList.userChangeSignal.add(userChangeHandler);
FlexGlobals.topLevelApplication.stage.addEventListener(ResizeEvent.RESIZE, stageOrientationChangingHandler);
FlexGlobals.topLevelApplication.backBtn.visible = false;
FlexGlobals.topLevelApplication.profileBtn.visible = true;
FlexGlobals.topLevelApplication.topActionBar.backBtn.visible = false;
FlexGlobals.topLevelApplication.topActionBar.profileBtn.visible = true;
view.content.addEventListener(MouseEvent.CLICK, showOverlay);
dataProvider = new ArrayCollection();
var users:ArrayCollection = userSession.userList.users;
for each (var u:User in users) {
if (u.streamName && u.streamName != "" && !dataProvider.contains(u)) {
addUserStreamNames(u);
}
}
var selectedUserProfile:User = userUISession.currentPageDetails as User;
var displayUserStreamName:UserStreamName = null;
if (selectedUserProfile) {
var userStreamNames:Array = getUserStreamNamesByUserID(selectedUserProfile.userID);
displayUserStreamName = userStreamNames[0];
}
if (displayUserStreamName) {
startStream(selectedUserProfile, displayUserStreamName.streamName);
//displayVideo(true);
} else {
globalVideoStreamNameHandler();
}
setTemporaryOverlay();
var displayUser:User;
for each (var u:User in users) {
if (u.streamName && u.streamName != "") {
displayUser = u;
}
}
if (displayUser) {
startStream(displayUser, displayUser.streamName);
}
(view as IPresentationViewAir).videoStream.addEventListener(MouseEvent.CLICK, changeWebcamStream);
(view as IPresentationViewAir).showSharedCamsGroup.addEventListener(MouseEvent.CLICK, changeWebcamStream);
view.slide.addEventListener(ResizeEvent.RESIZE, presentationUpdated);
}
private function presentationUpdated(e:ResizeEvent):void {
setCamPosition();
}
private function setTemporaryOverlay():void {
FlexGlobals.topLevelApplication.topActionBar.visible = false;
FlexGlobals.topLevelApplication.topActionBar.includeInLayout = false;
FlexGlobals.topLevelApplication.topActionBar.skin.setCurrentState("transparent");
FlexGlobals.topLevelApplication.bottomMenu.visible = false;
FlexGlobals.topLevelApplication.bottomMenu.includeInLayout = false;
updatePresentationDimensions();
}
private function stageOrientationChangingHandler(e:Event):void {
updatePresentationDimensions();
FlexGlobals.topLevelApplication.bottomMenu.width = FlexGlobals.topLevelApplication.width;
FlexGlobals.topLevelApplication.bottomMenu.y = FlexGlobals.topLevelApplication.height - FlexGlobals.topLevelApplication.bottomMenu.height;
FlexGlobals.topLevelApplication.topActionBar.width = FlexGlobals.topLevelApplication.width;
setCamPosition();
}
private function isVideoOutsideOfTheScreen():Boolean {
return ((view as IPresentationViewAir).slide.height + (view as IPresentationViewAir).video.height > FlexGlobals.topLevelApplication.height)
}
private function setCamPosition():void {
(view as IPresentationViewAir).videoStream.x = 0;
(view as IPresentationViewAir).videoStream.y = 0;
if ((view as IPresentationViewAir).video && isVideoOutsideOfTheScreen()) {
(view as IPresentationViewAir).videoStream.addEventListener(MouseEvent.MOUSE_DOWN, moveCamBegin);
(view as IPresentationViewAir).videoStream.addEventListener(MouseEvent.MOUSE_UP, moveCamEnd);
(view as IPresentationViewAir).videoGroup.includeInLayout = false;
(view as IPresentationViewAir).videoGroup.y = FlexGlobals.topLevelApplication.height - (view as IPresentationViewAir).videoGroup.height * 1.1;
if (FlexGlobals.topLevelApplication.aspectRatio == "landscape") {
(view as IPresentationViewAir).videoGroup.x = FlexGlobals.topLevelApplication.width - (view as IPresentationViewAir).video.width / 1.7;
} else {
(view as IPresentationViewAir).videoGroup.x = (FlexGlobals.topLevelApplication.width - (view as IPresentationViewAir).videoGroup.width) / 2;
}
} else {
(view as IPresentationViewAir).videoStream.removeEventListener(MouseEvent.MOUSE_DOWN, moveCamBegin);
(view as IPresentationViewAir).videoStream.removeEventListener(MouseEvent.MOUSE_UP, moveCamEnd);
if ((view as IPresentationViewAir).videoGroup.visible) {
(view as IPresentationViewAir).videoGroup.includeInLayout = true;
}
}
}
private function moveCamBegin(e:MouseEvent):void {
e.target.alpha = 0.5;
videoOffsetX = e.stageX - e.target.x;
videoOffsetY = e.stageY - e.target.y;
originalVideoX = (view as IPresentationViewAir).videoStream.x;
originalVideoY = (view as IPresentationViewAir).videoStream.y;
(view as IPresentationViewAir).content.addEventListener(MouseEvent.MOUSE_MOVE, dragCam);
}
private function dragCam(e:MouseEvent):void {
var oldXPos:Number = (view as IPresentationViewAir).videoStream.x;
var oldYPos:Number = (view as IPresentationViewAir).videoStream.y;
(view as IPresentationViewAir).videoStream.x = e.stageX - videoOffsetX;
(view as IPresentationViewAir).videoStream.y = e.stageY - videoOffsetY;
videoMovedDistanceX += Math.abs((view as IPresentationViewAir).videoStream.x - oldXPos);
videoMovedDistanceY += Math.abs((view as IPresentationViewAir).videoStream.y - oldYPos);
e.updateAfterEvent();
}
private function moveCamEnd(e:MouseEvent):void {
e.target.alpha = 1;
if (videoMovedDistanceX < 10 || videoMovedDistanceY < 10) {
(view as IPresentationViewAir).videoStream.x = originalVideoX;
(view as IPresentationViewAir).videoStream.y = originalVideoY;
changeStream = true;
} else {
changeStream = false;
}
videoMovedDistanceX = 0;
videoMovedDistanceY = 0;
(view as IPresentationViewAir).content.removeEventListener(MouseEvent.MOUSE_MOVE, dragCam);
}
private function updatePresentationDimensions():void {
var newWidth:Number = FlexGlobals.topLevelApplication.width;
var newHeight:Number = FlexGlobals.topLevelApplication.height;
_slideModel.parentChange(newWidth, newHeight);
resizePresentation();
}
private function getDisplayedUser():User {
for each (var userStreamName:UserStreamName in dataProvider) {
if (userStreamName.streamName == userUISession.currentStreamName) {
return userStreamName.user;
}
}
return null;
}
private function userChangeHandler(user:User, property:int):void {
if (property == UserList.HAS_STREAM) {
var displayedUser:User = getDisplayedUser();
if (displayedUser) {
if (user.userID == displayedUser.userID && !user.hasStream) {
stopStream(user.userID);
}
}
var userStreamNames:Array = getUserStreamNamesByUserID(user.userID);
for each (var userStreamName:UserStreamName in userStreamNames) {
if (!(userStreamName.user.streamName.indexOf(userStreamName.streamName) >= 0)) {
dataProvider.removeItemAt(dataProvider.getItemIndex(userStreamName));
if (userUISession.currentStreamName == userStreamName.streamName) {
userUISession.currentStreamName = "";
if (!speaker) {
checkVideo();
}
}
}
}
if (user.streamName.split("|").length > userStreamNames.length && user.streamName.length > 0) {
var camNumber:int = dataProvider.length;
addUserStreamNames(user);
if (userUISession.currentStreamName == userSession.userList.me.streamName && camNumber == 1) {
if (!speaker) {
checkVideo();
}
}
}
if (userUISession.currentStreamName == "") {
if (!speaker) {
checkVideo();
}
}
if (dataProvider.length == 0) {
displayVideo(false);
} else {
displayVideo(true && !camerasHidden);
}
} else if (property == UserList.PRESENTER) {
if (!speaker) {
checkVideo();
}
}
dataProvider.refresh();
}
private function checkVideo(changedUser:User = null):void {
if (!manualSelection || userUISession.currentStreamName == "" && userSession.videoConnection.connection) {
// get id of the user that is currently displayed
var currentUser:User = getDisplayedUser();
// get presenter user
var presenter:User = userSession.userList.getPresenter();
// get any user that has video stream
var userWithCamera:User = getUserWithCamera();
var newUser:User;
if (changedUser) {
var userStreamNames:Array = getUserStreamNamesByUserID(changedUser.userID);
// Priority state machine
if (changedUser.presenter && changedUser.hasStream) {
if ((view as IPresentationViewAir))
(view as IPresentationViewAir).stopStream();
startStream(changedUser, userStreamNames[0].streamName);
} else if (currentUser && changedUser.userID == currentUser.userID) {
if (view)
(view as IPresentationViewAir).stopStream();
startStream(changedUser, userStreamNames[0].streamName);
} else if (userWithCamera) {
if (userWithCamera.userID == changedUser.userID) {
if (view)
(view as IPresentationViewAir).stopStream();
startStream(changedUser, userStreamNames[0].streamName);
} else if (!changedUser.hasStream && userWithCamera.me) {
var userStreamNames:Array = getUserStreamNamesByUserID(userWithCamera.userID);
if (view)
(view as IPresentationViewAir).stopStream();
startStream(userWithCamera, userStreamNames[0].streamName);
}
}
} else {
// Priority state machine
if (speaker) {
newUser = speaker;
} else if (presenter != null && presenter.hasStream && !presenter.me) { // if presenter is transmitting a video - put them in first priority
newUser = presenter;
} // current user is the second priority
else if (currentUser != null && currentUser.hasStream && !currentUser.me) {
newUser = currentUser;
} // any user with camera is the last priority
else if (userWithCamera != null && userWithCamera.hasStream) {
newUser = userWithCamera;
} // otherwise, nobody transmitts video at this moment
else {
return;
}
if (newUser) {
var userStreamNames:Array = getUserStreamNamesByUserID(newUser.userID);
var displayUserStreamName:UserStreamName = userStreamNames[0];
for each (var userStreamName:UserStreamName in userStreamNames) {
if (userStreamName.user.hasStream && userUISession.currentStreamName == userStreamName.streamName) {
displayUserStreamName = userStreamName;
break;
}
}
if (view) {
(view as IPresentationViewAir).stopStream();
startStream(newUser, displayUserStreamName.streamName);
displayVideo(true && !camerasHidden);
}
}
}
}
}
protected function getUserWithCamera():User {
var users:ArrayCollection = userSession.userList.users;
var userMe:User = null;
for each (var u:User in users) {
if (u.hasStream) {
if (u.me) {
userMe = u;
} else {
return u;
}
}
}
return userMe;
}
private function displayVideo(value:Boolean):void {
if ((view as IPresentationViewAir).videoGroup) {
(view as IPresentationViewAir).videoGroup.visible = value;
(view as IPresentationViewAir).videoGroup.includeInLayout = value;
}
if (!value) {
userUISession.currentStreamName = "";
} else {
setCamPosition();
}
enableShowCamsButton((dataProvider.length > 0) && !value);
}
private function enableShowCamsButton(enable:Boolean):void {
(view as IPresentationViewAir).showSharedCamsGroup.visible = enable;
(view as IPresentationViewAir).showSharedCamsGroup.includeInLayout = enable;
(view as IPresentationViewAir).showSharedCams.text = dataProvider.length.toString();
if (dataProvider.length > 1) {
(view as IPresentationViewAir).showSharedCams.text += " " + ResourceManager.getInstance().getString('resources', 'presentation.sharedWebcams');
} else {
(view as IPresentationViewAir).showSharedCams.text += " " + ResourceManager.getInstance().getString('resources', 'presentation.sharedWebcam');
}
}
private function globalVideoStreamNameHandler():void {
if (userSession.globalVideoStreamName != "") {
speaker = new User();
speaker.name = ResourceManager.getInstance().getString('resources', 'videoChat.speaker');
speaker.userID = "sipVideoUser";
speaker.streamName = userSession.globalVideoStreamName;
speaker.hasStream = true;
var userStreamName:UserStreamName = new UserStreamName(speaker.streamName, speaker);
removeUserFromDataProvider(speaker.userID);
dataProvider.addItem(userStreamName);
} else {
if (speaker) {
removeUserFromDataProvider(speaker.userID);
speaker = null;
}
}
if (dataProvider.length == 0) {
//displayVideo(false);
} else {
//displayVideo(true);
//checkVideo();
}
}
private function removeUserFromDataProvider(userID:String) {
for (var item:int; item < dataProvider.length; item++) {
if ((dataProvider.getItemAt(item).user as User).userID == userID) {
// -- in the end. see: http://stackoverflow.com/questions/4255226/how-to-remove-an-item-while-iterating-over-collection
dataProvider.removeItemAt(item--);
}
}
}
private function addUserStreamNames(u:User):void {
var existingStreamNames:Array = getUserStreamNamesByUserID(u.userID);
var streamNames:Array = u.streamName.split("|");
for each (var streamName:String in streamNames) {
var addNew:Boolean = true;
for each (var existingUserStreamName:UserStreamName in existingStreamNames) {
if (streamName == existingUserStreamName.streamName) {
addNew = false;
}
}
if (addNew) {
var userStreamName:UserStreamName = new UserStreamName(streamName, u);
dataProvider.addItem(userStreamName);
}
}
dataProvider.refresh();
}
private function getUserStreamNamesByUserID(userID:String):Array {
var userStreamNames:Array = new Array();
for each (var userStreamName:UserStreamName in dataProvider) {
if (userStreamName.user.userID == userID) {
userStreamNames.push(userStreamName);
}
}
return userStreamNames;
}
private function changeWebcamStream(e:MouseEvent) {
e.stopPropagation();
if (changeStream) {
var popUp:SelectStreamPopUp = new SelectStreamPopUp();
popUp.addEventListener(PopUpEvent.CLOSE, onPopUpClose, false, 0, true);
popUp.width = view.content.width * 0.9;
popUp.open(view as DisplayObjectContainer, true);
mediatorMap.mediate(popUp);
PopUpManager.centerPopUp(popUp);
}
}
private function onPopUpClose(event:PopUpEvent):void {
if (event.commit) {
if (event.data == null) {
camerasHidden = true;
displayVideo(false);
} else {
camerasHidden = false;
displayVideo(true);
startStream(event.data.user, event.data.streamName);
}
}
}
private function showOverlay(e:MouseEvent) {
FlexGlobals.topLevelApplication.topActionBar.visible = true;
FlexGlobals.topLevelApplication.bottomMenu.visible = true;
overlayTimer.addEventListener(TimerEvent.TIMER_COMPLETE, hideOverlay);
if (overlayTimer.running) {
hideOverlay(null);
} else {
overlayTimer.start();
}
}
private function hideOverlay(e:Event) {
overlayTimer.stop();
FlexGlobals.topLevelApplication.topActionBar.visible = false;
FlexGlobals.topLevelApplication.bottomMenu.visible = false;
}
private function swipehandler(e:TransformGestureEvent):void {
@ -46,16 +491,44 @@ package org.bigbluebutton.air.presentation.views {
}
}
private function stageOrientationChangingHandler(e:Event):void {
if (userUISession.currentPage == PagesENUM.PRESENTATION) { //apply rotation only if user didn´t change view at the same time
var newWidth:Number = FlexGlobals.topLevelApplication.width;
var newHeight:Number = FlexGlobals.topLevelApplication.height - FlexGlobals.topLevelApplication.topActionBar.height - FlexGlobals.topLevelApplication.bottomMenu.height;
_slideModel.parentChange(newWidth, newHeight);
resizePresentation();
private function startStream(user:User, streamName:String):void {
if (view) {
var videoProfile:VideoProfile = (user == speaker) ? userSession.globalVideoProfile : userSession.videoProfileManager.getVideoProfileByStreamName(streamName);
var screenWidth:Number = (view as IPresentationViewAir).content.width / 3;
var screenHeight:Number = (view as IPresentationViewAir).content.height / 3;
if (FlexGlobals.topLevelApplication.aspectRatio == "landscape") {
var temp:Number = screenWidth;
screenWidth = screenHeight;
screenHeight = temp;
}
(view as IPresentationViewAir).startStream(userSession.videoConnection.connection, user.name, streamName, user.userID, videoProfile.width, videoProfile.height, screenWidth, screenHeight);
userUISession.currentStreamName = streamName;
//currentUser = user;
(view as IPresentationViewAir).videoGroup.height = (view as IPresentationViewAir).video.height;
}
}
private function stopStream(userID:String):void {
if (view) {
(view as IPresentationViewAir).stopStream();
userUISession.currentStreamName = "";
}
}
/**
*
*/
override public function destroy():void {
view.slide.removeEventListener(ResizeEvent.RESIZE, presentationUpdated);
userSession.userList.userChangeSignal.remove(userChangeHandler);
(view as IPresentationViewAir).videoStream.removeEventListener(MouseEvent.CLICK, changeWebcamStream);
(view as IPresentationViewAir).showSharedCamsGroup.removeEventListener(MouseEvent.CLICK, changeWebcamStream);
FlexGlobals.topLevelApplication.topActionBar.skin.setCurrentState("normal");
FlexGlobals.topLevelApplication.topActionBar.includeInLayout = true;
FlexGlobals.topLevelApplication.topActionBar.visible = true;
FlexGlobals.topLevelApplication.bottomMenu.visible = false;
view.content.removeEventListener(MouseEvent.CLICK, showOverlay);
overlayTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, hideOverlay);
FlexGlobals.topLevelApplication.stage.removeEventListener(ResizeEvent.RESIZE, stageOrientationChangingHandler);
(view as IPresentationViewAir).dispose();
super.destroy();

View File

@ -0,0 +1,13 @@
package org.bigbluebutton.air.presentation.views.selectWebcam {
import org.bigbluebutton.air.common.views.IView;
import spark.components.Button;
import spark.components.Group;
import spark.components.List;
public interface ISelectStreamPopUp extends IView {
function get streamList():List;
function get actionButton():Button;
}
}

View File

@ -0,0 +1,46 @@
package org.bigbluebutton.air.presentation.views.selectWebcam {
import robotlegs.bender.extensions.mediatorMap.api.IMediatorMap;
import robotlegs.bender.extensions.signalCommandMap.api.ISignalCommandMap;
import robotlegs.bender.framework.api.IConfig;
import robotlegs.bender.framework.api.IInjector;
public class SelectStreamConfig implements IConfig {
[Inject]
public var injector:IInjector;
[Inject]
public var mediatorMap:IMediatorMap;
[Inject]
public var signalCommandMap:ISignalCommandMap;
public function configure():void {
dependencies();
mediators();
signals();
}
/**
* Specifies all the dependencies for the feature
* that will be injected onto objects used by the
* application.
*/
private function dependencies():void {
}
/**
* Maps view mediators to views.
*/
private function mediators():void {
mediatorMap.map(ISelectStreamPopUp).toMediator(SelectStreamPopUpMediator);
}
/**
* Maps signals to commands using the signalCommandMap.
*/
private function signals():void {
}
}
}

View File

@ -0,0 +1,20 @@
package org.bigbluebutton.air.presentation.views.selectWebcam {
import spark.components.Button;
import spark.components.Group;
import spark.components.List;
import spark.components.supportClasses.SkinnableComponent;
public class SelectStreamPopUp extends SelectStreamPopUpBase implements ISelectStreamPopUp {
public function get streamList():List {
return streamList0;
}
public function get actionButton():Button {
return actionButton0;
}
public function dispose():void {
}
}
}

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<s:SkinnablePopUpContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="100%"
styleName="selectStreamPopUp">
<s:Group width="100%"
height="100%">
<!-- titlebar background -->
<s:Rect width="100%"
height="{title.height * 2}">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="#F1F3F7" />
<s:GradientEntry color="#F2F2F5" />
</s:LinearGradient>
</s:fill>
</s:Rect>
<s:VGroup width="100%"
horizontalAlign="center"
paddingTop="{title.height/2}">
<s:HGroup width="90%"
id="titleGroup"
horizontalAlign="right"
verticalAlign="middle">
<s:Label text="{resourceManager.getString('resources', 'selectStream.title')}"
id="title"
styleName="selectStreamTitle" />
<s:Spacer width="{(titleGroup.width - closeButton.width - title.width)/2}" />
<!-- close button -->
<s:Group mouseDown="close(false)"
id="closeButton"
height="100%">
<s:Line xFrom="0"
xTo="{title.height * 3/4}"
yFrom="0"
yTo="{title.height * 3/4}">
<s:stroke>
<s:SolidColorStroke color="{getStyle('closeButtonColor')}" />
</s:stroke>
</s:Line>
<s:Line xFrom="{title.height * 3/4}"
xTo="0"
yFrom="0"
yTo="{title.height * 3/4}">
<s:stroke>
<s:SolidColorStroke color="{getStyle('closeButtonColor')}" />
</s:stroke>
</s:Line>
</s:Group>
</s:HGroup>
<!-- content -->
</s:VGroup>
</s:Group>
<s:VGroup width="100%"
horizontalAlign="center"
verticalAlign="middle"
y="{title.y + (title.height) * 2 }">
<s:List id="streamList0"
width="90%"
height="100%"
itemRenderer="org.bigbluebutton.air.presentation.views.selectWebcam.StreamItemRenderer" />
<s:Button label="Stop viewing webcams"
id="actionButton0"
width="90%"
styleName="userSettingsButtonStyle" />
<s:Spacer height="10%">
</s:Spacer>
</s:VGroup>
</s:SkinnablePopUpContainer>

View File

@ -0,0 +1,221 @@
package org.bigbluebutton.air.presentation.views.selectWebcam {
import flash.display.Screen;
import flash.events.Event;
import flash.events.MouseEvent;
import mx.collections.ArrayCollection;
import mx.core.FlexGlobals;
import mx.events.FlexMouseEvent;
import mx.events.ResizeEvent;
import mx.resources.ResourceManager;
import mx.utils.ObjectUtil;
import org.bigbluebutton.air.common.views.PagesENUM;
import org.bigbluebutton.air.main.models.IUserUISession;
import org.bigbluebutton.lib.main.models.IUserSession;
import org.bigbluebutton.lib.user.models.User;
import org.bigbluebutton.lib.user.models.UserList;
import org.bigbluebutton.lib.video.models.UserStreamName;
import org.bigbluebutton.lib.video.models.VideoProfile;
import robotlegs.bender.bundles.mvcs.Mediator;
import spark.components.SkinnablePopUpContainer;
import spark.events.IndexChangeEvent;
public class SelectStreamPopUpMediator extends Mediator {
[Inject]
public var view:ISelectStreamPopUp;
[Inject]
public var userSession:IUserSession;
[Inject]
public var userUISession:IUserUISession;
protected var dataProvider:ArrayCollection;
private var manualSelection:Boolean = false;
private var speaker:User = null;
private var currentUser:User = null;
private var selectedIndex:int = -1;
private var indexChange:Boolean = false;
private var displayWebcam:Boolean;
override public function initialize():void {
userSession.userList.userRemovedSignal.add(userRemovedHandler);
userSession.userList.userAddedSignal.add(userAddedHandler);
userSession.userList.userChangeSignal.add(userChangeHandler);
userSession.globalVideoSignal.add(globalVideoStreamNameHandler);
view.streamList.addEventListener(MouseEvent.CLICK, onSelectStream);
view.actionButton.addEventListener(MouseEvent.CLICK, clickedActionButton);
dataProvider = new ArrayCollection();
view.streamList.dataProvider = dataProvider;
var users:ArrayCollection = userSession.userList.users;
for each (var u:User in users) {
if (u.streamName && u.streamName != "" && !dataProvider.contains(u)) {
addUserStreamNames(u);
}
}
updateSelectedIndex();
(view as SkinnablePopUpContainer).addEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE, closePopUp);
}
private function closePopUp(e:FlexMouseEvent):void {
(view as SkinnablePopUpContainer).close(false);
}
/**
*
*/
private function updateSelectedIndex() {
view.streamList.selectedIndex = selectedIndex;
if (selectedIndex == -1) {
view.actionButton.enabled = false;
view.actionButton.skin.setCurrentState("disabled");
view.actionButton.label = ResourceManager.getInstance().getString('resources', 'selectStream.viewWebcam');
} else {
view.actionButton.enabled = true
view.actionButton.skin.setCurrentState("up");
if (userUISession.currentStreamName == "" || indexChange) {
displayWebcam = true;
view.actionButton.label = ResourceManager.getInstance().getString('resources', 'selectStream.viewWebcam');
} else {
displayWebcam = false;
view.actionButton.label = ResourceManager.getInstance().getString('resources', 'selectStream.hideWebcam');
}
}
}
private function clickedActionButton(e:MouseEvent) {
var selectedStream:Object = null;
if (displayWebcam) {
selectedStream = dataProvider.getItemAt(view.streamList.selectedIndex);
}
(view as SkinnablePopUpContainer).close(true, selectedStream);
}
private function globalVideoStreamNameHandler():void {
if (userSession.globalVideoStreamName != "") {
speaker = new User();
speaker.name = ResourceManager.getInstance().getString('resources', 'videoChat.speaker');
speaker.userID = "sipVideoUser";
speaker.streamName = userSession.globalVideoStreamName;
speaker.hasStream = true;
var userStreamName:UserStreamName = new UserStreamName(speaker.streamName, speaker);
removeUserFromDataProvider(speaker.userID);
dataProvider.addItem(userStreamName);
} else {
if (speaker) {
removeUserFromDataProvider(speaker.userID);
speaker = null;
}
}
}
private function addUserStreamNames(u:User):void {
var existingStreamNames:Array = getUserStreamNamesByUserID(u.userID);
var streamNames:Array = u.streamName.split("|");
for each (var streamName:String in streamNames) {
var addNew:Boolean = true;
for each (var existingUserStreamName:UserStreamName in existingStreamNames) {
if (streamName == existingUserStreamName.streamName) {
addNew = false;
}
}
if (addNew) {
var userStreamName:UserStreamName = new UserStreamName(streamName, u);
dataProvider.addItem(userStreamName);
if (streamName == userUISession.currentStreamName) {
selectedIndex = dataProvider.getItemIndex(userStreamName);
}
}
}
dataProvider.refresh();
}
private function onSelectStream(event:MouseEvent):void {
if (view.streamList.selectedIndex != selectedIndex) {
indexChange = true;
}
selectedIndex = view.streamList.selectedIndex;
updateSelectedIndex();
}
override public function destroy():void {
userSession.userList.userRemovedSignal.remove(userRemovedHandler);
userSession.userList.userAddedSignal.remove(userAddedHandler);
userSession.userList.userChangeSignal.remove(userChangeHandler);
userSession.globalVideoSignal.remove(globalVideoStreamNameHandler);
view.dispose();
view = null;
super.destroy();
}
private function userAddedHandler(user:User):void {
if (user.streamName && user.streamName != "") {
var streamNames:Array = user.streamName.split("|");
for each (var streamName:String in streamNames) {
var userStreamName:UserStreamName = new UserStreamName(streamName, user);
dataProvider.addItem(userStreamName);
}
}
}
private function removeUserFromDataProvider(userID:String) {
for (var item:int; item < dataProvider.length; item++) {
if ((dataProvider.getItemAt(item).user as User).userID == userID) {
// -- in the end. see: http://stackoverflow.com/questions/4255226/how-to-remove-an-item-while-iterating-over-collection
dataProvider.removeItemAt(item--);
}
}
}
private function userRemovedHandler(userID:String):void {
var displayedUser:User = getDisplayedUser();
removeUserFromDataProvider(userID);
}
private function getUserStreamNamesByUserID(userID:String):Array {
var userStreamNames:Array = new Array();
for each (var userStreamName:UserStreamName in dataProvider) {
if (userStreamName.user.userID == userID) {
userStreamNames.push(userStreamName);
}
}
return userStreamNames;
}
private function userChangeHandler(user:User, property:int):void {
if (property == UserList.HAS_STREAM) {
var userStreamNames:Array = getUserStreamNamesByUserID(user.userID);
for each (var userStreamName:UserStreamName in userStreamNames) {
if (!(userStreamName.user.streamName.indexOf(userStreamName.streamName) >= 0)) {
dataProvider.removeItemAt(dataProvider.getItemIndex(userStreamName));
}
}
if (user.streamName.split("|").length > userStreamNames.length && user.streamName.length > 0) {
var camNumber:int = dataProvider.length;
addUserStreamNames(user);
}
dataProvider.refresh();
}
}
private function getDisplayedUser():User {
for each (var userStreamName:UserStreamName in dataProvider) {
if (userStreamName.streamName == userUISession.currentStreamName) {
return userStreamName.user;
}
}
return null;
}
}
}

View File

@ -0,0 +1,83 @@
<?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:selection="org.bigbluebutton.air.common.views.*"
xmlns:participanticon="org.bigbluebutton.air.common.views.*"
styleName="streamItemStyle"
dataChange="onDataChange(event)"
height="100%"
xmlns:views="org.bigbluebutton.air.common.views.*">
<s:states>
<s:State name="normal" />
<s:State name="selected" />
</s:states>
<fx:Script>
<![CDATA[
import mx.events.StateChangeEvent;
private function selectionChange(evt:StateChangeEvent):void {
selectionIcon.setCurrentState(this.currentState);
}
override public function set data(obj:Object):void {
this.addEventListener(StateChangeEvent.CURRENT_STATE_CHANGE, selectionChange);
super.data = obj;
if (obj) {
title.text = obj.user.name;
presenter.visible = obj.user.presenter;
presenter.includeInLayout = obj.user.presenter;
participantIcon.participantName = obj.user.name;
if (obj.user.me) {
title.text += " " + resourceManager.getString('resources', 'userDetail.you');
}
}
}
protected function onDataChange(event:Event):void {
invalidateRendererState();
}
]]>
</fx:Script>
<s:Group width="100%"
height="{getStyle('itemHeight')}"
id="content">
<s:layout>
<s:HorizontalLayout verticalAlign="middle"
horizontalAlign="center"
paddingTop="{getStyle('paddingTop')}"
paddingBottom="{getStyle('paddingBottom')}" />
</s:layout>
<participanticon:ParticipantIcon width="10%"
id="participantIcon" />
<s:VGroup width="100%"
height="100%"
verticalAlign="middle">
<s:Label id="title"
styleName="videoStreamName contentFontSize" />
<s:Label id="presenter"
text="{resourceManager.getString('resources', 'participants.status.presenting')}"
styleName="videoStreamNamePresenter subContentFontSize" />
</s:VGroup>
<s:Spacer width="25%" />
<views:SelectionIcon id="selectionIcon" />
</s:Group>
<s:Line width="100%">
<s:stroke>
<s:SolidColorStroke color="{getStyle('lineColor')}"
weight="{getStyle('lineWeight')}" />
</s:stroke>
</s:Line>
</s:ItemRenderer>

View File

@ -42,7 +42,7 @@ package org.bigbluebutton.air.settings.views.audio {
override public function initialize():void {
userSession.userList.userChangeSignal.add(userChangeHandler);
FlexGlobals.topLevelApplication.pageName.text = ResourceManager.getInstance().getString('resources', 'audioSettings.title');
FlexGlobals.topLevelApplication.topActionBar.pageName.text = ResourceManager.getInstance().getString('resources', 'audioSettings.title');
var userMe:User = userSession.userList.me;
view.continueBtn.addEventListener(MouseEvent.CLICK, onContinueClick);
view.enableAudio.addEventListener(Event.CHANGE, onEnableAudioClick);
@ -54,8 +54,8 @@ package org.bigbluebutton.air.settings.views.audio {
view.enableAudio.selected = (userMe.voiceJoined || userMe.listenOnly);
view.enablePushToTalk.enabled = view.enableMic.selected = userMe.voiceJoined;
view.enablePushToTalk.selected = (userSession.pushToTalk || userSession.phoneOptions.autoJoin);
FlexGlobals.topLevelApplication.backBtn.visible = true;
FlexGlobals.topLevelApplication.profileBtn.visible = false;
FlexGlobals.topLevelApplication.topActionBar.backBtn.visible = true;
FlexGlobals.topLevelApplication.topActionBar.profileBtn.visible = false;
loadMicGain();
micActivityTimer = new Timer(100);
micActivityTimer.addEventListener(TimerEvent.TIMER, micActivity);

View File

@ -7,10 +7,9 @@ package org.bigbluebutton.air.settings.views.lock {
import org.bigbluebutton.air.main.models.IUserUISession;
import org.bigbluebutton.lib.main.models.IUserSession;
import org.bigbluebutton.lib.main.models.UserSession;
import org.bigbluebutton.lib.user.services.IUsersService;
import robotlegs.bender.bundles.mvcs.Mediator;
import robotlegs.bender.bundles.mvcs.Mediator;
public class LockSettingsViewMediator extends Mediator {
@ -39,11 +38,6 @@ package org.bigbluebutton.air.settings.views.lock {
override public function initialize():void {
loadLockSettings();
view.applyButton.addEventListener(MouseEvent.CLICK, onApply);
FlexGlobals.topLevelApplication.pageName.text = ResourceManager.getInstance().getString('resources', 'lockSettings.title');
FlexGlobals.topLevelApplication.backBtn.visible = true;
FlexGlobals.topLevelApplication.profileBtn.visible = false;
}
FlexGlobals.topLevelApplication.topActionBar.pageName.text = ResourceManager.getInstance().getString('resources', 'lockSettings.title');
FlexGlobals.topLevelApplication.topActionBar.backBtn.visible = true;
FlexGlobals.topLevelApplication.topActionBar.profileBtn.visible = false;
@ -63,8 +57,8 @@ package org.bigbluebutton.air.settings.views.lock {
userUISession.popPage();
}
private function loadLockSettings() {
view.cameraSwitch.selected = !UserSession.lockSettings.disableCam;
private function loadLockSettings():void {
view.cameraSwitch.selected = !userSession.lockSettings.disableCam;
view.micSwitch.selected = !userSession.lockSettings.disableMic;
view.publicChatSwitch.selected = !userSession.lockSettings.disablePublicChat;
view.privateChatSwitch.selected = !userSession.lockSettings.disablePrivateChat;

View File

@ -1,14 +0,0 @@
package org.bigbluebutton.air.settings.views.status {
import org.bigbluebutton.air.common.views.IView;
import spark.components.Button;
import spark.components.Group;
import spark.components.Label;
import spark.components.List;
import spark.components.RadioButtonGroup;
public interface IStatusView extends IView {
function get statusList():List;
}
}

View File

@ -1,66 +0,0 @@
<?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"
styleName="participantItemStyle">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import org.bigbluebutton.lib.user.models.User;
override public function set data(obj:Object):void {
super.data = obj;
if (obj) {
profileIcon.visible = profileIcon.includeInLayout = obj.signal == User.NO_STATUS;
handIcon.visible = handIcon.includeInLayout = obj.signal == User.RAISE_HAND;
beRightBackIcon.visible = beRightBackIcon.includeInLayout = obj.signal == User.AWAY;
laughterIcon.visible = laughterIcon.includeInLayout = obj.signal == User.HAPPY;
sadIcon.visible = sadIcon.includeInLayout = obj.signal == User.SAD;
}
}
]]>
</fx:Script>
<s:Group width="100%"
height="{getStyle('itemHeight')}">
<s:layout>
<s:HorizontalLayout verticalAlign="middle"
paddingLeft="{getStyle('itemPaddingLeft')}"
paddingRight="{getStyle('itemPaddingRight')}" />
</s:layout>
<s:Image id="profileIcon"
styleName="iconStyle userIconStyle"
height="100%" />
<s:Image id="handIcon"
styleName="iconStyle handIconStyle"
height="100%" />
<s:Image id="beRightBackIcon"
styleName="iconStyle beRightBackIconStyle"
height="100%" />
<s:Image id="laughterIcon"
styleName="iconStyle laughterIconStyle"
height="100%" />
<s:Image id="sadIcon"
styleName="iconStyle sadIconStyle"
height="100%" />
<s:Group width="70%">
<s:layout>
<s:VerticalLayout />
</s:layout>
<s:Label id="labelDisplay"
width="100%"
height="100%"
styleName="contentFontSize" />
</s:Group>
</s:Group>
<s:Line width="100%">
<s:stroke>
<s:SolidColorStroke color="{getStyle('lineColor')}"
weight="{getStyle('lineWeight')}" />
</s:stroke>
</s:Line>
</s:ItemRenderer>

View File

@ -1,25 +0,0 @@
package org.bigbluebutton.air.settings.views.status {
import flash.events.MouseEvent;
import org.bigbluebutton.air.settings.views.status.StatusViewBase;
import spark.components.Button;
import spark.components.Group;
import spark.components.Label;
import spark.components.List;
import spark.components.RadioButtonGroup;
public class StatusView extends StatusViewBase implements IStatusView {
override protected function childrenCreated():void {
super.childrenCreated();
}
public function dispose():void {
}
public function get statusList():List {
return statusList0;
}
}
}

View File

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<view:NoTabView 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:view="org.bigbluebutton.air.common.views.*"
xmlns:ui="org.bigbluebutton.view.ui.*">
<s:Scroller width="100%"
height="100%">
<s:VGroup width="100%"
height="100%"
horizontalAlign="center">
<s:List id="statusList0"
width="100%"
itemRenderer="org.bigbluebutton.air.settings.views.status.StatusItemRenderer"
height="100%"
labelField="data">
<s:ArrayList>
<fx:Object data="{resourceManager.getString('resources', 'profile.settings.clearStatus')}"
signal="none" />
<fx:Object data="{resourceManager.getString('resources', 'profile.settings.handRaise')}"
signal="raiseHand" />
<fx:Object data="{resourceManager.getString('resources', 'profile.settings.beRightBack')}"
signal="away" />
<fx:Object data="{resourceManager.getString('resources', 'profile.settings.laughter')}"
signal="happy" />
<fx:Object data="{resourceManager.getString('resources', 'profile.settings.sad')}"
signal="sad" />
</s:ArrayList>
</s:List>
</s:VGroup>
</s:Scroller>
</view:NoTabView>

View File

@ -1,91 +0,0 @@
package org.bigbluebutton.air.settings.views.status {
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.StageOrientationEvent;
import mx.core.FlexGlobals;
import mx.events.ItemClickEvent;
import mx.events.ResizeEvent;
import mx.resources.ResourceManager;
import org.bigbluebutton.air.common.views.PagesENUM;
import org.bigbluebutton.air.main.models.IUserUISession;
import org.bigbluebutton.air.settings.views.status.IStatusView;
import org.bigbluebutton.lib.main.commands.EmojiSignal;
import org.bigbluebutton.lib.main.models.IUserSession;
import org.bigbluebutton.lib.user.models.User;
import robotlegs.bender.bundles.mvcs.Mediator;
import spark.events.IndexChangeEvent;
public class StatusViewMediator extends Mediator {
[Inject]
public var view:IStatusView;
[Inject]
public var userSession:IUserSession;
[Inject]
public var userUISession:IUserUISession;
[Inject]
public var emojiSignal:EmojiSignal;
override public function initialize():void {
var userMe:User = userSession.userList.me;
view.statusList.addEventListener(IndexChangeEvent.CHANGE, onEmojiChange);
userSession.userList.userChangeSignal.add(userChanged);
FlexGlobals.topLevelApplication.stage.addEventListener(ResizeEvent.RESIZE, stageOrientationChangingHandler);
FlexGlobals.topLevelApplication.pageName.text = ResourceManager.getInstance().getString('resources', 'profile.status');
FlexGlobals.topLevelApplication.profileBtn.visible = false;
FlexGlobals.topLevelApplication.backBtn.visible = true;
selectEmoji(userMe.status);
}
private function stageOrientationChangingHandler(e:Event):void {
var tabletLandscape = FlexGlobals.topLevelApplication.isTabletLandscape();
if (tabletLandscape) {
userUISession.popPage();
userUISession.popPage();
userUISession.pushPage(PagesENUM.SPLITSETTINGS, PagesENUM.STATUS);
}
}
private function userChanged(user:User, type:int):void {
if (user == userSession.userList.me) {
selectEmoji(user.status);
}
}
private function selectEmoji(status:String):void {
for (var i:Number = 0; i < view.statusList.dataProvider.length; i++) {
if (status == view.statusList.dataProvider.getItemAt(i).signal) {
view.statusList.setSelectedIndex(i);
break;
}
}
}
protected function onEmojiChange(event:IndexChangeEvent):void {
var obj:Object;
obj = view.statusList.selectedItem;
emojiSignal.dispatch(view.statusList.selectedItem.signal);
if (!FlexGlobals.topLevelApplication.isTabletLandscape()) {
userUISession.popPage();
userUISession.popPage();
}
}
override public function destroy():void {
super.destroy();
view.statusList.removeEventListener(IndexChangeEvent.CHANGE, onEmojiChange);
FlexGlobals.topLevelApplication.stage.removeEventListener(ResizeEvent.RESIZE, stageOrientationChangingHandler);
userSession.userList.userChangeSignal.remove(userChanged);
view.dispose();
view = null;
}
}
}

View File

@ -12,5 +12,6 @@ package org.bigbluebutton.air.users.views.participants {
function get allGuests():SkinnableComponent;
function get allowAllButton():Button;
function get denyAllButton():Button;
function get conversationsList():List;
}
}

View File

@ -2,20 +2,17 @@
<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:participanticon="org.bigbluebutton.air.common.views.*"
styleName="participantItemStyle">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import org.bigbluebutton.lib.user.models.User;
override public function set data(obj:Object):void {
super.data = obj;
if (obj) {
presentationIcon.visible = presentationIcon.includeInLayout = obj.presenter && (obj.status == User.NO_STATUS);
profileIcon.visible = ((obj.role == User.MODERATOR) && (!obj.presenter) && (obj.status == User.NO_STATUS));
profileIcon.includeInLayout = (!obj.presenter) && (obj.status == User.NO_STATUS);
cameraIcon.visible = obj.hasStream;
micIcon.visible = micIcon.includeInLayout = (obj.voiceJoined && !obj.muted);
lockIcon.visible = obj.locked;
@ -28,19 +25,10 @@
} else {
labelDisplay.text = obj.name;
}
handIcon.visible = handIcon.includeInLayout = obj.status == User.RAISE_HAND;
beRightBackIcon.visible = beRightBackIcon.includeInLayout = obj.status == User.AWAY;
laughterIcon.visible = laughterIcon.includeInLayout = obj.status == User.HAPPY;
sadIcon.visible = sadIcon.includeInLayout = obj.status == User.SAD;
participantIcon.participantName = obj.name;
if (obj.presenter) {
subLabelDisplay.visible = subLabelDisplay.includeInLayout = true;
subLabelDisplay.text = resourceManager.getString('resources', 'participants.status.presenter');
if (obj.role == User.MODERATOR) {
subLabelDisplay.text += "/" + resourceManager.getString('resources', 'participants.status.moderator');
}
} else if (obj.role == User.MODERATOR) {
subLabelDisplay.visible = subLabelDisplay.includeInLayout = true;
subLabelDisplay.text = resourceManager.getString('resources', 'participants.status.moderator');
} else {
subLabelDisplay.visible = subLabelDisplay.includeInLayout = false;
}
@ -55,44 +43,10 @@
paddingLeft="{getStyle('itemPaddingLeft')}"
paddingRight="{getStyle('itemPaddingRight')}" />
</s:layout>
<s:Image id="profileIcon"
styleName="iconStyle moderatorIconStyle"
height="100%" />
<s:Image id="presentationIcon"
styleName="iconStyle presentationIconStyle"
height="100%" />
<s:Image id="handIcon"
styleName="iconStyle handIconStyle"
height="100%" />
<s:Image id="agreeIcon"
styleName="iconStyle agreeIconStyle"
height="100%" />
<s:Image id="disagreeIcon"
styleName="iconStyle disagreeIconStyle"
height="100%" />
<s:Image id="speakLouderIcon"
styleName="iconStyle speakLouderIconStyle"
height="100%" />
<s:Image id="speakSofterIcon"
styleName="iconStyle speakSofterIconStyle"
height="100%" />
<s:Image id="speakFasterIcon"
styleName="iconStyle speakFasterIconStyle"
height="100%" />
<s:Image id="speakSlowerIcon"
styleName="iconStyle speakSlowerIconStyle"
height="100%" />
<s:Image id="beRightBackIcon"
styleName="iconStyle beRightBackIconStyle"
height="100%" />
<s:Image id="laughterIcon"
styleName="iconStyle laughterIconStyle"
height="100%" />
<s:Image id="sadIcon"
styleName="iconStyle sadIconStyle"
height="100%" />
<s:Group width="70%">
<participanticon:ParticipantIcon id="participantIcon" />
<s:Group width="100%">
<s:layout>
<s:VerticalLayout />
</s:layout>

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<s:List xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
itemRenderer="org.bigbluebutton.air.users.views.participants.ParticipantItemRenderer">
itemRenderer="org.bigbluebutton.air.users.views.participants.ParticipantItemRenderer"
verticalScrollPolicy="off">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>

View File

@ -34,6 +34,10 @@ package org.bigbluebutton.air.users.views.participants {
return denyAllButton0;
}
public function get conversationsList():List {
return conversationslist;
}
/*
public function onClick(e:MouseEvent):void
{

View File

@ -5,54 +5,96 @@
xmlns:participants="org.bigbluebutton.air.users.views.participants.*"
xmlns:guests="org.bigbluebutton.air.users.views.participants.guests.*"
xmlns:common="org.bigbluebutton.air.common.views.*"
xmlns:chatrooms="org.bigbluebutton.air.chat.views.chatrooms.*"
styleName="participantsViewStyle">
<s:Group width="100%"
height="100%">
<s:layout>
<s:VerticalLayout />
</s:layout>
<participants:ParticipantsList id="participantslist"
width="100%"
height="100%" />
<s:SkinnableContainer includeInLayout="false"
visible="false"
id="allguests"
width="100%"
height="{getStyle('toolBarHeight')}"
styleName="topToolBarStyle"
verticalCenter="0">
<s:HGroup width="100%"
height="100%"
verticalAlign="middle"
paddingRight="{getStyle('itemPaddingRight')}"
paddingLeft="{getStyle('itemPaddingLeft')}">
<s:Group width="70%">
<s:layout>
<s:VerticalLayout />
</s:layout>
<s:Label id="guestsLabel"
text="{resourceManager.getString('resources', 'participants.guests')}"
width="100%"
<s:Scroller width="100%"
height="100%">
<s:Group width="100%"
height="100%">
<s:layout>
<s:VerticalLayout verticalAlign="middle"
gap="0" />
</s:layout>
<s:Group width="100%"
height="{getStyle('itemHeight')}">
<s:Rect width="100%"
height="100%">
<s:fill>
<s:SolidColor color="{getStyle('subRectangleColor')}" />
</s:fill>
</s:Rect>
<s:HGroup height="100%">
<s:Spacer width="2%" />
<s:Label id="conversationLabel"
styleName="settingsSubtitleStyle subContentFontSize"
height="100%"
styleName="pageNameStyle" />
</s:Group>
text="{resourceManager.getString('resources', 'participants.conversations')}" />
</s:HGroup>
</s:Group>
<s:Button id="allowAllButton0"
width="20%"
styleName="allowButtonStyle guestResponseButtonStyle" />
<mx:Spacer width="3%" />
<s:Button id="denyAllButton0"
width="20%"
styleName="denyButtonStyle guestResponseButtonStyle" />
</s:HGroup>
</s:SkinnableContainer>
<chatrooms:ChatRoomsList id="conversationslist"
width="100%" />
<s:Group width="100%"
height="{getStyle('itemHeight')}">
<s:Rect width="100%"
height="100%">
<s:fill>
<s:SolidColor color="{getStyle('subRectangleColor')}" />
</s:fill>
</s:Rect>
<s:HGroup height="100%">
<s:Spacer width="2%" />
<s:Label id="onlineLabel"
styleName="settingsSubtitleStyle subContentFontSize"
height="100%"
text="{resourceManager.getString('resources', 'participants.online')}" />
</s:HGroup>
</s:Group>
<guests:GuestsList includeInLayout="false"
visible="false"
id="guestslist"
width="100%"
height="100%" />
</s:Group>
<participants:ParticipantsList id="participantslist"
width="100%"
height="100%" />
<s:SkinnableContainer includeInLayout="false"
visible="false"
id="allguests"
width="100%"
height="{getStyle('toolBarHeight')}"
styleName="topToolBarStyle"
verticalCenter="0">
<s:HGroup width="100%"
height="100%"
verticalAlign="middle"
paddingRight="{getStyle('itemPaddingRight')}"
paddingLeft="{getStyle('itemPaddingLeft')}">
<s:Group width="70%">
<s:layout>
<s:VerticalLayout />
</s:layout>
<s:Label id="guestsLabel"
text="{resourceManager.getString('resources', 'participants.guests')}"
width="100%"
height="100%"
styleName="pageNameStyle" />
</s:Group>
<s:Button id="allowAllButton0"
width="20%"
styleName="allowButtonStyle guestResponseButtonStyle" />
<mx:Spacer width="3%" />
<s:Button id="denyAllButton0"
width="20%"
styleName="denyButtonStyle guestResponseButtonStyle" />
</s:HGroup>
</s:SkinnableContainer>
<guests:GuestsList includeInLayout="false"
visible="false"
id="guestslist"
width="100%"
height="100%" />
</s:Group>
</s:Scroller>
</common:NoTabView>

View File

@ -14,6 +14,8 @@ package org.bigbluebutton.air.users.views.participants {
import org.bigbluebutton.air.common.views.TransitionAnimationENUM;
import org.bigbluebutton.air.main.models.IUserUISession;
import org.bigbluebutton.air.users.views.participants.guests.GuestResponseEvent;
import org.bigbluebutton.lib.chat.models.IChatMessagesSession;
import org.bigbluebutton.lib.chat.models.PrivateChatMessage;
import org.bigbluebutton.lib.main.models.IUserSession;
import org.bigbluebutton.lib.user.models.User;
import org.bigbluebutton.lib.user.services.IUsersService;
@ -37,6 +39,11 @@ package org.bigbluebutton.air.users.views.participants {
[Inject]
public var usersService:IUsersService;
[Inject]
public var chatMessagesSession:IChatMessagesSession;
protected var dataProviderConversations:ArrayCollection;
protected var dataProvider:ArrayCollection;
protected var dataProviderGuests:ArrayCollection;
@ -49,6 +56,8 @@ package org.bigbluebutton.air.users.views.participants {
private var _userMe:User;
private var _usersAdded:Array = new Array();
override public function initialize():void {
dataProvider = new ArrayCollection();
view.list.dataProvider = dataProvider;
@ -65,11 +74,10 @@ package org.bigbluebutton.air.users.views.participants {
userSession.userList.userAddedSignal.add(addUser);
userSession.userList.userRemovedSignal.add(userRemoved);
setPageTitle();
FlexGlobals.topLevelApplication.profileBtn.visible = true;
FlexGlobals.topLevelApplication.backBtn.visible = false;
dataProviderGuests = new ArrayCollection();
view.guestsList.dataProvider = dataProviderGuests;
view.guestsList.addEventListener(GuestResponseEvent.GUEST_RESPONSE, onSelectGuest);
view.conversationsList.addEventListener(IndexChangeEvent.CHANGE, onSelectChat);
view.allowAllButton.addEventListener(MouseEvent.CLICK, allowAllGuests);
view.denyAllButton.addEventListener(MouseEvent.CLICK, denyAllGuests);
dicUserIdtoGuest = new Dictionary();
@ -84,11 +92,89 @@ package org.bigbluebutton.air.users.views.participants {
view.guestsList.includeInLayout = true;
view.allGuests.visible = true;
view.allGuests.includeInLayout = true;
}
userUISession.pushPage(PagesENUM.PARTICIPANTS);
initializeDataProviderConversations();
}
protected function onSelectChat(event:IndexChangeEvent):void {
var item:Object = dataProviderConversations.getItemAt(event.newIndex);
if (item) {
if (item.hasOwnProperty("button")) {
userUISession.pushPage(PagesENUM.SELECT_PARTICIPANT, item, TransitionAnimationENUM.SLIDE_LEFT)
} else {
userUISession.pushPage(PagesENUM.CHAT, item, TransitionAnimationENUM.SLIDE_LEFT)
}
} else {
throw new Error("item null on ChatRoomsViewMediator");
}
}
private function initializeDataProviderConversations() {
dataProviderConversations = new ArrayCollection();
dataProviderConversations.addItem({name: ResourceManager.getInstance().getString('resources', 'chat.item.publicChat'), publicChat: true, user: null, chatMessages: chatMessagesSession.publicChat});
for each (var chatObject:PrivateChatMessage in chatMessagesSession.privateChats) {
chatObject.userOnline = userSession.userList.hasUser(chatObject.userID);
chatObject.privateChat.chatMessageChangeSignal.add(populateList);
if (chatObject.privateChat.messages.length > 0) {
addChat({name: chatObject.userName, publicChat: false, user: userSession.userList.getUser(chatObject.userID), chatMessages: chatObject.privateChat, userID: chatObject.userID, online: chatObject.userOnline});
}
}
view.conversationsList.dataProvider = dataProviderConversations;
}
public function populateList(UserID:String = null):void {
var newUser:User = userSession.userList.getUserByUserId(UserID);
if ((newUser != null) && (!isExist(newUser, dataProviderConversations)) && (!newUser.me)) {
var pcm:PrivateChatMessage = chatMessagesSession.getPrivateMessages(newUser.userID, newUser.name);
addChat({name: pcm.userName, publicChat: false, user: newUser, chatMessages: pcm.privateChat, userID: pcm.userID, online: true}, dataProvider.length - 1);
}
dataProviderConversations.refresh();
}
/**
* If user wasn't already added, adding to the data provider
**/
private function addChat(chat:Object, pos:Number = NaN):void {
if (!userAlreadyAdded(chat.userID)) {
_usersAdded.push(chat.userID);
if (isNaN(pos)) {
dataProviderConversations.addItem(chat);
} else {
dataProviderConversations.addItemAt(chat, pos);
}
}
//dataProvider.setItemAt(button, dataProvider.length-1);
dataProviderConversations.refresh();
setPageTitle();
//dicUsertoChat[chat.user] = chat;
}
/**
* Check if User was already added to the data provider
**/
private function userAlreadyAdded(userID:String):Boolean {
for each (var str:String in _usersAdded) {
if (userID == str) {
return true;
}
}
return false;
}
/**
* Check if User is already added to the dataProvider
*
* @param User
*/
private function isExist(user:User, dp:ArrayCollection):Boolean {
for (var i:int = 0; i < dp.length; i++) {
if (dp.getItemAt(i).userID == user.userID) {
return true;
}
}
return false;
}
private function addUser(user:User):void {
dataProvider.addItem(user);
@ -171,7 +257,7 @@ package org.bigbluebutton.air.users.views.participants {
**/
private function setPageTitle():void {
if (dataProvider != null) {
FlexGlobals.topLevelApplication.pageName.text = ResourceManager.getInstance().getString('resources', 'participants.title') + " (" + dataProvider.length + ")";
FlexGlobals.topLevelApplication.topActionBar.pageName.text = ResourceManager.getInstance().getString('resources', 'participants.title');
}
}

View File

@ -23,7 +23,8 @@
</s:stroke>
<s:fill>
<s:SolidColor color="{hostComponent.getStyle('backgroundColor')}"
color.down="{hostComponent.getStyle('onClickBackgroundColor')}" />
color.down="{hostComponent.getStyle('onClickBackgroundColor')}"
color.disabled="{hostComponent.getStyle('disabledBackgroundColor')}" />
</s:fill>
</s:Rect>
<s:Label width="100%"
@ -31,5 +32,7 @@
text="{hostComponent.label}"
textAlign="center"
color="{hostComponent.getStyle('textColor')}"
verticalCenter="0" />
color.disabled="{hostComponent.getStyle('disabledTextColor')}"
verticalCenter="0"
alpha.disabled="0.5" />
</s:Skin>

View File

@ -49,9 +49,9 @@ package org.bigbluebutton.air.video.views.videochat {
userSession.globalVideoSignal.add(globalVideoStreamNameHandler);
view.streamlist.addEventListener(MouseEvent.CLICK, onSelectStream);
FlexGlobals.topLevelApplication.stage.addEventListener(ResizeEvent.RESIZE, stageOrientationChangingHandler);
FlexGlobals.topLevelApplication.pageName.text = ResourceManager.getInstance().getString('resources', 'video.title');
FlexGlobals.topLevelApplication.backBtn.visible = false;
FlexGlobals.topLevelApplication.profileBtn.visible = true;
FlexGlobals.topLevelApplication.topActionBar.pageName.text = ResourceManager.getInstance().getString('resources', 'video.title');
FlexGlobals.topLevelApplication.topActionBar.backBtn.visible = false;
FlexGlobals.topLevelApplication.topActionBar.profileBtn.visible = true;
dataProvider = new ArrayCollection();
view.streamlist.dataProvider = dataProvider;
var users:ArrayCollection = userSession.userList.users;