| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| const FilesQuickView = Polymer({ |
| is: 'files-quick-view', |
| |
| properties: { |
| // File media type, e.g. image, video. |
| type: String, |
| subtype: String, |
| filePath: String, |
| |
| // True if there is a file task that can open the file type. |
| hasTask: Boolean, |
| |
| // URLs should be accessible from the <webview> since their content is |
| // rendered inside the <wevbiew>. Hint: use URL.createObjectURL. |
| contentUrl: String, |
| videoPoster: String, |
| audioArtwork: String, |
| |
| // Autoplay property for audio, video. |
| autoplay: Boolean, |
| |
| // True if this file is not image, audio, video nor HTML but is supported |
| // by Chrome - content that is directly preview-able in Chrome by setting |
| // the <webview> src attribute. Examples: pdf, text. |
| browsable: Boolean, |
| |
| // The metadata-box-active-changed event is fired on attribute change. |
| metadataBoxActive: { |
| value: true, |
| type: Boolean, |
| notify: true, |
| }, |
| |
| // Text shown when there is no playback/preview available. |
| noPlaybackText: String, |
| noPreviewText: String, |
| |
| /** |
| * True if the Files app window is a dialog, e.g. save-as or open-with. |
| * @type {boolean} |
| */ |
| isModal: Boolean, |
| }, |
| |
| listeners: { |
| 'files-safe-media-tap-outside': 'close', |
| }, |
| |
| /** |
| * Apply custom CSS to autogenerated webview content. |
| * |
| * @param {!Event} e |
| */ |
| applyTextCss: function(e) { |
| // Don't override the Chrome PDF viewer's CSS: crbug.com/1001034. |
| if (this.subtype === 'PDF') { |
| return; |
| } |
| |
| const webview = /** @type {WebView} */ (e.target); |
| webview.insertCSS({ |
| 'file': 'foreground/elements/files_safe_text_webview_content.css', |
| }); |
| }, |
| |
| // Clears fields. |
| clear: function() { |
| this.setProperties({ |
| type: '', |
| subtype: '', |
| filePath: '', |
| hasTask: false, |
| contentUrl: '', |
| videoPoster: '', |
| audioArtwork: '', |
| autoplay: false, |
| browsable: false, |
| }); |
| const video = this.$.contentPanel.querySelector('#videoSafeMedia'); |
| if (video) { |
| video.src = ''; |
| video.fire('src-changed'); |
| } |
| }, |
| |
| /** @return {boolean} */ |
| isOpened: function() { |
| return this.$.dialog.open; |
| }, |
| |
| // Opens the dialog. |
| open: function() { |
| if (!this.isOpened()) { |
| this.$.dialog.showModal(); |
| // Make dialog focusable and set focus to a dialog. This is how we can |
| // prevent default behaviour of a dialog which by default sets focus to |
| // the first input inside itself. When a dialog gains focus we remove |
| // focusability to prevent selecting dialog when moving with a keyboard. |
| this.$.dialog.setAttribute('tabindex', '0'); |
| this.$.dialog.focus(); |
| this.$.dialog.setAttribute('tabindex', '-1'); |
| } |
| }, |
| |
| // Closes the dialog. |
| close: function() { |
| if (this.isOpened()) { |
| this.$.dialog.close(); |
| } |
| }, |
| |
| /** |
| * @return {!FilesMetadataBox} |
| */ |
| getFilesMetadataBox: function() { |
| return this.$['metadata-box']; |
| }, |
| |
| /** |
| * Client should assign the function to open the file. |
| * |
| * @param {!Event} event |
| */ |
| onOpenInNewButtonTap: function(event) {}, |
| |
| /** |
| * @param {boolean} hasTask |
| * @param {boolean} isModal |
| * @return {boolean} |
| * |
| * @private |
| */ |
| shouldShowOpenButton_: function(hasTask, isModal) { |
| return hasTask && !isModal; |
| }, |
| |
| /** |
| * @param {!Event} event tap event. |
| * |
| * @private |
| */ |
| onMetadataButtonTap_: function(event) { |
| // Set focus back to innerContent panel so that pressing space key next |
| // closes Quick View. |
| this.$.innerContentPanel.focus(); |
| }, |
| |
| /** |
| * Close Quick View unless the clicked target or its ancestor contains |
| * 'no-close-on-click' class. |
| * |
| * @param {!Event} event tap event. |
| * |
| * @private |
| */ |
| onContentPanelTap_: function(event) { |
| let target = event.detail.sourceEvent.target; |
| while (target) { |
| if (target.classList.contains('no-close-on-click')) { |
| return; |
| } |
| target = target.parentElement; |
| } |
| this.close(); |
| }, |
| |
| /** |
| * @param {string} type |
| * @param {string} subtype |
| * @return {boolean} |
| * |
| * @private |
| */ |
| isHtml_: function(type, subtype) { |
| return type === 'document' && subtype === 'HTML'; |
| }, |
| |
| /** |
| * @param {string} type |
| * @return {boolean} |
| * |
| * @private |
| */ |
| isImage_: function(type) { |
| return type === 'image'; |
| }, |
| |
| /** |
| * @param {string} type |
| * @return {boolean} |
| * |
| * @private |
| */ |
| isVideo_: function(type) { |
| return type === 'video'; |
| }, |
| |
| /** |
| * @param {string} type |
| * @return {boolean} |
| * |
| * @private |
| */ |
| isAudio_: function(type) { |
| return type === 'audio'; |
| }, |
| |
| /** |
| * @param {string} contentUrl |
| * @param {string} type |
| * @return {string} |
| * |
| * @private |
| */ |
| audioUrl_: function(contentUrl, type) { |
| return this.isAudio_(type) ? contentUrl : ''; |
| }, |
| |
| /** |
| * @param {string} type |
| * @return {boolean} |
| * |
| * @private |
| */ |
| isUnsupported_: function(type, subtype, browsable) { |
| return !this.isImage_(type) && !this.isVideo_(type) && |
| !this.isAudio_(type) && !this.isHtml_(type, subtype) && !browsable; |
| }, |
| |
| /** @private */ |
| onDialogClose_: function(e) { |
| assert(e.target === this.$.dialog); |
| |
| this.clear(); |
| |
| // Catch and re-fire the 'close' event such that it bubbles across Shadow |
| // DOM v1. |
| this.fire('close'); |
| } |
| }); |