+ when-connection="secure-ev">&identity.connectionVerified1;
diff --git a/browser/components/loop/content/css/contacts.css b/browser/components/loop/content/css/contacts.css
index 381bb89c3e03..722d742d7aab 100644
--- a/browser/components/loop/content/css/contacts.css
+++ b/browser/components/loop/content/css/contacts.css
@@ -165,30 +165,6 @@ html {
width: 100%;
}
-.contact-list-empty {
- background-image: url("../shared/img/empty_contacts.svg");
- background-repeat: no-repeat;
- background-position: top center;
- padding-top: 28%;
- padding-bottom: 5%;
- text-align: center;
- color: #4a4a4a;
- font-weight: lighter;
-}
-
-.panel-text-medium,
-.panel-text-large {
- margin: 3px;
-}
-
-.panel-text-medium {
- font-size: 1.6rem;
-}
-
-.panel-text-large {
- font-size: 2.2rem;
-}
-
.contact > .details > .username {
font-size: 1.3rem;
line-height: 20px;
diff --git a/browser/components/loop/content/css/panel.css b/browser/components/loop/content/css/panel.css
index 3e2caa737f70..fb932aef8b29 100644
--- a/browser/components/loop/content/css/panel.css
+++ b/browser/components/loop/content/css/panel.css
@@ -274,18 +274,61 @@ html[dir="rtl"] .tab-view li:nth-child(2).selected ~ .slide-bar {
border: 0.1rem solid #5cccee;
}
+/* Rooms and contacts shared CSS */
+
+.contact-list-empty,
+.room-list-empty {
+ background-image: url("../shared/img/empty_contacts.svg");
+ background-repeat: no-repeat;
+ background-position: top center;
+ padding-top: 19%;
+ padding-bottom: 3%;
+ text-align: center;
+ color: #4a4a4a;
+ font-weight: lighter;
+}
+
+.contact-list-empty {
+ padding-top: 27%;
+}
+
+.room-list-empty {
+ margin: 5% 15px;
+ background-image: url("../shared/img/empty_conversations.svg");
+}
+
+.panel-text-medium,
+.panel-text-large {
+ margin: 3px 0;
+}
+
+.panel-text-medium {
+ font-size: 1.6rem;
+}
+
+.panel-text-large {
+ font-size: 2.2rem;
+}
+
+
/* Rooms */
.rooms {
min-height: 100px;
- padding: 0 1rem;
}
.rooms > h1 {
font-weight: bold;
- color: #999;
+ color: #666;
padding: .5rem 0;
height: 3rem;
line-height: 3rem;
+ font-size: 1.1rem;
+ margin: 0 15px;
+}
+
+.new-room-view {
+ display: flex;
+ flex-direction: column;
}
.new-room-view > .context-checkbox-checked {
@@ -293,11 +336,10 @@ html[dir="rtl"] .tab-view li:nth-child(2).selected ~ .slide-bar {
}
.new-room-view > .context {
- margin: .5rem 0 .5rem;
+ flex: 1;
border-radius: 3px 3px 0 0;
- padding: .5rem 1rem ;
- margin-left: -1rem;
- margin-right: -1rem;
+ margin: 1rem 0 .5rem;
+ padding: 1rem 15px;
}
.new-room-view > .context > .context-enabled {
@@ -330,11 +372,11 @@ html[dir="rtl"] .tab-view li:nth-child(2).selected ~ .slide-bar {
}
.new-room-view > .btn {
+ flex: 1;
height: 3rem;
display: block;
font-size: 1.2rem;
- margin: 0 auto 1rem;
- width: 100%;
+ margin: 0 15px 1rem 15px;
padding: .5rem 1rem;
border-radius: 4px;
}
@@ -349,10 +391,6 @@ html[dir="rtl"] .tab-view li:nth-child(2).selected ~ .slide-bar {
max-height: 335px; /* XXX better computation needed */
min-height: 7px;
overflow: auto;
- border-top: 1px solid #ccc;
- border-bottom: 1px solid #ccc;
- margin-left: -1rem;
- margin-right: -1rem;
}
.room-list:empty {
@@ -360,15 +398,16 @@ html[dir="rtl"] .tab-view li:nth-child(2).selected ~ .slide-bar {
}
.room-list > .room-entry {
- padding: .2rem 1rem;
+ padding: .2rem 15px;
/* Always show the default pointer, even over the text part of the entry. */
cursor: default;
}
.room-list > .room-entry > h2 {
display: inline-block;
- font-size: 1rem;
- color: #777;
+ font-size: 1.3rem;
+ line-height: 2.4rem;
+ color: #000;
/* See .room-entry-context-item for the margin/size reductions. */
width: calc(100% - 1rem - 16px);
}
@@ -378,19 +417,6 @@ html[dir="rtl"] .tab-view li:nth-child(2).selected ~ .slide-bar {
color: #000;
}
-.room-list > .room-entry > h2 > .room-notification {
- display: none;
- background: #00a0ec;
- width: 8px;
- height: 8px;
- border-radius: 50%;
- -moz-margin-end: .3rem;
-}
-
-.room-list > .room-entry.room-active > h2 > .room-notification {
- display: inline-block;
-}
-
.room-list > .room-entry:hover {
background: #dbf7ff;
}
@@ -462,6 +488,23 @@ html[dir="rtl"] .tab-view li:nth-child(2).selected ~ .slide-bar {
vertical-align: middle;
}
+.room-list > .room-entry > h2:before {
+ content: "";
+ display: inline-block;
+ background-image: url("../shared/img/icons-14x14.svg#hello");
+ background-repeat: no-repeat;
+ background-size: cover;
+ width: 13px;
+ height: 13px;
+ -moz-margin-end: 1rem;
+ margin-bottom: -3px;
+}
+
+.room-list > .room-entry.room-active > h2:before {
+ background-image: url("../shared/img/icons-14x14.svg#hello-active");
+}
+
+
/* Keep ".room-list > .room-entry > h2" in sync with these. */
.room-entry-context-item {
display: inline-block;
@@ -744,7 +787,7 @@ html[dir="rtl"] .generate-url-spinner {
background-repeat: no-repeat;
background-size: cover;
-moz-margin-end: .2rem;
- margin-bottom: -2px;
+ margin-bottom: -3px;
}
.dropdown-menu-item.status-available:before,
diff --git a/browser/components/loop/content/js/panel.js b/browser/components/loop/content/js/panel.js
index 0dce84bd6bfe..13dfca0e541a 100644
--- a/browser/components/loop/content/js/panel.js
+++ b/browser/components/loop/content/js/panel.js
@@ -580,7 +580,6 @@ loop.panel = (function(_, mozL10n) {
React.createElement("div", {className: roomClasses, onClick: this.handleClickEntry,
onMouseLeave: this.handleMouseLeave},
React.createElement("h2", null,
- React.createElement("span", {className: "room-notification"}),
this.props.room.decryptedContext.roomName,
React.createElement("button", {className: copyButtonClasses,
onClick: this.handleCopyButtonClick,
@@ -652,28 +651,50 @@ loop.panel = (function(_, mozL10n) {
this.setState(this.props.store.getStoreState());
},
- _getListHeading: function() {
- var numRooms = this.state.rooms.length;
- if (numRooms === 0) {
- return mozL10n.get("rooms_list_no_current_conversations");
- }
- return mozL10n.get("rooms_list_current_conversations", {num: numRooms});
- },
-
_getUserDisplayName: function() {
return this.props.userProfile && this.props.userProfile.email ||
mozL10n.get("display_name_guest");
},
+ _renderNoRoomsView: function() {
+ return (
+ React.createElement("div", {className: "room-list"},
+ React.createElement("div", {className: "room-list-empty"},
+ React.createElement("p", {className: "panel-text-large"},
+ mozL10n.get("no_conversations_message_heading")
+ ),
+ React.createElement("p", {className: "panel-text-medium"},
+ mozL10n.get("no_conversations_start_message")
+ )
+ ),
+ this._renderNewRoomButton()
+ )
+ );
+ },
+
+ _renderNewRoomButton: function() {
+ return (
+ React.createElement(NewRoomView, {dispatcher: this.props.dispatcher,
+ mozLoop: this.props.mozLoop,
+ pendingOperation: this.state.pendingCreation ||
+ this.state.pendingInitialRetrieval,
+ userDisplayName: this._getUserDisplayName()})
+ );
+ },
+
render: function() {
if (this.state.error) {
// XXX Better end user reporting of errors.
console.error("RoomList error", this.state.error);
}
+ if (!this.state.rooms.length) {
+ return this._renderNoRoomsView();
+ }
+
return (
React.createElement("div", {className: "rooms"},
- React.createElement("h1", null, this._getListHeading()),
+ React.createElement("h1", null, mozL10n.get("rooms_list_recent_conversations")),
React.createElement("div", {className: "room-list"},
this.state.rooms.map(function(room, i) {
return (
@@ -685,11 +706,7 @@ loop.panel = (function(_, mozL10n) {
);
}, this)
),
- React.createElement(NewRoomView, {dispatcher: this.props.dispatcher,
- mozLoop: this.props.mozLoop,
- pendingOperation: this.state.pendingCreation ||
- this.state.pendingInitialRetrieval,
- userDisplayName: this._getUserDisplayName()})
+ this._renderNewRoomButton()
)
);
}
diff --git a/browser/components/loop/content/js/panel.jsx b/browser/components/loop/content/js/panel.jsx
index e2dbfed2d834..04641fbe34eb 100644
--- a/browser/components/loop/content/js/panel.jsx
+++ b/browser/components/loop/content/js/panel.jsx
@@ -580,7 +580,6 @@ loop.panel = (function(_, mozL10n) {
-
{this.props.room.decryptedContext.roomName}
+
+
+ {mozL10n.get("no_conversations_message_heading")}
+
+
+ {mozL10n.get("no_conversations_start_message")}
+
+
+ {this._renderNewRoomButton()}
+
+ );
+ },
+
+ _renderNewRoomButton: function() {
+ return (
+
+ );
+ },
+
render: function() {
if (this.state.error) {
// XXX Better end user reporting of errors.
console.error("RoomList error", this.state.error);
}
+ if (!this.state.rooms.length) {
+ return this._renderNoRoomsView();
+ }
+
return (
-
{this._getListHeading()}
+
{mozL10n.get("rooms_list_recent_conversations")}
{
this.state.rooms.map(function(room, i) {
return (
@@ -685,11 +706,7 @@ loop.panel = (function(_, mozL10n) {
);
}, this)
}
-
+ {this._renderNewRoomButton()}
);
}
diff --git a/browser/components/loop/content/shared/css/conversation.css b/browser/components/loop/content/shared/css/conversation.css
index 86ba6e5dad57..01e8921aceb8 100644
--- a/browser/components/loop/content/shared/css/conversation.css
+++ b/browser/components/loop/content/shared/css/conversation.css
@@ -1401,24 +1401,6 @@ html[dir="rtl"] .room-context-btn-close {
max-width: 400px;
}
-.standalone .room-conversation .media {
- background: #000;
-}
-
-.standalone .room-conversation .video_wrapper.remote_wrapper {
- background-color: #4e4e4e;
- width: calc(75% - 10px); /* Take the left margin into account. */
-}
-
-.standalone .room-conversation .conversation-toolbar {
- background: #000;
- border: none;
-}
-
-.standalone .room-conversation .conversation-toolbar .btn-hangup-entry {
- display: block;
-}
-
.standalone .room-conversation-wrapper .ended-conversation {
position: relative;
height: auto;
diff --git a/browser/components/loop/content/shared/img/empty_conversations.svg b/browser/components/loop/content/shared/img/empty_conversations.svg
new file mode 100644
index 000000000000..384ce98e41a8
--- /dev/null
+++ b/browser/components/loop/content/shared/img/empty_conversations.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/browser/components/loop/jar.mn b/browser/components/loop/jar.mn
index 0771fd67286c..828aeab7c721 100644
--- a/browser/components/loop/jar.mn
+++ b/browser/components/loop/jar.mn
@@ -74,6 +74,7 @@ browser.jar:
content/browser/loop/shared/img/telefonica@2x.png (content/shared/img/telefonica@2x.png)
content/browser/loop/shared/img/ellipsis-v.svg (content/shared/img/ellipsis-v.svg)
content/browser/loop/shared/img/empty_contacts.svg (content/shared/img/empty_contacts.svg)
+ content/browser/loop/shared/img/empty_conversations.svg (content/shared/img/empty_conversations.svg)
content/browser/loop/shared/img/avatars.svg (content/shared/img/avatars.svg)
# Shared scripts
diff --git a/browser/components/loop/test/desktop-local/panel_test.js b/browser/components/loop/test/desktop-local/panel_test.js
index 7fb17251374f..565f4d2246f5 100644
--- a/browser/components/loop/test/desktop-local/panel_test.js
+++ b/browser/components/loop/test/desktop-local/panel_test.js
@@ -799,6 +799,20 @@ describe("loop.panel", function() {
sinon.assert.calledOnce(fakeWindow.close);
});
+
+ it("should render the no rooms view when no rooms available", function() {
+ var view = createTestComponent();
+ var node = view.getDOMNode();
+
+ expect(node.querySelectorAll(".room-list-empty").length).to.eql(1);
+ });
+
+ it("should call mozL10n.get for room empty strings", function() {
+ var view = createTestComponent();
+
+ sinon.assert.calledWithExactly(document.mozL10n.get,
+ "no_conversations_message_heading");
+ });
});
describe("loop.panel.NewRoomView", function() {
diff --git a/browser/components/loop/test/functional/config.py b/browser/components/loop/test/functional/config.py
index fcd39cdb4000..9b2c8e8bf3ca 100644
--- a/browser/components/loop/test/functional/config.py
+++ b/browser/components/loop/test/functional/config.py
@@ -13,7 +13,6 @@ FIREFOX_PREFERENCES = {
"devtools.debugger.remote-enabled": True,
"media.volume_scale": "0",
"loop.gettingStarted.seen": True,
- "loop.seenToS": "seen",
# this dialog is fragile, and likely to introduce intermittent failures
"media.navigator.permission.disabled": True,
diff --git a/browser/components/loop/test/xpcshell/test_loopservice_busy.js b/browser/components/loop/test/xpcshell/test_loopservice_busy.js
index d7fa867ad835..15b21d2eb90a 100644
--- a/browser/components/loop/test/xpcshell/test_loopservice_busy.js
+++ b/browser/components/loop/test/xpcshell/test_loopservice_busy.js
@@ -115,9 +115,6 @@ function run_test() {
// Revert fake login state
MozLoopServiceInternal.fxAOAuthTokenData = null;
- // clear test pref
- Services.prefs.clearUserPref("loop.seenToS");
-
LoopCallsInternal.mocks.webSocket = undefined;
});
diff --git a/browser/components/loop/ui/ui-showcase.css b/browser/components/loop/ui/ui-showcase.css
index 0975953c53bd..b7b9cae2d7a6 100644
--- a/browser/components/loop/ui/ui-showcase.css
+++ b/browser/components/loop/ui/ui-showcase.css
@@ -71,6 +71,7 @@ body {
.showcase > section > .example {
margin-bottom: 6em;
+ background: #fbfbfb;
}
.showcase > section > h2 {
@@ -94,10 +95,6 @@ body {
color: #555;
}
-.showcase .checkbox-wrapper label {
- font-weight: bold;
-}
-
.showcase .checkbox.checked {
background-image: url("../content/shared/img/check.svg#check-blue");
}
diff --git a/browser/components/loop/ui/ui-showcase.js b/browser/components/loop/ui/ui-showcase.js
index b20439498265..519c95320bd0 100644
--- a/browser/components/loop/ui/ui-showcase.js
+++ b/browser/components/loop/ui/ui-showcase.js
@@ -441,6 +441,18 @@
});
// Local mocks
+ var mockMozLoopNoRooms = _.cloneDeep(navigator.mozLoop);
+ mockMozLoopNoRooms.rooms.getAll = function(version, callback) {
+ callback(null, []);
+ };
+
+ var roomStoreNoRooms = new loop.store.RoomStore(new loop.Dispatcher(), {
+ mozLoop: mockMozLoopNoRooms,
+ activeRoomStore: new loop.store.ActiveRoomStore(new loop.Dispatcher(), {
+ mozLoop: mockMozLoopNoRooms,
+ sdkDriver: mockSDK
+ })
+ });
var mockMozLoopLoggedIn = _.cloneDeep(navigator.mozLoop);
mockMozLoopLoggedIn.userProfile = {
@@ -712,6 +724,21 @@
)
),
+ React.createElement(FramedExample, {cssClass: "fx-embedded-panel",
+ dashed: true,
+ height: 410,
+ summary: "Room list tab (no rooms)",
+ width: 332},
+ React.createElement("div", {className: "panel"},
+ React.createElement(PanelView, {client: mockClient,
+ dispatcher: dispatcher,
+ mozLoop: mockMozLoopNoRooms,
+ notifications: notifications,
+ roomStore: roomStoreNoRooms,
+ selectedTab: "rooms"})
+ )
+ ),
+
React.createElement(FramedExample, {cssClass: "fx-embedded-panel",
dashed: true,
height: 410,
diff --git a/browser/components/loop/ui/ui-showcase.jsx b/browser/components/loop/ui/ui-showcase.jsx
index 35d30251ab37..ada5c7b32164 100644
--- a/browser/components/loop/ui/ui-showcase.jsx
+++ b/browser/components/loop/ui/ui-showcase.jsx
@@ -441,6 +441,18 @@
});
// Local mocks
+ var mockMozLoopNoRooms = _.cloneDeep(navigator.mozLoop);
+ mockMozLoopNoRooms.rooms.getAll = function(version, callback) {
+ callback(null, []);
+ };
+
+ var roomStoreNoRooms = new loop.store.RoomStore(new loop.Dispatcher(), {
+ mozLoop: mockMozLoopNoRooms,
+ activeRoomStore: new loop.store.ActiveRoomStore(new loop.Dispatcher(), {
+ mozLoop: mockMozLoopNoRooms,
+ sdkDriver: mockSDK
+ })
+ });
var mockMozLoopLoggedIn = _.cloneDeep(navigator.mozLoop);
mockMozLoopLoggedIn.userProfile = {
@@ -712,6 +724,21 @@
+
+
+
+
-
+
diff --git a/browser/locales/en-US/chrome/browser/loop/loop.properties b/browser/locales/en-US/chrome/browser/loop/loop.properties
index 4b1f9c23f4c6..d2a95a69311b 100644
--- a/browser/locales/en-US/chrome/browser/loop/loop.properties
+++ b/browser/locales/en-US/chrome/browser/loop/loop.properties
@@ -137,6 +137,12 @@ no_contacts_message_heading=No contacts yet
## LOCALIZATION NOTE(no_contacts_import_or_add): Subheading inviting the user
## to add people to his contact list
no_contacts_import_or_add=Import or add someone
+## LOCALIZATION NOTE(no_conversations_message_heading): Title shown when user
+## has no conversations available.
+no_conversations_message_heading=There are no conversations yet
+## LOCALIZATION NOTE(no_converastions_start_message): Subheading inviting the
+## user to start a new conversation.
+no_conversations_start_message=start a new conversation!
## LOCALIZATION NOTE(import_failed_description simple): Displayed when an import of
## contacts fails. This is displayed in the error field.
@@ -308,15 +314,11 @@ tour_label=Tour
rooms_default_room_name_template=Conversation {{conversationLabel}}
rooms_leave_button_label=Leave
rooms_list_copy_url_tooltip=Copy Link
-## LOCALIZATION NOTE (rooms_list_current_conversations):
-## Semicolon-separated list of plural forms. See:
-## http://developer.mozilla.org/en/docs/Localization_and_Plurals
-## We prefer to have no number in the string, but if you need it for your
-## language please use {{num}}.
-rooms_list_current_conversations=Current conversation;Current conversations
+## LOCALIZATION NOTE (rooms_list_recent_conversations): String is in all caps
+## for emphasis reasons, it is a heading. Proceed as appropriate for locale.
+rooms_list_recent_conversations=RECENT CONVERSATIONS
rooms_list_delete_tooltip=Delete conversation
rooms_list_deleteConfirmation_label=Are you sure?
-rooms_list_no_current_conversations=No current conversations
rooms_change_failed_label=Conversation cannot be updated
rooms_new_room_button_label=Start a conversation
rooms_only_occupant_label=You're the first one here.
diff --git a/browser/themes/windows/browser-aero.css b/browser/themes/windows/browser-aero.css
index 700a91f8714e..1ad23025f3ed 100644
--- a/browser/themes/windows/browser-aero.css
+++ b/browser/themes/windows/browser-aero.css
@@ -69,10 +69,6 @@
background-color: @customToolbarColor@;
}
- #navigator-toolbox:not(:-moz-lwtheme)::after {
- background-color: #aabccf;
- }
-
#urlbar:not(:-moz-lwtheme):not([focused]):hover,
.searchbar-textbox:not(:-moz-lwtheme):not([focused]):hover {
border-color: hsla(210,54%,20%,.35) hsla(210,54%,20%,.37) hsla(210,54%,20%,.4);
diff --git a/browser/themes/windows/browser.css b/browser/themes/windows/browser.css
index 8717fc84114d..69be1be1ebc6 100644
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -104,6 +104,22 @@
background-color: ThreeDShadow;
}
+@media (-moz-windows-default-theme) {
+ @media (-moz-os-version: windows-vista),
+ (-moz-os-version: windows-win7) {
+ #navigator-toolbox:not(:-moz-lwtheme)::after {
+ background-color: #aabccf;
+ }
+ }
+
+ @media (-moz-os-version: windows-win8),
+ (-moz-os-version: windows-win10) {
+ #navigator-toolbox:not(:-moz-lwtheme)::after {
+ background-color: #c2c2c2;
+ }
+ }
+}
+
#navigator-toolbox > toolbar {
-moz-appearance: none;
border-style: none;
@@ -1252,6 +1268,8 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
border-color: hsl(0,0%,90%);
padding: 1px;
-moz-padding-end: 3px;
+ transition-property: border-color, box-shadow;
+ transition-duration: .1s;
}
#urlbar:not(:-moz-lwtheme):hover,
@@ -1283,8 +1301,6 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
.searchbar-textbox {
font-size: 1.15em;
min-height: 28px;
- transition-property: border-color, box-shadow;
- transition-duration: .1s;
}
:root {