Commit 3aa2c925 authored by Naoki Fukino's avatar Naoki Fukino Committed by Commit Bot

Extract logic to compute path components from Entry.

I'd like to move LocationLine.PathComponent class and
LocationLine.getComponents_() method out of LocationLine
to share the logic in LocationLine and QuickView.

Bug: 1092950
Test: Existing test passes / closure compiles
Change-Id: I394a4a99815f9d6d8f60aefb7fd76cf0d8e423d9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2237570
Commit-Queue: Naoki Fukino <fukino@chromium.org>
Reviewed-by: default avatarNoel Gordon <noel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#776837}
parent c03c3972
...@@ -59,6 +59,7 @@ js_type_check("closure_compile_module") { ...@@ -59,6 +59,7 @@ js_type_check("closure_compile_module") {
":naming_controller", ":naming_controller",
":navigation_list_model", ":navigation_list_model",
":navigation_uma", ":navigation_uma",
":path_component",
":progress_center_item_group", ":progress_center_item_group",
":providers_model", ":providers_model",
":quick_view_controller", ":quick_view_controller",
...@@ -639,6 +640,10 @@ js_unittest("navigation_list_model_unittest") { ...@@ -639,6 +640,10 @@ js_unittest("navigation_list_model_unittest") {
] ]
} }
js_library("path_component") {
deps = [ "//ui/file_manager/base/js:volume_manager_types" ]
}
js_library("progress_center_item_group") { js_library("progress_center_item_group") {
deps = [ deps = [
"//ui/file_manager/file_manager/common/js:progress_center_common", "//ui/file_manager/file_manager/common/js:progress_center_common",
......
...@@ -140,6 +140,7 @@ ...@@ -140,6 +140,7 @@
// <include src="naming_controller.js"> // <include src="naming_controller.js">
// <include src="navigation_list_model.js"> // <include src="navigation_list_model.js">
// <include src="navigation_uma.js"> // <include src="navigation_uma.js">
// <include src="path_component.js">
// <include src="progress_center_item_group.js"> // <include src="progress_center_item_group.js">
// <include src="quick_view_controller.js"> // <include src="quick_view_controller.js">
// <include src="quick_view_model.js"> // <include src="quick_view_model.js">
......
// Copyright 2020 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.
/**
* File path component.
*
* File path can be represented as a series of path components. Each component
* has its name used as a visible label and URL which point to the component
* in the path.
* PathComponent.computeComponentsFromEntry computes an array of PathComponent
* of the given entry.
*/
class PathComponent {
/**
* @param {string} name Name.
* @param {string} url Url.
* @param {FilesAppEntry=} opt_fakeEntry Fake entry should be set when
* this component represents fake entry.
*/
constructor(name, url, opt_fakeEntry) {
this.name = name;
this.url_ = url;
this.fakeEntry_ = opt_fakeEntry || null;
}
/**
* Resolve an entry of the component.
* @return {!Promise<!Entry|!FilesAppEntry>} A promise which is
* resolved with an entry.
*/
resolveEntry() {
if (this.fakeEntry_) {
return /** @type {!Promise<!Entry|!FilesAppEntry>} */ (
Promise.resolve(this.fakeEntry_));
} else {
return new Promise(
window.webkitResolveLocalFileSystemURL.bind(null, this.url_));
}
}
/**
* Computes path components for the path of entry.
* @param {!Entry|!FilesAppEntry} entry An entry.
* @return {!Array<!PathComponent>} Components.
*/
static computeComponentsFromEntry(entry, volumeManager) {
/**
* Replace the root directory name at the end of a url.
* The input, |url| is a displayRoot URL of a Drive volume like
* filesystem:chrome-extension://....foo.com-hash/root
* The output is like:
* filesystem:chrome-extension://....foo.com-hash/other
*
* @param {string} url which points to a volume display root
* @param {string} newRoot new root directory name
* @return {string} new URL with the new root directory name
*/
const replaceRootName = (url, newRoot) => {
return url.slice(0, url.length - '/root'.length) + newRoot;
};
const components = [];
const locationInfo = volumeManager.getLocationInfo(entry);
if (!locationInfo) {
return components;
}
if (util.isFakeEntry(entry)) {
components.push(new PathComponent(
util.getEntryLabel(locationInfo, entry), entry.toURL(),
/** @type {!FakeEntry} */ (entry)));
return components;
}
// Add volume component.
let displayRootUrl = locationInfo.volumeInfo.displayRoot.toURL();
let displayRootFullPath = locationInfo.volumeInfo.displayRoot.fullPath;
const prefixEntry = locationInfo.volumeInfo.prefixEntry;
if (prefixEntry) {
components.push(new PathComponent(
prefixEntry.name, prefixEntry.toURL(), prefixEntry));
}
if (locationInfo.rootType === VolumeManagerCommon.RootType.DRIVE_OTHER) {
// When target path is a shared directory, volume should be shared with
// me.
const match = entry.fullPath.match(/\/\.files-by-id\/\d+\//);
if (match) {
displayRootFullPath = match[0];
} else {
displayRootFullPath = '/other';
}
displayRootUrl = replaceRootName(displayRootUrl, displayRootFullPath);
const sharedWithMeFakeEntry =
locationInfo.volumeInfo
.fakeEntries[VolumeManagerCommon.RootType.DRIVE_SHARED_WITH_ME];
components.push(new PathComponent(
str('DRIVE_SHARED_WITH_ME_COLLECTION_LABEL'),
sharedWithMeFakeEntry.toURL(), sharedWithMeFakeEntry));
} else if (
locationInfo.rootType === VolumeManagerCommon.RootType.SHARED_DRIVE) {
displayRootUrl = replaceRootName(
displayRootUrl, VolumeManagerCommon.SHARED_DRIVES_DIRECTORY_PATH);
components.push(new PathComponent(
util.getRootTypeLabel(locationInfo), displayRootUrl));
} else if (
locationInfo.rootType === VolumeManagerCommon.RootType.COMPUTER) {
displayRootUrl = replaceRootName(
displayRootUrl, VolumeManagerCommon.COMPUTERS_DIRECTORY_PATH);
components.push(new PathComponent(
util.getRootTypeLabel(locationInfo), displayRootUrl));
} else {
components.push(new PathComponent(
util.getRootTypeLabel(locationInfo), displayRootUrl));
}
// Get relative path to display root (e.g. /root/foo/bar -> foo/bar).
let relativePath = entry.fullPath.slice(displayRootFullPath.length);
if (entry.fullPath.startsWith(
VolumeManagerCommon.SHARED_DRIVES_DIRECTORY_PATH)) {
relativePath = entry.fullPath.slice(
VolumeManagerCommon.SHARED_DRIVES_DIRECTORY_PATH.length);
} else if (entry.fullPath.startsWith(
VolumeManagerCommon.COMPUTERS_DIRECTORY_PATH)) {
relativePath = entry.fullPath.slice(
VolumeManagerCommon.COMPUTERS_DIRECTORY_PATH.length);
}
if (relativePath.indexOf('/') === 0) {
relativePath = relativePath.slice(1);
}
if (relativePath.length === 0) {
return components;
}
// currentUrl should be without trailing slash.
let currentUrl = /^.+\/$/.test(displayRootUrl) ?
displayRootUrl.slice(0, displayRootUrl.length - 1) :
displayRootUrl;
// Add directory components to the target path.
const paths = relativePath.split('/');
for (let i = 0; i < paths.length; i++) {
currentUrl += '/' + encodeURIComponent(paths[i]);
let path = paths[i];
if (i === 0 &&
locationInfo.rootType === VolumeManagerCommon.RootType.DOWNLOADS) {
if (path === 'Downloads') {
path = str('DOWNLOADS_DIRECTORY_LABEL');
}
if (path === 'PvmDefault') {
path = str('PLUGIN_VM_DIRECTORY_LABEL');
}
}
components.push(new PathComponent(path, currentUrl));
}
return components;
}
}
\ No newline at end of file
...@@ -427,6 +427,7 @@ js_library("location_line") { ...@@ -427,6 +427,7 @@ js_library("location_line") {
"//ui/file_manager/file_manager/common/js:files_app_entry_types", "//ui/file_manager/file_manager/common/js:files_app_entry_types",
"//ui/file_manager/file_manager/common/js:metrics", "//ui/file_manager/file_manager/common/js:metrics",
"//ui/file_manager/file_manager/common/js:util", "//ui/file_manager/file_manager/common/js:util",
"//ui/file_manager/file_manager/foreground/js:path_component",
] ]
} }
......
...@@ -45,7 +45,8 @@ class LocationLine extends cr.EventTarget { ...@@ -45,7 +45,8 @@ class LocationLine extends cr.EventTarget {
return; return;
} }
const components = this.getComponents_(entry); const components =
PathComponent.computeComponentsFromEntry(entry, this.volumeManager_);
if (util.isFilesNg()) { if (util.isFilesNg()) {
this.updateNg_(components); this.updateNg_(components);
} else { } else {
...@@ -55,138 +56,15 @@ class LocationLine extends cr.EventTarget { ...@@ -55,138 +56,15 @@ class LocationLine extends cr.EventTarget {
/** /**
* Returns current path components built by the current directory entry. * Returns current path components built by the current directory entry.
* @return {!Array<!LocationLine.PathComponent>} Current path components. * @return {!Array<!PathComponent>} Current path components.
*/ */
getCurrentPathComponents() { getCurrentPathComponents() {
return this.components_; return this.components_;
} }
/**
* Replace the root directory name at the end of a url.
* The input, |url| is a displayRoot URL of a Drive volume like
* filesystem:chrome-extension://....foo.com-hash/root
* The output is like:
* filesystem:chrome-extension://....foo.com-hash/other
*
* @param {string} url which points to a volume display root
* @param {string} newRoot new root directory name
* @return {string} new URL with the new root directory name
* @private
*/
replaceRootName_(url, newRoot) {
return url.slice(0, url.length - '/root'.length) + newRoot;
}
/**
* Get components for the path of entry.
* @param {!Entry|!FilesAppEntry} entry An entry.
* @return {!Array<!LocationLine.PathComponent>} Components.
* @private
*/
getComponents_(entry) {
const components = [];
const locationInfo = this.volumeManager_.getLocationInfo(entry);
if (!locationInfo) {
return components;
}
if (util.isFakeEntry(entry)) {
components.push(new LocationLine.PathComponent(
util.getEntryLabel(locationInfo, entry), entry.toURL(),
/** @type {!FakeEntry} */ (entry)));
return components;
}
// Add volume component.
let displayRootUrl = locationInfo.volumeInfo.displayRoot.toURL();
let displayRootFullPath = locationInfo.volumeInfo.displayRoot.fullPath;
const prefixEntry = locationInfo.volumeInfo.prefixEntry;
if (prefixEntry) {
components.push(new LocationLine.PathComponent(
prefixEntry.name, prefixEntry.toURL(), prefixEntry));
}
if (locationInfo.rootType === VolumeManagerCommon.RootType.DRIVE_OTHER) {
// When target path is a shared directory, volume should be shared with
// me.
const match = entry.fullPath.match(/\/\.files-by-id\/\d+\//);
if (match) {
displayRootFullPath = match[0];
} else {
displayRootFullPath = '/other';
}
displayRootUrl =
this.replaceRootName_(displayRootUrl, displayRootFullPath);
const sharedWithMeFakeEntry =
locationInfo.volumeInfo
.fakeEntries[VolumeManagerCommon.RootType.DRIVE_SHARED_WITH_ME];
components.push(new LocationLine.PathComponent(
str('DRIVE_SHARED_WITH_ME_COLLECTION_LABEL'),
sharedWithMeFakeEntry.toURL(), sharedWithMeFakeEntry));
} else if (
locationInfo.rootType === VolumeManagerCommon.RootType.SHARED_DRIVE) {
displayRootUrl = this.replaceRootName_(
displayRootUrl, VolumeManagerCommon.SHARED_DRIVES_DIRECTORY_PATH);
components.push(new LocationLine.PathComponent(
util.getRootTypeLabel(locationInfo), displayRootUrl));
} else if (
locationInfo.rootType === VolumeManagerCommon.RootType.COMPUTER) {
displayRootUrl = this.replaceRootName_(
displayRootUrl, VolumeManagerCommon.COMPUTERS_DIRECTORY_PATH);
components.push(new LocationLine.PathComponent(
util.getRootTypeLabel(locationInfo), displayRootUrl));
} else {
components.push(new LocationLine.PathComponent(
util.getRootTypeLabel(locationInfo), displayRootUrl));
}
// Get relative path to display root (e.g. /root/foo/bar -> foo/bar).
let relativePath = entry.fullPath.slice(displayRootFullPath.length);
if (entry.fullPath.startsWith(
VolumeManagerCommon.SHARED_DRIVES_DIRECTORY_PATH)) {
relativePath = entry.fullPath.slice(
VolumeManagerCommon.SHARED_DRIVES_DIRECTORY_PATH.length);
} else if (entry.fullPath.startsWith(
VolumeManagerCommon.COMPUTERS_DIRECTORY_PATH)) {
relativePath = entry.fullPath.slice(
VolumeManagerCommon.COMPUTERS_DIRECTORY_PATH.length);
}
if (relativePath.indexOf('/') === 0) {
relativePath = relativePath.slice(1);
}
if (relativePath.length === 0) {
return components;
}
// currentUrl should be without trailing slash.
let currentUrl = /^.+\/$/.test(displayRootUrl) ?
displayRootUrl.slice(0, displayRootUrl.length - 1) :
displayRootUrl;
// Add directory components to the target path.
const paths = relativePath.split('/');
for (let i = 0; i < paths.length; i++) {
currentUrl += '/' + encodeURIComponent(paths[i]);
let path = paths[i];
if (i === 0 &&
locationInfo.rootType === VolumeManagerCommon.RootType.DOWNLOADS) {
if (path === 'Downloads') {
path = str('DOWNLOADS_DIRECTORY_LABEL');
}
if (path === 'PvmDefault') {
path = str('PLUGIN_VM_DIRECTORY_LABEL');
}
}
components.push(new LocationLine.PathComponent(path, currentUrl));
}
return components;
}
/** /**
* Updates the breadcrumb display for files-ng. * Updates the breadcrumb display for files-ng.
* @param {!Array<!LocationLine.PathComponent>} components Components to the * @param {!Array<!PathComponent>} components Components to the
* target path. * target path.
* @private * @private
*/ */
...@@ -212,7 +90,7 @@ class LocationLine extends cr.EventTarget { ...@@ -212,7 +90,7 @@ class LocationLine extends cr.EventTarget {
/** /**
* Updates the breadcrumb display. * Updates the breadcrumb display.
* @param {!Array<!LocationLine.PathComponent>} components Components to the * @param {!Array<!PathComponent>} components Components to the
* target path. * target path.
* @private * @private
*/ */
...@@ -468,35 +346,3 @@ class LocationLine extends cr.EventTarget { ...@@ -468,35 +346,3 @@ class LocationLine extends cr.EventTarget {
this.navigateToIndex_(index); this.navigateToIndex_(index);
} }
} }
/**
* Path component.
*/
LocationLine.PathComponent = class {
/**
* @param {string} name Name.
* @param {string} url Url.
* @param {FilesAppEntry=} opt_fakeEntry Fake entry should be set when
* this component represents fake entry.
*/
constructor(name, url, opt_fakeEntry) {
this.name = name;
this.url_ = url;
this.fakeEntry_ = opt_fakeEntry || null;
}
/**
* Resolve an entry of the component.
* @return {!Promise<!Entry|!FilesAppEntry>} A promise which is
* resolved with an entry.
*/
resolveEntry() {
if (this.fakeEntry_) {
return /** @type {!Promise<!Entry|!FilesAppEntry>} */ (
Promise.resolve(this.fakeEntry_));
} else {
return new Promise(
window.webkitResolveLocalFileSystemURL.bind(null, this.url_));
}
}
};
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