Commit c47494fa authored by Naoki Fukino's avatar Naoki Fukino Committed by Commit Bot

Files app: Add "Open with..." sub menu in the context menu.

In the context menu, we have "More actions..." menu item to open a task
picker dialog for all actions.
We are going to have separated following two menu items to organize them.
"Open with..."    <= Open a task picker for OPEN actions.
"More actions..." <= Open a task picker for any other actions.

Bug: 740821
Cq-Include-Trybots: master.tryserver.chromium.linux:closure_compilation
Change-Id: I4e75c27ac32c2a6da23adfc787db9078662fa19f
Reviewed-on: https://chromium-review.googlesource.com/594759
Commit-Queue: Naoki Fukino <fukino@chromium.org>
Reviewed-by: default avatarTatsuhisa Yamaguchi <yamaguchi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#491311}
parent 534bb7ba
......@@ -603,6 +603,7 @@ ExtensionFunction::ResponseAction FileManagerPrivateGetStringsFunction::Run() {
SET_STRING("OPEN_IN_OTHER_DESKTOP_MESSAGE_PLURAL",
IDS_FILE_BROWSER_OPEN_IN_OTHER_DESKTOP_MESSAGE_PLURAL);
SET_STRING("OPEN_LABEL", IDS_FILE_BROWSER_OPEN_LABEL);
SET_STRING("OPEN_WITH_BUTTON_LABEL", IDS_FILE_BROWSER_OPEN_WITH_BUTTON_LABEL);
SET_STRING("MORE_ACTIONS_BUTTON_LABEL",
IDS_FILE_BROWSER_MORE_ACTIONS_BUTTON_LABEL);
SET_STRING("OPEN_WITH_VERB_BUTTON_LABEL",
......
......@@ -1041,7 +1041,7 @@ CommandHandler.COMMANDS_['default-task'] = /** @type {Command} */ ({
});
/**
* Displays "open with"/"more actions" dialog for current selection.
* Displays "open with" dialog for current selection.
* @type {Command}
*/
CommandHandler.COMMANDS_['open-with'] = /** @type {Command} */ ({
......@@ -1050,19 +1050,52 @@ CommandHandler.COMMANDS_['open-with'] = /** @type {Command} */ ({
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
fileManager.taskController.getFileTasks().then(function(tasks) {
tasks.showTaskPicker(fileManager.ui.defaultTaskPicker,
str('MORE_ACTIONS_BUTTON_LABEL'),
'',
function(task) {
tasks.execute(task.taskId);
},
false);
})
.catch(function(error) {
if (error)
console.error(error.stack || error);
});
fileManager.taskController.getFileTasks()
.then(function(tasks) {
tasks.showTaskPicker(
fileManager.ui.defaultTaskPicker, str('OPEN_WITH_BUTTON_LABEL'),
'', function(task) {
tasks.execute(task.taskId);
}, FileTasks.TaskPickerType.OpenWith);
})
.catch(function(error) {
if (error)
console.error(error.stack || error);
});
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
var canExecute = fileManager.taskController.canExecuteOpenActions();
event.canExecute = canExecute;
event.command.setHidden(!canExecute);
}
});
/**
* Displays "More actions" dialog for current selection.
* @type {Command}
*/
CommandHandler.COMMANDS_['more-actions'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
fileManager.taskController.getFileTasks()
.then(function(tasks) {
tasks.showTaskPicker(
fileManager.ui.defaultTaskPicker,
str('MORE_ACTIONS_BUTTON_LABEL'), '', function(task) {
tasks.execute(task.taskId);
}, FileTasks.TaskPickerType.MoreActions);
})
.catch(function(error) {
if (error)
console.error(error.stack || error);
});
},
/**
* @param {!Event} event Command event.
......
......@@ -109,6 +109,16 @@ FileTasks.TaskMenuButtonItemType = {
ChangeDefaultTask: 'ChangeDefaultTask'
};
/**
* Dialog types to show a task picker.
* @enum {string}
*/
FileTasks.TaskPickerType = {
ChangeDefault: 'ChangeDefault',
OpenWith: 'OpenWith',
MoreActions: 'MoreActions'
};
/**
* Creates an instance of FileTasks for the specified list of entries with mime
* types.
......@@ -154,12 +164,28 @@ FileTasks.create = function(
/**
* Obtains the task items.
* @return {Array<!Object>}
* @return {!Array<!Object>}
*/
FileTasks.prototype.getTaskItems = function() {
return this.tasks_;
};
/**
* Obtain tasks which are categorized as OPEN tasks.
* @return {!Array<!Object>}
*/
FileTasks.prototype.getOpenTaskItems = function() {
return this.tasks_.filter(FileTasks.isOpenTask);
};
/**
* Obtain tasks which are not categorized as OPEN tasks.
* @return {!Array<!Object>}
*/
FileTasks.prototype.getNonOpenTaskItems = function() {
return this.tasks_.filter(task => !FileTasks.isOpenTask(task));
};
/**
* Opens the suggest file dialog.
*
......@@ -873,17 +899,16 @@ FileTasks.prototype.createCombobuttonItem_ = function(task, opt_title,
* @param {string} title Title to use.
* @param {string} message Message to use.
* @param {function(Object)} onSuccess Callback to pass selected task.
* @param {boolean=} opt_forChangeDefault Whether to return items which are for
* change-default dialog.
* @param {FileTasks.TaskPickerType} pickerType Task picker type.
*/
FileTasks.prototype.showTaskPicker = function(
taskDialog, title, message, onSuccess, opt_forChangeDefault) {
var items = !opt_forChangeDefault ?
this.createItems_(this.tasks_) :
this.createItems_(this.tasks_.filter(FileTasks.isOpenTask))
.filter(function(item) {
return !item.isGenericFileHandler;
});
taskDialog, title, message, onSuccess, pickerType) {
var tasks = pickerType == FileTasks.TaskPickerType.MoreActions ?
this.getNonOpenTaskItems() :
this.getOpenTaskItems();
var items = this.createItems_(tasks);
if (pickerType == FileTasks.TaskPickerType.ChangeDefault)
items = items.filter(item => !item.isGenericFileHandler);
var defaultIdx = 0;
for (var j = 0; j < items.length; j++) {
......
......@@ -71,6 +71,11 @@ function TaskController(
*/
this.canExecuteDefaultTask_ = false;
/**
* @private {boolean}
*/
this.canExecuteOpenActions_ = false;
/**
* @private {boolean}
*/
......@@ -89,9 +94,18 @@ function TaskController(
* @private {!cr.ui.Command}
* @const
*/
this.moreActionsCommand_ =
this.openWithCommand_ =
assertInstanceof(document.querySelector('#open-with'), cr.ui.Command);
/**
* More actions command that uses #open-with as selector due to the open-with
* command used previously for the same task.
* @private {!cr.ui.Command}
* @const
*/
this.moreActionsCommand_ =
assertInstanceof(document.querySelector('#more-actions'), cr.ui.Command);
/**
* @private {Promise<!FileTasks>}
*/
......@@ -200,7 +214,8 @@ TaskController.prototype.onTaskItemClicked_ = function(event) {
this.ui_.defaultTaskPicker,
loadTimeData.getString('CHANGE_DEFAULT_MENU_ITEM'),
strf('CHANGE_DEFAULT_CAPTION', format),
this.changeDefaultTask_.bind(this, selection), true);
this.changeDefaultTask_.bind(this, selection),
FileTasks.TaskPickerType.ChangeDefault);
break;
default:
assertNotReached('Unknown task.');
......@@ -303,11 +318,12 @@ TaskController.prototype.onSelectionChanged_ = function() {
// Show disabled items for position calculation of the menu. They will be
// overridden in this.updateTasks_().
this.updateContextMenuTaskItems_(
[TaskController.createTemporaryDisabledTaskItem_()],
[TaskController.createTemporaryDisabledTaskItem_()]);
}
} else {
// Update context menu.
this.updateContextMenuTaskItems_([]);
this.updateContextMenuTaskItems_([], []);
}
this.lastSelectedEntries_ = selection.entries;
};
......@@ -323,7 +339,8 @@ TaskController.prototype.updateTasks_ = function() {
this.getFileTasks()
.then(function(tasks) {
tasks.display(this.ui_.taskMenuButton, this.ui_.shareMenuButton);
this.updateContextMenuTaskItems_(tasks.getTaskItems());
this.updateContextMenuTaskItems_(
tasks.getOpenTaskItems(), tasks.getNonOpenTaskItems());
}.bind(this))
.catch(function(error) {
if (error)
......@@ -376,6 +393,14 @@ TaskController.prototype.canExecuteDefaultTask = function() {
return this.canExecuteDefaultTask_;
};
/**
* Returns whether open with command can be executed or not.
* @return {boolean} True if open with command is executable.
*/
TaskController.prototype.canExecuteOpenActions = function() {
return this.canExecuteOpenActions_;
};
/**
* Returns whether open with command can be executed or not.
* @return {boolean} True if open with command is executable.
......@@ -387,16 +412,18 @@ TaskController.prototype.canExecuteMoreActions = function() {
/**
* Updates tasks menu item to match passed task items.
*
* @param {!Array<!Object>} items List of items.
* @param {!Array<!Object>} openTasks List of OPEN tasks.
* @param {!Array<!Object>} nonOpenTasks List of non-OPEN tasks.
* @private
*/
TaskController.prototype.updateContextMenuTaskItems_ = function(items) {
TaskController.prototype.updateContextMenuTaskItems_ = function(
openTasks, nonOpenTasks) {
// Always show a default item in case at least one task is available, even
// if there is no corresponding default task (i.e. the available task is
// a generic handler).
if (items.length >= 1) {
if (openTasks.length >= 1) {
var defaultTask = FileTasks.getDefaultTask(
items, items[0] /* task to use in case of no default */);
openTasks, openTasks[0] /* task to use in case of no default */);
if (defaultTask.iconType) {
this.ui_.fileContextMenu.defaultTaskMenuItem.style.backgroundImage = '';
......@@ -417,13 +444,17 @@ TaskController.prototype.updateContextMenuTaskItems_ = function(items) {
this.ui_.fileContextMenu.defaultTaskMenuItem.taskId = defaultTask.taskId;
}
this.canExecuteDefaultTask_ = items.length >= 1;
this.canExecuteDefaultTask_ = openTasks.length >= 1;
this.defaultTaskCommand_.canExecuteChange(this.ui_.listContainer.element);
this.canExecuteMoreActions_ = items.length > 1;
this.canExecuteOpenActions_ = openTasks.length > 1;
this.openWithCommand_.canExecuteChange(this.ui_.listContainer.element);
this.canExecuteMoreActions_ = nonOpenTasks.length >= 1;
this.moreActionsCommand_.canExecuteChange(this.ui_.listContainer.element);
this.ui_.fileContextMenu.tasksSeparator.hidden = items.length === 0;
this.ui_.fileContextMenu.tasksSeparator.hidden =
openTasks.length === 0 && nonOpenTasks.length == 0;
};
/**
......
......@@ -5,6 +5,7 @@
-->
<command id="default-task">
<command id="open-with">
<command id="more-actions">
<script src="../../../../../ui/webui/resources/js/assert.js"></script>
<script src="../../../../../ui/webui/resources/js/cr.js"></script>
......
......@@ -141,7 +141,8 @@
shortcut=".|Ctrl" hide-shortcut-text>
<command id="default-task">
<command id="open-with" i18n-values="label:MORE_ACTIONS_BUTTON_LABEL">
<command id="open-with" i18n-values="label:OPEN_WITH_BUTTON_LABEL">
<command id="more-actions" i18n-values="label:MORE_ACTIONS_BUTTON_LABEL">
<command id="zip-selection"
i18n-values="label:ZIP_SELECTION_BUTTON_LABEL">
<command id="set-wallpaper"
......@@ -176,6 +177,8 @@
visibleif="full-page" class="hide-on-toolbar" hidden></cr-menu-item>
<cr-menu-item command="#open-with"
visibleif="full-page" class="hide-on-toolbar" hidden></cr-menu-item>
<cr-menu-item command="#more-actions"
visibleif="full-page" class="hide-on-toolbar" hidden></cr-menu-item>
<hr id="tasks-separator" visibleif="full-page" class="hide-on-toolbar" hidden>
<hr id="actions-separator" hidden>
<cr-menu-item command="#cut" visibleif="full-page"></cr-menu-item>
......
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