Bug 1269962 - Implement a popup menu for showing a submenu in Downloads Panel Footer., r=Paolo

MozReview-Commit-ID: 7K1W15039W8

--HG--
extra : rebase_source : 01b66909876cb22ea8442d037ebd8b8f3f5748ec
This commit is contained in:
Sean Lee 2016-07-13 13:39:00 +08:00
Родитель ff7bc87130
Коммит 9b70990ee3
11 изменённых файлов: 241 добавлений и 23 удалений

Просмотреть файл

@ -508,20 +508,32 @@ this.DownloadsCommon = {
// or the file doesn't exist), try using the parent if we have it.
let parent = aFile.parent;
if (parent) {
try {
// Open the parent directory to show where the file should be.
parent.launch();
} catch (ex) {
// If launch also fails (probably because it's not implemented), let
// the OS handler try to open the parent.
Cc["@mozilla.org/uriloader/external-protocol-service;1"]
.getService(Ci.nsIExternalProtocolService)
.loadUrl(NetUtil.newURI(parent));
}
this.showDirectory(parent);
}
}
},
/**
* Show the specified folder in the system file manager.
*
* @param aDirectory
* a directory to be opened with system file manager.
*/
showDirectory(aDirectory) {
if (!(aDirectory instanceof Ci.nsIFile)) {
throw new Error("aDirectory must be a nsIFile object");
}
try {
aDirectory.launch();
} catch (ex) {
// If launch fails (probably because it's not implemented), let
// the OS handler try to open the directory.
Cc["@mozilla.org/uriloader/external-protocol-service;1"]
.getService(Ci.nsIExternalProtocolService)
.loadUrl(NetUtil.newURI(aDirectory));
}
},
/**
* Displays an alert message box which asks the user if they want to
* unblock the downloaded file or not.

Просмотреть файл

@ -19,7 +19,7 @@ richlistitem[type="download"].download-state[state="1"]:not([exists]) .downloadS
#downloadsSummary:not([inprogress]) > vbox > #downloadsSummaryProgress,
#downloadsSummary:not([inprogress]) > vbox > #downloadsSummaryDetails,
#downloadsFooter[showingsummary] > #downloadsHistory,
#downloadsFooter[showingsummary] > #downloadsFooterButtons,
#downloadsFooter:not([showingsummary]) > #downloadsSummary {
display: none;
}

Просмотреть файл

@ -367,6 +367,23 @@ const DownloadsPanel = {
this._state = this.kStateHidden;
},
onFooterPopupShowing(aEvent) {
let itemClearList = document.getElementById("downloadsDropdownItemClearList");
if (DownloadsCommon.getData(window).canRemoveFinished) {
itemClearList.removeAttribute("hidden");
} else {
itemClearList.setAttribute("hidden", "true");
}
document.getElementById("downloadsFooterButtonsSplitter").classList
.add("downloadsDropmarkerSplitterExtend");
},
onFooterPopupHidden(aEvent) {
document.getElementById("downloadsFooterButtonsSplitter").classList
.remove("downloadsDropmarkerSplitterExtend");
},
//////////////////////////////////////////////////////////////////////////////
//// Related operations
@ -382,6 +399,13 @@ const DownloadsPanel = {
BrowserDownloadsUI();
},
openDownloadsFolder() {
Downloads.getPreferredDownloadsDirectory().then(downloadsPath => {
DownloadsCommon.showDirectory(new FileUtils.File(downloadsPath));
}).catch(Cu.reportError);
this.hidePanel();
},
//////////////////////////////////////////////////////////////////////////////
//// Internal functions
@ -1188,6 +1212,9 @@ const DownloadsViewController = {
//// nsIController
supportsCommand(aCommand) {
if (aCommand === "downloadsCmd_clearList") {
return true;
}
// Firstly, determine if this is a command that we can handle.
if (!DownloadsViewUI.isCommandName(aCommand)) {
return false;

Просмотреть файл

@ -104,8 +104,8 @@
<menuseparator/>
<menuitem command="downloadsCmd_clearList"
label="&cmd.clearList.label;"
accesskey="&cmd.clearList.accesskey;"/>
label="&cmd.clearList2.label;"
accesskey="&cmd.clearList2.accesskey;"/>
</menupopup>
<panelmultiview id="downloadsPanel-multiView"
@ -148,11 +148,31 @@
crop="end"/>
</vbox>
</hbox>
<button id="downloadsHistory"
class="plain downloadsPanelFooterButton"
label="&downloadsHistory.label;"
accesskey="&downloadsHistory.accesskey;"
oncommand="DownloadsPanel.showDownloadsHistory();"/>
<hbox id="downloadsFooterButtons">
<button id="downloadsHistory"
class="plain downloadsPanelFooterButton"
label="&downloadsHistory.label;"
accesskey="&downloadsHistory.accesskey;"
flex="1"
oncommand="DownloadsPanel.showDownloadsHistory();"/>
<toolbarseparator id="downloadsFooterButtonsSplitter"
class="downloadsDropmarkerSplitter"/>
<button id="downloadsFooterDropmarker"
class="plain downloadsPanelFooterButton downloadsDropmarker"
type="menu">
<menupopup id="downloadSubPanel"
onpopupshowing="DownloadsPanel.onFooterPopupShowing(event);"
onpopuphidden="DownloadsPanel.onFooterPopupHidden(event);"
position="after_end">
<menuitem id="downloadsDropdownItemClearList"
command="downloadsCmd_clearList"
label="&cmd.clearList2.label;"/>
<menuitem id="downloadsDropdownItemOpenDownloadsFolder"
oncommand="DownloadsPanel.openDownloadsFolder();"
label="&openDownloadsFolder.label;"/>
</menupopup>
</button>
</hbox>
</vbox>
</panelview>

Просмотреть файл

@ -10,3 +10,4 @@ skip-if = os == "linux" # Bug 952422
[browser_confirm_unblock_download.js]
[browser_iframe_gone_mid_download.js]
[browser_downloads_panel_block.js]
[browser_downloads_panel_footer.js]

Просмотреть файл

@ -0,0 +1,94 @@
"use strict";
function *task_openDownloadsSubPanel() {
let downloadSubPanel = document.getElementById("downloadSubPanel");
let popupShownPromise = BrowserTestUtils.waitForEvent(downloadSubPanel, "popupshown");
let downloadsDropmarker = document.getElementById("downloadsFooterDropmarker");
EventUtils.synthesizeMouseAtCenter(downloadsDropmarker, {}, window);
yield popupShownPromise;
}
add_task(function* test_openDownloadsFolder() {
yield task_openPanel();
yield task_openDownloadsSubPanel();
yield new Promise(resolve => {
sinon.stub(DownloadsCommon, "showDirectory", file => {
resolve(Downloads.getPreferredDownloadsDirectory().then(downloadsPath => {
is(file.path, downloadsPath, "Check the download folder path.");
}));
});
let itemOpenDownloadsFolder =
document.getElementById("downloadsDropdownItemOpenDownloadsFolder");
EventUtils.synthesizeMouseAtCenter(itemOpenDownloadsFolder, {}, window);
});
yield task_resetState();
});
add_task(function* test_clearList() {
const kTestCases = [{
downloads: [
{ state: nsIDM.DOWNLOAD_NOTSTARTED },
{ state: nsIDM.DOWNLOAD_FINISHED },
{ state: nsIDM.DOWNLOAD_FAILED },
{ state: nsIDM.DOWNLOAD_CANCELED },
],
expectClearListShown: true,
expectedItemNumber: 0,
},{
downloads: [
{ state: nsIDM.DOWNLOAD_NOTSTARTED },
{ state: nsIDM.DOWNLOAD_FINISHED },
{ state: nsIDM.DOWNLOAD_FAILED },
{ state: nsIDM.DOWNLOAD_PAUSED },
{ state: nsIDM.DOWNLOAD_CANCELED },
],
expectClearListShown: true,
expectedItemNumber: 1,
},{
downloads: [
{ state: nsIDM.DOWNLOAD_PAUSED },
],
expectClearListShown: false,
expectedItemNumber: 1,
}];
for (let testCase of kTestCases) {
yield verify_clearList(testCase);
}
});
function *verify_clearList(testCase) {
let downloads = testCase.downloads;
yield task_addDownloads(downloads);
yield task_openPanel();
is(DownloadsView._downloads.length, downloads.length,
"Expect the number of download items");
yield task_openDownloadsSubPanel();
let itemClearList = document.getElementById("downloadsDropdownItemClearList");
let itemNumberPromise = BrowserTestUtils.waitForCondition(() => {
return DownloadsView._downloads.length === testCase.expectedItemNumber;
});
if (testCase.expectClearListShown) {
isnot("true", itemClearList.getAttribute("hidden"),
"Should show Clear Preview Panel button");
EventUtils.synthesizeMouseAtCenter(itemClearList, {}, window);
} else {
is("true", itemClearList.getAttribute("hidden"),
"Should not show Clear Preview Panel button");
}
yield itemNumberPromise;
is(DownloadsView._downloads.length, testCase.expectedItemNumber,
"Download items remained.");
yield task_resetState();
}

Просмотреть файл

@ -24,8 +24,17 @@ const nsIDM = Ci.nsIDownloadManager;
var gTestTargetFile = FileUtils.getFile("TmpD", ["dm-ui-test.file"]);
gTestTargetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
// Load mocking/stubbing library, sinon
// docs: http://sinonjs.org/docs/
Services.scriptloader.loadSubScript("resource://testing-common/sinon-1.16.1.js");
registerCleanupFunction(function () {
gTestTargetFile.remove(false);
delete window.sinon;
delete window.setImmediate;
delete window.clearImmediate;
});
////////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -62,8 +62,8 @@
<!ENTITY cmd.copyDownloadLink.accesskey "L">
<!ENTITY cmd.removeFromHistory.label "Remove From History">
<!ENTITY cmd.removeFromHistory.accesskey "e">
<!ENTITY cmd.clearList.label "Clear List">
<!ENTITY cmd.clearList.accesskey "a">
<!ENTITY cmd.clearList2.label "Clear Preview Panel">
<!ENTITY cmd.clearList2.accesskey "a">
<!ENTITY cmd.clearDownloads.label "Clear Downloads">
<!ENTITY cmd.clearDownloads.accesskey "D">
<!-- LOCALIZATION NOTE (cmd.unblock2.label):
@ -109,6 +109,8 @@
<!ENTITY downloadsHistory.label "Show All Downloads">
<!ENTITY downloadsHistory.accesskey "S">
<!ENTITY openDownloadsFolder.label "Open Downloads Folder">
<!ENTITY clearDownloadsButton.label "Clear Downloads">
<!ENTITY clearDownloadsButton.tooltip "Clears completed, canceled and failed downloads">

Просмотреть файл

@ -30,7 +30,8 @@
}
#emptyDownloads {
padding: 10px 20px;
padding: 16px 25px;
margin: 0;
/* The panel can be wider than this description after the blocked subview is
shown, so center the text. */
text-align: center;
@ -41,7 +42,7 @@
border-top: 1px solid var(--panel-separator-color);
}
.downloadsPanelFooter > toolbarseparator {
.downloadsPanelFooter toolbarseparator {
margin: 0;
border: 0;
min-width: 0;
@ -55,6 +56,7 @@
color: inherit;
margin: 0;
padding: 0;
min-width: 0;
min-height: 40px;
}
@ -63,7 +65,8 @@
background-color: hsla(210,4%,10%,.07);
}
.downloadsPanelFooterButton:hover:active {
.downloadsPanelFooterButton:hover:active,
.downloadsPanelFooterButton[open="true"] {
outline: 1px solid hsla(210,4%,10%,.12);
background-color: hsla(210,4%,10%,.12);
box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
@ -82,6 +85,47 @@
background-color: #0568ba;
}
#downloadsPanel[hasdownloads] #downloadsHistory {
padding-left: 58px !important;
}
toolbarseparator.downloadsDropmarkerSplitter {
margin: 7px 0;
}
#downloadsFooter:hover toolbarseparator.downloadsDropmarkerSplitter,
#downloadsFooter toolbarseparator.downloadsDropmarkerSplitterExtend {
margin: 0;
}
.downloadsDropmarker {
padding: 0 19px !important;
}
.downloadsDropmarker > .button-box > hbox {
display: none;
}
.downloadsDropmarker > .button-box > .button-menu-dropmarker {
/* This is to override the linux !important */
-moz-appearance: none !important;
display: -moz-box;
}
.downloadsDropmarker > .button-box > .button-menu-dropmarker > .dropmarker-icon {
width: 16px;
height: 16px;
list-style-image: url("chrome://browser/skin/downloads/menubutton-dropmarker.svg");
filter: url("chrome://browser/skin/filters.svg#fill");
fill: currentColor;
}
/* Override default icon size which is too small for this dropdown */
.downloadsDropmarker > .button-box > .button-menu-dropmarker {
width: 16px;
height: 16px;
}
#downloadsSummary {
--summary-padding-end: 38px;
--summary-padding-start: 12px;

Просмотреть файл

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<!-- 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/. -->
<svg xmlns="http://www.w3.org/2000/svg"
width="16" height="16" viewBox="0 0 16 16">
<path d="m 2,6 6,6 6,-6 -1.5,-1.5 -4.5,4.5 -4.5,-4.5 z" />
</svg>

После

Ширина:  |  Высота:  |  Размер: 391 B

Просмотреть файл

@ -54,6 +54,7 @@
skin/classic/browser/customizableui/whimsy@2x.png (../shared/customizableui/whimsy@2x.png)
skin/classic/browser/downloads/contentAreaDownloadsView.css (../shared/downloads/contentAreaDownloadsView.css)
skin/classic/browser/downloads/download-blocked.svg (../shared/downloads/download-blocked.svg)
skin/classic/browser/downloads/menubutton-dropmarker.svg (../shared/downloads/menubutton-dropmarker.svg)
skin/classic/browser/drm-icon.svg (../shared/drm-icon.svg)
skin/classic/browser/filters.svg (../shared/filters.svg)
skin/classic/browser/fullscreen/insecure.svg (../shared/fullscreen/insecure.svg)