Commit 231d565d authored by Gavin Williams's avatar Gavin Williams Committed by Chromium LUCI CQ

scanning: Show canceling progress bar

Add a new state CANCELING for showing a continuous progress bar when
waiting for a cancel request to complete.

http://screen/BJsFQbdZFDZscdV

Bug: 1059779
Change-Id: I98ee9863367b602b3a29f8cd3583db36112cc081
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2561505
Commit-Queue: Gavin Williams <gavinwill@chromium.org>
Reviewed-by: default avatarJesse Schettler <jschettler@chromium.org>
Cr-Commit-Position: refs/heads/master@{#832423}
parent 0d721ac1
...@@ -23,6 +23,8 @@ export function scanPreviewTest() { ...@@ -23,6 +23,8 @@ export function scanPreviewTest() {
let scanProgress; let scanProgress;
/** @type {!HTMLElement} */ /** @type {!HTMLElement} */
let scannedImages; let scannedImages;
/** @type {!HTMLElement} */
let cancelingProgress;
setup(() => { setup(() => {
scanPreview = /** @type {!ScanPreviewElement} */ ( scanPreview = /** @type {!ScanPreviewElement} */ (
...@@ -38,6 +40,8 @@ export function scanPreviewTest() { ...@@ -38,6 +40,8 @@ export function scanPreviewTest() {
/** @type {!HTMLElement} */ (scanPreview.$$('#scanProgress')); /** @type {!HTMLElement} */ (scanPreview.$$('#scanProgress'));
scannedImages = scannedImages =
/** @type {!HTMLElement} */ (scanPreview.$$('#scannedImages')); /** @type {!HTMLElement} */ (scanPreview.$$('#scannedImages'));
cancelingProgress =
/** @type {!HTMLElement} */ (scanPreview.$$('#cancelingProgress'));
}); });
teardown(() => { teardown(() => {
...@@ -52,14 +56,16 @@ export function scanPreviewTest() { ...@@ -52,14 +56,16 @@ export function scanPreviewTest() {
* @param {boolean} isHelperTextVisible * @param {boolean} isHelperTextVisible
* @param {boolean} isScanProgressVisible * @param {boolean} isScanProgressVisible
* @param {boolean} isScannedImagesVisible * @param {boolean} isScannedImagesVisible
* @param {boolean} isCancelingProgressVisible
*/ */
function assertVisible( function assertVisible(
isHelpOrProgressVisible, isHelperTextVisible, isScanProgressVisible, isHelpOrProgressVisible, isHelperTextVisible, isScanProgressVisible,
isScannedImagesVisible) { isScannedImagesVisible, isCancelingProgressVisible) {
assertEquals(isHelpOrProgressVisible, isVisible(helpOrProgress)); assertEquals(isHelpOrProgressVisible, isVisible(helpOrProgress));
assertEquals(isHelperTextVisible, isVisible(helperText)); assertEquals(isHelperTextVisible, isVisible(helperText));
assertEquals(isScanProgressVisible, isVisible(scanProgress)); assertEquals(isScanProgressVisible, isVisible(scanProgress));
assertEquals(isScannedImagesVisible, isVisible(scannedImages)); assertEquals(isScannedImagesVisible, isVisible(scannedImages));
assertEquals(isCancelingProgressVisible, isVisible(cancelingProgress));
} }
test('initializeScanPreview', () => { test('initializeScanPreview', () => {
...@@ -86,37 +92,50 @@ export function scanPreviewTest() { ...@@ -86,37 +92,50 @@ export function scanPreviewTest() {
flush(); flush();
assertVisible( assertVisible(
/*isHelpOrProgressVisible*/ true, /*isHelperTextVisible*/ true, /*isHelpOrProgressVisible*/ true, /*isHelperTextVisible*/ true,
/*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false); /*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false,
/*isCancelingProgressVisible*/ false);
scanPreview.appState = AppState.GOT_SCANNERS; scanPreview.appState = AppState.GOT_SCANNERS;
flush(); flush();
assertVisible( assertVisible(
/*isHelpOrProgressVisible*/ true, /*isHelperTextVisible*/ true, /*isHelpOrProgressVisible*/ true, /*isHelperTextVisible*/ true,
/*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false); /*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false,
/*isCancelingProgressVisible*/ false);
scanPreview.appState = AppState.GETTING_CAPS; scanPreview.appState = AppState.GETTING_CAPS;
flush(); flush();
assertVisible( assertVisible(
/*isHelpOrProgressVisible*/ true, /*isHelperTextVisible*/ true, /*isHelpOrProgressVisible*/ true, /*isHelperTextVisible*/ true,
/*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false); /*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false,
/*isCancelingProgressVisible*/ false);
scanPreview.appState = AppState.READY; scanPreview.appState = AppState.READY;
flush(); flush();
assertVisible( assertVisible(
/*isHelpOrProgressVisible*/ true, /*isHelperTextVisible*/ true, /*isHelpOrProgressVisible*/ true, /*isHelperTextVisible*/ true,
/*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false); /*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false,
/*isCancelingProgressVisible*/ false);
scanPreview.appState = AppState.SCANNING; scanPreview.appState = AppState.SCANNING;
flush(); flush();
assertVisible( assertVisible(
/*isHelpOrProgressVisible*/ true, /*isHelperTextVisible*/ false, /*isHelpOrProgressVisible*/ true, /*isHelperTextVisible*/ false,
/*isScanProgressVisible*/ true, /*isScannedImagesVisible*/ false); /*isScanProgressVisible*/ true, /*isScannedImagesVisible*/ false,
/*isCancelingProgressVisible*/ false);
scanPreview.appState = AppState.CANCELING;
flush();
assertVisible(
/*isHelpOrProgressVisible*/ true, /*isHelperTextVisible*/ false,
/*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false,
/*isCancelingProgressVisible*/ true);
scanPreview.objectUrls = ['image']; scanPreview.objectUrls = ['image'];
scanPreview.appState = AppState.DONE; scanPreview.appState = AppState.DONE;
flush(); flush();
assertVisible( assertVisible(
/*isHelpOrProgressVisible*/ false, /*isHelperTextVisible*/ false, /*isHelpOrProgressVisible*/ false, /*isHelperTextVisible*/ false,
/*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ true); /*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ true,
/*isCancelingProgressVisible*/ false);
}); });
} }
...@@ -553,6 +553,8 @@ export function scanningAppTest() { ...@@ -553,6 +553,8 @@ export function scanningAppTest() {
return fakeScanService_.whenCalled('cancelScan'); return fakeScanService_.whenCalled('cancelScan');
}) })
.then(() => { .then(() => {
// Cancel button should be disabled while canceling is in progress.
assertTrue(cancelButton.disabled);
// Simulate cancel completing successfully. // Simulate cancel completing successfully.
return fakeScanService_.simulateCancelComplete(true); return fakeScanService_.simulateCancelComplete(true);
}) })
...@@ -610,6 +612,8 @@ export function scanningAppTest() { ...@@ -610,6 +612,8 @@ export function scanningAppTest() {
return fakeScanService_.whenCalled('cancelScan'); return fakeScanService_.whenCalled('cancelScan');
}) })
.then(() => { .then(() => {
// Cancel button should be disabled while canceling is in progress.
assertTrue(cancelButton.disabled);
// Simulate cancel failing. // Simulate cancel failing.
return fakeScanService_.simulateCancelComplete(false); return fakeScanService_.simulateCancelComplete(false);
}) })
......
...@@ -588,6 +588,9 @@ Try tapping the mic to ask me anything. ...@@ -588,6 +588,9 @@ Try tapping the mic to ask me anything.
<message name="IDS_SCANNING_APP_SCAN_CANCELED_TOAST_TEXT" desc="The message displayed when a scan job is successfully canceled."> <message name="IDS_SCANNING_APP_SCAN_CANCELED_TOAST_TEXT" desc="The message displayed when a scan job is successfully canceled.">
Scanning has been canceled Scanning has been canceled
</message> </message>
<message name="IDS_SCANNING_APP_CANCELING_SCANNING_TEXT" desc="The text displayed in the scan preview to indicate a scan job is being canceled.">
Canceling scanning
</message>
<!-- Diagnostics App --> <!-- Diagnostics App -->
<!-- TODO(michaelcheco): Update with finalized copies of the strings --> <!-- TODO(michaelcheco): Update with finalized copies of the strings -->
......
209056995bbc15942d75ea539ef44749d1d14cd1
\ No newline at end of file
...@@ -18,12 +18,14 @@ ...@@ -18,12 +18,14 @@
height: calc(1.2941 * var(--left-panel-width)); height: calc(1.2941 * var(--left-panel-width));
} }
#progressText { #progressText,
#cancelingText {
@apply --scanning-progress-text-font; @apply --scanning-progress-text-font;
color: var(--scanning-progress-text-color); color: var(--scanning-progress-text-color);
} }
#scanProgress { #scanProgress,
#cancelingProgress {
margin: auto; margin: auto;
text-align: center; text-align: center;
width: 60%; width: 60%;
...@@ -57,13 +59,21 @@ ...@@ -57,13 +59,21 @@
} }
paper-progress { paper-progress {
--paper-progress-active-color: var(--google-blue-600);
--paper-progress-container-color: var(--google-blue-200);
border-radius: 4px; border-radius: 4px;
height: 4px; height: 4px;
margin-top: 12px; margin-top: 12px;
width: 256px; width: 256px;
} }
#scanProgressBar {
--paper-progress-active-color: var(--google-blue-600);
--paper-progress-container-color: var(--google-blue-200);
}
#cancelingProgressBar {
--paper-progress-active-color: var(--google-grey-refresh-500);
--paper-progress-container-color: var(--google-grey-200);
}
</style> </style>
<div class="preview"> <div class="preview">
<div id="helpOrProgress" class="preview-item" <div id="helpOrProgress" class="preview-item"
...@@ -73,7 +83,12 @@ ...@@ -73,7 +83,12 @@
</div> </div>
<div id="scanProgress" hidden$="[[!showScanProgress_]]"> <div id="scanProgress" hidden$="[[!showScanProgress_]]">
<span id="progressText">[[getProgressTextString_(pageNumber)]]</span> <span id="progressText">[[getProgressTextString_(pageNumber)]]</span>
<paper-progress value="[[progressPercent]]"></paper-progress> <paper-progress id="scanProgressBar" value="[[progressPercent]]">
</paper-progress>
</div>
<div id="cancelingProgress" hidden$="[[!showCancelingProgress_]]">
<span id="cancelingText">[[i18n('cancelingScanningText')]]</span>
<paper-progress id="cancelingProgressBar" indeterminate></paper-progress>
</div> </div>
</div> </div>
<div id="scannedImages" hidden$="[[!showScannedImages_]]"> <div id="scannedImages" hidden$="[[!showScannedImages_]]">
......
...@@ -59,6 +59,12 @@ Polymer({ ...@@ -59,6 +59,12 @@ Polymer({
type: Boolean, type: Boolean,
value: false, value: false,
}, },
/** @private {boolean} */
showCancelingProgress_: {
type: Boolean,
value: false,
},
}, },
/** /**
...@@ -84,8 +90,10 @@ Polymer({ ...@@ -84,8 +90,10 @@ Polymer({
onAppStateChange_() { onAppStateChange_() {
this.showScannedImages_ = this.showScannedImages_ =
this.appState === AppState.DONE && this.objectUrls.length > 0; this.appState === AppState.DONE && this.objectUrls.length > 0;
this.showScanProgress_ =
this.appState === AppState.SCANNING || this.appState === AppState.DONE;
this.showCancelingProgress_ = this.appState === AppState.CANCELING;
this.showHelperText_ = this.showHelperText_ =
this.appState !== AppState.SCANNING && this.appState !== AppState.DONE; !this.showScanProgress_ && !this.showCancelingProgress_;
this.showScanProgress_ = !this.showHelperText_;
}, },
}); });
...@@ -164,7 +164,8 @@ ...@@ -164,7 +164,8 @@
[[i18n('scanButtonText')]] [[i18n('scanButtonText')]]
</cr-button> </cr-button>
<cr-button id="cancelButton" on-click="onCancelClick_" <cr-button id="cancelButton" on-click="onCancelClick_"
hidden$="[[!showCancelButton_]]"> hidden$="[[!showCancelButton_]]"
disabled$="[[cancelButtonDisabled_]]">
[[i18n('cancelButtonText')]] [[i18n('cancelButtonText')]]
</cr-button> </cr-button>
</div> </div>
......
...@@ -174,6 +174,12 @@ Polymer({ ...@@ -174,6 +174,12 @@ Polymer({
value: false, value: false,
}, },
/** @private {boolean} */
cancelButtonDisabled_: {
type: Boolean,
value: false,
},
/** /**
* The file path of the last scanned page of a successful scan job. Used to * The file path of the last scanned page of a successful scan job. Used to
* open the Files app with the correct file highlighted. * open the Files app with the correct file highlighted.
...@@ -240,7 +246,9 @@ Polymer({ ...@@ -240,7 +246,9 @@ Polymer({
* @param {number} progressPercent * @param {number} progressPercent
*/ */
onPageProgress(pageNumber, progressPercent) { onPageProgress(pageNumber, progressPercent) {
assert(this.appState_ === AppState.SCANNING); assert(
this.appState_ === AppState.SCANNING ||
this.appState_ === AppState.CANCELING);
this.pageNumber_ = pageNumber; this.pageNumber_ = pageNumber;
this.progressPercent_ = progressPercent; this.progressPercent_ = progressPercent;
}, },
...@@ -250,7 +258,9 @@ Polymer({ ...@@ -250,7 +258,9 @@ Polymer({
* @param {!Array<number>} pageData * @param {!Array<number>} pageData
*/ */
onPageComplete(pageData) { onPageComplete(pageData) {
assert(this.appState_ === AppState.SCANNING); assert(
this.appState_ === AppState.SCANNING ||
this.appState_ === AppState.CANCELING);
const blob = new Blob([Uint8Array.from(pageData)], {'type': 'image/png'}); const blob = new Blob([Uint8Array.from(pageData)], {'type': 'image/png'});
this.push('objectUrls_', URL.createObjectURL(blob)); this.push('objectUrls_', URL.createObjectURL(blob));
}, },
...@@ -278,6 +288,7 @@ Polymer({ ...@@ -278,6 +288,7 @@ Polymer({
onCancelComplete(success) { onCancelComplete(success) {
// If the cancel request fails, continue showing the scan progress page. // If the cancel request fails, continue showing the scan progress page.
if (!success) { if (!success) {
this.setAppState_(AppState.SCANNING);
this.showToast_('cancelFailedToastText'); this.showToast_('cancelFailedToastText');
return; return;
} }
...@@ -444,6 +455,7 @@ Polymer({ ...@@ -444,6 +455,7 @@ Polymer({
/** @private */ /** @private */
onCancelClick_() { onCancelClick_() {
assert(this.appState_ === AppState.SCANNING); assert(this.appState_ === AppState.SCANNING);
this.setAppState_(AppState.CANCELING);
this.scanService_.cancelScan(); this.scanService_.cancelScan();
}, },
...@@ -480,13 +492,21 @@ Polymer({ ...@@ -480,13 +492,21 @@ Polymer({
assert( assert(
this.appState_ === AppState.GETTING_CAPS || this.appState_ === AppState.GETTING_CAPS ||
this.appState_ === AppState.SCANNING || this.appState_ === AppState.SCANNING ||
this.appState_ === AppState.DONE); this.appState_ === AppState.DONE ||
this.appState_ === AppState.CANCELING);
this.clearObjectUrls_(); this.clearObjectUrls_();
break; break;
case (AppState.SCANNING): case (AppState.SCANNING):
assert(this.appState_ === AppState.READY); assert(
this.appState_ === AppState.READY ||
this.appState_ === AppState.CANCELING);
break; break;
case (AppState.DONE): case (AppState.DONE):
assert(
this.appState_ === AppState.SCANNING ||
this.appState_ === AppState.CANCELING);
break;
case (AppState.CANCELING):
assert(this.appState_ === AppState.SCANNING); assert(this.appState_ === AppState.SCANNING);
break; break;
} }
...@@ -498,7 +518,9 @@ Polymer({ ...@@ -498,7 +518,9 @@ Polymer({
onAppStateChange_() { onAppStateChange_() {
this.scannersLoaded_ = this.appState_ !== AppState.GETTING_SCANNERS; this.scannersLoaded_ = this.appState_ !== AppState.GETTING_SCANNERS;
this.settingsDisabled_ = this.appState_ !== AppState.READY; this.settingsDisabled_ = this.appState_ !== AppState.READY;
this.showCancelButton_ = this.appState_ === AppState.SCANNING; this.showCancelButton_ = this.appState_ === AppState.SCANNING ||
this.appState_ === AppState.CANCELING;
this.cancelButtonDisabled_ = this.appState_ === AppState.CANCELING;
this.showDoneSection_ = this.appState_ === AppState.DONE; this.showDoneSection_ = this.appState_ === AppState.DONE;
}, },
......
...@@ -13,6 +13,7 @@ export const AppState = { ...@@ -13,6 +13,7 @@ export const AppState = {
READY: 3, READY: 3,
SCANNING: 4, SCANNING: 4,
DONE: 5, DONE: 5,
CANCELING: 6,
}; };
/** /**
......
...@@ -57,6 +57,7 @@ void AddScanningAppStrings(content::WebUIDataSource* html_source) { ...@@ -57,6 +57,7 @@ void AddScanningAppStrings(content::WebUIDataSource* html_source) {
{"blackAndWhiteOptionText", IDS_SCANNING_APP_BLACK_AND_WHITE_OPTION_TEXT}, {"blackAndWhiteOptionText", IDS_SCANNING_APP_BLACK_AND_WHITE_OPTION_TEXT},
{"cancelButtonText", IDS_SCANNING_APP_CANCEL_BUTTON_TEXT}, {"cancelButtonText", IDS_SCANNING_APP_CANCEL_BUTTON_TEXT},
{"cancelFailedToastText", IDS_SCANNING_APP_CANCEL_FAILED_TOAST_TEXT}, {"cancelFailedToastText", IDS_SCANNING_APP_CANCEL_FAILED_TOAST_TEXT},
{"cancelingScanningText", IDS_SCANNING_APP_CANCELING_SCANNING_TEXT},
{"colorModeDropdownLabel", IDS_SCANNING_APP_COLOR_MODE_DROPDOWN_LABEL}, {"colorModeDropdownLabel", IDS_SCANNING_APP_COLOR_MODE_DROPDOWN_LABEL},
{"colorOptionText", IDS_SCANNING_APP_COLOR_OPTION_TEXT}, {"colorOptionText", IDS_SCANNING_APP_COLOR_OPTION_TEXT},
{"defaultSourceOptionText", IDS_SCANNING_APP_DEFAULT_SOURCE_OPTION_TEXT}, {"defaultSourceOptionText", IDS_SCANNING_APP_DEFAULT_SOURCE_OPTION_TEXT},
......
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