From bfe48acf8ffe062ec78f37aa529b1bbf44f64a3e Mon Sep 17 00:00:00 2001 From: Nicolas Perriault Date: Mon, 2 Jun 2014 20:30:02 +0100 Subject: [PATCH] Bug 994152 Loop needs a "do not disturb" control. r=mhammond,r=Standard8 --- browser/app/profile/firefox.js | 1 + browser/components/loop/MozLoopAPI.jsm | 14 ++++ browser/components/loop/MozLoopService.jsm | 40 ++++++++++++ browser/components/loop/content/js/panel.js | 61 ++++++++++++++++-- .../loop/content/shared/css/panel.css | 13 ++-- .../loop/test/desktop-local/panel_test.js | 64 ++++++++++++++++++- .../test/xpcshell/test_loopservice_dnd.js | 34 ++++++++++ .../loop/test/xpcshell/xpcshell.ini | 1 + .../en-US/chrome/browser/loop/loop.properties | 1 + 9 files changed, 213 insertions(+), 16 deletions(-) create mode 100644 browser/components/loop/test/xpcshell/test_loopservice_dnd.js diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 49da008e7479..4fb543bcfda8 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1505,6 +1505,7 @@ pref("image.mem.max_decoded_image_kb", 256000); // XXX This is a temporary development server. The production one will be // coming soon. pref("loop.server", "http://loop.dev.mozaws.net"); +pref("loop.do_not_disturb", false); #endif // serverURL to be assigned by services team diff --git a/browser/components/loop/MozLoopAPI.jsm b/browser/components/loop/MozLoopAPI.jsm index ad317ff6191c..9fe14bd0b163 100644 --- a/browser/components/loop/MozLoopAPI.jsm +++ b/browser/components/loop/MozLoopAPI.jsm @@ -25,6 +25,20 @@ this.EXPORTED_SYMBOLS = ["injectLoopAPI"]; */ function injectLoopAPI(targetWindow) { let api = { + /** + * Sets and gets the "do not disturb" mode activation flag. + */ + doNotDisturb: { + enumerable: true, + configurable: true, + get: function() { + return MozLoopService.doNotDisturb; + }, + set: function(aFlag) { + MozLoopService.doNotDisturb = aFlag; + } + }, + /** * Returns the url for the Loop server from preferences. * diff --git a/browser/components/loop/MozLoopService.jsm b/browser/components/loop/MozLoopService.jsm index 9783f8dda2ac..d66fe1ee200c 100644 --- a/browser/components/loop/MozLoopService.jsm +++ b/browser/components/loop/MozLoopService.jsm @@ -200,6 +200,24 @@ let MozLoopServiceInternal = { } }, + /** + * Retrieves MozLoopService "do not disturb" pref value. + * + * @return {Boolean} aFlag + */ + get doNotDisturb() { + return Services.prefs.getBoolPref("loop.do_not_disturb"); + }, + + /** + * Sets MozLoopService "do not disturb" pref value. + * + * @param {Boolean} aFlag + */ + set doNotDisturb(aFlag) { + Services.prefs.setBoolPref("loop.do_not_disturb", Boolean(aFlag)); + }, + /** * Starts the initialization of the service, which goes and registers * with the push server and the loop server. @@ -327,6 +345,10 @@ let MozLoopServiceInternal = { * @param {String} version The version information from the server. */ onHandleNotification: function(version) { + if (this.doNotDisturb) { + return; + } + this.openChatWindow(null, "LooP", "about:loopconversation#start/" + version); }, @@ -503,6 +525,24 @@ this.MozLoopService = { return JSON.stringify(stringData[key]); }, + /** + * Retrieves MozLoopService "do not disturb" value. + * + * @return {Boolean} + */ + get doNotDisturb() { + return MozLoopServiceInternal.doNotDisturb; + }, + + /** + * Sets MozLoopService "do not disturb" value. + * + * @param {Boolean} aFlag + */ + set doNotDisturb(aFlag) { + MozLoopServiceInternal.doNotDisturb = aFlag; + }, + /** * Returns the current locale * diff --git a/browser/components/loop/content/js/panel.js b/browser/components/loop/content/js/panel.js index 6ddc69a454ee..60456bd8dc52 100644 --- a/browser/components/loop/content/js/panel.js +++ b/browser/components/loop/content/js/panel.js @@ -18,6 +18,37 @@ loop.panel = (function(_, mozL10n) { */ var router; + /** + * Do not disturb panel subview. + */ + var DoNotDisturbView = sharedViews.BaseView.extend({ + template: _.template([ + '', + ].join('')), + + events: { + "click input[type=checkbox]": "toggle" + }, + + /** + * Toggles mozLoop activation status. + */ + toggle: function() { + navigator.mozLoop.doNotDisturb = !navigator.mozLoop.doNotDisturb; + this.render(); + }, + + render: function() { + this.$el.html(this.template({ + checked: navigator.mozLoop.doNotDisturb ? "checked" : "" + })); + return this; + } + }); + /** * Panel view. */ @@ -27,23 +58,30 @@ loop.panel = (function(_, mozL10n) { '

', '', '
', - '

', - ' ', - ' ', - '

', + ' ', '

', ' ', ' ', '

', + '

', '
', ].join("")), className: "share generate-url", + /** + * Do not disturb view. + * @type {DoNotDisturbView|undefined} + */ + dndView: undefined, + events: { "keyup input[name=caller]": "changeButtonState", - "click .get-url": "getCallUrl", + "submit form.invite": "getCallUrl", "click a.go-back": "goBack" }, @@ -54,7 +92,7 @@ loop.panel = (function(_, mozL10n) { } this.notifier = options.notifier; this.client = new loop.shared.Client({ - baseServerUrl: window.navigator.mozLoop.serverUrl + baseServerUrl: navigator.mozLoop.serverUrl }); }, @@ -69,6 +107,7 @@ loop.panel = (function(_, mozL10n) { this.clearPending(); if (err) { this.notifier.errorL10n("unable_retrieve_url"); + this.render(); return; } this.onCallUrlReceived(callUrlData); @@ -113,6 +152,13 @@ loop.panel = (function(_, mozL10n) { } else { this.$(".get-url").addClass("disabled").attr("disabled", "disabled"); } + }, + + render: function() { + this.$el.html(this.template()); + // Do not Disturb sub view + this.dndView = new DoNotDisturbView({el: this.$(".dnd")}).render(); + return this; } }); @@ -179,7 +225,7 @@ loop.panel = (function(_, mozL10n) { function init() { // Do the initial L10n setup, we do this before anything // else to ensure the L10n environment is setup correctly. - mozL10n.initialize(window.navigator.mozLoop); + mozL10n.initialize(navigator.mozLoop); router = new PanelRouter({ document: document, @@ -196,6 +242,7 @@ loop.panel = (function(_, mozL10n) { return { init: init, PanelView: PanelView, + DoNotDisturbView: DoNotDisturbView, PanelRouter: PanelRouter }; })(_, document.mozL10n); diff --git a/browser/components/loop/content/shared/css/panel.css b/browser/components/loop/content/shared/css/panel.css index 7960692c81ce..c99d09840b35 100644 --- a/browser/components/loop/content/shared/css/panel.css +++ b/browser/components/loop/content/shared/css/panel.css @@ -49,12 +49,17 @@ margin: 0 0 1em 0; } -.share .action input { +.share .action p.dnd { + margin-top: 1em; +} + +.share .action input[type="text"], +.share .action input[type="url"] { border: 1px solid #ccc; /* Overriding background style for a text input (see below) resets its borders to a weird beveled style; defining a default 1px border solves the issue. */ font-size: .9em; - width: 60%; + width: 65%; padding: .5em; } @@ -73,10 +78,6 @@ /* Specific cases */ -.share.generate-url .action { - text-align: center; -} - .panel #messages .alert { margin-bottom: 0; } diff --git a/browser/components/loop/test/desktop-local/panel_test.js b/browser/components/loop/test/desktop-local/panel_test.js index ccba5a729cfd..f167b1d56ab3 100644 --- a/browser/components/loop/test/desktop-local/panel_test.js +++ b/browser/components/loop/test/desktop-local/panel_test.js @@ -35,7 +35,8 @@ describe("loop.panel", function() { errorL10n: sandbox.spy() }; - window.navigator.mozLoop = { + navigator.mozLoop = { + doNotDisturb: true, get serverUrl() { return "http://example.com"; }, @@ -46,11 +47,11 @@ describe("loop.panel", function() { return "en-US"; } }; - document.mozL10n.initialize(window.navigator.mozLoop); + document.mozL10n.initialize(navigator.mozLoop); }); afterEach(function() { - delete window.navigator.mozLoop; + delete navigator.mozLoop; $("#fixtures").empty(); sandbox.restore(); }); @@ -157,6 +158,51 @@ describe("loop.panel", function() { }); }); + describe("loop.panel.DoNotDisturbView", function() { + var view; + + beforeEach(function() { + $("#fixtures").append('
'); + view = new loop.panel.DoNotDisturbView({el: $("#dnd-view")}); + }); + + describe("#toggle", function() { + beforeEach(function() { + navigator.mozLoop.doNotDisturb = false; + }); + + it("should toggle the value of mozLoop.doNotDisturb", function() { + view.toggle(); + + expect(navigator.mozLoop.doNotDisturb).eql(true); + }); + + it("should update the DnD checkbox value", function() { + view.toggle(); + + expect(view.$("input").is(":checked")).eql(true); + }); + }); + + describe("render", function() { + it("should check the dnd checkbox when dnd is enabled", function() { + navigator.mozLoop.doNotDisturb = false; + + view.render(); + + expect(view.$("input").is(":checked")).eql(false); + }); + + it("should uncheck the dnd checkbox when dnd is disabled", function() { + navigator.mozLoop.doNotDisturb = true; + + view.render(); + + expect(view.$("input").is(":checked")).eql(true); + }); + }); + }); + describe("loop.panel.PanelView", function() { beforeEach(function() { $("#fixtures").append('
'); @@ -265,5 +311,17 @@ describe("loop.panel", function() { it("should do set the enabled state if there is text"); }); }); + + describe("#render", function() { + it("should render a DoNotDisturbView", function() { + var renderDnD = sandbox.stub(loop.panel.DoNotDisturbView.prototype, + "render"); + var view = new loop.panel.PanelView({notifier: notifier}); + + view.render(); + + sinon.assert.calledOnce(renderDnD); + }); + }); }); }); diff --git a/browser/components/loop/test/xpcshell/test_loopservice_dnd.js b/browser/components/loop/test/xpcshell/test_loopservice_dnd.js new file mode 100644 index 000000000000..bd2f426bd05c --- /dev/null +++ b/browser/components/loop/test/xpcshell/test_loopservice_dnd.js @@ -0,0 +1,34 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +XPCOMUtils.defineLazyModuleGetter(this, "MozLoopService", + "resource:///modules/loop/MozLoopService.jsm"); + +do_register_cleanup(function() { + Services.prefs.clearUserPref("loop.do_not_disturb"); +}); + +function test_get_do_not_disturb() { + Services.prefs.setBoolPref("loop.do_not_disturb", false); + + do_check_false(MozLoopService.doNotDisturb); + + Services.prefs.setBoolPref("loop.do_not_disturb", true); + + do_check_true(MozLoopService.doNotDisturb); +} + +function test_set_do_not_disturb() { + Services.prefs.setBoolPref("loop.do_not_disturb", false); + + MozLoopService.doNotDisturb = true; + + do_check_true(Services.prefs.getBoolPref("loop.do_not_disturb")); +} + +function run_test() +{ + test_get_do_not_disturb(); + test_set_do_not_disturb(); +} diff --git a/browser/components/loop/test/xpcshell/xpcshell.ini b/browser/components/loop/test/xpcshell/xpcshell.ini index d784e770ad88..96259ea0170c 100644 --- a/browser/components/loop/test/xpcshell/xpcshell.ini +++ b/browser/components/loop/test/xpcshell/xpcshell.ini @@ -3,6 +3,7 @@ head = head.js tail = firefox-appdir = browser +[test_loopservice_dnd.js] [test_loopservice_expiry.js] [test_loopservice_initialize.js] [test_loopservice_locales.js] diff --git a/browser/locales/en-US/chrome/browser/loop/loop.properties b/browser/locales/en-US/chrome/browser/loop/loop.properties index 4aaf7fbe2858..492f38d4bb0f 100644 --- a/browser/locales/en-US/chrome/browser/loop/loop.properties +++ b/browser/locales/en-US/chrome/browser/loop/loop.properties @@ -10,3 +10,4 @@ peer_ended_conversation=Your peer ended the conversation. stop=Stop call_has_ended=Your call has ended. close_window=Close this window +do_not_disturb=Do not disturb