Commit 5930c965 authored by Gavin Williams's avatar Gavin Williams Committed by Commit Bot

scanning: Add 'Show file location' link to done page

Adds a link button after a successfully scan that calls the
ScanningBrowserProxy to open the Files app. The last page of the scanned
in the scan job will be highlighted.

A follow up CL will use the return value from the call to
showFileInLocation() to show an error-state when Files app fails to
open.

http://screen/BANhubFawHU6oLM

Bug: 1059779
Change-Id: I0368c91393382f5f46ea21dd530801e12a4035cd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2546102
Commit-Queue: Gavin Williams <gavinwill@chromium.org>
Reviewed-by: default avatarZentaro Kavanagh <zentaro@chromium.org>
Cr-Commit-Position: refs/heads/master@{#831155}
parent 3308bd2b
...@@ -4,13 +4,24 @@ ...@@ -4,13 +4,24 @@
import 'chrome://scanning/scan_done_section.js'; import 'chrome://scanning/scan_done_section.js';
import {ScanningBrowserProxyImpl} from 'chrome://scanning/scanning_browser_proxy.js';
import {assertEquals, assertTrue} from '../../chai_assert.js'; import {assertEquals, assertTrue} from '../../chai_assert.js';
import {flushTasks} from '../../test_util.m.js';
import {TestScanningBrowserProxy} from './test_scanning_browser_proxy.js';
export function scanDoneSectionTest() { export function scanDoneSectionTest() {
/** @type {?ScanDoneSectionElement} */ /** @type {?ScanDoneSectionElement} */
let scanDoneSection = null; let scanDoneSection = null;
/** @type {?TestScanningBrowserProxy} */
let scanningBrowserProxy = null;
setup(() => { setup(() => {
scanningBrowserProxy = new TestScanningBrowserProxy();
ScanningBrowserProxyImpl.instance_ = scanningBrowserProxy;
scanDoneSection = /** @type {!ScanDoneSectionElement} */ ( scanDoneSection = /** @type {!ScanDoneSectionElement} */ (
document.createElement('scan-done-section')); document.createElement('scan-done-section'));
assertTrue(!!scanDoneSection); assertTrue(!!scanDoneSection);
...@@ -37,4 +48,14 @@ export function scanDoneSectionTest() { ...@@ -37,4 +48,14 @@ export function scanDoneSectionTest() {
assertEquals( assertEquals(
'Scanned files saved!', scanDoneSection.$.title.textContent.trim()); 'Scanned files saved!', scanDoneSection.$.title.textContent.trim());
}); });
test('showFileLocation', () => {
const lastScannedFilePath = {'path': '/test/path/scan.jpg'};
scanningBrowserProxy.setPathToFile(lastScannedFilePath.path);
scanDoneSection.lastScannedFilePath = lastScannedFilePath;
scanDoneSection.$$('#showFileButton').click();
return flushTasks().then(() => {
assertEquals(1, scanningBrowserProxy.getCallCount('showFileInLocation'));
});
});
} }
...@@ -165,10 +165,11 @@ class FakeScanService { ...@@ -165,10 +165,11 @@ class FakeScanService {
/** /**
* @param {boolean} success * @param {boolean} success
* @param {!mojoBase.mojom.FilePath} lastScannedFilePath
* @return {!Promise} * @return {!Promise}
*/ */
simulateScanComplete(success) { simulateScanComplete(success, lastScannedFilePath) {
this.scanJobObserverRemote_.onScanComplete(success, {'path': ''}); this.scanJobObserverRemote_.onScanComplete(success, lastScannedFilePath);
return flushTasks(); return flushTasks();
} }
...@@ -300,6 +301,9 @@ export function scanningAppTest() { ...@@ -300,6 +301,9 @@ export function scanningAppTest() {
capabilities.set(firstScannerId, firstCapabilities); capabilities.set(firstScannerId, firstCapabilities);
capabilities.set(secondScannerId, secondCapabilities); capabilities.set(secondScannerId, secondCapabilities);
/** @type {!mojoBase.mojom.FilePath} */
const lastScannedFilePath = {'path': '/test/path/scan.jpg'};
/** @type {!HTMLSelectElement} */ /** @type {!HTMLSelectElement} */
let scannerSelect; let scannerSelect;
/** @type {!HTMLSelectElement} */ /** @type {!HTMLSelectElement} */
...@@ -441,7 +445,8 @@ export function scanningAppTest() { ...@@ -441,7 +445,8 @@ export function scanningAppTest() {
}) })
.then(() => { .then(() => {
// Complete the scan. // Complete the scan.
return fakeScanService_.simulateScanComplete(true); return fakeScanService_.simulateScanComplete(
true, lastScannedFilePath);
}) })
.then(() => { .then(() => {
assertTrue(isVisible(scannedImages)); assertTrue(isVisible(scannedImages));
...@@ -449,6 +454,9 @@ export function scanningAppTest() { ...@@ -449,6 +454,9 @@ export function scanningAppTest() {
assertTrue(isVisible( assertTrue(isVisible(
/** @type {!HTMLElement} */ ( /** @type {!HTMLElement} */ (
scanningApp.$$('scan-done-section')))); scanningApp.$$('scan-done-section'))));
assertEquals(
lastScannedFilePath.path,
scanningApp.$$('scan-done-section').lastScannedFilePath.path);
// Click the Done button to return to READY state. // Click the Done button to return to READY state.
return clickDoneButton(); return clickDoneButton();
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
// found in the LICENSE file. // found in the LICENSE file.
import {ScanningBrowserProxy, SelectedPath} from 'chrome://scanning/scanning_browser_proxy.js'; import {ScanningBrowserProxy, SelectedPath} from 'chrome://scanning/scanning_browser_proxy.js';
import {assertEquals} from '../../chai_assert.js';
import {TestBrowserProxy} from '../../test_browser_proxy.m.js'; import {TestBrowserProxy} from '../../test_browser_proxy.m.js';
/** /**
...@@ -14,10 +16,14 @@ export class TestScanningBrowserProxy extends TestBrowserProxy { ...@@ -14,10 +16,14 @@ export class TestScanningBrowserProxy extends TestBrowserProxy {
super([ super([
'initialize', 'initialize',
'requestScanToLocation', 'requestScanToLocation',
'showFileInLocation',
]); ]);
/** @private {?SelectedPath} */ /** @private {?SelectedPath} */
this.selectedPath_ = null; this.selectedPath_ = null;
/** @private {?string} */
this.pathToFile_ = null;
} }
/** @override */ /** @override */
...@@ -34,8 +40,20 @@ export class TestScanningBrowserProxy extends TestBrowserProxy { ...@@ -34,8 +40,20 @@ export class TestScanningBrowserProxy extends TestBrowserProxy {
return Promise.resolve(this.selectedPath_); return Promise.resolve(this.selectedPath_);
} }
/** @param {string} pathToFile */
showFileInLocation(pathToFile) {
this.methodCalled('showFileInLocation');
assertEquals(this.pathToFile_, pathToFile);
return Promise.resolve(true);
}
/** @param {!SelectedPath} selectedPath */ /** @param {!SelectedPath} selectedPath */
setSelectedPath(selectedPath) { setSelectedPath(selectedPath) {
this.selectedPath_ = selectedPath; this.selectedPath_ = selectedPath;
} }
/** @param {string} pathToFile */
setPathToFile(pathToFile) {
this.pathToFile_ = pathToFile;
}
} }
...@@ -573,6 +573,9 @@ Try tapping the mic to ask me anything. ...@@ -573,6 +573,9 @@ Try tapping the mic to ask me anything.
<message name="IDS_SCANNING_APP_CANCEL_BUTTON_TEXT" desc="The text displayed for the button to cancel an ongoing scan job."> <message name="IDS_SCANNING_APP_CANCEL_BUTTON_TEXT" desc="The text displayed for the button to cancel an ongoing scan job.">
Cancel Cancel
</message> </message>
<message name="IDS_SCANNING_APP_SHOW_FILE_LOCATION_LABEL" desc="The label for the button that opens the Files app. The Files app will open with the user's saved scan file highlighted.">
Show file location
</message>
<!-- Diagnostics App --> <!-- Diagnostics App -->
<!-- TODO(michaelcheco): Update with finalized copies of the strings --> <!-- TODO(michaelcheco): Update with finalized copies of the strings -->
......
045d413eba40b73fd7ee46e1db668e9900879f64
\ No newline at end of file
<style include="scanning-fonts"> <style include="scanning-fonts">
.container {
@apply --scanning-done-page-option-font;
color: var(--scanning-done-page-option-text-color);
display: flex;
}
#checkMarkIcon { #checkMarkIcon {
margin-inline-end: 12px; margin-inline-end: 12px;
min-width: 24px; min-width: 24px;
...@@ -17,11 +23,31 @@ ...@@ -17,11 +23,31 @@
color: var(--scanning-done-section-title-text-color); color: var(--scanning-done-section-title-text-color);
display: inline-block; display: inline-block;
} }
.button,
.label {
flex-direction: column;
min-height: 32px;
}
.label {
flex-basis: 222px;
flex-grow: 0;
flex-shrink: 0;
margin-top: 5px;
padding-top: 8px;
}
</style> </style>
<iron-icon id="checkMarkIcon" icon="scanning:check-mark"></iron-icon> <iron-icon id="checkMarkIcon" icon="scanning:check-mark"></iron-icon>
<h1 id="title" > <h1 id="title" >
[[getTitleText_(pageNumber)]] [[getTitleText_(pageNumber)]]
</h1> </h1>
<div class="container">
<span class="label">[[i18n('showFileLocationLabel')]]</span>
<cr-icon-button id="showFileButton" class="button" iron-icon="cr:open-in-new"
on-click="showFileInLocation_">
</cr-icon-button>
</div>
<div class="done-button-container"> <div class="done-button-container">
<cr-button id="doneButton" class="action-button" <cr-button id="doneButton" class="action-button"
on-click="onDoneClick_"> on-click="onDoneClick_">
......
...@@ -3,13 +3,16 @@ ...@@ -3,13 +3,16 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
import './file_path.mojom-lite.js';
import './icons.js'; import './icons.js';
import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {AppState} from './scanning_app_types.js'; import {AppState} from './scanning_app_types.js';
import {ScanningBrowserProxy, ScanningBrowserProxyImpl} from './scanning_browser_proxy.js';
/** /**
* @fileoverview * @fileoverview
...@@ -22,9 +25,21 @@ Polymer({ ...@@ -22,9 +25,21 @@ Polymer({
behaviors: [I18nBehavior], behaviors: [I18nBehavior],
/** @private {?ScanningBrowserProxy}*/
browserProxy_: null,
properties: { properties: {
/** @type {number} */ /** @type {number} */
pageNumber: Number, pageNumber: Number,
/** @type {?mojoBase.mojom.FilePath} */
lastScannedFilePath: Object,
},
/** @override */
created() {
this.browserProxy_ = ScanningBrowserProxyImpl.getInstance();
this.browserProxy_.initialize();
}, },
/** /**
...@@ -40,4 +55,9 @@ Polymer({ ...@@ -40,4 +55,9 @@ Polymer({
onDoneClick_() { onDoneClick_() {
this.fire('done-click'); this.fire('done-click');
}, },
/** @private */
showFileInLocation_() {
this.browserProxy_.showFileInLocation(this.lastScannedFilePath.path);
},
}); });
...@@ -140,7 +140,9 @@ ...@@ -140,7 +140,9 @@
</template> </template>
<template is="dom-if" if="[[showDoneSection_]]"> <template is="dom-if" if="[[showDoneSection_]]">
<scan-done-section page-number="[[pageNumber_]]" <scan-done-section page-number="[[pageNumber_]]"
on-done-click="onDoneClick_"></scan-done-section> on-done-click="onDoneClick_"
last-scanned-file-path="[[lastScannedFilePath_]]">
</scan-done-section>
</template> </template>
</div> </div>
</div> </div>
......
...@@ -28,6 +28,13 @@ export class ScanningBrowserProxy { ...@@ -28,6 +28,13 @@ export class ScanningBrowserProxy {
* @return {!Promise<!SelectedPath>} * @return {!Promise<!SelectedPath>}
*/ */
requestScanToLocation() {} requestScanToLocation() {}
/**
* Opens the Files app with the file |pathToFile| highlighted.
* @param {string} pathToFile
* @return {!Promise<boolean>} True if the file is found and Files app opens.
*/
showFileInLocation(pathToFile) {}
} }
/** @implements {ScanningBrowserProxy} */ /** @implements {ScanningBrowserProxy} */
...@@ -41,6 +48,11 @@ export class ScanningBrowserProxyImpl { ...@@ -41,6 +48,11 @@ export class ScanningBrowserProxyImpl {
requestScanToLocation() { requestScanToLocation() {
return sendWithPromise('requestScanToLocation'); return sendWithPromise('requestScanToLocation');
} }
/** @override */
showFileInLocation(pathToFile) {
return sendWithPromise('showFileInLocation', pathToFile);
}
} }
// The singleton instance_ can be replaced with a test version of this wrapper // The singleton instance_ can be replaced with a test version of this wrapper
......
...@@ -87,6 +87,7 @@ void AddScanningAppStrings(content::WebUIDataSource* html_source) { ...@@ -87,6 +87,7 @@ void AddScanningAppStrings(content::WebUIDataSource* html_source) {
{"scanToDropdownLabel", IDS_SCANNING_APP_SCAN_TO_DROPDOWN_LABEL}, {"scanToDropdownLabel", IDS_SCANNING_APP_SCAN_TO_DROPDOWN_LABEL},
{"scannerDropdownLabel", IDS_SCANNING_APP_SCANNER_DROPDOWN_LABEL}, {"scannerDropdownLabel", IDS_SCANNING_APP_SCANNER_DROPDOWN_LABEL},
{"selectFolderOption", IDS_SCANNING_APP_SELECT_FOLDER_OPTION}, {"selectFolderOption", IDS_SCANNING_APP_SELECT_FOLDER_OPTION},
{"showFileLocationLabel", IDS_SCANNING_APP_SHOW_FILE_LOCATION_LABEL},
{"sourceDropdownLabel", IDS_SCANNING_APP_SOURCE_DROPDOWN_LABEL}, {"sourceDropdownLabel", IDS_SCANNING_APP_SOURCE_DROPDOWN_LABEL},
{"twoSidedDocFeederOptionText", {"twoSidedDocFeederOptionText",
IDS_SCANNING_APP_TWO_SIDED_DOC_FEEDER_OPTION_TEXT}}; IDS_SCANNING_APP_TWO_SIDED_DOC_FEEDER_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