diff --git a/browser/components/loop/content/js/conversationViews.js b/browser/components/loop/content/js/conversationViews.js index 258b60fc6a0f..95d85d8196ef 100644 --- a/browser/components/loop/content/js/conversationViews.js +++ b/browser/components/loop/content/js/conversationViews.js @@ -698,14 +698,15 @@ loop.conversationViews = (function(mozL10n) { screenSharePosterUrl: null, screenShareVideoObject: this.state.screenShareVideoObject, showContextRoomName: false, - useDesktopPaths: true}), - React.createElement(loop.shared.views.ConversationToolbar, { - audio: this.props.audio, - dispatcher: this.props.dispatcher, - edit: { visible: false, enabled: false}, - hangup: this.hangup, - publishStream: this.publishStream, - video: this.props.video}) + useDesktopPaths: true}, + React.createElement(loop.shared.views.ConversationToolbar, { + audio: this.props.audio, + dispatcher: this.props.dispatcher, + edit: { visible: false, enabled: false}, + hangup: this.hangup, + publishStream: this.publishStream, + video: this.props.video}) + ) ) ); } @@ -802,13 +803,13 @@ loop.conversationViews = (function(mozL10n) { } case CALL_STATES.ONGOING: { return (React.createElement(OngoingConversationView, { - audio: {enabled: !this.state.audioMuted}, + audio: { enabled: !this.state.audioMuted, visible: true}, conversationStore: this.getStore(), dispatcher: this.props.dispatcher, mediaConnected: this.state.mediaConnected, remoteSrcVideoObject: this.state.remoteSrcVideoObject, remoteVideoEnabled: this.state.remoteVideoEnabled, - video: {enabled: !this.state.videoMuted}}) + video: { enabled: !this.state.videoMuted, visible: true}}) ); } case CALL_STATES.FINISHED: { diff --git a/browser/components/loop/content/js/conversationViews.jsx b/browser/components/loop/content/js/conversationViews.jsx index 0318fb7df1f4..624b5189197d 100644 --- a/browser/components/loop/content/js/conversationViews.jsx +++ b/browser/components/loop/content/js/conversationViews.jsx @@ -698,14 +698,15 @@ loop.conversationViews = (function(mozL10n) { screenSharePosterUrl={null} screenShareVideoObject={this.state.screenShareVideoObject} showContextRoomName={false} - useDesktopPaths={true} /> - + useDesktopPaths={true}> + + ); } @@ -802,13 +803,13 @@ loop.conversationViews = (function(mozL10n) { } case CALL_STATES.ONGOING: { return ( + video={{ enabled: !this.state.videoMuted, visible: true }} /> ); } case CALL_STATES.FINISHED: { diff --git a/browser/components/loop/content/js/roomViews.js b/browser/components/loop/content/js/roomViews.js index 92e3dee6e144..e9958321e80c 100644 --- a/browser/components/loop/content/js/roomViews.js +++ b/browser/components/loop/content/js/roomViews.js @@ -743,6 +743,15 @@ loop.roomViews = (function(mozL10n) { screenShareVideoObject: this.state.screenShareVideoObject, showContextRoomName: false, useDesktopPaths: true}, + React.createElement(sharedViews.ConversationToolbar, { + audio: {enabled: !this.state.audioMuted, visible: true}, + dispatcher: this.props.dispatcher, + edit: { visible: this.state.contextEnabled, enabled: !this.state.showEditContext}, + hangup: this.leaveRoom, + onEditClick: this.handleEditContextClick, + publishStream: this.publishStream, + screenShare: screenShareData, + video: {enabled: !this.state.videoMuted, visible: true}}), React.createElement(DesktopRoomInvitationView, { dispatcher: this.props.dispatcher, error: this.state.error, @@ -762,16 +771,7 @@ loop.roomViews = (function(mozL10n) { roomData: roomData, savingContext: this.state.savingContext, show: !shouldRenderInvitationOverlay && shouldRenderEditContextView}) - ), - React.createElement(sharedViews.ConversationToolbar, { - audio: {enabled: !this.state.audioMuted, visible: true}, - dispatcher: this.props.dispatcher, - edit: { visible: this.state.contextEnabled, enabled: !this.state.showEditContext}, - hangup: this.leaveRoom, - onEditClick: this.handleEditContextClick, - publishStream: this.publishStream, - screenShare: screenShareData, - video: {enabled: !this.state.videoMuted, visible: true}}) + ) ) ); } diff --git a/browser/components/loop/content/js/roomViews.jsx b/browser/components/loop/content/js/roomViews.jsx index c27b51164d9a..a6705125a7b8 100644 --- a/browser/components/loop/content/js/roomViews.jsx +++ b/browser/components/loop/content/js/roomViews.jsx @@ -743,6 +743,15 @@ loop.roomViews = (function(mozL10n) { screenShareVideoObject={this.state.screenShareVideoObject} showContextRoomName={false} useDesktopPaths={true}> + - ); } diff --git a/browser/components/loop/content/shared/css/common.css b/browser/components/loop/content/shared/css/common.css index 7df0c4d4a4db..7428a5d54faf 100644 --- a/browser/components/loop/content/shared/css/common.css +++ b/browser/components/loop/content/shared/css/common.css @@ -118,15 +118,15 @@ p { .btn-accept, .btn-success, .btn-accept + .btn-chevron { - background-color: #5bc0a4; - border: 1px solid #5bc0a4; + background-color: #56b397; + border: 1px solid #56b397; } .btn-accept:hover, .btn-success:hover, .btn-accept + .btn-chevron:hover { - background-color: #47b396; - border: 1px solid #47b396; + background-color: #50e3c2; + border: 1px solid #50e3c2; } .btn-accept:active, diff --git a/browser/components/loop/content/shared/css/conversation.css b/browser/components/loop/content/shared/css/conversation.css index 86ba6e5dad57..cd5515e826b3 100644 --- a/browser/components/loop/content/shared/css/conversation.css +++ b/browser/components/loop/content/shared/css/conversation.css @@ -2,111 +2,135 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +html { + font-size: 10px; + font-family: menu; +} + /* Shared conversation window styles */ .conversation { position: relative; } -.conversation-toolbar { - z-index: 999; /* required to have it superimposed to the video element */ - border: 1px solid #5a5a5a; - border-left: 0; - border-right: 0; - background: rgba(0,0,0,.70); +button::-moz-focus-inner { + border: 0; } -/* desktop version */ -.fx-embedded .conversation-toolbar { - /* required to have dropdowns float atop the .room-invitation-overlay: */ - z-index: 1020; +.conversation-toolbar { + z-index: 1020; /* required to have it superimposed to the video element */ + border: 0; + left: 1.2rem; + right: .7rem; + height: 2.6rem; position: absolute; - top: 0; - left: 0; - right: 0; - /* note that .room-invitation-overlay top matches this */ - height: 26px; + bottom: 1.5rem; +} + +html[dir="rtl"] .conversation-toolbar { + left: .7rem; + right: 1.2rem; +} + +.idle { + transition: opacity 1.5s; + opacity: .75; } /* standalone version */ -.standalone .conversation-toolbar { - padding: 20px; - height: 64px; - border: none; -} - -.standalone .focus-stream { - /* Set at maximum height, minus height of conversation toolbar */ - height: calc(100% - 64px); -} - -.standalone .in-call .focus-stream { - height: 100%; -} .conversation-toolbar > li { float: left; + margin-right: .7rem; font-size: 0; /* prevents vertical bottom padding added to buttons in google chrome */ } - .standalone .conversation-toolbar > li { - /* XXX Might make sense to use relative units here. - */ - margin-right: 16px; - } - -.btn-edit-entry { - float: right !important; - border-left: 1px solid #5a5a5a; +html[dir="rtl"] .conversation-toolbar > li { + float: right; + margin-left: .7rem; + margin-right: auto; } -.conversation-toolbar-btn-box { - border-right: 1px solid #5a5a5a; -} - - .standalone .conversation-toolbar-btn-box { - /* overwrite the style for standalone - * because we reuse the same component */ - border: none; - } - .conversation-toolbar .btn { - /* dimensions according to spec - * https://people.mozilla.org/~dhenein/labs/loop-link-spec/#video-call */ - width: 32px; - height: 24px; background-position: center; - background-size: 40%; + background-size: 28px; background-repeat: no-repeat; + background-color: transparent; + height: 28px; + width: 33px; } -.standalone .media-control { - width: 36px; +.conversation-toolbar-media-btn-group-box { background-position: center; - border-radius: 28px; + background-repeat: no-repeat; + background-color: transparent; + background-image: url("../img/svg/media-group.svg"); + background-size: cover; + height: 28px; + width: 67px; } - .standalone-conversation-toolbar-media-btn:hover { - background-color: rgba(255,255,255,.35); - } +.conversation-toolbar-media-btn-group-box > button:last-child:active, +.conversation-toolbar-media-btn-group-box > button:last-child:hover { + background-image: url("../img/svg/media-group-right-hover.svg"); + background-size: cover; +} + +html[dir="rtl"] .conversation-toolbar-media-btn-group-box > button:last-child:active, +html[dir="rtl"] .conversation-toolbar-media-btn-group-box > button:last-child:hover { + background-image: url("../img/svg/media-group-left-hover.svg"); + background-size: cover; +} + +.conversation-toolbar-media-btn-group-box > button:first-child:active, +.conversation-toolbar-media-btn-group-box > button:first-child:hover { + background-image: url("../img/svg/media-group-left-hover.svg"); + background-size: cover; +} + +html[dir="rtl"] .conversation-toolbar-media-btn-group-box > button:first-child:active, +html[dir="rtl"] .conversation-toolbar-media-btn-group-box > button:first-child:hover { + background-image: url("../img/svg/media-group-right-hover.svg"); + background-size: cover; +} + +.conversation-toolbar-media-btn-group-box > li { + float: left; +} + +html[dir="rtl"] .conversation-toolbar-media-btn-group-box > li { + float: right; +} + +.conversation-toolbar-btn-box.btn-edit-entry { + float: right; +} + +html[dir="rtl"] .conversation-toolbar-btn-box.btn-edit-entry { + float: left; +} .fx-embedded-answer-btn-text { - vertical-align: bottom; /* always leave space for the icon (width and margin) */ - max-width: calc(100% - .8rem - .2rem); + max-width: calc(100% - 24px - .2rem); + height: 22px; + line-height: 22px; } .fx-embedded-btn-icon-video, .fx-embedded-btn-icon-audio { + width: 24px; + height: 24px; display: inline-block; - vertical-align: top; - width: .8rem; - height: .8rem; background-repeat: no-repeat; - cursor: pointer; + background-position: center; + background-size: 14px 14px; + border-radius: 50%; -moz-margin-start: .2rem; } +/* conversationViews.jsx */ + .fx-embedded-btn-icon-video, .fx-embedded-btn-video-small, .fx-embedded-tiny-video-icon { @@ -124,113 +148,80 @@ width: 26px; height: 26px; border-left: 1px solid rgba(255,255,255,.4); + background-color: #56b397; border-top-right-radius: 2px; border-bottom-right-radius: 2px; - background-color: #5bc0a4; background-position: center; - background-size: 1rem; background-repeat: no-repeat; cursor: pointer; } .fx-embedded-btn-video-small:hover, .fx-embedded-btn-audio-small:hover { - background-color: #6cb23e; + background-color: #50e3c2; } -@media (min-resolution: 2dppx) { - .fx-embedded-btn-audio-small { - background-image: url("../img/audio-inverse-14x14@2x.png"); - } - .fx-embedded-btn-video-small { - background-image: url("../img/video-inverse-14x14@2x.png"); - } -} - -.standalone .btn-hangup { - width: auto; - font-size: 12px; - border-radius: 2px; - padding: 0 20px; -} - -.fx-embedded .conversation-toolbar .btn-hangup { - background-image: url(../img/hangup-inverse-14x14.png); -} -@media (min-resolution: 2dppx) { - .fx-embedded .conversation-toolbar .btn-hangup { - background-image: url(../img/hangup-inverse-14x14@2x.png); - } -} - -/* Common media control buttons behavior */ -.conversation-toolbar .transparent-button { - background-color: transparent; - opacity: 1; -} -.conversation-toolbar .transparent-button:hover, -.conversation-toolbar .transparent-button.menu-showing { - background-color: rgba(255,255,255,.35); - opacity: 1; -} -.conversation-toolbar .media-control.muted { - background-color: #0096DD; - opacity: 1; +.conversation-toolbar .btn-hangup { + background-image: url("../img/svg/exit.svg"); + border: 0; } /* Audio mute button */ -.btn-mute-audio { - background-image: url(../img/audio-inverse-14x14.png); +.btn-mute-audio:after { + content: url("../img/svg/audio.svg"); } -.btn-mute-audio.muted { - background-image: url(../img/mute-inverse-14x14.png); + +.btn-mute-audio.muted:after { + content: url("../img/svg/audio-mute.svg"); } -@media (min-resolution: 2dppx) { - .btn-mute-audio { - background-image: url(../img/audio-inverse-14x14@2x.png); - } - .btn-mute-audio.muted { - background-image: url(../img/mute-inverse-14x14@2x.png); - } +.btn-mute-audio:hover:after, +.btn-mute-audio:active:after { + content: url("../img/svg/audio-hover.svg"); +} + +.btn-mute-audio.muted:hover:after, +.btn-mute-audio.muted:active:after { + content: url("../img/svg/audio-mute-hover.svg"); } /* Video mute button */ -.btn-mute-video { - background-image: url(../img/video-inverse-14x14.png); -} -.btn-mute-video.muted { - background-image: url(../img/facemute-14x14.png); -} -@media (min-resolution: 2dppx) { - .btn-mute-video { - background-image: url(../img/video-inverse-14x14@2x.png); - } - .btn-mute-video.muted { - background-image: url(../img/facemute-14x14@2x.png); - } +.btn-mute-video:after { + content: url("../img/svg/video.svg"); } -/* Screen share button */ -.btn-mute-edit, -.btn-screen-share { - position: relative; - background-image: url(../img/icons-10x10.svg#edit-white); - background-size: 16px 16px; +.btn-mute-video:active:after, +.btn-mute-video:hover:after { + content: url("../img/svg/video-hover.svg"); +} + +.btn-mute-video.muted:after { + content: url("../img/svg/video-mute.svg"); +} + +.btn-mute-video.muted:hover:after, +.btn-mute-video.muted:active:after { + content: url("../img/svg/video-mute-hover.svg"); +} + +.btn-mute-edit { + width: 28px; + height: 28px; + background-size: 28px; + background-image: url("../img/svg/settings.svg"); +} + +.btn-mute-edit:hover, +.btn-mute-edit:active { + background-image: url("../img/svg/settings-hover.svg"); } .btn-screen-share { - background-image: url(../img/icons-16x16.svg#screen-white); - width: 42px; + background-image: url("../img/svg/sharing.svg"); } -/* Make room for the chevron. */ -.conversation-toolbar .btn-screen-share:not(.active) { - background-position: 5px center; -} - -.btn-screen-share.active { - background-image: url(../img/icons-16x16.svg#screenmute-white); - background-color: #6CB23E; +.btn-screen-share:hover, +.btn-screen-share:active { + background-image: url("../img/svg/sharing-hover.svg"); } .btn-mute-edit.muted, @@ -239,21 +230,7 @@ } .btn-screen-share.disabled { - background-image: url(../img/icons-16x16.svg#screen-disabled); -} - -.btn-screen-share .chevron { - background-image: url(../img/icons-10x10.svg#dropdown-white); - background-size: 10px 10px; - position: absolute; - right: 2px; - top: 8px; - width: 10px; - height: 10px; -} - -.btn-screen-share.disabled .chevron { - background-image: url(../img/icons-10x10.svg#dropdown-disabled); + background-image: url("../img/svg/sharing-mute.svg"); } .fx-embedded .remote_wrapper { @@ -398,9 +375,13 @@ background-color: #111; } +.conversation-window-dropdown { + bottom: 4rem; +} + .conversation-window-dropdown > li { - padding: 2px; - font-size: .7rem; + padding: .2rem; + font-size: 1rem; white-space: nowrap; } @@ -535,7 +516,8 @@ /* * Used to center the loading spinner */ -.focus-stream, .remote { +.focus-stream, +.media-wrapper:not(.receiving-screen-share) > .remote { position: relative; } @@ -620,19 +602,18 @@ } .fx-embedded-call-detail { - padding-top: 1.2em; + padding-top: 0.6em; } .fx-embedded-tiny-video-icon { - margin: 0 0.8em; + margin: 0 .8em; } .fx-embedded-tiny-audio-icon, .fx-embedded-tiny-video-icon { - width: 18px; - height: 18px; - background-size: 12px 12px; - background-color: #4ba6e7; + width: 24px; + height: 24px; + background-color: #00a9dc; display: inline-block; background-repeat: no-repeat; background-position: center; @@ -799,15 +780,14 @@ html[dir="rtl"] .room-conversation-wrapper header a { } .fx-embedded .room-conversation .conversation-toolbar .btn-hangup { - background-image: url("../img/icons-16x16.svg#leave"); + background-image: url("../img/icons-14x14.svg#exit-white"); } .room-invitation-overlay { position: absolute; - background: rgba(0,0,0,.6); - /* This matches .fx-embedded .conversation toolbar height */ - top: 26px; - height: calc(100% - 26px); + background: rgba(255, 255, 255, 0.6); + top: 0; + height: 100%; right: 0; left: 0; text-align: center; @@ -835,7 +815,7 @@ html[dir="rtl"] .room-conversation-wrapper header a { } .room-invitation-overlay .btn-group { - padding: 0 0 1em 0; + padding: 0 0 5rem 0; } .room-invitation-addcontext { @@ -915,9 +895,7 @@ body[platform="win"] .share-service-dropdown.overflow > .dropdown-menu-item { left: 0; bottom: 0; width: 100%; - /* Stretch to the maximum available space whilst not covering the conversation - toolbar (26px). */ - height: calc(100% - 26px); + height: 100%; font-size: .9em; display: flex; flex-flow: column nowrap; @@ -1060,8 +1038,8 @@ html[dir="rtl"] .room-context-btn-close { } .standalone-room-wrapper > .media-layout { - /* 50px is the header, 64px for toolbar, 3em is the footer. */ - height: calc(100% - 50px - 64px - 3em); + /* 50px is the header, 3em is the footer. */ + height: calc(100% - 50px - 3em); margin: 0 10px; } @@ -1109,6 +1087,10 @@ html[dir="rtl"] .room-context-btn-close { height: calc(100% - 150px); } +.media-wrapper.showing-local-streams.receiving-screen-share { + position: relative; +} + .media-wrapper.showing-local-streams.receiving-screen-share > .text-chat-view { /* When we're displaying the local streams, then we need to make the text chat view a bit shorter to give room. */ @@ -1117,10 +1099,7 @@ html[dir="rtl"] .room-context-btn-close { .desktop-call-wrapper > .media-layout > .media-wrapper > .text-chat-view, .desktop-room-wrapper > .media-layout > .media-wrapper > .text-chat-view { - /* Account for height of .conversation-toolbar on desktop */ - /* When we change the toolbar in bug 1184559 we can remove this. */ - margin-top: 26px; - height: calc(100% - 150px - 26px); + height: calc(100% - 150px); } /* Temporarily slaved from .media-wrapper until we use it in more places @@ -1199,6 +1178,11 @@ html[dir="rtl"] .room-context-btn-close { height: 100%; } + .media-wrapper > .focus-stream > .local ~ .conversation-toolbar { + /* 22px are the margins, 120px is for the local video area. */ + max-width: calc(100% - 22px - 120px); + } + .media-wrapper > .focus-stream > .local { /* Position over the remote video */ position: absolute; @@ -1206,6 +1190,7 @@ html[dir="rtl"] .room-context-btn-close { z-index: 2; margin: 3px; right: 0; + left:auto; /* 29px is (30% of 50px high header) + (height toolbar (38px) + height footer (25px) - height header (50px)) */ bottom: 0; @@ -1213,6 +1198,12 @@ html[dir="rtl"] .room-context-btn-close { height: 120px; } + html[dir="rtl"] .media-wrapper > .focus-stream > .local { + right: auto; + left: 0; + } + + .standalone-room-wrapper > .media-layout > .media-wrapper > .local { /* Add 10px for the margin on standalone */ right: 10px; @@ -1239,9 +1230,6 @@ html[dir="rtl"] .room-context-btn-close { .desktop-call-wrapper > .media-layout > .media-wrapper > .text-chat-view, .desktop-room-wrapper > .media-layout > .media-wrapper > .text-chat-view { - /* When we change the toolbar in bug 1184559 we can remove this. */ - /* Reset back to 0 for .conversation-toolbar override on desktop */ - margin-top: 0; /* This is temp, to echo the .media-wrapper > .text-chat-view above */ height: 30%; } @@ -1293,9 +1281,15 @@ html[dir="rtl"] .room-context-btn-close { flex-flow: column nowrap; } + .media-wrapper > .focus-stream > .local ~ .conversation-toolbar { + max-width: calc(75% - 22px); + } + .media-wrapper > .focus-stream > .local { position: absolute; + display:fixed; right: 0; + left: auto; /* 30% is the height of the text chat. As we have a margin, we don't need to worry about any offset for a border */ bottom: 0; @@ -1307,6 +1301,11 @@ html[dir="rtl"] .room-context-btn-close { height: 25%; } + html[dir="rtl"] .media-wrapper > .focus-stream > .local { + left: 0; + right: auto; + } + .media-wrapper:not(.showing-remote-streams) > .focus-stream > .no-video { display: none; } @@ -1322,6 +1321,10 @@ html[dir="rtl"] .room-context-btn-close { background-color: black; } + .media-wrapper:not(.showing-remote-streams) > .focus-stream > .local ~ .conversation-toolbar { + max-width: calc(100% - 22px); + } + .media-wrapper > .focus-stream { flex: 1 1 auto; height: auto; @@ -1339,7 +1342,6 @@ html[dir="rtl"] .room-context-btn-close { height: 100%; background: #000; } - .standalone .room-conversation-wrapper .video-layout-wrapper { /* 50px = height of header, 3em = height of footer */ /* XXX This is currently wrong for narrow/mobile display, @@ -1709,11 +1711,6 @@ html[dir="rtl"] .text-chat-entry.received .text-chat-arrow { .standalone .room-conversation .video_wrapper.remote_wrapper.not-joined { width: 100%; } - - .standalone .conversation-toolbar { - height: 38px; - padding: 8px; - } .standalone .conversation .focus-stream { /* Set at maximum height, minus height of conversation toolbar */ height: 100%; @@ -1734,20 +1731,14 @@ html[dir="rtl"] .text-chat-entry.received .text-chat-arrow { max-height: 160px; /* 60px min-height of .text-chat-entries plus 40px of .text-chat-box */ min-height: 100px; - /* The !important is to override the values defined above which have more - specificity when we fix bug 1184559, we should be able to remove it, - but this should be tested first. */ - height: auto !important; + height: auto; /* Let the view be the minimum size it needs to be - don't flex to take up more. */ flex: 0 0 auto !important; } .text-chat-entries { - /* The !important is to override the values defined above which have more - specificity when we fix bug 1184559, we should be able to remove it, - but this should be tests first. */ - flex: 1 1 auto !important; + flex: 1 1 auto; max-height: 120px; min-height: 60px; } @@ -1834,7 +1825,7 @@ html[dir="rtl"] .text-chat-entry.received .text-chat-arrow { /* Make sure the loading spinner always gets the same background */ .loading-background { background: black; - position: absolute; + position: relative; width: 100%; height: 100%; } diff --git a/browser/components/loop/content/shared/img/icons-14x14.svg b/browser/components/loop/content/shared/img/icons-14x14.svg index 7a6fb5d37335..d9fece9655a6 100644 --- a/browser/components/loop/content/shared/img/icons-14x14.svg +++ b/browser/components/loop/content/shared/img/icons-14x14.svg @@ -14,28 +14,30 @@ fill: #444; } use[id$="-active"] { - fill: #0095dd; + fill: #5cccee; + } + use[id$="-still"] { + fill: #00a9dc; } use[id$="-white"] { - fill: #fff; + fill: #ffffff; + } + use[id$="-grey"] { + fill: #4a4a4a; } - - - - - - - - - - - - - - - + + + + + + + + + + + @@ -43,16 +45,25 @@ + + + + + + + + + @@ -67,13 +78,20 @@ + + + + + + + diff --git a/browser/components/loop/content/shared/img/icons-16x16.svg b/browser/components/loop/content/shared/img/icons-16x16.svg index 01e9ebaaeaf3..81ee421ad368 100644 --- a/browser/components/loop/content/shared/img/icons-16x16.svg +++ b/browser/components/loop/content/shared/img/icons-16x16.svg @@ -14,7 +14,7 @@ fill: #444; } use[id$="-active"] { - fill: #0095dd; + fill: #5cccee; } use[id$="-red"] { fill: #d74345 @@ -28,6 +28,9 @@ use[id$="-disabled"] { fill: rgba(255,255,255,.6); } + use[id$="-still"] { + fill: #00a9dc; + } @@ -69,14 +72,6 @@ - - - - - - - - @@ -93,8 +88,6 @@ - - @@ -124,12 +117,7 @@ - - - - - diff --git a/browser/components/loop/content/shared/img/svg/audio-hover.svg b/browser/components/loop/content/shared/img/svg/audio-hover.svg new file mode 100644 index 000000000000..f2a1510ae2e9 --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/audio-hover.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/audio-mute-hover.svg b/browser/components/loop/content/shared/img/svg/audio-mute-hover.svg new file mode 100644 index 000000000000..488a4fce3e0d --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/audio-mute-hover.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/audio-mute.svg b/browser/components/loop/content/shared/img/svg/audio-mute.svg new file mode 100644 index 000000000000..14f86376113b --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/audio-mute.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/audio.svg b/browser/components/loop/content/shared/img/svg/audio.svg new file mode 100644 index 000000000000..4077b0d60d7e --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/audio.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/cam_audio-no.svg b/browser/components/loop/content/shared/img/svg/cam_audio-no.svg new file mode 100644 index 000000000000..9f86bb0d2e56 --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/cam_audio-no.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/cam_audio.svg b/browser/components/loop/content/shared/img/svg/cam_audio.svg new file mode 100644 index 000000000000..6c2af143969f --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/cam_audio.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/cam_audio_h.svg b/browser/components/loop/content/shared/img/svg/cam_audio_h.svg new file mode 100644 index 000000000000..b64d8441389c --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/cam_audio_h.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/exit.svg b/browser/components/loop/content/shared/img/svg/exit.svg new file mode 100644 index 000000000000..e96a3c5d96b9 --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/exit.svg @@ -0,0 +1,9 @@ + + + + Layer 1 + + + + + diff --git a/browser/components/loop/content/shared/img/svg/media-group-left-hover.svg b/browser/components/loop/content/shared/img/svg/media-group-left-hover.svg new file mode 100644 index 000000000000..01172d7cb258 --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/media-group-left-hover.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/media-group-right-hover.svg b/browser/components/loop/content/shared/img/svg/media-group-right-hover.svg new file mode 100644 index 000000000000..3aba07b75c1a --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/media-group-right-hover.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/media-group.svg b/browser/components/loop/content/shared/img/svg/media-group.svg new file mode 100644 index 000000000000..6c2af143969f --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/media-group.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/settings-hover.svg b/browser/components/loop/content/shared/img/svg/settings-hover.svg new file mode 100644 index 000000000000..2c6150ec64fc --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/settings-hover.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/settings.svg b/browser/components/loop/content/shared/img/svg/settings.svg new file mode 100644 index 000000000000..8bebe2d1bbfd --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/sharing-hover.svg b/browser/components/loop/content/shared/img/svg/sharing-hover.svg new file mode 100644 index 000000000000..db49fa223614 --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/sharing-hover.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/sharing-mute.svg b/browser/components/loop/content/shared/img/svg/sharing-mute.svg new file mode 100644 index 000000000000..4872f280ae80 --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/sharing-mute.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/sharing.svg b/browser/components/loop/content/shared/img/svg/sharing.svg new file mode 100644 index 000000000000..e7804c226b00 --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/sharing.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/video-hover.svg b/browser/components/loop/content/shared/img/svg/video-hover.svg new file mode 100644 index 000000000000..eb6b8035491e --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/video-hover.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/video-mute-hover.svg b/browser/components/loop/content/shared/img/svg/video-mute-hover.svg new file mode 100644 index 000000000000..959408ecfb99 --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/video-mute-hover.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/video-mute.svg b/browser/components/loop/content/shared/img/svg/video-mute.svg new file mode 100644 index 000000000000..879f1c62d37b --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/video-mute.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/browser/components/loop/content/shared/img/svg/video.svg b/browser/components/loop/content/shared/img/svg/video.svg new file mode 100644 index 000000000000..65fb0f5fa1cf --- /dev/null +++ b/browser/components/loop/content/shared/img/svg/video.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/browser/components/loop/content/shared/js/views.js b/browser/components/loop/content/shared/js/views.js index 6c14b424f59c..8e057924c824 100644 --- a/browser/components/loop/content/shared/js/views.js +++ b/browser/components/loop/content/shared/js/views.js @@ -194,6 +194,12 @@ loop.shared.views = (function(_, mozL10n) { }; }, + getInitialState: function() { + return { + idle: false + }; + }, + propTypes: { audio: React.PropTypes.object.isRequired, dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, @@ -225,13 +231,83 @@ loop.shared.views = (function(_, mozL10n) { } }, + componentDidMount: function() { + this.userActivity = false; + this.startIdleCountDown(); + document.body.addEventListener("mousemove", this._onBodyMouseMove); + }, + + componentWillUnmount: function() { + clearTimeout(this.inactivityTimeout); + clearInterval(this.inactivityPollInterval); + document.body.removeEventListener("mousemove", this._onBodyMouseMove); + }, + + /** + * If the conversation toolbar is idle, update its state and initialize the countdown + * to return of the idle state. If the toolbar is active, only it's updated the userActivity flag. + */ + _onBodyMouseMove: function() { + if (this.state.idle) { + this.setState({idle: false}); + this.startIdleCountDown(); + } else { + this.userActivity = true; + } + }, + + /** + * Instead of resetting the timeout for every mousemove (this event is called to many times, + * when the mouse is moving, we check the flat userActivity every 4 seconds. If the flag is activated, + * the user is still active, and we can restart the countdown for the idle state + */ + checkUserActivity: function() { + this.inactivityPollInterval = setInterval(function() { + if (this.userActivity) { + this.userActivity = false; + this.restartIdleCountDown(); + } + }.bind(this), 4000); + }, + + /** + * Stop the execution of the current inactivity countdown and it starts a new one. + */ + restartIdleCountDown: function() { + clearTimeout(this.inactivityTimeout); + this.startIdleCountDown(); + }, + + /** + * Launchs the process to check the user activity and the inactivity countdown to change + * the toolbar to idle. + * When the toolbar changes to idle, we remove the procces to check the user activity, + * because the toolbar is going to be updated directly when the user moves the mouse. + */ + startIdleCountDown: function() { + this.checkUserActivity(); + this.inactivityTimeout = setTimeout(function() { + this.setState({idle: true}); + clearInterval(this.inactivityPollInterval); + }.bind(this), 6000); + }, + _getHangupButtonLabel: function() { return this.props.hangupButtonLabel || mozL10n.get("hangup_button_caption2"); }, render: function() { + var cx = React.addons.classSet; + var conversationToolbarCssClasses = cx({ + "conversation-toolbar": true, + "idle": this.state.idle + }); + var mediaButtonGroupCssClasses = cx({ + "conversation-toolbar-media-btn-group-box": true, + "hide": (!this.props.video.visible && !this.props.audio.visible) + }); return ( - React.createElement("ul", {className: "conversation-toolbar"}, + React.createElement("ul", {className: conversationToolbarCssClasses}, React.createElement("li", {className: "conversation-toolbar-btn-box btn-hangup-entry"}, React.createElement("button", {className: "btn btn-hangup", disabled: !this.props.enableHangup, @@ -241,16 +317,17 @@ loop.shared.views = (function(_, mozL10n) { ) ), React.createElement("li", {className: "conversation-toolbar-btn-box"}, - React.createElement(MediaControlButton, {action: this.handleToggleVideo, - enabled: this.props.video.enabled, - scope: "local", type: "video", - visible: this.props.video.visible}) - ), - React.createElement("li", {className: "conversation-toolbar-btn-box"}, - React.createElement(MediaControlButton, {action: this.handleToggleAudio, - enabled: this.props.audio.enabled, - scope: "local", type: "audio", - visible: this.props.audio.visible}) + React.createElement("div", {className: mediaButtonGroupCssClasses}, + React.createElement(MediaControlButton, {action: this.handleToggleVideo, + enabled: this.props.video.enabled, + scope: "local", type: "video", + visible: this.props.video.visible}), + React.createElement(MediaControlButton, {action: this.handleToggleAudio, + enabled: this.props.audio.enabled, + scope: "local", type: "audio", + visible: this.props.audio.visible}) + + ) ), React.createElement("li", {className: "conversation-toolbar-btn-box"}, React.createElement(ScreenShareControlButton, {dispatcher: this.props.dispatcher, @@ -477,16 +554,18 @@ loop.shared.views = (function(_, mozL10n) { React.createElement("div", {className: "conversation in-call"}, React.createElement("div", {className: "media nested"}, React.createElement("div", {className: "video_wrapper remote_wrapper"}, - React.createElement("div", {className: "video_inner remote focus-stream"}) + React.createElement("div", {className: "video_inner remote focus-stream"}, + React.createElement(ConversationToolbar, { + audio: this.state.audio, + dispatcher: this.props.dispatcher, + hangup: this.hangup, + publishStream: this.publishStream, + video: this.state.video}) + ) ), React.createElement("div", {className: localStreamClasses}) - ), - React.createElement(ConversationToolbar, { - audio: this.state.audio, - dispatcher: this.props.dispatcher, - hangup: this.hangup, - publishStream: this.publishStream, - video: this.state.video}) + + ) ) ) ); @@ -1064,6 +1143,7 @@ loop.shared.views = (function(_, mozL10n) { this.state.localMediaAboslutelyPositioned ? this.renderLocalVideo() : null, this.props.children + ), React.createElement("div", {className: screenShareStreamClasses}, React.createElement(MediaView, {displayAvatar: false, diff --git a/browser/components/loop/content/shared/js/views.jsx b/browser/components/loop/content/shared/js/views.jsx index 497df94b5482..ab5ac1553718 100644 --- a/browser/components/loop/content/shared/js/views.jsx +++ b/browser/components/loop/content/shared/js/views.jsx @@ -194,6 +194,12 @@ loop.shared.views = (function(_, mozL10n) { }; }, + getInitialState: function() { + return { + idle: false + }; + }, + propTypes: { audio: React.PropTypes.object.isRequired, dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, @@ -225,13 +231,83 @@ loop.shared.views = (function(_, mozL10n) { } }, + componentDidMount: function() { + this.userActivity = false; + this.startIdleCountDown(); + document.body.addEventListener("mousemove", this._onBodyMouseMove); + }, + + componentWillUnmount: function() { + clearTimeout(this.inactivityTimeout); + clearInterval(this.inactivityPollInterval); + document.body.removeEventListener("mousemove", this._onBodyMouseMove); + }, + + /** + * If the conversation toolbar is idle, update its state and initialize the countdown + * to return of the idle state. If the toolbar is active, only it's updated the userActivity flag. + */ + _onBodyMouseMove: function() { + if (this.state.idle) { + this.setState({idle: false}); + this.startIdleCountDown(); + } else { + this.userActivity = true; + } + }, + + /** + * Instead of resetting the timeout for every mousemove (this event is called to many times, + * when the mouse is moving, we check the flat userActivity every 4 seconds. If the flag is activated, + * the user is still active, and we can restart the countdown for the idle state + */ + checkUserActivity: function() { + this.inactivityPollInterval = setInterval(function() { + if (this.userActivity) { + this.userActivity = false; + this.restartIdleCountDown(); + } + }.bind(this), 4000); + }, + + /** + * Stop the execution of the current inactivity countdown and it starts a new one. + */ + restartIdleCountDown: function() { + clearTimeout(this.inactivityTimeout); + this.startIdleCountDown(); + }, + + /** + * Launchs the process to check the user activity and the inactivity countdown to change + * the toolbar to idle. + * When the toolbar changes to idle, we remove the procces to check the user activity, + * because the toolbar is going to be updated directly when the user moves the mouse. + */ + startIdleCountDown: function() { + this.checkUserActivity(); + this.inactivityTimeout = setTimeout(function() { + this.setState({idle: true}); + clearInterval(this.inactivityPollInterval); + }.bind(this), 6000); + }, + _getHangupButtonLabel: function() { return this.props.hangupButtonLabel || mozL10n.get("hangup_button_caption2"); }, render: function() { + var cx = React.addons.classSet; + var conversationToolbarCssClasses = cx({ + "conversation-toolbar": true, + "idle": this.state.idle + }); + var mediaButtonGroupCssClasses = cx({ + "conversation-toolbar-media-btn-group-box": true, + "hide": (!this.props.video.visible && !this.props.audio.visible) + }); return ( -
    +
    • - -
    • -
    • - +
      + + + +
    • -
      +
      + +
      +
      - ); @@ -1064,6 +1143,7 @@ loop.shared.views = (function(_, mozL10n) { { this.state.localMediaAboslutelyPositioned ? this.renderLocalVideo() : null } { this.props.children } +
      + - diff --git a/browser/components/loop/test/shared/views_test.js b/browser/components/loop/test/shared/views_test.js index d0b2952bca26..2222e3d533f1 100644 --- a/browser/components/loop/test/shared/views_test.js +++ b/browser/components/loop/test/shared/views_test.js @@ -253,7 +253,7 @@ describe("loop.shared.views", function() { }); describe("ConversationToolbar", function() { - var hangup, publishStream; + var clock, hangup, publishStream; function mountTestComponent(props) { props = _.extend({ @@ -266,6 +266,47 @@ describe("loop.shared.views", function() { beforeEach(function() { hangup = sandbox.stub(); publishStream = sandbox.stub(); + clock = sinon.useFakeTimers(); + }); + + afterEach(function() { + clock.restore(); + }); + + it("should start no idle", function() { + var comp = mountTestComponent({ + hangupButtonLabel: "foo", + hangup: hangup, + publishStream: publishStream + }); + expect(comp.getDOMNode().classList.contains("idle")).eql(false); + }); + + it("should be on idle state after 6 seconds", function() { + var comp = mountTestComponent({ + hangupButtonLabel: "foo", + hangup: hangup, + publishStream: publishStream + }); + expect(comp.getDOMNode().classList.contains("idle")).eql(false); + + clock.tick(6001); + expect(comp.getDOMNode().classList.contains("idle")).eql(true); + }); + + it("should remove idle state when the user moves the mouse", function() { + var comp = mountTestComponent({ + hangupButtonLabel: "foo", + hangup: hangup, + publishStream: publishStream + }); + + clock.tick(6001); + expect(comp.getDOMNode().classList.contains("idle")).eql(true); + + document.body.dispatchEvent(new CustomEvent("mousemove")); + + expect(comp.getDOMNode().classList.contains("idle")).eql(false); }); it("should accept a hangupButtonLabel optional prop", function() { diff --git a/browser/components/loop/ui/ui-showcase.js b/browser/components/loop/ui/ui-showcase.js index b20439498265..927ac94e805a 100644 --- a/browser/components/loop/ui/ui-showcase.js +++ b/browser/components/loop/ui/ui-showcase.js @@ -518,7 +518,7 @@ "dropdown-white", "dropdown-active", "dropdown-disabled", "edit", "edit-active", "edit-disabled", "edit-white", "expand", "expand-active", "expand-disabled", "minimize", "minimize-active", "minimize-disabled", - "settings-cog" + "settings-cog-grey", "settings-cog-white" ], "14x14": ["audio", "audio-active", "audio-disabled", "facemute", "facemute-active", "facemute-disabled", "hangup", "hangup-active", @@ -928,76 +928,38 @@ ), React.createElement(Section, {name: "ConversationToolbar"}, - React.createElement("h2", null, "Desktop Conversation Window"), React.createElement("div", null, React.createElement(FramedExample, {dashed: true, - height: 26, + height: 56, summary: "Default", width: 300}, React.createElement("div", {className: "fx-embedded"}, - React.createElement(ConversationToolbar, {audio: {enabled: true}, + React.createElement(ConversationToolbar, {audio: { enabled: true, visible: true}, hangup: noop, publishStream: noop, - video: {enabled: true}}) + video: { enabled: true, visible: true}}) ) ), React.createElement(FramedExample, {dashed: true, - height: 26, + height: 56, summary: "Video muted", width: 300}, React.createElement("div", {className: "fx-embedded"}, - React.createElement(ConversationToolbar, {audio: {enabled: true}, + React.createElement(ConversationToolbar, {audio: { enabled: true, visible: true}, hangup: noop, publishStream: noop, - video: {enabled: false}}) + video: { enabled: false, visible: true}}) ) ), React.createElement(FramedExample, {dashed: true, - height: 26, + height: 56, summary: "Audio muted", width: 300}, React.createElement("div", {className: "fx-embedded"}, - React.createElement(ConversationToolbar, {audio: {enabled: false}, + React.createElement(ConversationToolbar, {audio: { enabled: false, visible: true}, hangup: noop, publishStream: noop, - video: {enabled: true}}) - ) - ) - ), - - React.createElement("h2", null, "Standalone"), - React.createElement("div", {className: "standalone override-position"}, - React.createElement(FramedExample, {dashed: true, - height: 26, - summary: "Default", - width: 300}, - React.createElement("div", {className: "fx-embedded"}, - React.createElement(ConversationToolbar, {audio: {enabled: true}, - hangup: noop, - publishStream: noop, - video: {enabled: true}}) - ) - ), - React.createElement(FramedExample, {dashed: true, - height: 26, - summary: "Video muted", - width: 300}, - React.createElement("div", {className: "fx-embedded"}, - React.createElement(ConversationToolbar, {audio: {enabled: true}, - hangup: noop, - publishStream: noop, - video: {enabled: false}}) - ) - ), - React.createElement(FramedExample, {dashed: true, - height: 26, - summary: "Audio muted", - width: 300}, - React.createElement("div", {className: "fx-embedded"}, - React.createElement(ConversationToolbar, {audio: {enabled: false}, - hangup: noop, - publishStream: noop, - video: {enabled: true}}) + video: { enabled: true, visible: true}}) ) ) ) @@ -1057,14 +1019,14 @@ width: 298}, React.createElement("div", {className: "fx-embedded"}, React.createElement(OngoingConversationView, { - audio: {enabled: true}, + audio: { enabled: true, visible: true}, conversationStore: conversationStores[0], dispatcher: dispatcher, localPosterUrl: "sample-img/video-screen-local.png", mediaConnected: true, remotePosterUrl: "sample-img/video-screen-remote.png", remoteVideoEnabled: true, - video: {enabled: true}}) + video: { enabled: true, visible: true}}) ) ), @@ -1075,14 +1037,14 @@ width: 600}, React.createElement("div", {className: "fx-embedded"}, React.createElement(OngoingConversationView, { - audio: {enabled: true}, + audio: { enabled: true, visible: true}, conversationStore: conversationStores[1], dispatcher: dispatcher, localPosterUrl: "sample-img/video-screen-local.png", mediaConnected: true, remotePosterUrl: "sample-img/video-screen-remote.png", remoteVideoEnabled: true, - video: {enabled: true}}) + video: { enabled: true, visible: true}}) ) ), @@ -1092,14 +1054,14 @@ width: 800}, React.createElement("div", {className: "fx-embedded"}, React.createElement(OngoingConversationView, { - audio: {enabled: true}, + audio: { enabled: true, visible: true}, conversationStore: conversationStores[2], dispatcher: dispatcher, localPosterUrl: "sample-img/video-screen-local.png", mediaConnected: true, remotePosterUrl: "sample-img/video-screen-remote.png", remoteVideoEnabled: true, - video: {enabled: true}}) + video: { enabled: true, visible: true}}) ) ), @@ -1110,14 +1072,14 @@ width: 298}, React.createElement("div", {className: "fx-embedded"}, React.createElement(OngoingConversationView, { - audio: {enabled: true}, + audio: { enabled: true, visible: true}, conversationStore: conversationStores[3], dispatcher: dispatcher, localPosterUrl: "sample-img/video-screen-local.png", mediaConnected: true, remotePosterUrl: "sample-img/video-screen-remote.png", remoteVideoEnabled: true, - video: {enabled: false}}) + video: { enabled: true, visible: true}}) ) ), @@ -1128,14 +1090,14 @@ width: 298}, React.createElement("div", {className: "fx-embedded"}, React.createElement(OngoingConversationView, { - audio: {enabled: true}, + audio: { enabled: true, visible: true}, conversationStore: conversationStores[4], dispatcher: dispatcher, localPosterUrl: "sample-img/video-screen-local.png", mediaConnected: true, remotePosterUrl: "sample-img/video-screen-remote.png", remoteVideoEnabled: false, - video: {enabled: true}}) + video: { enabled: true, visible: true}}) ) ) @@ -1628,7 +1590,7 @@ // This simulates the mocha layout for errors which means we can run // this alongside our other unit tests but use the same harness. - var expectedWarningsCount = 16; + var expectedWarningsCount = 10; var warningsMismatch = caughtWarnings.length !== expectedWarningsCount; if (uncaughtError || warningsMismatch) { $("#results").append("
      " + diff --git a/browser/components/loop/ui/ui-showcase.jsx b/browser/components/loop/ui/ui-showcase.jsx index 35d30251ab37..993f9c072ee3 100644 --- a/browser/components/loop/ui/ui-showcase.jsx +++ b/browser/components/loop/ui/ui-showcase.jsx @@ -518,7 +518,7 @@ "dropdown-white", "dropdown-active", "dropdown-disabled", "edit", "edit-active", "edit-disabled", "edit-white", "expand", "expand-active", "expand-disabled", "minimize", "minimize-active", "minimize-disabled", - "settings-cog" + "settings-cog-grey", "settings-cog-white" ], "14x14": ["audio", "audio-active", "audio-disabled", "facemute", "facemute-active", "facemute-disabled", "hangup", "hangup-active", @@ -928,76 +928,38 @@
      -

      Desktop Conversation Window

      - + video={{ enabled: true, visible: true }} />
      - + video={{ enabled: false, visible: true }} />
      - -
      -
      -
      - -

      Standalone

      -
      - -
      - -
      -
      - -
      - -
      -
      - -
      - + video={{ enabled: true, visible: true }} />
      @@ -1057,14 +1019,14 @@ width={298}>
      + video={{ enabled: true, visible: true }} />
      @@ -1075,14 +1037,14 @@ width={600}>
      + video={{ enabled: true, visible: true }} />
      @@ -1092,14 +1054,14 @@ width={800}>
      + video={{ enabled: true, visible: true }} />
      @@ -1110,14 +1072,14 @@ width={298}>
      + video={{ enabled: true, visible: true }} />
      @@ -1128,14 +1090,14 @@ width={298} >
      + video={{ enabled: true, visible: true }} />
      @@ -1628,7 +1590,7 @@ // This simulates the mocha layout for errors which means we can run // this alongside our other unit tests but use the same harness. - var expectedWarningsCount = 16; + var expectedWarningsCount = 10; var warningsMismatch = caughtWarnings.length !== expectedWarningsCount; if (uncaughtError || warningsMismatch) { $("#results").append("
      " +