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

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

Issue 2503513003: Show a label to describe some invalid drag-drop operations in Files app. (Closed)
Patch Set: Fix test failure of FileManagerJsTest.DirectoryTreeTest. Created 4 years 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: ui/file_manager/file_manager/foreground/js/file_transfer_controller.js
diff --git a/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js b/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js
index eb9eda879d845f9069816467855d09c0fd684b94..337c5e431c0ee864176401126435b8d5d3728da3 100644
--- a/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js
@@ -187,6 +187,13 @@ function FileTransferController(doc,
this.dropTarget_ = null;
/**
+ * The element for showing a label while dragging files.
+ * @type {Element}
+ * @private
+ */
+ this.dropLabel_ = null;
+
+ /**
* @type {number}
*/
this.navigateTimer_ = 0;
@@ -219,6 +226,15 @@ function FileTransferController(doc,
FileTransferController.DRAG_THUMBNAIL_SIZE_ = 64;
/**
+ * Y coordinate of the label to describe drop action, relative to mouse cursor.
+ *
+ * @type {number}
+ * @const
+ * @private
+ */
+FileTransferController.DRAG_LABEL_Y_OFFSET_ = -32;
+
+/**
* Converts list of urls to list of Entries with granting R/W permissions to
* them, which is essential when pasting files from a different profile.
*
@@ -822,8 +838,22 @@ FileTransferController.prototype.onDragOver_ =
var entry = this.destinationEntry_;
if (!entry && !onlyIntoDirectories)
entry = this.directoryModel_.getCurrentDirEntry();
- event.dataTransfer.dropEffect = this.selectDropEffect_(event, entry);
+ var effectAndLabel = this.selectDropEffect_(event, entry);
+ event.dataTransfer.dropEffect = effectAndLabel.getDropEffect();
event.preventDefault();
+ var label = effectAndLabel.getLabel();
+ if (!this.dropLabel_) {
+ this.dropLabel_ = document.querySelector("div#drop-label");
+ }
+ if (label) {
+ this.dropLabel_.innerText = label;
+ this.dropLabel_.style.left = event.pageX + 'px';
+ this.dropLabel_.style.top =
+ (event.pageY + FileTransferController.DRAG_LABEL_Y_OFFSET_) + 'px';
+ this.dropLabel_.style.display = 'block';
+ } else {
+ this.dropLabel_.style.display = 'none';
+ }
};
/**
@@ -887,6 +917,9 @@ FileTransferController.prototype.onDragLeave_ = function(list, event) {
this.clearDropTarget_();
this.lastEnteredTarget_ = null;
}
+ if (this.dropLabel_) {
+ this.dropLabel_.style.display = 'none';
+ }
};
/**
@@ -906,7 +939,7 @@ FileTransferController.prototype.onDrop_ =
event.preventDefault();
this.paste(event.dataTransfer,
/** @type {DirectoryEntry} */ (destinationEntry),
- this.selectDropEffect_(event, destinationEntry));
+ this.selectDropEffect_(event, destinationEntry).getDropEffect());
this.clearDropTarget_();
};
@@ -929,9 +962,7 @@ FileTransferController.prototype.setDropTarget_ =
// Set the new drop target.
this.dropTarget_ = domElement;
- if (!domElement ||
- !destinationEntry.isDirectory ||
- !this.canPasteOrDrop_(clipboardData, destinationEntry)) {
+ if (!domElement || !destinationEntry.isDirectory) {
return;
}
@@ -1283,35 +1314,50 @@ FileTransferController.prototype.onFileSelectionChangedThrottled_ = function() {
/**
* @param {!Event} event Drag event.
* @param {DirectoryEntry|FakeEntry} destinationEntry Destination entry.
- * @return {string} Returns the appropriate drop query type ('none', 'move'
- * or copy') to the current modifiers status and the destination.
+ * @return {DropEffectAndLabel} Returns the appropriate drop query type
+ * ('none', 'move' or copy') to the current modifiers status and the
+ * destination, as well as label message to describe why the operation is
+ * not allowed.
* @private
*/
FileTransferController.prototype.selectDropEffect_ =
function(event, destinationEntry) {
if (!destinationEntry)
- return 'none';
+ return new DropEffectAndLabel(DropEffectType.NONE, null);
var destinationLocationInfo =
this.volumeManager_.getLocationInfo(destinationEntry);
if (!destinationLocationInfo)
- return 'none';
- if (destinationLocationInfo.isReadOnly)
- return 'none';
+ return new DropEffectAndLabel(DropEffectType.NONE, null);
+ if (destinationLocationInfo.isReadOnly) {
+ if (destinationLocationInfo.isSpecialSearchRoot) {
+ // The location is a fake entry that corresponds to special search.
+ return new DropEffectAndLabel(DropEffectType.NONE, null);
+ }
+ if (destinationLocationInfo.volumeInfo.isReadOnlyRemovableDevice) {
+ return new DropEffectAndLabel(DropEffectType.NONE,
+ strf('DEVICE_WRITE_PROTECTED'));
+ }
+ // The disk device is not write-protected but read-only.
+ // Currently, the only remaining possibility is that write access to
+ // removable drives is restricted by device policy.
+ return new DropEffectAndLabel(DropEffectType.NONE,
+ strf('DEVICE_ACCESS_RESTRICTED'));
+ }
if (util.isDropEffectAllowed(event.dataTransfer.effectAllowed, 'move')) {
if (!util.isDropEffectAllowed(event.dataTransfer.effectAllowed, 'copy'))
- return 'move';
+ return new DropEffectAndLabel(DropEffectType.MOVE, null);
// TODO(mtomasz): Use volumeId instead of comparing roots, as soon as
// volumeId gets unique.
if (this.getSourceRootURL_(event.dataTransfer) ===
destinationLocationInfo.volumeInfo.fileSystem.root.toURL() &&
!event.ctrlKey) {
- return 'move';
+ return new DropEffectAndLabel(DropEffectType.MOVE, null);
}
if (event.shiftKey) {
- return 'move';
+ return new DropEffectAndLabel(DropEffectType.MOVE, null);
}
}
- return 'copy';
+ return new DropEffectAndLabel(DropEffectType.COPY, null);
};
/**

Powered by Google App Engine
This is Rietveld 408576698