Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(559)

Unified Diff: ui/file_manager/file_manager/foreground/js/ui/single_file_details.js

Issue 1789593002: Files app: Loading detailed information for single file. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/file_manager/file_manager/foreground/js/ui/file_table.js ('k') | ui/file_manager/file_manager/main.html » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/file_manager/file_manager/foreground/js/ui/single_file_details.js
diff --git a/ui/file_manager/file_manager/foreground/js/ui/single_file_details.js b/ui/file_manager/file_manager/foreground/js/ui/single_file_details.js
index 5329e1c3325c27da73d146a9bf5a3ee79ed93d01..6a191a82962f9be7d8da695988d0172de115febe 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/single_file_details.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/single_file_details.js
@@ -20,111 +20,299 @@ function SingleFileDetailsPanel() {
SingleFileDetailsPanel.prototype = {
__proto__: HTMLDivElement.prototype,
onFileSelectionChanged: function(entry) {
+ this.setFileName_(entry);
+ this.setGenericThumbnail_(entry);
+ this.loadMetadata_(entry);
+ },
+
+ /**
+ * Display filename for the filename.
+ * @param {!FileEntry} entry
+ * @private
+ */
+ setFileName_: function(entry) {
+ this.filenameIcon_.setAttribute('file-type-icon', FileType.getIcon(entry));
this.filename_.textContent = entry.name;
- }
-};
+ },
-/**
- * Decorates an HTML element to be a SingleFileDetailsList.
- * @param {!HTMLDivElement} self The grid to decorate.
- * @param {!MetadataModel} metadataModel File system metadata.
- */
-SingleFileDetailsPanel.decorate = function(self, metadataModel) {
- self.__proto__ = SingleFileDetailsPanel.prototype;
- self.metadataModel = metadataModel;
/**
- * Data model of detail infos.
- * @private {!SingleFileDetailsDataModel}
- * @const
+ * Display generic thumbnail for the entry.
+ * @param {!FileEntry} entry
+ * @private
*/
- self.model_ = new SingleFileDetailsDataModel();
- self.filename_ = assertInstanceof(queryRequiredElement('.filename', self),
- HTMLDivElement);
- var list = queryRequiredElement('.details-list', self);
- SingleFileDetailsList.decorate(list, metadataModel);
- self.list_ = assertInstanceof(list, SingleFileDetailsList);
- self.list_.dataModel = self.model_;
- self.list_.autoExpands = true;
-};
+ setGenericThumbnail_: function(entry) {
+ if (entry.isDirectory) {
+ this.thumbnail_.setAttribute('generic-thumbnail', 'folder');
+ } else {
+ var mediaType = FileType.getMediaType(entry);
+ this.thumbnail_.setAttribute('generic-thumbnail', mediaType);
+ }
+ },
-/**
- * SingleFileDetailsList constructor.
- *
- * Represents grid for the details list for a single file in Files app.
- * @constructor
- * @extends {cr.ui.List}
- */
-function SingleFileDetailsList() {
- throw new Error('Use SingleFileDetailsList.decorate');
-}
+ /**
+ * Load metadata for the entry.
+ * @param {!FileEntry} entry
+ * @private
+ */
+ loadMetadata_: function(entry) {
+ this.ticket_++;
+ var ticket = this.ticket_;
+ this.thumbnail_.innerHTML = '';
+ this.preview_ = null;
+ this.thumbnail_.classList.toggle('loaded', false);
+ this.metadataModel_.get([entry], SingleFileDetailsPanel.LOADING_ITEMS)
+ .then(this.onMetadataLoaded_.bind(this, ticket, entry));
+ },
-/**
- * Inherits from cr.ui.List.
- */
-SingleFileDetailsList.prototype = {
- __proto__: cr.ui.List.prototype,
- onFileSelectionChanged: function(entry) {
- console.log(entry);
- }
-};
+ /**
+ * Called when a metadata is fetched.
+ * @param {number} ticket Ticket number.
+ * @param {!FileEntry} entry
+ * @param {!Array<!MetadataItem>} items metadata items
+ * @private
+ */
+ onMetadataLoaded_: function(ticket, entry, items) {
+ if (this.ticket_ !== ticket) {
+ return;
+ }
+ var item = items[0];
+ this.setPreview_(ticket, entry, item);
+ this.setDetails_(entry, item);
+ },
-/**
- * Decorates an HTML element to be a SingleFileDetailsList.
- * @param {!Element} self The grid to decorate.
- * @param {!MetadataModel} metadataModel File system metadata.
- */
-SingleFileDetailsList.decorate = function(self, metadataModel) {
- cr.ui.Grid.decorate(self);
- self.__proto__ = SingleFileDetailsList.prototype;
- self.metadataModel_ = metadataModel;
+ /**
+ * Display preview for the file entry.
+ * @param {number} ticket Ticket number.
+ * @param {!FileEntry} entry
+ * @param {!MetadataItem} item metadata
+ * @private
+ */
+ setPreview_: function(ticket, entry, item) {
+ var type = FileType.getType(entry);
+ var thumbnailUrl = item.thumbnailUrl || item.croppedThumbnailUrl;
+ if (type.type === 'image') {
+ if (item.externalFileUrl) {
+ // it's in Google Drive. Use ImageLoader.
+ if (item.thumbnailUrl) {
+ this.loadThumbnailFromDrive_(item.thumbnailUrl,
+ function (result) {
+ if (ticket !== this.ticket_) {
+ return;
+ }
+ if (result.status !== 'success') {
+ return;
+ }
+ var url = result.data;
+ var img = document.createElement('img');
+ this.thumbnail_.appendChild(img);
+ img.src = url;
+ this.thumbnail_.classList.toggle('loaded', true);
+ }.bind(this));
+ }
+ } else {
+ var img = document.createElement('img');
+ this.thumbnail_.appendChild(img);
+ img.src = thumbnailUrl || entry.toURL();
+ this.thumbnail_.classList.toggle('loaded', true);
+ }
+ } else if (type.type === 'video') {
+ var video = document.createElement('video');
+ video.controls = true;
+ this.thumbnail_.appendChild(video);
+ this.thumbnail_.classList.toggle('loaded', true);
+ video.src = entry.toURL();
+ if (item.externalFileUrl) {
+ // it's in google drive.
+ if (item.thumbnailUrl) {
+ this.loadThumbnailFromDrive_(item.thumbnailUrl,
+ function (result) {
+ if (ticket !== this.ticket_) {
+ return;
+ }
+ if (result.status !== 'success') {
+ return;
+ }
+ video.poster = result.data;
+ }.bind(this));
+ }
+ }else if (thumbnailUrl) {
+ video.poster = thumbnailUrl;
+ }
+ this.preview_ = video;
+ } else if (type.type === 'audio') {
+ if (item.externalFileUrl) {
+ // it's in google drive.
+ if (item.thumbnailUrl) {
+ this.loadThumbnailFromDrive_(item.thumbnailUrl,
+ function (result) {
+ if (ticket !== this.ticket_) {
+ return;
+ }
+ if (result.status !== 'success') {
+ return;
+ }
+ var url = result.data;
+ var img = document.createElement('img');
+ this.thumbnail_.appendChild(img);
+ img.src = url;
+ this.thumbnail_.classList.toggle('loaded', true);
+ }.bind(this));
+ }
+ } else {
+ this.loadContentMetadata_(entry, function(entry, items) {
+ if (ticket !== this.ticket_) {
+ return;
+ }
+ var item = items[0];
+ if (!item.contentThumbnailUrl) {
+ return;
+ }
+ var img = document.createElement('img');
+ this.thumbnail_.appendChild(img);
+ img.src = item.externalFileUrl;
+ this.thumbnail_.classList.toggle('loaded', true);
+ }.bind(this));
+ }
+ var audio = document.createElement('audio');
+ audio.controls = true;
+ this.thumbnail_.appendChild(audio);
+ audio.src = entry.toURL();
+ this.preview_ = audio;
+ }
+ },
- self.scrollBar_ = new ScrollBar();
- self.scrollBar_.initialize(self.parentElement, self);
+ /**
+ * Load content metadata
+ * @param {!FileEntry} entry
+ * @param {function(!FileEntry, !Array<!MetadataItem>)} callback
+ * @private
+ */
+ loadContentMetadata_: function(entry, callback) {
+ this.metadataModel_.get([entry], SingleFileDetailsPanel.CONTENT_ITEMS)
+ .then(callback.bind(null, entry));
+ },
+
+ /**
+ * Load thumbnails from Drive.
+ * @param {string} url Thumbnail url
+ * @param {function({status: string, data:string, width:number,
+ * height:number})} callback
+ * @private
+ */
+ loadThumbnailFromDrive_: function (url, callback) {
+ ImageLoaderClient.getInstance().load(url, callback);
+ },
- self.itemConstructor = function(entry) {
- var item = self.ownerDocument.createElement('li');
- SingleFileDetailsList.Item.decorate(
- item,
- entry,
- /** @type {FileGrid} */ (self));
- return item;
- };
+ /**
+ * Display detailed information from metadata item.
+ * @param {!FileEntry} entry
+ * @param {!MetadataItem} item metadata
+ * @private
+ */
+ setDetails_: function(entry, item) {
+ var elem;
+ // Modification Time
+ elem = queryRequiredElement('.modification-time', this.list_);
+ if (item.modificationTime) {
+ elem.classList.toggle('available', true);
+ queryRequiredElement('.content', elem).textContent =
+ this.formatter_.formatModDate(item.modificationTime);
+ } else {
+ elem.classList.toggle('available', false);
+ }
+ // Filesize
+ elem = queryRequiredElement('.file-size', this.list_);
+ if (item.size) {
+ elem.classList.toggle('available', true);
+ queryRequiredElement('.content', elem).textContent =
+ this.formatter_.formatSize(item.size, item.hosted);
+ } else {
+ elem.classList.toggle('available', false);
+ }
+ // TODO(ryoh): Display more and more details...
+ },
+ /**
+ * Called when visibility of this panel is changed.
+ * @param {boolean} visibility True if the details panel is visible.
+ */
+ onVisibilityChanged: function(visibility) {
+ if (!visibility) {
+ if (this.preview_) {
+ this.preview_.pause();
+ }
+ }
+ }
};
/**
- * Item for the Grid View.
- * @constructor
- * @extends {cr.ui.ListItem}
+ * Metadata items to display in details panel.
+ * @const
*/
-SingleFileDetailsList.Item = function() {
- throw new Error();
-};
+SingleFileDetailsPanel.LOADING_ITEMS = [
+ 'availableOffline',
+ 'availableWhenMetered',
+ 'croppedThumbnailUrl',
+ 'customIconUrl',
+ 'dirty',
+ 'externalFileUrl',
+ 'hosted',
+ 'imageHeight',
+ 'imageRotation',
+ 'imageWidth',
+ 'mediaArtist',
+ 'mediaMimeType',
+ 'mediaTitle',
+ 'modificationTime',
+ 'pinned',
+ 'present',
+ 'shared',
+ 'sharedWithMe',
+ 'size',
+ 'thumbnailUrl'
+];
/**
- * Inherits from cr.ui.DetailsItem.
+ * Metadata items to display content metadatas in details panel.
+ * @const
*/
-SingleFileDetailsList.Item.prototype.__proto__ = cr.ui.ListItem.prototype;
+SingleFileDetailsPanel.CONTENT_ITEMS = [
+ 'contentThumbnailUrl'
+];
/**
- * @param {Element} li List item element.
- * @param {!Entry} entry File entry.
- * @param {FileGrid} grid Owner.
+ * Decorates an HTML element to be a SingleFileDetailsList.
+ * @param {!HTMLDivElement} self The grid to decorate.
+ * @param {!MetadataModel} metadataModel File system metadata.
*/
-SingleFileDetailsList.Item.decorate = function(li, entry, grid) {
- li.__proto__ = SingleFileDetailsList.Item.prototype;
+SingleFileDetailsPanel.decorate = function(self, metadataModel) {
+ self.__proto__ = SingleFileDetailsPanel.prototype;
+ self.metadataModel_ = metadataModel;
+ self.formatter_ = new FileMetadataFormatter();
+ self.filename_ = assertInstanceof(queryRequiredElement('.filename', self),
+ HTMLDivElement);
+ self.filenameIcon_ = assertInstanceof(
+ queryRequiredElement('.filename-icon', self), HTMLDivElement);
+ self.thumbnail_ = assertInstanceof(
+ queryRequiredElement('.thumbnail', self), HTMLDivElement);
+ self.list_ = queryRequiredElement('.details-list', self);
+ /**
+ * Preview element. Video or Audio element.
+ * @private {HTMLMediaElement}
+ */
+ self.preview_ = null;
+ /**
+ * A ticket to display metadata.
+ * It strictly increases as the user selects files.
+ * Only the task that has the latest ticket can update the view.
+ * @private {number}
+ */
+ self.ticket_ = 0;
};
/**
- * Data model for details panel.
- *
- * @constructor
- * @extends {cr.ui.ArrayDataModel}
+ * Sets date and time format.
+ * @param {boolean} use12hourClock True if 12 hours clock, False if 24 hours.
*/
-function SingleFileDetailsDataModel() {
- cr.ui.ArrayDataModel.call(this, []);
-}
-
-SingleFileDetailsDataModel.prototype = {
- __proto__: cr.ui.ArrayDataModel.prototype,
-
+SingleFileDetailsPanel.prototype.setDateTimeFormat = function(use12hourClock) {
+ this.formatter_.setDateTimeFormat(use12hourClock);
};
« no previous file with comments | « ui/file_manager/file_manager/foreground/js/ui/file_table.js ('k') | ui/file_manager/file_manager/main.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698