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

Unified Diff: chrome/browser/resources/file_manager/foreground/js/progress_center_item_group.js

Issue 127763002: Files.app: Make ProgressCenterItemGroup class to manage the states of items. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove an unused member. Created 6 years, 11 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
Index: chrome/browser/resources/file_manager/foreground/js/progress_center_item_group.js
diff --git a/chrome/browser/resources/file_manager/foreground/js/progress_center_item_group.js b/chrome/browser/resources/file_manager/foreground/js/progress_center_item_group.js
new file mode 100644
index 0000000000000000000000000000000000000000..a178ba7458fb20042047b8b99da3ca4cdcf8e174
--- /dev/null
+++ b/chrome/browser/resources/file_manager/foreground/js/progress_center_item_group.js
@@ -0,0 +1,414 @@
+// Copyright 2013 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.
+
+'use strict';
+
+/**
+ * Group of progress item in the progress center panels.
+ *
+ * This is responsible for generating the summarized item and managing lifetime
+ * of error items.
+ * @param {string} name Name of the group.
+ * @constructor
+ */
+function ProgressCenterItemGroup(name) {
+ /**
+ * Name of the group.
+ * @type {string}
+ */
+ this.name = name;
+
+ /**
+ * State of the group.
+ * @type {ProgressCenterItemGroup.State}
+ * @private
+ */
+ this.state_ = ProgressCenterItemGroup.State.EMPTY;
+
+ /**
+ * Items that are progressing, or completed but still animated.
+ * Key is item ID.
+ * @type {Object.<string, ProgressCenterItem>}
+ * @private
+ */
+ this.items_ = {};
+
+ /**
+ * Set of animated state of items. Key is item ID and value is whether the
+ * item is animated or not.
+ * @type {Object.<string, boolean>}
+ * @private
+ */
+ this.animated_ = {};
+
+ /**
+ * Last summarized item.
+ * @type {ProgressCenterItem}
+ * @private
+ */
+ this.summarizedItem_ = null;
+
+ /**
+ * Whether the summarized item is animated or not.
+ * @type {boolean}
+ * @private
+ */
+ this.summarizedItemAnimated_ = false;
+
+ /**
+ * Total maximum progress value of items already completed and removed from
+ * this.items_.
+ * @type {number}
+ * @private
+ */
+ this.totalProgressMax_ = 0;
+
+ /**
+ * Total progress value of items already completed and removed from
+ * this.items_.
+ * @type {number}
+ * @private
+ */
+ this.totalProgressValue_ = 0;
+
+ Object.seal(this);
+}
+
+/**
+ * State of ProgressCenterItemGroup.
+ * @enum {string}
+ * @const
+ */
+ProgressCenterItemGroup.State = Object.freeze({
+ // Group has no items.
+ EMPTY: 'empty',
+ // Group has at least 1 progressing item.
+ ACTIVE: 'active',
+ // Group has no progressing items but still shows error items.
+ INACTIVE: 'inactive'
+});
+
+/**
+ * Makes the summarized item for the groups.
+ *
+ * When a group has only error items, getSummarizedItem of the item returns
+ * null. Basically the first result of the groups that the progress center panel
+ * contains is used as a summarized item. But If all the group returns null, the
+ * progress center panel generates the summarized item by using the method.
+ *
+ * @param {Array.<ProgressCenterItemGroup>} var_groups List of groups.
+ * @return {ProgressCenterItem} Summarized item.
+ */
+ProgressCenterItemGroup.getSummarizedErrorItem = function(var_groups) {
+ var groups = Array.prototype.slice.call(arguments);
+ var errorItems = [];
+ for (var i = 0; i < groups.length; i++) {
+ for (var id in groups[i].items_) {
+ var item = groups[i].items_[id];
+ if (item.state === ProgressItemState.ERROR)
+ errorItems.push(item);
+ }
+ }
+ if (errorItems.length === 0)
+ return null;
+
+ if (errorItems.length === 1)
+ return errorItems[0].clone();
+
+ var item = new ProgressCenterItem();
+ item.state = ProgressItemState.ERROR;
+ item.message = strf('ERROR_PROGRESS_SUMMARY_PLURAL',
+ errorItems.length);
+ return item;
+};
+
+/**
+ * Obtains Whether the item should be animated or not.
+ * @param {boolean} previousAnimated Whether the item is previously animated or
+ * not.
+ * @param {ProgressCenterItem} previousItem Item before updating.
+ * @param {ProgressCenterItem} item New item.
+ * @return {boolean} Whether the item should be animated or not.
+ * @private
+ */
+ProgressCenterItemGroup.shouldAnimate_ = function(
+ previousAnimated, previousItem, item) {
+ if (!previousItem)
+ return false;
+ if (!item)
+ return false;
+ if (previousItem.progressRateInPercent < item.progressRateInPercent)
+ return true;
+ if (previousAnimated &&
+ previousItem.progressRateInPercent === item.progressRateInPercent)
+ return true;
+ return false;
+};
+
+ProgressCenterItemGroup.prototype = {
+ /**
+ * @return {ProgressCenterItemGroup.State} State of the group.
+ */
+ get state() {
+ return this.state_;
+ },
+
+ /**
+ * @return {number} Number of error items that the group contains.
+ */
+ get numErrors() {
+ var result = 0;
+ for (var id in this.items_) {
+ if (this.items_[id].state === ProgressItemState.ERROR)
+ result++;
+ }
+ return result;
+ }
+};
+
+/**
+ * Obtains the progressing (or completed but animated) item.
+ *
+ * @param {string} id Item ID.
+ * @return {ProgressCenterItem} Item having the ID.
+ */
+ProgressCenterItemGroup.prototype.getItem = function(id) {
+ return this.items_[id] || null;
+};
+
+/**
+ * Obtains whether the item should be animated or not.
+ * @param {string} id Item ID.
+ * @return {boolean} Whether the item should be animated or not.
+ */
+ProgressCenterItemGroup.prototype.isAnimated = function(id) {
+ return !!this.animated_[id];
+};
+
+/**
+ * Obtains whether the summarized item should be animated or not.
+ * @return {boolean} Whether the summarized item should be animated or not.
+ */
+ProgressCenterItemGroup.prototype.isSummarizedAnimated = function() {
+ return this.summarizedItemAnimated_;
+};
+
+/**
+ * Starts item update.
+ * Marks the given item as updating.
+ * @param {ProgressCenterItem} item Item containing updated information.
+ */
+ProgressCenterItemGroup.prototype.update = function(item) {
+ // If the group is inactive, go back to the empty state.
+ this.endInactive();
+
+ // Compares the current state and the new state to check if the update is
+ // valid or not.
+ var previousItem = this.items_[item.id];
+ switch (item.state) {
+ case ProgressItemState.ERROR:
+ if (previousItem && previousItem.state !== ProgressItemState.PROGRESSING)
+ return;
+ if (this.state_ === ProgressCenterItemGroup.State.EMPTY)
+ this.state_ = ProgressCenterItemGroup.State.INACTIVE;
+ this.items_[item.id] = item.clone();
+ this.animated_[item.id] = false;
+ break;
+
+ case ProgressItemState.PROGRESSING:
+ case ProgressItemState.COMPLETED:
+ if ((!previousItem && item.state === ProgressItemState.COMPLETED) ||
+ (previousItem &&
+ previousItem.state !== ProgressItemState.PROGRESSING))
+ return;
+ if (this.state_ === ProgressCenterItemGroup.State.EMPTY)
+ this.state_ = ProgressCenterItemGroup.State.ACTIVE;
+ this.items_[item.id] = item.clone();
+ this.animated_[item.id] = ProgressCenterItemGroup.shouldAnimate_(
+ !!this.animated_[item.id],
+ previousItem,
+ item);
+ if (!this.animated_[item.id])
+ this.completeItemAnimation(item.id);
+ break;
+
+ case ProgressItemState.CANCELED:
+ if (!previousItem ||
+ previousItem.state !== ProgressItemState.PROGRESSING)
+ return;
+ delete this.items_[item.id];
+ this.animated_[item.id] = false;
+ this.summarizedItem_ = null;
+ }
+
+ // Update the internal summarized item cache.
+ var previousSummarizedItem = this.summarizedItem_;
+ this.summarizedItem_ = this.getSummarizedItem(0);
+ this.summarizedItemAnimated_ = ProgressCenterItemGroup.shouldAnimate_(
+ !!this.summarizedItemAnimated_,
+ previousSummarizedItem,
+ this.summarizedItem_);
+ if (!this.summarizedItemAnimated_)
+ this.completeSummarizedItemAnimation();
+};
+
+/**
+ * Notifies the end of the item's animation to the group.
+ * If all the items except error items completes, the group enter the inactive
+ * state.
+ * @param {string} id Item ID.
+ */
+ProgressCenterItemGroup.prototype.completeItemAnimation = function(id) {
+ if (this.state_ !== ProgressCenterItemGroup.State.ACTIVE)
+ return;
+
+ this.animated_[id] = false;
+ if (this.items_[id].state === ProgressItemState.COMPLETED) {
+ this.totalProgressValue_ += (this.items_[id].progressValue || 0.0);
+ this.totalProgressMax_ += (this.items_[id].progressMax || 0.0);
+ delete this.items_[id];
+ this.tryEndActive_();
+ }
+};
+
+/**
+ * Notifies the end of the summarized item's animation.
+ * This may update summarized view. (1 progressing + 1 error -> 1 error)
+ */
+ProgressCenterItemGroup.prototype.completeSummarizedItemAnimation = function() {
+ this.summarizedItemAnimated_ = false;
+ this.tryEndActive_();
+};
+
+/**
+ * Obtains the summary of the set.
+ * @param {number} numOtherErrors Number of errors contained by other groups.
+ * @return {ProgressCenterItem} Item.
+ */
+ProgressCenterItemGroup.prototype.getSummarizedItem =
+ function(numOtherErrors) {
+ if (this.state_ === ProgressCenterItemGroup.State.EMPTY ||
+ this.state_ === ProgressCenterItemGroup.State.INACTIVE)
+ return null;
+
+ var summarizedItem = new ProgressCenterItem();
+ summarizedItem.progressMax += this.totalProgressMax_;
+ summarizedItem.progressValue += this.totalProgressValue_;
+ var progressingItems = [];
+ var errorItems = [];
+ var numItems = 0;
+
+ for (var id in this.items_) {
+ var item = this.items_[id];
+ numItems++;
+
+ // Count states.
+ switch (item.state) {
+ case ProgressItemState.PROGRESSING:
+ case ProgressItemState.COMPLETED:
+ progressingItems.push(item);
+ break;
+ case ProgressItemState.ERROR:
+ errorItems.push(item);
+ continue;
+ }
+
+ // If all of the progressing items have the same type, then use
+ // it. Otherwise use TRANSFER, since it is the most generic.
+ if (summarizedItem.type === null)
+ summarizedItem.type = item.type;
+ else if (summarizedItem.type !== item.type)
+ summarizedItem.type = ProgressItemType.TRANSFER;
+
+ // Sum up the progress values.
+ summarizedItem.progressMax += item.progressMax;
+ summarizedItem.progressValue += item.progressValue;
+ }
+
+ // Returns 1 item.
+ if (progressingItems.length === 1 &&
+ errorItems.length + numOtherErrors === 0) {
+ summarizedItem.id = progressingItems[0].id;
+ summarizedItem.cancelCallback = progressingItems[0].cancelCallback;
+ summarizedItem.message = progressingItems[0].message;
+ summarizedItem.state = progressingItems[0].state;
+ return summarizedItem;
+ }
+
+ // Returns integrated items.
+ if (progressingItems.length > 0) {
+ var messages = [];
+ switch (summarizedItem.type) {
+ case ProgressItemType.COPY:
+ messages.push(str('COPY_PROGRESS_SUMMARY'));
+ break;
+ case ProgressItemType.MOVE:
+ messages.push(str('MOVE_PROGRESS_SUMMARY'));
+ break;
+ case ProgressItemType.DELETE:
+ messages.push(str('DELETE_PROGRESS_SUMMARY'));
+ break;
+ case ProgressItemType.ZIP:
+ messages.push(str('ZIP_PROGRESS_SUMMARY'));
+ break;
+ case ProgressItemType.TRANSFER:
+ messages.push(str('TRANSFER_PROGRESS_SUMMARY'));
+ break;
+ }
+ var numErrors = errorItems.length + numOtherErrors;
+ if (numErrors === 1)
+ messages.push(str('ERROR_PROGRESS_SUMMARY'));
+ else if (numErrors > 1)
+ messages.push(strf('ERROR_PROGRESS_SUMMARY_PLURAL', numErrors));
+ summarizedItem.summarized = true;
+ summarizedItem.message = messages.join(' ');
+ summarizedItem.state = ProgressItemState.PROGRESSING;
+ return summarizedItem;
+ }
+
+ // Retruns error.
+ if (errorItems.length > 0)
+ return null;
+
+ // Returns complete items.
+ summarizedItem.state = ProgressItemState.COMPLETED;
+ return summarizedItem;
+};
+
+/**
+ * Goes back to the EMPTY state from the INACTIVE state. Removes all the items.
+ * If the current state is not the INACTIVE, nothing happens.
+ */
+ProgressCenterItemGroup.prototype.endInactive = function() {
+ if (this.state_ !== ProgressCenterItemGroup.State.INACTIVE)
+ return;
+ this.items_ = {};
+ this.animated_ = {};
+ this.summarizedItem_ = null;
+ this.summarizedItemAnimated_ = false;
+ this.totalProgressValue_ = 0.0;
+ this.totalProgressMax_ = 0.0;
+ this.state_ = ProgressCenterItemGroup.State.EMPTY;
+};
+
+/**
+ * Ends active state if there is no progressing and animated items.
+ * @private
+ */
+ProgressCenterItemGroup.prototype.tryEndActive_ = function() {
+ if (this.state_ !== ProgressCenterItemGroup.State.ACTIVE ||
+ this.summarizedItemAnimated_)
+ return;
+ var hasError = false;
+ for (var id in this.items_) {
+ // If there is non-error item (progressing, or completed but still
+ // animated), we should stay the active state.
+ if (this.items_[id].state !== ProgressItemState.ERROR)
+ return;
+ hasError = true;
+ }
+ this.state_ = ProgressCenterItemGroup.State.INACTIVE;
+ if (!hasError)
+ this.endInactive();
+};

Powered by Google App Engine
This is Rietveld 408576698