Commit ad54c512 authored by Jimmy Gong's avatar Jimmy Gong Committed by Commit Bot

Add Show more button to CupsPrinterEntryList

- Introduces a Show more button that expands the printer list and shows
  the complete printer list.
- With this change, we only show the first 3 saved printers while the
  rest are hidden beneath a "Show more" button.
- Adds browser test to test all corner cases with the list behavior.

Bug:993822
Test: end to end manual, browsertest

Change-Id: Ia2128482b02ce759fa94cf9345473664b37877bf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1808079
Commit-Queue: jimmy gong <jimmyxgong@chromium.org>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Reviewed-by: default avatarBailey Berro <baileyberro@chromium.org>
Cr-Commit-Position: refs/heads/master@{#706214}
parent c3963b1b
......@@ -1511,6 +1511,9 @@
<message name="IDS_SETTINGS_PRINTING_CUPS_SAVED_PRINTERS_TITLE" desc="Text for the title of the user's saved printers list.">
Your saved printers
</message>
<message name="IDS_SETTINGS_PRINTING_CUPS_SHOW_MORE" desc="Text for the button to show more printers when there are more printers than currently displayed to the user.">
Show more
</message>
<message name="IDS_SETTINGS_PRINTING_CUPS_ADD_PRINTERS_NEARBY_TITLE" desc="Text for the title of the dialog that is used to add nearby printers.">
Add a nearby printer
</message>
......
......@@ -166,6 +166,15 @@ cr.define('settings.printing', function() {
return printer.printerName.toLowerCase().includes(searchTerm.toLowerCase());
}
/**
* @param {!PrinterListEntry} first
* @param {!PrinterListEntry} second
* @return {boolean}
*/
function arePrinterIdsEqual(first, second) {
return first.printerInfo.printerId == second.printerInfo.printerId;
}
return {
isNetworkProtocol: isNetworkProtocol,
isNameAndAddressValid: isNameAndAddressValid,
......@@ -175,5 +184,6 @@ cr.define('settings.printing', function() {
getErrorText: getErrorText,
sortPrinters: sortPrinters,
matchesSearchTerm: matchesSearchTerm,
arePrinterIdsEqual: arePrinterIdsEqual,
};
});
......@@ -156,7 +156,7 @@ Polymer({
* }>} event
* @private
*/
openResultToast_: function(event) {
openResultToast_: function(event) {
const printerName = event.detail.printerName;
switch (event.detail.resultCode) {
case PrinterSetupResult.SUCCESS:
......
......@@ -56,7 +56,7 @@ const CupsPrintersEntryListBehavior = {
},
/**
* Non-empty/null fields indicate the applicable change to be notified.
* Non-empty params indicate the applicable change to be notified.
* @param {!Array<!PrinterListEntry>} savedPrinters
* @param {!Array<!PrinterListEntry>} addedPrinters
* @param {!Array<!PrinterListEntry>} removedPrinters
......@@ -67,6 +67,14 @@ const CupsPrintersEntryListBehavior = {
this.updateList(
'savedPrinters', printer => printer.printerInfo.printerId,
savedPrinters);
assert(!(addedPrinters.length && removedPrinters.length));
if (addedPrinters.length) {
this.onSavedPrintersAdded(addedPrinters);
} else if (removedPrinters.length) {
this.onSavedPrintersRemoved(removedPrinters);
}
},
/**
......@@ -77,5 +85,14 @@ const CupsPrintersEntryListBehavior = {
this.updateList(
'nearbyPrinters', printer => printer.printerInfo.printerId,
printerList);
}
},
// CupsPrintersEntryListBehavior methods. Override these in the
// implementations.
/** @param{!Array<!PrinterListEntry>} addedPrinters */
onSavedPrintersAdded: function(addedPrinters) {},
/** @param{!Array<!PrinterListEntry>} removedPrinters */
onSavedPrintersRemoved: function(removedPrinters) {},
};
\ No newline at end of file
......@@ -22,16 +22,6 @@ let PrintersListWithDeltasCallback;
let PrintersListCallback;
cr.define('settings.printing', function() {
/**
* @param {!PrinterListEntry} first
* @param {!PrinterListEntry} second
* @return {boolean}
* @private
*/
function arePrinterIdsEqual_(first, second) {
return first.printerInfo.printerId == second.printerInfo.printerId;
}
/**
* Finds the printers that are in |firstArr| but not in |secondArr|.
* @param {!Array<!PrinterListEntry>} firstArr
......@@ -41,7 +31,8 @@ cr.define('settings.printing', function() {
*/
function findDifference_(firstArr, secondArr) {
return firstArr.filter((firstArrEntry) => {
return !secondArr.some(arePrinterIdsEqual_.bind(this, firstArrEntry));
return !secondArr.some(
p => p.printerInfo.printerId == firstArrEntry.printerInfo.printerId);
});
}
......
......@@ -3,6 +3,7 @@
<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
<link rel="import" href="chrome://resources/html/list_property_update_behavior.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
<link rel="import" href="cups_printer_types.html">
<link rel="import" href="cups_printers_browser_proxy.html">
......@@ -12,7 +13,8 @@
<dom-module id="settings-cups-saved-printers">
<template>
<style include="cups-printer-shared">
<style include="settings-shared iron-flex iron-flex-alignment
iron-flex-factors">
:host {
display: flex;
flex-direction: column;
......@@ -21,6 +23,28 @@
#no-search-results {
margin-bottom: 20px;
}
/** Height of iron list row entry. */
#show-more-container {
min-height: var(--settings-row-min-height);
}
/** Border line that is the same size as a list entry's border. */
#show-more-line-separator {
border-bottom: var(--cr-separator-line);
left: 60px;
position: relative;
right: 20px;
width: 596px;
}
#show-more-icon {
--cr-icon-button-margin-end: 0;
}
#show-more-text {
flex: 1;
}
</style>
<cr-action-menu>
......@@ -39,6 +63,20 @@
</settings-cups-printers-entry>
</template>
</iron-list>
<template is="dom-if" id="show-more-button-section"
if="[[shouldPrinterListBeCollapsed_(searchTerm, savedPrinters.*,
newPrinters_.*, hasShowMoreBeenTapped_)]]" restamp>
<div id="show-more-line-separator"></div>
<div class="list-frame layout horizontal" id="show-more-container">
<div id="show-more-text">$i18n{showMorePrinters}</div>
<cr-icon-button class="action-button" id="show-more-icon"
iron-icon="cr:expand-more"
on-click="onShowMoreTap_"
title=$i18n{showMorePrinters}>
</cr-icon-button>
</div>
</template>
<div id="no-search-results"
hidden="[[!showNoSearchResultsMessage_(searchTerm,
filteredPrinters_.*)]]">
......
......@@ -2,6 +2,24 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function() {
// If the Show more button is visible, the minimum number of printers we show
// is 3.
const kMinVisiblePrinters = 3;
/**
* Move a printer's position in |printerArr| from |fromIndex| to |toIndex|.
* @param {!Array<!PrinterListEntry>} printerArr
* @param {number} fromIndex
* @param {number} toIndex
*/
function moveEntryInPrinters(printerArr, fromIndex, toIndex) {
const element = printerArr[fromIndex];
printerArr.splice(fromIndex, 1);
printerArr.splice(toIndex, 0, element);
}
/**
* @fileoverview 'settings-cups-saved-printers' is a list container for Saved
* Printers.
......@@ -50,17 +68,49 @@ Polymer({
type: Array,
value: () => [],
},
/**
* Array of new PrinterListEntry's that were added during this session.
* @type {!Array<!PrinterListEntry>}
* @private
*/
newPrinters_: {
type: Array,
value: () => [],
},
/**
* Keeps track of whether the user has tapped the Show more button. A search
* term will expand the collapsed list, so we need to keep track of whether
* the list expanded because of a search term or because the user tapped on
* the Show more button.
* @private
*/
hasShowMoreBeenTapped_: {
type: Boolean,
value: false,
},
},
listeners: {
'open-action-menu': 'onOpenActionMenu_',
},
observers: ['onSearchOrPrintersChanged_(savedPrinters.*, searchTerm)'],
observers: [
'onSearchOrPrintersChanged_(savedPrinters.*, searchTerm,' +
'hasShowMoreBeenTapped_, newPrinters_.*)'
],
/** @private {settings.CupsPrintersBrowserProxy} */
browserProxy_: null,
/**
* The number of printers we display if hidden printers are allowed.
* kMinVisiblePrinters is the default value and we never show fewer printers
* if the Show more button is visible.
*/
visiblePrinterCounter_: kMinVisiblePrinters,
/** @override */
created: function() {
this.browserProxy_ = settings.CupsPrintersBrowserProxyImpl.getInstance();
......@@ -74,15 +124,8 @@ Polymer({
if (!this.savedPrinters) {
return;
}
// Filter printers through |searchTerm|. If |searchTerm| is empty,
// |filteredPrinters_| is just |savedPrinters|.
const updatedPrinters = this.searchTerm ?
this.savedPrinters.filter(
item => settings.printing.matchesSearchTerm(
item.printerInfo, this.searchTerm)) :
this.savedPrinters.slice();
updatedPrinters.sort(settings.printing.sortPrinters);
const updatedPrinters = this.getVisiblePrinters_();
this.updateList(
'filteredPrinters_', printer => printer.printerInfo.printerId,
......@@ -121,6 +164,40 @@ Polymer({
this.closeActionMenu_();
},
/** @private */
onShowMoreTap_: function() {
this.hasShowMoreBeenTapped_ = true;
},
/**
* Gets the printers to be shown in the UI. These printers are filtered
* by the search term, alphabetically sorted (if applicable), and are the
* printers not hidden by the Show more section.
* @return {!Array<!PrinterListEntry>} Returns only the visible printers.
* @private
*/
getVisiblePrinters_: function() {
// Filter printers through |searchTerm|. If |searchTerm| is empty,
// |filteredPrinters_| is just |savedPrinters|.
const updatedPrinters = this.searchTerm ?
this.savedPrinters.filter(
item => settings.printing.matchesSearchTerm(
item.printerInfo, this.searchTerm)) :
this.savedPrinters.slice();
updatedPrinters.sort(settings.printing.sortPrinters);
this.moveNewlyAddedPrinters_(updatedPrinters, 0 /* toIndex */);
if (this.shouldPrinterListBeCollapsed_()) {
// If the Show more button is visible, we only display the first
// N < |visiblePrinterCounter_| printers and the rest are hidden.
return updatedPrinters.filter(
(printer, idx) => idx < this.visiblePrinterCounter_);
}
return updatedPrinters;
},
/** @private */
closeActionMenu_: function() {
this.$$('cr-action-menu').close();
......@@ -132,6 +209,87 @@ Polymer({
*/
showNoSearchResultsMessage_: function() {
return !!this.searchTerm && !this.filteredPrinters_.length;
}
},
/** @param{!Array<!PrinterListEntry>} addedPrinters */
onSavedPrintersAdded: function(addedPrinters) {
const currArr = this.newPrinters_.slice();
for (const printer of addedPrinters) {
this.visiblePrinterCounter_++;
currArr.push(printer);
}
this.set('newPrinters_', currArr);
},
/** @param{!Array<!PrinterListEntry>} removedPrinters */
onSavedPrintersRemoved: function(removedPrinters) {
const currArr = this.newPrinters_.slice();
for (const printer of removedPrinters) {
const newPrinterRemovedIdx = currArr.findIndex(
p => p.printerInfo.printerId == printer.printerInfo.printerId);
// If the removed printer is a recently added printer, remove it from
// |currArr|.
if (newPrinterRemovedIdx > -1) {
currArr.splice(newPrinterRemovedIdx, 1);
}
this.visiblePrinterCounter_ = Math.max(
kMinVisiblePrinters, --this.visiblePrinterCounter_);
}
this.set('newPrinters_', currArr);
},
/**
* Keeps track of whether the Show more button should be visible which means
* that the printer list is collapsed. There are two ways a collapsed list
* may be expanded: the Show more button is tapped or if there is a search
* term.
* @return {boolean} True if the printer list should be collapsed.
* @private
*/
shouldPrinterListBeCollapsed_: function() {
// If |searchTerm| is set, never collapse the list.
if (this.searchTerm) {
return false;
}
// If |hasShowMoreBeenTapped_| is set to true, never collapse the list.
if (this.hasShowMoreBeenTapped_) {
return false;
}
// If the total number of saved printers does not exceed the number of
// visible printers, there is no need for the list to be collapsed.
if (this.savedPrinters.length - this.visiblePrinterCounter_ < 1) {
return false;
}
return true;
},
/**
* Moves printers that are in |newPrinters_| to position |toIndex| of
* |printerArr|. This moves all recently added printers to the top of the
* printer list.
* @param {!Array<!PrinterListEntry>} printerArr
* @param {number} toIndex
* @private
*/
moveNewlyAddedPrinters_: function(printerArr, toIndex) {
if (!this.newPrinters_.length) {
return;
}
// We have newly added printers, move them to the top of the list.
for (const printer of this.newPrinters_) {
const idx = printerArr.findIndex(
p => p.printerInfo.printerId == printer.printerInfo.printerId);
if (idx > -1) {
moveEntryInPrinters(printerArr, idx, toIndex);
}
}
}
});
})();
......@@ -2363,6 +2363,7 @@ void AddPrintingStrings(content::WebUIDataSource* html_source) {
{"printerModel", IDS_SETTINGS_PRINTING_CUPS_PRINTER_DETAILS_MODEL},
{"printerQueue", IDS_SETTINGS_PRINTING_CUPS_PRINTER_DETAILS_QUEUE},
{"savedPrintersTitle", IDS_SETTINGS_PRINTING_CUPS_SAVED_PRINTERS_TITLE},
{"showMorePrinters", IDS_SETTINGS_PRINTING_CUPS_SHOW_MORE},
{"addPrintersNearbyTitle",
IDS_SETTINGS_PRINTING_CUPS_ADD_PRINTERS_NEARBY_TITLE},
{"addPrintersManuallyTitle",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment