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

Side by Side Diff: chrome/browser/resources/file_manager/js/directory_model.js

Issue 10146008: Remember current directory for each volume. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 8 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | chrome/browser/resources/file_manager/js/file_manager.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // If directory files changes too often, don't rescan directory more than once 5 // If directory files changes too often, don't rescan directory more than once
6 // per specified interval 6 // per specified interval
7 var SIMULTANEOUS_RESCAN_INTERVAL = 1000; 7 var SIMULTANEOUS_RESCAN_INTERVAL = 1000;
8 // Used for operations that require almost instant rescan. 8 // Used for operations that require almost instant rescan.
9 var SHORT_RESCAN_INTERVAL = 100; 9 var SHORT_RESCAN_INTERVAL = 100;
10 10
(...skipping 21 matching lines...) Expand all
32 this.scanFailures_ = 0; 32 this.scanFailures_ = 0;
33 33
34 // DirectoryEntry representing the current directory of the dialog. 34 // DirectoryEntry representing the current directory of the dialog.
35 this.currentDirEntry_ = root; 35 this.currentDirEntry_ = root;
36 36
37 this.fileList_.prepareSort = this.prepareSort_.bind(this); 37 this.fileList_.prepareSort = this.prepareSort_.bind(this);
38 this.autoSelectIndex_ = 0; 38 this.autoSelectIndex_ = 0;
39 39
40 this.rootsList_ = new cr.ui.ArrayDataModel([]); 40 this.rootsList_ = new cr.ui.ArrayDataModel([]);
41 this.rootsListSelection_ = new cr.ui.ListSingleSelectionModel(); 41 this.rootsListSelection_ = new cr.ui.ListSingleSelectionModel();
42 this.rootsListSelection_.addEventListener( 42
43 'change', this.onRootsSelectionChanged_.bind(this)); 43 /**
44 * A map root.fullPath -> currentDirectory.fullPath.
45 * @private
46 * @type {Object.<string, string>}
47 */
48 this.currentDirByRoot_ = {};
44 49
45 // The map 'name' -> callback. Callbacks are function(entry) -> boolean. 50 // The map 'name' -> callback. Callbacks are function(entry) -> boolean.
46 this.filters_ = {}; 51 this.filters_ = {};
47 this.filterHidden = true; 52 this.filterHidden = true;
48 53
49 // Readonly status. 54 // Readonly status.
50 this.readonly_ = false; 55 this.readonly_ = false;
51 this.currentVolumeMetadata_ = {rootPath: '/'}; 56 this.currentVolumeMetadata_ = {rootPath: '/'};
52 this.offline_ = false; 57 this.offline_ = false;
53 } 58 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 }, 102 },
98 103
99 /** 104 /**
100 * Selection in the fileList. 105 * Selection in the fileList.
101 * @type {cr.ui.ListSelectionModel|cr.ui.ListSingleSelectionModel} 106 * @type {cr.ui.ListSelectionModel|cr.ui.ListSingleSelectionModel}
102 */ 107 */
103 get fileListSelection() { 108 get fileListSelection() {
104 return this.fileListSelection_; 109 return this.fileListSelection_;
105 }, 110 },
106 111
107 /**
108 * Top level Directories from user perspective.
109 * @type {cr.ui.ArrayDataModel}
110 */
111 get rootsList() {
112 return this.rootsList_;
113 },
114
115 /**
116 * Selection in the rootsList.
117 * @type {cr.ui.ListSingleSelectionModel}
118 */
119 get rootsListSelection() {
120 return this.rootsListSelection_;
121 },
122
123 /**
124 * Root path for the current directory (parent directory is not navigatable
125 * for the user).
126 * @type {string}
127 */
128 get rootPath() {
129 return DirectoryModel.getRootPath(this.currentEntry.fullPath);
130 },
131
132 get rootType() { 112 get rootType() {
133 return DirectoryModel.getRootType(this.currentEntry.fullPath); 113 return DirectoryModel.getRootType(this.currentEntry.fullPath);
134 }, 114 },
135 115
136 get rootName() { 116 get rootName() {
137 return DirectoryModel.getRootName(this.currentEntry.fullPath); 117 return DirectoryModel.getRootName(this.currentEntry.fullPath);
138 }, 118 },
139 119
140 get rootEntry() {
141 return this.rootsList.item(this.rootsListSelection.selectedIndex);
142 },
143
144 /** 120 /**
145 * True if current directory is read only. 121 * True if current directory is read only.
146 * @type {boolean} 122 * @type {boolean}
147 */ 123 */
148 get readonly() { 124 get readonly() {
149 return this.readonly_; 125 return this.readonly_;
150 }, 126 },
151 127
152 get offline() { 128 get offline() {
153 return this.offline_; 129 return this.offline_;
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 for (var i = 0; i < this.fileList_.length; i++) { 218 for (var i = 0; i < this.fileList_.length; i++) {
243 if (this.fileList_.item(i).name == value) { 219 if (this.fileList_.item(i).name == value) {
244 this.fileListSelection_.leadIndex = i; 220 this.fileListSelection_.leadIndex = i;
245 return; 221 return;
246 } 222 }
247 } 223 }
248 } 224 }
249 }; 225 };
250 226
251 /** 227 /**
228 * @return {cr.ui.ArrayDataModel} The list of roots.
229 */
230 DirectoryModel.prototype.getRootsList = function() {
231 return this.rootsList_;
232 };
233
234 /**
235 * @return {Entry} Directory entry of the current root.
236 */
237 DirectoryModel.prototype.getCurrentRootDirEntry = function() {
238 return this.rootsList_.item(this.rootsListSelection_.selectedIndex);
239 };
240
241 /**
242 * @return {string} Root path for the current directory (parent directory is
243 * not navigatable for the user).
244 */
245 DirectoryModel.prototype.getCurrentRootPath = function() {
246 return DirectoryModel.getRootPath(this.currentDirEntry_.fullPath);
247 };
248
249 /**
250 * @return {cr.ui.ListSingleSelectionModel} Root list selection model.
251 */
252 DirectoryModel.prototype.getRootsListSelectionModel = function() {
253 return this.directoryModel_.rootsListSelection_;
254 };
255
256 /**
252 * Add a filter for directory contents. 257 * Add a filter for directory contents.
253 * @param {string} name An identifier of the filter (used when removing it). 258 * @param {string} name An identifier of the filter (used when removing it).
254 * @param {function(Entry):boolean} filter Hide file if false. 259 * @param {function(Entry):boolean} filter Hide file if false.
255 */ 260 */
256 DirectoryModel.prototype.addFilter = function(name, filter) { 261 DirectoryModel.prototype.addFilter = function(name, filter) {
257 this.filters_[name] = filter; 262 this.filters_[name] = filter;
258 this.rescanSoon(); 263 this.rescanSoon();
259 }; 264 };
260 265
261 /** 266 /**
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 return; 327 return;
323 } 328 }
324 329
325 this.runningScan_ = this.createScanner_(fileList, successCallback); 330 this.runningScan_ = this.createScanner_(fileList, successCallback);
326 this.runningScan_.run(); 331 this.runningScan_.run();
327 }; 332 };
328 333
329 /** 334 /**
330 * @private 335 * @private
331 * @param {Array.<Entry>|cr.ui.ArrayDataModel} list 336 * @param {Array.<Entry>|cr.ui.ArrayDataModel} list
332 * @param {function} successCallback 337 * @param {function} successCallback Callback on success.
333 * @return {DirectoryModel.Scanner} 338 * @return {DirectoryModel.Scanner} New Scanner instance.
334 */ 339 */
335 DirectoryModel.prototype.createScanner_ = function(list, successCallback) { 340 DirectoryModel.prototype.createScanner_ = function(list, successCallback) {
336 var self = this; 341 var self = this;
337 function onSuccess() { 342 function onSuccess() {
338 self.scanFailures_ = 0; 343 self.scanFailures_ = 0;
339 successCallback(); 344 successCallback();
340 if (self.pendingScan_) { 345 if (self.pendingScan_) {
341 self.runningScan_ = self.pendingScan_; 346 self.runningScan_ = self.pendingScan_;
342 self.pendingScan_ = null; 347 self.pendingScan_ = null;
343 self.runningScan_.run(); 348 self.runningScan_.run();
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
659 function onRescanComplete() { 664 function onRescanComplete() {
660 action(); 665 action();
661 // For tests that open the dialog to empty directories, everything 666 // For tests that open the dialog to empty directories, everything
662 // is loaded at this point. 667 // is loaded at this point.
663 chrome.test.sendMessage('directory-change-complete'); 668 chrome.test.sendMessage('directory-change-complete');
664 } 669 }
665 this.updateReadonlyStatus_(); 670 this.updateReadonlyStatus_();
666 this.updateVolumeMetadata_(); 671 this.updateVolumeMetadata_();
667 this.updateRootsListSelection_(); 672 this.updateRootsListSelection_();
668 this.scan_(onRescanComplete); 673 this.scan_(onRescanComplete);
674 this.currentDirByRoot_[this.getCurrentRootPath()] = dirEntry.fullPath;
669 675
670 var e = new cr.Event('directory-changed'); 676 var e = new cr.Event('directory-changed');
671 e.previousDirEntry = previous; 677 e.previousDirEntry = previous;
672 e.newDirEntry = dirEntry; 678 e.newDirEntry = dirEntry;
673 e.initial = initial; 679 e.initial = initial;
674 this.dispatchEvent(e); 680 this.dispatchEvent(e);
675 }; 681 };
676 682
677 /** 683 /**
678 * Change the state of the model to reflect the specified path (either a 684 * Change the state of the model to reflect the specified path (either a
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
994 } 1000 }
995 }; 1001 };
996 1002
997 /** 1003 /**
998 * @param {function} opt_callback Called when all roots are resolved. 1004 * @param {function} opt_callback Called when all roots are resolved.
999 * @param {boolean} opt_resolveGData If true GData should be resolved for real, 1005 * @param {boolean} opt_resolveGData If true GData should be resolved for real,
1000 * If false a stub entry should be created. 1006 * If false a stub entry should be created.
1001 */ 1007 */
1002 DirectoryModel.prototype.updateRoots = function(opt_callback, 1008 DirectoryModel.prototype.updateRoots = function(opt_callback,
1003 opt_resolveGData) { 1009 opt_resolveGData) {
1004 console.log('resolving roots');
1005 var self = this; 1010 var self = this;
1006 this.resolveRoots_(function(rootEntries) { 1011 this.resolveRoots_(function(rootEntries) {
1007 console.log('resolved roots:', rootEntries);
1008 var dm = self.rootsList_; 1012 var dm = self.rootsList_;
1009 var args = [0, dm.length].concat(rootEntries); 1013 var args = [0, dm.length].concat(rootEntries);
1010 dm.splice.apply(dm, args); 1014 dm.splice.apply(dm, args);
1011 1015
1012 self.updateRootsListSelection_(); 1016 self.updateRootsListSelection_();
1013 1017
1014 if (opt_callback) 1018 if (opt_callback)
1015 opt_callback(); 1019 opt_callback();
1016 }, opt_resolveGData); 1020 }, opt_resolveGData);
1017 }; 1021 };
1018 1022
1019 /** 1023 /**
1024 * Register a listener for a new root element in left menu.
1020 * @private 1025 * @private
1021 * @param {Event} event 1026 * @param {HTMLElement} li List item representing a volume.
1027 * @param {Entry} entry Root directory entry.
1022 */ 1028 */
1023 DirectoryModel.prototype.onRootsSelectionChanged_ = function(event) { 1029 DirectoryModel.prototype.registerRootClickListener_ = function append(li,
SeRya 2012/04/20 16:06:46 What's wrong with onRootsSelectionChanged_? I thin
Oleg Eterevsky 2012/04/23 10:50:40 I agree, but this event is not fired when user cli
1024 var root = this.rootsList.item(this.rootsListSelection.selectedIndex); 1030 entry) {
1025 if (root && this.rootPath != root.fullPath) 1031 li.addEventListener('click', this.onRootClick_.bind(this, entry));
1026 this.changeDirectory(root.fullPath); 1032 };
1033
1034 /**
1035 * Handler for root item being clicked.
1036 * @private
1037 * @param {Entry} entry Entry to navigate to.
1038 * @param {Event} event The event.
1039 */
1040 DirectoryModel.prototype.onRootClick_ = function(entry, event) {
1041 var new_path = entry.fullPath;
1042 if (entry.fullPath == this.getCurrentRootPath()) {
1043 this.changeDirectory(entry.fullPath);
1044 } else {
1045 this.changeDirectory(this.currentDirByRoot_[entry.fullPath] ||
1046 entry.fullPath);
1047 }
1027 }; 1048 };
1028 1049
1029 /** 1050 /**
1030 * @private 1051 * @private
1031 */ 1052 */
1032 DirectoryModel.prototype.updateRootsListSelection_ = function() { 1053 DirectoryModel.prototype.updateRootsListSelection_ = function() {
1033 var roots = this.rootsList_; 1054 var roots = this.rootsList_;
1034 var rootPath = this.rootPath; 1055 var rootPath = this.getCurrentRootPath();
1035 for (var index = 0; index < roots.length; index++) { 1056 for (var index = 0; index < roots.length; index++) {
1036 if (roots.item(index).fullPath == rootPath) { 1057 if (roots.item(index).fullPath == rootPath) {
1037 this.rootsListSelection.selectedIndex = index; 1058 this.rootsListSelection_.selectedIndex = index;
1038 return; 1059 return;
1039 } 1060 }
1040 } 1061 }
1041 this.rootsListSelection.selectedIndex = -1; 1062 this.rootsListSelection_.selectedIndex = -1;
1042 }; 1063 };
1043 1064
1044 /** 1065 /**
1045 * @private 1066 * @private
1046 */ 1067 */
1047 DirectoryModel.prototype.updateReadonlyStatus_ = function() { 1068 DirectoryModel.prototype.updateReadonlyStatus_ = function() {
1048 switch (this.rootType) { 1069 switch (this.rootType) {
1049 case DirectoryModel.RootType.REMOVABLE: 1070 case DirectoryModel.RootType.REMOVABLE:
1050 this.readonly_ = !!this.currentVolumeMetadata_.isReadOnly; 1071 this.readonly_ = !!this.currentVolumeMetadata_.isReadOnly;
1051 break; 1072 break;
1052 case DirectoryModel.RootType.ARCHIVE: 1073 case DirectoryModel.RootType.ARCHIVE:
1053 this.readonly_ = true; 1074 this.readonly_ = true;
1054 break; 1075 break;
1055 case DirectoryModel.RootType.DOWNLOADS: 1076 case DirectoryModel.RootType.DOWNLOADS:
1056 this.readonly_ = false; 1077 this.readonly_ = false;
1057 break; 1078 break;
1058 case DirectoryModel.RootType.GDATA: 1079 case DirectoryModel.RootType.GDATA:
1059 this.readonly_ = this.offline; 1080 this.readonly_ = this.offline;
1060 break; 1081 break;
1061 default: 1082 default:
1062 this.readonly_ = true; 1083 this.readonly_ = true;
1063 break; 1084 break;
1064 } 1085 }
1065 }; 1086 };
1066 1087
1067 /** 1088 /**
1068 * @private 1089 * @private
1069 */ 1090 */
1070 DirectoryModel.prototype.updateVolumeMetadata_ = function() { 1091 DirectoryModel.prototype.updateVolumeMetadata_ = function() {
1071 var rootPath = this.rootPath; 1092 var rootPath = this.getCurrentRootPath();
1072 if (this.currentVolumeMetadata_.rootPath != rootPath) { 1093 if (this.currentVolumeMetadata_.rootPath != rootPath) {
1073 var metadata = this.currentVolumeMetadata_ = {rootPath: rootPath}; 1094 var metadata = this.currentVolumeMetadata_ = {rootPath: rootPath};
1074 if (DirectoryModel.getRootType(rootPath) == 1095 if (DirectoryModel.getRootType(rootPath) ==
1075 DirectoryModel.RootType.REMOVABLE) { 1096 DirectoryModel.RootType.REMOVABLE) {
1076 var self = this; 1097 var self = this;
1077 this.root_.getDirectory(rootPath, {}, function(entry) { 1098 this.root_.getDirectory(rootPath, {}, function(entry) {
1078 chrome.fileBrowserPrivate.getVolumeMetadata(entry.toURL(), 1099 chrome.fileBrowserPrivate.getVolumeMetadata(entry.toURL(),
1079 function(systemMetadata) { 1100 function(systemMetadata) {
1080 if (systemMetadata) { 1101 if (systemMetadata) {
1081 metadata.isReadOnly = systemMetadata.isReadOnly; 1102 metadata.isReadOnly = systemMetadata.isReadOnly;
1082 self.updateReadonlyStatus_(); 1103 self.updateReadonlyStatus_();
1083 } 1104 }
1084 }); 1105 });
1085 }); 1106 });
1086 } 1107 }
1087 } 1108 }
1088 }; 1109 };
1089 1110
1090 /** 1111 /**
1091 * @param {string} path 1112 * @param {string} path Any path in the file system.
1092 * @return {string} The root path. 1113 * @return {string} The root path.
1093 */ 1114 */
1094 DirectoryModel.getRootPath = function(path) { 1115 DirectoryModel.getRootPath = function(path) {
1095 var type = DirectoryModel.getRootType(path); 1116 var type = DirectoryModel.getRootType(path);
1096 1117
1097 if (type == DirectoryModel.RootType.DOWNLOADS) 1118 if (type == DirectoryModel.RootType.DOWNLOADS)
1098 return '/' + DirectoryModel.DOWNLOADS_DIRECTORY; 1119 return '/' + DirectoryModel.DOWNLOADS_DIRECTORY;
1099 if (type == DirectoryModel.RootType.GDATA) 1120 if (type == DirectoryModel.RootType.GDATA)
1100 return '/' + DirectoryModel.GDATA_DIRECTORY; 1121 return '/' + DirectoryModel.GDATA_DIRECTORY;
1101 1122
(...skipping 13 matching lines...) Expand all
1115 * @param {string} path 1136 * @param {string} path
1116 * @return {string} 1137 * @return {string}
1117 */ 1138 */
1118 DirectoryModel.getRootName = function(path) { 1139 DirectoryModel.getRootName = function(path) {
1119 var root = DirectoryModel.getRootPath(path); 1140 var root = DirectoryModel.getRootPath(path);
1120 var index = root.lastIndexOf('/'); 1141 var index = root.lastIndexOf('/');
1121 return index == -1 ? root : root.substring(index + 1); 1142 return index == -1 ? root : root.substring(index + 1);
1122 }; 1143 };
1123 1144
1124 /** 1145 /**
1125 * @param {string} path 1146 * @param {string} path Path.
1126 * @return {string} 1147 * @return {string} A root type.
1127 */ 1148 */
1128 DirectoryModel.getRootType = function(path) { 1149 DirectoryModel.getRootType = function(path) {
1129 function isTop(dir) { 1150 function isTop(dir) {
1130 return path.substr(1, dir.length) == dir; 1151 return path.substr(1, dir.length) == dir;
1131 } 1152 }
1132 1153
1133 if (isTop(DirectoryModel.DOWNLOADS_DIRECTORY)) 1154 if (isTop(DirectoryModel.DOWNLOADS_DIRECTORY))
1134 return DirectoryModel.RootType.DOWNLOADS; 1155 return DirectoryModel.RootType.DOWNLOADS;
1135 else if (isTop(DirectoryModel.GDATA_DIRECTORY)) 1156 if (isTop(DirectoryModel.GDATA_DIRECTORY))
1136 return DirectoryModel.RootType.GDATA; 1157 return DirectoryModel.RootType.GDATA;
1137 else if (isTop(DirectoryModel.ARCHIVE_DIRECTORY)) 1158 if (isTop(DirectoryModel.ARCHIVE_DIRECTORY))
1138 return DirectoryModel.RootType.ARCHIVE; 1159 return DirectoryModel.RootType.ARCHIVE;
1139 else if (isTop(DirectoryModel.REMOVABLE_DIRECTORY)) 1160 if (isTop(DirectoryModel.REMOVABLE_DIRECTORY))
1140 return DirectoryModel.RootType.REMOVABLE; 1161 return DirectoryModel.RootType.REMOVABLE;
1141 return ''; 1162 return '';
1142 }; 1163 };
1143 1164
1144 /** 1165 /**
1145 * @param {string} path 1166 * @param {string} path
1146 * @return {boolean} 1167 * @return {boolean}
1147 */ 1168 */
1148 DirectoryModel.isRootPath = function(path) { 1169 DirectoryModel.isRootPath = function(path) {
1149 if (path[path.length - 1] == '/') 1170 if (path[path.length - 1] == '/')
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1241 /** 1262 /**
1242 * @private 1263 * @private
1243 */ 1264 */
1244 DirectoryModel.Scanner.prototype.recordMetrics_ = function() { 1265 DirectoryModel.Scanner.prototype.recordMetrics_ = function() {
1245 metrics.recordInterval('DirectoryScan'); 1266 metrics.recordInterval('DirectoryScan');
1246 if (this.dir_.fullPath == 1267 if (this.dir_.fullPath ==
1247 '/' + DirectoryModel.DOWNLOADS_DIRECTORY) { 1268 '/' + DirectoryModel.DOWNLOADS_DIRECTORY) {
1248 metrics.recordMediumCount('DownloadsCount', this.list_.length); 1269 metrics.recordMediumCount('DownloadsCount', this.list_.length);
1249 } 1270 }
1250 }; 1271 };
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/resources/file_manager/js/file_manager.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698