Bug 1246156 - Show additional link options in the synced tabs sidebar context menu. r=markh

MozReview-Commit-ID: 44KlEasJiLc

--HG--
extra : rebase_source : ccd6b124d5d8159d47ad8918710ad7060e63b750
This commit is contained in:
Kit Cambridge 2016-03-10 15:56:25 -08:00
parent 4d03aea7f9
commit 81cb8e12e4
7 changed files with 94 additions and 26 deletions

View File

@ -461,12 +461,25 @@
onpopupshowing="UpdateDynamicShortcutTooltipText(this);"/>
<menupopup id="SyncedTabsSidebarContext">
<menuitem label="&syncedTabs.context.openTab.label;"
accesskey="&syncedTabs.context.openTab.accesskey;"
id="syncedTabsOpenSelected"/>
<menuitem label="&syncedTabs.context.open.label;"
accesskey="&syncedTabs.context.open.accesskey;"
id="syncedTabsOpenSelected" where="current"/>
<menuitem label="&syncedTabs.context.openInNewTab.label;"
accesskey="&syncedTabs.context.openInNewTab.accesskey;"
id="syncedTabsOpenSelectedInTab" where="tab"/>
<menuitem label="&syncedTabs.context.openInNewWindow.label;"
accesskey="&syncedTabs.context.openInNewWindow.accesskey;"
id="syncedTabsOpenSelectedInWindow" where="window"/>
<menuitem label="&syncedTabs.context.openInNewPrivateWindow.label;"
accesskey="&syncedTabs.context.openInNewPrivateWindow.accesskey;"
id="syncedTabsOpenSelectedInPrivateWindow" where="window" private="true"/>
<menuseparator/>
<menuitem label="&syncedTabs.context.bookmarkSingleTab.label;"
accesskey="&syncedTabs.context.bookmarkSingleTab.accesskey;"
id="syncedTabsBookmarkSelected"/>
<menuitem label="&syncedTabs.context.copy.label;"
accesskey="&syncedTabs.context.copy.accesskey;"
id="syncedTabsCopySelected"/>
<menuseparator/>
<menuitem label="&syncSyncNowItem.label;"
accesskey="&syncSyncNowItem.accesskey;"

View File

@ -49,7 +49,9 @@ function SyncedTabsDeckComponent({
window: this._window,
store: this._syncedTabsListStore,
View: TabListView,
SyncedTabs: SyncedTabs
SyncedTabs: SyncedTabs,
clipboardHelper: Cc["@mozilla.org/widget/clipboardhelper;1"]
.getService(Ci.nsIClipboardHelper),
});
}

View File

@ -22,10 +22,11 @@ this.EXPORTED_SYMBOLS = [
* to state changes so it can rerender.
*/
function TabListComponent({window, store, View, SyncedTabs}) {
function TabListComponent({window, store, View, SyncedTabs, clipboardHelper}) {
this._window = window;
this._store = store;
this._View = View;
this._clipboardHelper = clipboardHelper;
// used to trigger Sync from context menu
this._SyncedTabs = SyncedTabs;
}
@ -45,6 +46,7 @@ TabListComponent.prototype = {
onMoveSelectionUp: (...args) => this.onMoveSelectionUp(...args),
onToggleBranch: (...args) => this.onToggleBranch(...args),
onBookmarkTab: (...args) => this.onBookmarkTab(...args),
onCopyTabLocation: (...args) => this.onCopyTabLocation(...args),
onSyncRefresh: (...args) => this.onSyncRefresh(...args),
onFilter: (...args) => this.onFilter(...args),
onClearFilter: (...args) => this.onClearFilter(...args),
@ -104,8 +106,12 @@ TabListComponent.prototype = {
.catch(Cu.reportError);
},
onOpenTab(url, event) {
this._window.openUILink(url, event);
onOpenTab(url, where, params) {
this._window.openLinkIn(url, where, params);
},
onCopyTabLocation(url) {
this._clipboardHelper.copyString(url);
},
onSyncRefresh() {

View File

@ -293,21 +293,28 @@ TabListView.prototype = {
},
onBookmarkTab() {
let item = this.container.querySelector('.item.selected');
if (!item || !item.dataset.url) {
return;
let item = this._getSelectedTabNode();
if (item) {
let title = item.querySelector(".item-title").textContent;
this.props.onBookmarkTab(item.dataset.url, title);
}
},
let uri = item.dataset.url;
let title = item.querySelector(".item-title").textContent;
this.props.onBookmarkTab(uri, title);
onCopyTabLocation() {
let item = this._getSelectedTabNode();
if (item) {
this.props.onCopyTabLocation(item.dataset.url);
}
},
onOpenSelected(event) {
let item = this.container.querySelector('.item.selected');
if (this._isTab(item) && item.dataset.url) {
this.props.onOpenTab(item.dataset.url, event);
let item = this._getSelectedTabNode();
if (item) {
let where = event.target.getAttribute("where");
let params = {
private: event.target.hasAttribute("private"),
};
this.props.onOpenTab(item.dataset.url, where, params);
}
},
@ -331,6 +338,14 @@ TabListView.prototype = {
this.props.onFilterBlur();
},
_getSelectedTabNode() {
let item = this.container.querySelector('.item.selected');
if (this._isTab(item) && item.dataset.url) {
return item;
}
return null;
},
// Set up the custom context menu
_setupContextMenu() {
Services.els.addSystemEventListener(this._window, "contextmenu", this, false);
@ -404,11 +419,17 @@ TabListView.prototype = {
let id = event.target.getAttribute("id");
switch (id) {
case "syncedTabsOpenSelected":
case "syncedTabsOpenSelectedInTab":
case "syncedTabsOpenSelectedInWindow":
case "syncedTabsOpenSelectedInPrivateWindow":
this.onOpenSelected(event);
break;
case "syncedTabsBookmarkSelected":
this.onBookmarkTab();
break;
case "syncedTabsCopySelected":
this.onCopyTabLocation();
break;
case "syncedTabsRefresh":
case "syncedTabsRefreshFilter":
this.props.onSyncRefresh();

View File

@ -303,7 +303,12 @@ add_task(function* testSyncedTabsSidebarContextMenu() {
info("Right-clicking a tab should show additional actions");
let tabMenuItems = [
["menuitem#syncedTabsOpenSelected", { hidden: false }],
["menuitem#syncedTabsOpenSelectedInTab", { hidden: false }],
["menuitem#syncedTabsOpenSelectedInWindow", { hidden: false }],
["menuitem#syncedTabsOpenSelectedInPrivateWindow", { hidden: false }],
["menuseparator", { hidden: false }],
["menuitem#syncedTabsBookmarkSelected", { hidden: false }],
["menuitem#syncedTabsCopySelected", { hidden: false }],
["menuseparator", { hidden: false }],
["menuitem#syncedTabsRefresh", { hidden: false }],
];
@ -315,7 +320,12 @@ add_task(function* testSyncedTabsSidebarContextMenu() {
info("Right-clicking a client shouldn't show any actions");
let sidebarMenuItems = [
["menuitem#syncedTabsOpenSelected", { hidden: true }],
["menuitem#syncedTabsOpenSelectedInTab", { hidden: true }],
["menuitem#syncedTabsOpenSelectedInWindow", { hidden: true }],
["menuitem#syncedTabsOpenSelectedInPrivateWindow", { hidden: true }],
["menuseparator", { hidden: true }],
["menuitem#syncedTabsBookmarkSelected", { hidden: true }],
["menuitem#syncedTabsCopySelected", { hidden: true }],
["menuseparator", { hidden: true }],
["menuitem#syncedTabsRefresh", { hidden: false }],
];

View File

@ -67,6 +67,9 @@ add_task(function* testInitUninit() {
add_task(function* testActions() {
let store = new SyncedTabsListStore();
let clipboardHelperMock = {
copyString() {},
};
let windowMock = {
top: {
PlacesCommandHook: {
@ -74,10 +77,11 @@ add_task(function* testActions() {
},
PlacesUtils: { bookmarksMenuFolderId: "id" }
},
openUILink() {}
openLinkIn() {}
};
let component = new TabListComponent({
window: windowMock, store, View: null, SyncedTabs});
window: windowMock, store, View: null, SyncedTabs,
clipboardHelper: clipboardHelperMock});
sinon.stub(store, "getData");
component.onFilter("query");
@ -117,9 +121,13 @@ add_task(function* testActions() {
Assert.equal(windowMock.top.PlacesCommandHook.bookmarkLink.args[0][1], "uri");
Assert.equal(windowMock.top.PlacesCommandHook.bookmarkLink.args[0][2], "title");
sinon.spy(windowMock, "openUILink");
component.onOpenTab("uri", "event");
Assert.ok(windowMock.openUILink.calledWith("uri", "event"));
sinon.spy(windowMock, "openLinkIn");
component.onOpenTab("uri", "where", "params");
Assert.ok(windowMock.openLinkIn.calledWith("uri", "where", "params"));
sinon.spy(clipboardHelperMock, "copyString");
component.onCopyTabLocation("uri");
Assert.ok(clipboardHelperMock.copyString.calledWith("uri"));
sinon.stub(SyncedTabs, "syncTabs");
component.onSyncRefresh();

View File

@ -733,10 +733,18 @@ you can use these alternative items. Otherwise, their values should be empty. -
when Sync is configured but syncing tabs is disabled. -->
<!ENTITY syncedTabs.sidebar.tabsnotsyncing.label "Turn on tab syncing to view a list of tabs from your other devices.">
<!ENTITY syncedTabs.context.openTab.label "Open This Tab">
<!ENTITY syncedTabs.context.openTab.accesskey "O">
<!ENTITY syncedTabs.context.bookmarkSingleTab.label "Bookmark This Tab…">
<!ENTITY syncedTabs.context.bookmarkSingleTab.accesskey "B">
<!ENTITY syncedTabs.context.open.label "Open">
<!ENTITY syncedTabs.context.open.accesskey "O">
<!ENTITY syncedTabs.context.openInNewTab.label "Open in a New Tab">
<!ENTITY syncedTabs.context.openInNewTab.accesskey "w">
<!ENTITY syncedTabs.context.openInNewWindow.label "Open in a New Window">
<!ENTITY syncedTabs.context.openInNewWindow.accesskey "N">
<!ENTITY syncedTabs.context.openInNewPrivateWindow.label "Open in a New Private Window">
<!ENTITY syncedTabs.context.openInNewPrivateWindow.accesskey "P">
<!ENTITY syncedTabs.context.bookmarkSingleTab.label "Bookmark This Tab…">
<!ENTITY syncedTabs.context.bookmarkSingleTab.accesskey "B">
<!ENTITY syncedTabs.context.copy.label "Copy">
<!ENTITY syncedTabs.context.copy.accesskey "C">
<!ENTITY syncBrand.shortName.label "Sync">