Bug 582615 - Sharing front-end [r=mfinkle]
--- a/mobile/chrome/content/browser-ui.js
+++ b/mobile/chrome/content/browser-ui.js
@@ -1172,16 +1172,26 @@ var PageActions = {
let strings = Elements.browserBundle;
let node = this.appendItem("saveas", strings.getString("pageactions.saveas.pdf"), "");
node.onclick = function(event) {
PageActions._savePageAsPDF();
}
},
+ updateShare: function updateShare() {
+ this.removeItems("share");
+ let label = Elements.browserBundle.getString("pageactions.share.page");
+ let node = this.appendItem("share", label, "");
+ node.onclick = function(event) {
+ let browser = Browser.selectedBrowser;
+ SharingUI.show(browser.currentURI.spec, browser.contentTitle)
+ }
+ },
+
appendItem: function appendItem(aType, aTitle, aDesc) {
let container = document.getElementById("pageactions-container");
let item = document.createElement("pageaction");
item.setAttribute("title", aTitle);
item.setAttribute("description", aDesc);
item.setAttribute("type", aType);
container.appendChild(item);
@@ -2106,36 +2116,113 @@ var ContextHelper = {
},
handleEvent: function handleEvent(aEvent) {
this.sizeToContent();
}
};
var ContextCommands = {
- openInNewTab: function cc_openInNewTab(aEvent) {
+ openInNewTab: function cc_openInNewTab() {
Browser.addTab(ContextHelper.popupState.linkURL, false, Browser.selectedTab);
},
- saveImage: function cc_saveImage(aEvent) {
+ saveImage: function cc_saveImage() {
let browser = ContextHelper.popupState.target;
saveImageURL(ContextHelper.popupState.mediaURL, null, "SaveImageTitle", false, false, browser.documentURI);
},
- editBookmark: function cc_editBookmark(aEvent) {
+ shareLink: function cc_shareLink() {
+ let state = ContextHelper.popupState;
+ SharingUI.show(state.linkURL, state.linkTitle);
+ },
+
+ shareMedia: function cc_shareMedia() {
+ let state = ContextHelper.popupState;
+ SharingUI.show(state.mediaURL, null);
+ },
+
+ editBookmark: function cc_editBookmark() {
let target = ContextHelper.popupState.target;
target.startEditing();
},
- removeBookmark: function cc_removeBookmark(aEvent) {
+ removeBookmark: function cc_removeBookmark() {
let target = ContextHelper.popupState.target;
target.remove();
}
}
+
+var SharingUI = {
+ _dialog: null,
+
+ show: function show(aURL, aTitle) {
+ this._dialog = importDialog(window, "chrome://browser/content/share.xul", null);
+ document.getElementById("share-title").value = aTitle || aURL;
+
+ BrowserUI.pushPopup(this, this._dialog);
+
+ let bbox = document.getElementById("share-buttons-box");
+ this._handlers.forEach(function(handler) {
+ let button = document.createElement("button");
+ button.setAttribute("label", handler.name);
+ button.addEventListener("command", function() {
+ handler.callback(aURL, aTitle);
+ SharingUI.hide();
+ }, false);
+ bbox.appendChild(button);
+ });
+ this._dialog.waitForClose();
+ BrowserUI.popPopup();
+ },
+
+ hide: function hide() {
+ this._dialog.close();
+ this._dialog = null;
+ },
+
+ _handlers: [
+ {
+ name: "Email",
+ callback: function callback(aURL, aTitle) {
+ let url = "mailto:?subject=" + encodeURIComponent(aTitle || "") +
+ "&body=" + encodeURIComponent(aURL);
+ let uri = Services.io.newURI(url, null, null);
+ let extProtocolSvc = Cc["@mozilla.org/uriloader/external-protocol-service;1"]
+ .getService(Ci.nsIExternalProtocolService);
+ extProtocolSvc.loadUrl(uri);
+ }
+ },
+ {
+ name: "Twitter",
+ callback: function callback(aURL, aTitle) {
+ let url = "http://twitter.com/home?status=" + encodeURIComponent((aTitle ? aTitle+": " : "")+aURL);
+ Browser.addTab(url, true, Browser.selectedTab);
+ }
+ },
+ {
+ name: "Google Reader",
+ callback: function callback(aURL, aTitle) {
+ let url = "http://www.google.com/reader/link?url=" + encodeURIComponent(aURL) +
+ "&title=" + encodeURIComponent(aTitle);
+ Browser.addTab(url, true, Browser.selectedTab);
+ }
+ },
+ {
+ name: "Facebook",
+ callback: function callback(aURL, aTitle) {
+ let url = "http://www.facebook.com/share.php?u=" + encodeURIComponent(aURL);
+ Browser.addTab(url, true, Browser.selectedTab);
+ }
+ }
+ ]
+};
+
+
function removeBookmarksForURI(aURI) {
//XXX blargle xpconnect! might not matter, but a method on
// nsINavBookmarksService that takes an array of items to
// delete would be faster. better yet, a method that takes a URI!
let itemIds = PlacesUtils.getBookmarksForURI(aURI);
itemIds.forEach(PlacesUtils.bookmarks.removeItem);
BrowserUI.updateStar();
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -1828,26 +1828,22 @@ IdentityHandler.prototype = {
}
// Push the appropriate strings out to the UI
this._identityPopupContentHost.textContent = host;
this._identityPopupContentOwner.textContent = owner;
this._identityPopupContentSupp.textContent = supplemental;
this._identityPopupContentVerif.textContent = verifier;
- // Update the find in page in-site menu
+ // Update the site menu
FindHelperUI.updateFindInPage();
-
- // Update the search engines results
BrowserSearch.updatePageSearchEngines();
-
- // Update the per site permissions results
PageActions.updatePagePermissions();
-
PageActions.updatePageSaveAs();
+ PageActions.updateShare();
},
show: function ih_show() {
// dismiss any dialog which hide the identity popup
while (BrowserUI.activeDialog)
BrowserUI.activeDialog.close();
this._identityPopup.hidden = false;
--- a/mobile/chrome/content/browser.xul
+++ b/mobile/chrome/content/browser.xul
@@ -510,26 +510,32 @@
</vbox>
<hbox id="context-container" class="window-width window-height context-block" top="0" left="0" hidden="true">
<vbox id="context-popup" class="dialog-dark">
<hbox id="context-header">
<label id="context-hint" crop="center" flex="1"/>
</hbox>
<richlistbox id="context-commands" onclick="ContextHelper.hide();">
- <richlistitem id="context-openinnewtab" type="link-saveable" onclick="ContextCommands.openInNewTab(event);">
+ <richlistitem id="context-openinnewtab" type="link-saveable" onclick="ContextCommands.openInNewTab();">
<label value="&contextOpenInNewTab.label;"/>
</richlistitem>
- <richlistitem id="context-saveimage" type="image-loaded" onclick="ContextCommands.saveImage(event);">
+ <richlistitem id="context-saveimage" type="image-loaded" onclick="ContextCommands.saveImage();">
<label value="&contextSaveImage.label;"/>
</richlistitem>
- <richlistitem id="context-editbookmark" type="edit-bookmark" onclick="ContextCommands.editBookmark(event);">
+ <richlistitem id="context-share-link" type="link" onclick="ContextCommands.shareLink();">
+ <label value="&contextShareLink.label;"/>
+ </richlistitem>
+ <richlistitem id="context-share-image" type="image" onclick="ContextCommands.shareMedia();">
+ <label value="&contextShareImage.label;"/>
+ </richlistitem>
+ <richlistitem id="context-editbookmark" type="edit-bookmark" onclick="ContextCommands.editBookmark();">
<label value="&contextEditBookmark.label;"/>
</richlistitem>
- <richlistitem id="context-removebookmark" type="edit-bookmark" onclick="ContextCommands.removeBookmark(event);">
+ <richlistitem id="context-removebookmark" type="edit-bookmark" onclick="ContextCommands.removeBookmark();">
<label value="&contextRemoveBookmark.label;"/>
</richlistitem>
</richlistbox>
</vbox>
</hbox>
<!-- alerts for content -->
<hbox id="alerts-container" hidden="true" align="start" class="dialog-dark" top="0" left="0"
--- a/mobile/chrome/content/content.js
+++ b/mobile/chrome/content/content.js
@@ -751,16 +751,17 @@ var ContextHandler = {
handleEvent: function ch_handleEvent(aEvent) {
if (aEvent.getPreventDefault())
return;
let state = {
types: [],
label: "",
linkURL: "",
+ linkTitle: "",
linkProtocol: null,
mediaURL: ""
};
let popupNode = aEvent.originalTarget;
// Do checks for nodes that never have children.
if (popupNode.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) {
@@ -779,16 +780,17 @@ var ContextHandler = {
if ((elem instanceof Ci.nsIDOMHTMLAnchorElement && elem.href) ||
(elem instanceof Ci.nsIDOMHTMLAreaElement && elem.href) ||
elem instanceof Ci.nsIDOMHTMLLinkElement ||
elem.getAttributeNS(kXLinkNamespace, "type") == "simple") {
// Target is a link or a descendant of a link.
state.types.push("link");
state.label = state.linkURL = this._getLinkURL(elem);
+ state.linkTitle = popupNode.textContent || popupNode.title;
state.linkProtocol = this._getProtocol(this._getURI(state.linkURL));
break;
}
}
elem = elem.parentNode;
}
--- a/mobile/chrome/content/prompt/alert.xul
+++ b/mobile/chrome/content/prompt/alert.xul
@@ -14,17 +14,17 @@
</keyset>
<commandset>
<command id="cmd_ok" oncommand="document.getElementById('prompt-alert-dialog').close()"/>
<command id="cmd_cancel" oncommand="document.getElementById('prompt-alert-dialog').close()"/>
</commandset>
<vbox class="prompt-header" flex="1">
- <label id="prompt-alert-title" class="prompt-title" crop="center"/>
+ <label id="prompt-alert-title" class="prompt-title" crop="center" flex="1"/>
<scrollbox orient="vertical" class="prompt-message" flex="1">
<description id="prompt-alert-message"/>
</scrollbox>
<button id="prompt-alert-checkbox" type="checkbox" class="button-checkbox" collapsed="true" pack="start" flex="1">
<image class="button-image-icon"/>
<description id="prompt-alert-checkbox-label" class="prompt-checkbox-label" flex="1"/>
--- a/mobile/chrome/content/prompt/confirm.xul
+++ b/mobile/chrome/content/prompt/confirm.xul
@@ -14,17 +14,17 @@
</keyset>
<commandset>
<command id="cmd_ok" oncommand="document.getElementById('prompt-confirm-dialog').PromptHelper.closeConfirm(true)"/>
<command id="cmd_cancel" oncommand="document.getElementById('prompt-confirm-dialog').PromptHelper.closeConfirm(false)"/>
</commandset>
<vbox class="prompt-header" flex="1">
- <label id="prompt-confirm-title" class="prompt-title" crop="center"/>
+ <label id="prompt-confirm-title" class="prompt-title" crop="center" flex="1"/>
<scrollbox orient="vertical" class="prompt-message" flex="1">
<description id="prompt-confirm-message"/>
</scrollbox>
<button id="prompt-confirm-checkbox" type="checkbox" class="button-checkbox" collapsed="true" pack="start" flex="1">
<image class="button-image-icon"/>
<description id="prompt-confirm-checkbox-label" class="prompt-checkbox-label" flex="1"/>
--- a/mobile/chrome/content/prompt/prompt.xul
+++ b/mobile/chrome/content/prompt/prompt.xul
@@ -14,17 +14,17 @@
</keyset>
<commandset>
<command id="cmd_ok" oncommand="document.getElementById('prompt-prompt-dialog').PromptHelper.closePrompt(true)"/>
<command id="cmd_cancel" oncommand="document.getElementById('prompt-prompt-dialog').PromptHelper.closePrompt(false)"/>
</commandset>
<vbox class="prompt-header" flex="1">
- <label id="prompt-prompt-title" class="prompt-title" crop="center"/>
+ <label id="prompt-prompt-title" class="prompt-title" crop="center" flex="1"/>
<scrollbox orient="vertical" class="prompt-message" flex="1">
<description id="prompt-prompt-message"/>
</scrollbox>
<textbox id="prompt-prompt-textbox"/>
<button id="prompt-prompt-checkbox" type="checkbox" class="button-checkbox" collapsed="true" pack="start" flex="1">
--- a/mobile/chrome/content/prompt/promptPassword.xul
+++ b/mobile/chrome/content/prompt/promptPassword.xul
@@ -19,17 +19,17 @@
</keyset>
<commandset>
<command id="cmd_ok" oncommand="document.getElementById('prompt-password-dialog').PromptHelper.closePassword(true)"/>
<command id="cmd_cancel" oncommand="document.getElementById('prompt-password-dialog').PromptHelper.closePassword(false)"/>
</commandset>
<vbox class="prompt-header" flex="1">
- <label id="prompt-password-title" class="prompt-title" crop="center"/>
+ <label id="prompt-password-title" class="prompt-title" crop="center" flex="1"/>
<scrollbox orient="vertical" class="prompt-message" flex="1">
<description id="prompt-password-message"/>
</scrollbox>
<grid>
<columns>
<column flex="1"/>
--- a/mobile/chrome/content/prompt/select.xul
+++ b/mobile/chrome/content/prompt/select.xul
@@ -14,17 +14,17 @@
</keyset>
<commandset>
<command id="cmd_ok" oncommand="document.getElementById('prompt-select-dialog').PromptHelper.closeSelect(true)"/>
<command id="cmd_cancel" oncommand="document.getElementById('prompt-select-dialog').PromptHelper.closeSelect(false)"/>
</commandset>
<vbox class="prompt-header" flex="1">
- <label id="prompt-select-title" class="prompt-title" crop="center"/>
+ <label id="prompt-select-title" class="prompt-title" crop="center" flex="1"/>
<scrollbox orient="vertical" class="prompt-message" flex="1">
<description id="prompt-select-message"/>
</scrollbox>
<menulist id="prompt-select-list" class="button-dark"/>
</vbox>
new file mode 100644
--- /dev/null
+++ b/mobile/chrome/content/share.xul
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+
+<!DOCTYPE prompt SYSTEM "chrome://browser/locale/prompt.dtd">
+
+<dialog id="share-dialog"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <keyset>
+ <key keycode="VK_ESCAPE" command="cmd_cancel"/>
+ </keyset>
+
+ <commandset>
+ <command id="cmd_cancel" oncommand="SharingUI.hide();"/>
+ </commandset>
+
+ <hbox class="prompt-header">
+ <label id="share-title" class="prompt-title" crop="center" flex="1"/>
+ </hbox>
+
+ <hbox id="share-buttons-box" class="prompt-buttons"/>
+</dialog>
--- a/mobile/chrome/jar.mn
+++ b/mobile/chrome/jar.mn
@@ -52,12 +52,13 @@ chrome.jar:
content/downloads.js (content/downloads.js)
content/console.js (content/console.js)
content/prompt/alert.xul (content/prompt/alert.xul)
content/prompt/confirm.xul (content/prompt/confirm.xul)
content/prompt/prompt.xul (content/prompt/prompt.xul)
content/prompt/promptPassword.xul (content/prompt/promptPassword.xul)
content/prompt/select.xul (content/prompt/select.xul)
content/prompt/prompt.js (content/prompt/prompt.js)
+ content/share.xul (content/share.xul)
content/AnimatedZoom.js (content/AnimatedZoom.js)
content/sync.js (content/sync.js)
% override chrome://global/content/config.xul chrome://browser/content/config.xul
--- a/mobile/locales/en-US/chrome/browser.dtd
+++ b/mobile/locales/en-US/chrome/browser.dtd
@@ -81,10 +81,12 @@
<!ENTITY consoleClear.label "Clear">
<!ENTITY consoleEvaluate.label "…">
<!ENTITY consoleErrFile.label "Source File:">
<!ENTITY consoleErrLine.label "Line:">
<!ENTITY consoleErrColumn.label "Column:">
<!ENTITY contextOpenInNewTab.label "Open Link in New Tab">
<!ENTITY contextSaveImage.label "Save Image">
+<!ENTITY contextShareLink.label "Share Link">
+<!ENTITY contextShareImage.label "Share Image">
<!ENTITY contextEditBookmark.label "Edit">
<!ENTITY contextRemoveBookmark.label "Remove">
--- a/mobile/locales/en-US/chrome/browser.properties
+++ b/mobile/locales/en-US/chrome/browser.properties
@@ -138,16 +138,17 @@ tabs.closeWarningPromptMe=Warn me when I
# LOCALIZATION NOTE: homepage.custom2 is the text displayed on the selector button if
# the user selects a webpage to be the startpage. We can't display the entire URL
# or webpage title on the menulist
homepage.custom2=Custom Page
# Page Actions
pageactions.saveas.pdf=Save As PDF
pageactions.search.addNew=Add Search Engine
+pageactions.share.page=Share Page
pageactions.password.forget=Forget Password
pageactions.reset=Clear Site Preferences
pageactions.geo=Location
pageactions.popup=Popups
pageactions.offline-app=Offline Storage
pageactions.password=Password
pageactions.findInPage=Find In Page
--- a/mobile/themes/core/platform.css
+++ b/mobile/themes/core/platform.css
@@ -625,12 +625,11 @@ progressmeter {
border: 3px solid #aaa;
-moz-border-top-colors: -moz-initial;
-moz-border-right-colors: -moz-initial;
-moz-border-bottom-colors: -moz-initial;
-moz-border-left-colors: -moz-initial;
-moz-border-radius: 8px;
}
-.progress-bar
-{
+.progress-bar {
background-color: #8db8d8;
}