Bug 779923 - implement social activity flyout panel. r=jaws

This commit is contained in:
Shane Caraveo 2012-08-23 17:11:02 -07:00
parent 262eea0132
commit 4bfc87bd67
15 changed files with 225 additions and 88 deletions

View File

@ -41,6 +41,7 @@ let SocialUI = {
SocialToolbar.updateButtonHiddenState();
SocialSidebar.updateSidebar();
SocialChatBar.update();
SocialFlyout.unload();
} catch (e) {
Components.utils.reportError(e);
throw e;
@ -179,6 +180,116 @@ let SocialChatBar = {
}
}
function sizeSocialPanelToContent(iframe) {
// FIXME: bug 764787: Maybe we can use nsIDOMWindowUtils.getRootBounds() here?
// Need to handle dynamic sizing
let doc = iframe.contentDocument;
if (!doc) {
return;
}
// "notif" is an implementation detail that we should get rid of
// eventually
let body = doc.getElementById("notif") || doc.body;
if (!body || !body.firstChild) {
return;
}
let [height, width] = [body.firstChild.offsetHeight || 300, 330];
iframe.style.width = width + "px";
iframe.style.height = height + "px";
}
let SocialFlyout = {
get panel() {
return document.getElementById("social-flyout-panel");
},
dispatchPanelEvent: function(name) {
let doc = this.panel.firstChild.contentDocument;
let evt = doc.createEvent("CustomEvent");
evt.initCustomEvent(name, true, true, {});
doc.documentElement.dispatchEvent(evt);
},
_createFrame: function() {
let panel = this.panel;
if (!Social.provider || panel.firstChild)
return;
// create and initialize the panel for this window
let iframe = document.createElement("iframe");
iframe.setAttribute("type", "content");
iframe.setAttribute("flex", "1");
iframe.setAttribute("origin", Social.provider.origin);
panel.appendChild(iframe);
},
unload: function() {
let panel = this.panel;
if (!panel.firstChild)
return
panel.removeChild(panel.firstChild);
},
onShown: function(aEvent) {
let iframe = this.panel.firstChild;
iframe.docShell.isActive = true;
iframe.docShell.isAppTab = true;
if (iframe.contentDocument.readyState == "complete") {
this.dispatchPanelEvent("socialFrameShow");
} else {
// first time load, wait for load and dispatch after load
iframe.addEventListener("load", function panelBrowserOnload(e) {
iframe.removeEventListener("load", panelBrowserOnload, true);
setTimeout(function() {
SocialFlyout.dispatchPanelEvent("socialFrameShow");
}, 0);
}, true);
}
},
onHidden: function(aEvent) {
this.panel.firstChild.docShell.isActive = false;
this.dispatchPanelEvent("socialFrameHide");
},
open: function(aURL, yOffset, aCallback) {
if (!Social.provider)
return;
let panel = this.panel;
if (!panel.firstChild)
this._createFrame();
panel.hidden = false;
let iframe = panel.firstChild;
let src = iframe.getAttribute("src");
if (src != aURL) {
iframe.addEventListener("load", function documentLoaded() {
iframe.removeEventListener("load", documentLoaded, true);
sizeSocialPanelToContent(iframe);
if (aCallback) {
try {
aCallback(iframe.contentWindow);
} catch(e) {
Cu.reportError(e);
}
}
}, true);
iframe.setAttribute("src", aURL);
}
else if (aCallback) {
try {
aCallback(iframe.contentWindow);
} catch(e) {
Cu.reportError(e);
}
}
sizeSocialPanelToContent(iframe);
let anchor = document.getElementById("social-sidebar-browser");
panel.openPopup(anchor, "start_before", 0, yOffset, false, false);
}
}
let SocialShareButton = {
// Called once, after window load, when the Social.provider object is initialized
init: function SSB_init() {
@ -397,35 +508,14 @@ var SocialToolbar = {
let notifBox = document.getElementById("social-notification-box");
let notificationFrame = document.getElementById(iconImage.getAttribute("notificationFrameId"));
function sizePanelToContent() {
// FIXME: bug 764787: Maybe we can use nsIDOMWindowUtils.getRootBounds() here?
// Need to handle dynamic sizing
let doc = notificationFrame.contentDocument;
if (!doc) {
return;
}
// "notif" is an implementation detail that we should get rid of
// eventually
let body = doc.getElementById("notif") || doc.body;
if (!body || !body.firstChild) {
return;
}
// Clear dimensions on all browsers so the panel size will
// only use the selected browser.
let frameIter = notifBox.firstElementChild;
while (frameIter) {
frameIter.collapsed = (frameIter != notificationFrame);
frameIter = frameIter.nextElementSibling;
}
let [height, width] = [body.firstChild.offsetHeight || 300, 330];
notificationFrame.style.width = width + "px";
notificationFrame.style.height = height + "px";
// Clear dimensions on all browsers so the panel size will
// only use the selected browser.
let frameIter = notifBox.firstElementChild;
while (frameIter) {
frameIter.collapsed = (frameIter != notificationFrame);
frameIter = frameIter.nextElementSibling;
}
sizePanelToContent();
function dispatchPanelEvent(name) {
let evt = notificationFrame.contentDocument.createEvent("CustomEvent");
evt.initCustomEvent(name, true, true, {});
@ -445,11 +535,13 @@ var SocialToolbar = {
notificationFrame.docShell.isActive = true;
notificationFrame.docShell.isAppTab = true;
if (notificationFrame.contentDocument.readyState == "complete") {
sizeSocialPanelToContent(notificationFrame);
dispatchPanelEvent("socialFrameShow");
} else {
// first time load, wait for load and dispatch after load
notificationFrame.addEventListener("load", function panelBrowserOnload(e) {
notificationFrame.removeEventListener("load", panelBrowserOnload, true);
sizeSocialPanelToContent(notificationFrame);
setTimeout(function() {
dispatchPanelEvent("socialFrameShow");
}, 0);

View File

@ -271,6 +271,13 @@
<panel id="social-notification-panel" type="arrow" hidden="true" noautofocus="true">
<box id="social-notification-box" flex="1"></box>
</panel>
<panel id="social-flyout-panel"
onpopupshown="SocialFlyout.onShown()"
onpopuphidden="SocialFlyout.onHidden()"
type="arrow"
hidden="true"
noautofocus="true"
position="topcenter topright"/>
<menupopup id="inspector-node-popup">
<menuitem id="inspectorHTMLCopyInner"

View File

@ -262,12 +262,14 @@ _BROWSER_FILES = \
browser_social_toolbar.js \
browser_social_shareButton.js \
browser_social_sidebar.js \
browser_social_flyout.js \
browser_social_mozSocial_API.js \
browser_social_isVisible.js \
browser_social_chatwindow.js \
social_panel.html \
social_sidebar.html \
social_chat.html \
social_flyout.html \
social_window.html \
social_worker.js \
$(NULL)

View File

@ -0,0 +1,48 @@
/* 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/. */
function test() {
waitForExplicitFinish();
let manifest = { // normal provider
name: "provider 1",
origin: "https://example.com",
sidebarURL: "https://example.com/browser/browser/base/content/test/social_sidebar.html",
workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
iconURL: "chrome://branding/content/icon48.png"
};
runSocialTestWithProvider(manifest, function (finishcb) {
runSocialTests(tests, undefined, undefined, finishcb);
});
}
var tests = {
testOpenCloseFlyout: function(next) {
let panel = document.getElementById("social-flyout-panel");
let port = Social.provider.port;
ok(port, "provider has a port");
port.onmessage = function (e) {
let topic = e.data.topic;
switch (topic) {
case "got-sidebar-message":
port.postMessage({topic: "test-flyout-open"});
break;
case "got-flyout-visibility":
if (e.data.result == "hidden") {
ok(true, "flyout visibility is 'hidden'");
next();
} else if (e.data.result == "shown") {
ok(true, "flyout visibility is 'shown");
panel.hidePopup();
}
break;
case "got-flyout-message":
ok(e.data.result == "ok", "got flyout message");
break;
}
}
port.postMessage({topic: "test-init"});
}
}

View File

@ -0,0 +1,22 @@
<html>
<head>
<meta charset="utf-8">
<script>
function pingWorker() {
var port = navigator.mozSocial.getWorker().port;
port.postMessage({topic: "flyout-message", result: "ok"});
}
window.addEventListener("socialFrameShow", function(e) {
var port = navigator.mozSocial.getWorker().port;
port.postMessage({topic: "flyout-visibility", result: "shown"});
}, false);
window.addEventListener("socialFrameHide", function(e) {
var port = navigator.mozSocial.getWorker().port;
port.postMessage({topic: "flyout-visibility", result: "hidden"});
}, false);
</script>
</head>
<body onload="pingWorker();">
<p>This is a test social flyout panel.</p>
</body>
</html>

View File

@ -8,6 +8,9 @@
port.onmessage = function(e) {
var topic = e.data.topic;
switch (topic) {
case "test-flyout-open":
navigator.mozSocial.openPanel("social_flyout.html");
break;
case "test-chatbox-open":
navigator.mozSocial.openChatWindow("social_chat.html", function(chatwin) {
port.postMessage({topic: "chatbox-opened", result: chatwin ? "ok" : "failed"});

View File

@ -54,6 +54,15 @@ onconnect = function(e) {
case "chatbox-visibility":
testPort.postMessage({topic:"got-chatbox-visibility", result: event.data.result});
break;
case "test-flyout-open":
sidebarPort.postMessage({topic:"test-flyout-open"});
break;
case "flyout-message":
testPort.postMessage({topic:"got-flyout-message", result: event.data.result});
break;
case "flyout-visibility":
testPort.postMessage({topic:"got-flyout-visibility", result: event.data.result});
break;
case "social.initialize":
// This is the workerAPI port, respond and set up a notification icon.
port.postMessage({topic: "social.initialize-response"});

View File

@ -2741,14 +2741,6 @@ stack[anonid=browserStack][responsivemode] {
text-decoration: underline;
}
#social-notification-panel {
min-height: 100px;
min-width: 100px;
max-height: 600px;
max-width: 400px;
}
.chat-status-icon {
max-height: 16px;
max-width: 16px;

View File

@ -3430,48 +3430,6 @@ stack[anonid=browserStack][responsivemode] {
/* === end of social toolbar provider menu === */
/* === start of social toolbar panels === */
#social-notification-panel {
min-height: 100px;
min-width: 240px;
max-height: 600px;
max-width: 400px;
}
#social-notification-panel .panel-arrowcontent {
margin: -4px 0 0 0;
padding: 0;
border-radius: 0px;
background: white;
}
#social-notification-panel .panel-arrow[side="top"] {
list-style-image: url("chrome://browser/skin/social/panelarrow-up.png");
margin-top: -4px;
margin-bottom: 3px;
height: 21px;
}
#social-notification-panel .panel-arrow[side="bottom"] {
list-style-image: url("chrome://browser/skin/social/panelarrow-down.png");
margin-top: -5px;
}
#social-notification-panel .panel-arrow[side="left"] {
list-style-image: url("chrome://browser/skin/social/panelarrow-horiz.png");
margin-right: -1px;
-moz-transform: scaleX(-1);
}
#social-notification-panel .panel-arrow[side="right"] {
list-style-image: url("chrome://browser/skin/social/panelarrow-horiz.png");
margin-left: -1px;
}
/* === end of social toolbar panels === */
.chat-status-icon {
max-height: 16px;
max-width: 16px;

View File

@ -110,9 +110,6 @@ browser.jar:
skin/classic/browser/preferences/applications.css (preferences/applications.css)
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
skin/classic/browser/social/social.png (social/social.png)
skin/classic/browser/social/panelarrow-down.png (social/panelarrow-down.png)
skin/classic/browser/social/panelarrow-horiz.png (social/panelarrow-horiz.png)
skin/classic/browser/social/panelarrow-up.png (social/panelarrow-up.png)
skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon.png (tabbrowser/alltabs-box-bkgnd-icon.png)
skin/classic/browser/tabbrowser/newtab.png (tabbrowser/newtab.png)
skin/classic/browser/tabbrowser/connecting.png (tabbrowser/connecting.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -3444,14 +3444,6 @@ stack[anonid=browserStack][responsivemode] {
text-decoration: underline;
}
#social-notification-panel {
min-height: 100px;
min-width: 100px;
max-height: 600px;
max-width: 400px;
}
.chat-status-icon {
max-height: 16px;
max-width: 16px;

View File

@ -119,6 +119,21 @@ function attachToWindow(provider, targetWindow) {
openChatWindow(getChromeWindow(targetWindow), provider, url, callback);
}
},
openPanel: {
enumerable: true,
configurable: true,
writable: true,
value: function(toURL, offset, callback) {
let chromeWindow = getChromeWindow(targetWindow);
if (!chromeWindow.SocialFlyout)
return;
let url = targetWindow.document.documentURIObject.resolve(toURL);
let fullURL = ensureProviderOrigin(provider, url);
if (!fullURL)
return;
chromeWindow.SocialFlyout.open(fullURL, offset, callback);
}
},
getAttention: {
enumerable: true,
configurable: true,