@opensumi/ide-file-tree-next 3.7.2-next-1740450374.0 → 3.7.2-next-1741226843.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/lib/browser/dialog/file-dialog.service.d.ts +0 -4
  2. package/lib/browser/dialog/file-dialog.service.d.ts.map +1 -1
  3. package/lib/browser/dialog/file-dialog.service.js +1 -7
  4. package/lib/browser/dialog/file-dialog.service.js.map +1 -1
  5. package/lib/browser/dialog/file-dialog.view.d.ts.map +1 -1
  6. package/lib/browser/dialog/file-dialog.view.js +9 -44
  7. package/lib/browser/dialog/file-dialog.view.js.map +1 -1
  8. package/lib/browser/file-tree-contribution.d.ts.map +1 -1
  9. package/lib/browser/file-tree-contribution.js +1 -8
  10. package/lib/browser/file-tree-contribution.js.map +1 -1
  11. package/lib/browser/services/file-tree-api.service.d.ts +2 -3
  12. package/lib/browser/services/file-tree-api.service.d.ts.map +1 -1
  13. package/lib/browser/services/file-tree-api.service.js +1 -3
  14. package/lib/browser/services/file-tree-api.service.js.map +1 -1
  15. package/lib/browser/services/file-tree-model.service.d.ts.map +1 -1
  16. package/lib/browser/services/file-tree-model.service.js +8 -29
  17. package/lib/browser/services/file-tree-model.service.js.map +1 -1
  18. package/lib/common/index.d.ts +1 -2
  19. package/lib/common/index.d.ts.map +1 -1
  20. package/lib/common/index.js.map +1 -1
  21. package/package.json +17 -18
  22. package/src/browser/dialog/file-dialog.service.ts +1 -12
  23. package/src/browser/dialog/file-dialog.view.tsx +9 -69
  24. package/src/browser/file-tree-contribution.ts +1 -8
  25. package/src/browser/services/file-tree-api.service.ts +2 -5
  26. package/src/browser/services/file-tree-model.service.ts +12 -34
  27. package/src/common/index.ts +1 -3
@@ -42,7 +42,6 @@ export const FileDialog = ({
42
42
  const [isReady, setIsReady] = useState<boolean>(false);
43
43
  const [selectPath, setSelectPath] = useState<string>('');
44
44
  const [directoryList, setDirectoryList] = useState<string[]>([]);
45
- const currentSaveFileName = useRef<string>((options as ISaveDialogOptions).defaultFileName || '');
46
45
 
47
46
  useEffect(() => {
48
47
  if (model) {
@@ -57,8 +56,7 @@ export const FileDialog = ({
57
56
 
58
57
  useEffect(() => {
59
58
  if ((options as ISaveDialogOptions).defaultFileName) {
60
- setFileName((options as ISaveDialogOptions).defaultFileName || '');
61
- currentSaveFileName.current = (options as ISaveDialogOptions).defaultFileName || '';
59
+ setFileName((options as ISaveDialogOptions).defaultFileName!);
62
60
  }
63
61
  }, [options]);
64
62
 
@@ -72,25 +70,19 @@ export const FileDialog = ({
72
70
  const ensure = useCallback(() => {
73
71
  const value: string[] = model.selectedFiles.map((file) => file.uri.path.toString());
74
72
  // 如果有文件名的,说明肯定是保存文件的情况
75
- if (
76
- currentSaveFileName.current &&
77
- (options as ISaveDialogOptions).showNameInput &&
78
- (value?.length === 1 || options.defaultUri)
79
- ) {
73
+ if (fileName && (options as ISaveDialogOptions).showNameInput && (value?.length === 1 || options.defaultUri)) {
80
74
  const filePath = value?.length === 1 ? value[0] : options.defaultUri!.path.toString();
81
75
  if ((options as ISaveDialogOptions & { saveAs?: boolean | undefined })?.saveAs) {
82
76
  fileService.saveAs({
83
77
  oldFilePath: path.join(filePath!, (options as ISaveDialogOptions)?.defaultFileName || ''),
84
- newFilePath: path.join(filePath!, currentSaveFileName.current),
78
+ newFilePath: path.join(filePath!, fileName),
85
79
  });
86
80
  }
87
81
 
88
- dialogService.hide([path.join(filePath!, currentSaveFileName.current)]);
82
+ dialogService.hide([path.join(filePath!, fileName)]);
89
83
  } else {
90
84
  if (value.length > 0) {
91
85
  dialogService.hide(value);
92
- } else if (selectPath) {
93
- dialogService.hide([selectPath]);
94
86
  } else if (options.defaultUri) {
95
87
  dialogService.hide([options.defaultUri!.path.toString()]);
96
88
  } else if (model.treeModel && model.treeModel.root) {
@@ -101,17 +93,7 @@ export const FileDialog = ({
101
93
  }
102
94
  setIsReady(false);
103
95
  fileService.contextKey.fileDialogViewVisibleContext.set(false);
104
- }, [isReady, dialogService, model, options, selectPath]);
105
-
106
- const getDefaultPath = async (model) => {
107
- let defaultPath = (model.treeModel.root as Directory).uri.codeUri.fsPath;
108
-
109
- if (fileService.getDefaultFilePath) {
110
- defaultPath = await fileService.getDefaultFilePath(model, defaultPath);
111
- }
112
-
113
- return defaultPath;
114
- };
96
+ }, [isReady, dialogService, model, fileName, options]);
115
97
 
116
98
  const close = useCallback(() => {
117
99
  setIsReady(false);
@@ -124,9 +106,7 @@ export const FileDialog = ({
124
106
  // 确保数据初始化完毕,减少初始化数据过程中多次刷新视图
125
107
  // 这里需要重新取一下treeModel的值确保为最新的TreeModel
126
108
  await model.treeModel.ensureReady;
127
- const path = await getDefaultPath(model);
128
-
129
- setSelectPath(path);
109
+ setSelectPath((model.treeModel.root as Directory).uri.codeUri.fsPath);
130
110
  setIsReady(true);
131
111
  }, [model, selectPath, isReady]);
132
112
 
@@ -221,24 +201,6 @@ export const FileDialog = ({
221
201
  [model, isReady, selectPath],
222
202
  );
223
203
 
224
- const onSearchChangeHandler = useCallback(
225
- async (value: string) => {
226
- setIsReady(false);
227
- setSelectPath(value);
228
- await model.updateTreeModel(value);
229
- setIsReady(true);
230
- },
231
- [model, isReady, selectPath, directoryList],
232
- );
233
-
234
- const renderCustomMsg = useCallback(() => {
235
- if (fileService.renderCustomMsg) {
236
- return fileService.renderCustomMsg();
237
- } else {
238
- return null;
239
- }
240
- }, [fileService.renderCustomMsg]);
241
-
242
204
  const renderDialogTreeNode = useCallback(
243
205
  (props: INodeRendererProps) => (
244
206
  <FileTreeDialogNode
@@ -272,23 +234,10 @@ export const FileDialog = ({
272
234
  }
273
235
  }, [isReady, model]);
274
236
 
275
- const showFilePathSearch = useMemo(
276
- () => (fileService.showFilePathSearch === false ? false : true),
277
- [fileService.showFilePathSearch],
278
- );
279
-
280
237
  const renderDirectorySelection = useCallback(() => {
281
238
  if (directoryList.length > 0) {
282
239
  return (
283
- <Select
284
- onChange={onRootChangeHandler}
285
- onSearchChange={onSearchChangeHandler}
286
- className={styles.select_control}
287
- size='large'
288
- searchPlaceholder={selectPath}
289
- value={selectPath}
290
- showSearch={showFilePathSearch}
291
- >
240
+ <Select onChange={onRootChangeHandler} className={styles.select_control} size={'small'} value={selectPath}>
292
241
  {directoryList.map((item, idx) => (
293
242
  <Option value={item} key={`${idx} - ${item}`}>
294
243
  {item}
@@ -324,7 +273,6 @@ export const FileDialog = ({
324
273
  const DialogContent = useMemo(
325
274
  () => (
326
275
  <>
327
- {renderCustomMsg()}
328
276
  <div className={styles.file_dialog_directory}>{renderDirectorySelection()}</div>
329
277
  <div className={styles.file_dialog_content}>{renderDialogTree()}</div>
330
278
  </>
@@ -335,7 +283,7 @@ export const FileDialog = ({
335
283
  const DialogButtons = useMemo(
336
284
  () => (
337
285
  <div className={styles.file_dialog_buttons}>
338
- <Button onClick={close} type='ghost' className={styles.button}>
286
+ <Button onClick={close} type='secondary' className={styles.button}>
339
287
  {localize('dialog.file.close')}
340
288
  </Button>
341
289
  <Button
@@ -353,14 +301,6 @@ export const FileDialog = ({
353
301
  [close, ensure, isSaveDialog, isOpenDialog, fileName, options],
354
302
  );
355
303
 
356
- const handleSaveInputChange = useCallback(
357
- (event: React.ChangeEvent<HTMLInputElement>) => {
358
- setFileName(event.target.value);
359
- currentSaveFileName.current = event.target.value;
360
- },
361
- [fileName],
362
- );
363
-
364
304
  return (
365
305
  <div className={styles.file_dialog_wrapper} ref={wrapperRef}>
366
306
  <div className={styles.file_dialog_directory_title}>
@@ -379,7 +319,7 @@ export const FileDialog = ({
379
319
  value={fileName}
380
320
  autoFocus={true}
381
321
  selection={{ start: 0, end: fileName.indexOf('.') || fileName.length }}
382
- onChange={handleSaveInputChange}
322
+ onChange={(event) => setFileName(event.target.value)}
383
323
  />
384
324
  </div>
385
325
  )}
@@ -50,7 +50,6 @@ import { EXPLORER_CONTAINER_ID } from '@opensumi/ide-explorer/lib/browser/explor
50
50
  import { IMainLayoutService, IViewsRegistry, MainLayoutContribution } from '@opensumi/ide-main-layout';
51
51
  import { ViewContentGroups } from '@opensumi/ide-main-layout/lib/browser/views-registry';
52
52
  import { IOpenDialogOptions, ISaveDialogOptions, IWindowDialogService } from '@opensumi/ide-overlay';
53
- import { Path } from '@opensumi/ide-utils/lib/path';
54
53
  import { IWorkspaceService, UNTITLED_WORKSPACE } from '@opensumi/ide-workspace';
55
54
 
56
55
  import { IFileTreeService, PasteTypes, RESOURCE_VIEW_ID } from '../common';
@@ -779,15 +778,9 @@ export class FileTreeContribution
779
778
  }
780
779
  if (uri.scheme === DIFF_SCHEME) {
781
780
  const query = uri.getParsedQuery();
781
+ // 需要file scheme才能与工作区计算相对路径
782
782
  uri = new URI(query.modified).withScheme('file');
783
783
  }
784
- const node = this.fileTreeService.getNodeByPathOrUri(uri);
785
- if (node) {
786
- if (node.filestat.isInSymbolicDirectory) {
787
- // 软链接文件需要通过直接通过文件树 Path 获取
788
- return await this.clipboardService.writeText(node.path.split(Path.separator).slice(2).join(Path.separator));
789
- }
790
- }
791
784
  let rootUri: URI;
792
785
  if (this.fileTreeService.isMultipleWorkspace) {
793
786
  // 多工作区额外处理
@@ -1,7 +1,7 @@
1
1
  import { Autowired, Injectable } from '@opensumi/di';
2
2
  import { ITree } from '@opensumi/ide-components';
3
3
  import { CorePreferences, EDITOR_COMMANDS } from '@opensumi/ide-core-browser';
4
- import { CommandService, Emitter, Event, URI, formatLocalize, localize, path } from '@opensumi/ide-core-common';
4
+ import { CommandService, URI, formatLocalize, localize, path } from '@opensumi/ide-core-common';
5
5
  import { FileStat } from '@opensumi/ide-file-service';
6
6
  import { IFileServiceClient } from '@opensumi/ide-file-service/lib/common';
7
7
  import { IDialogService } from '@opensumi/ide-overlay';
@@ -12,9 +12,6 @@ import { Directory, File } from '../../common/file-tree-node.define';
12
12
 
13
13
  @Injectable()
14
14
  export class FileTreeAPI implements IFileTreeAPI {
15
- private readonly onDidResolveChildrenEmitter: Emitter<string> = new Emitter();
16
- onDidResolveChildren: Event<string> = this.onDidResolveChildrenEmitter.event;
17
-
18
15
  @Autowired(IFileServiceClient)
19
16
  protected fileServiceClient: IFileServiceClient;
20
17
 
@@ -29,6 +26,7 @@ export class FileTreeAPI implements IFileTreeAPI {
29
26
 
30
27
  @Autowired(IDialogService)
31
28
  private readonly dialogService: IDialogService;
29
+ private cacheFileStat: Map<string, FileStat> = new Map();
32
30
 
33
31
  private userhomePath: URI;
34
32
 
@@ -47,7 +45,6 @@ export class FileTreeAPI implements IFileTreeAPI {
47
45
  }
48
46
 
49
47
  if (file) {
50
- this.onDidResolveChildrenEmitter.fire(file.uri.toString());
51
48
  if (file.children?.length === 1 && file.children[0].isDirectory && compact) {
52
49
  return await this.resolveChildren(tree, file.children[0].uri, parent, compact);
53
50
  } else {
@@ -23,7 +23,6 @@ import {
23
23
  IClipboardService,
24
24
  IContextKey,
25
25
  IStorage,
26
- MessageType,
27
26
  STORAGE_NAMESPACE,
28
27
  StorageProvider,
29
28
  ThrottledDelayer,
@@ -31,11 +30,9 @@ import {
31
30
  URI,
32
31
  arrays,
33
32
  formatLocalize,
34
- isLinux,
35
33
  localize,
36
34
  path,
37
35
  strings,
38
- toMarkdown,
39
36
  } from '@opensumi/ide-core-browser';
40
37
  import { ResourceContextKey } from '@opensumi/ide-core-browser/lib/contextkey/resource';
41
38
  import { AbstractContextMenuService, ICtxMenuRenderer, MenuId } from '@opensumi/ide-core-browser/lib/menu/next';
@@ -728,10 +725,6 @@ export class FileTreeModelService {
728
725
  };
729
726
 
730
727
  handleItemRangeClick = (item: File | Directory, type: TreeNodeType) => {
731
- // 由于文件树存在选择根目录的逻辑,使用 Shift+Click 时需要清理根目录选中态
732
- if (this.selectedFiles.length === 1 && Directory.isRoot(this.selectedFiles[0])) {
733
- this.clearFileSelectedDecoration();
734
- }
735
728
  if (!this.focusedFile) {
736
729
  this.handleItemClick(item, type);
737
730
  } else if (this.focusedFile && this.focusedFile !== item) {
@@ -751,10 +744,7 @@ export class FileTreeModelService {
751
744
  if (type !== TreeNodeType.CompositeTreeNode && type !== TreeNodeType.TreeNode) {
752
745
  return;
753
746
  }
754
- // 由于文件树存在选择根目录的逻辑,使用 Cmd/Ctrl+Click 时需要清理根目录选中态
755
- if (this.selectedFiles.length === 1 && Directory.isRoot(this.selectedFiles[0])) {
756
- this.clearFileSelectedDecoration();
757
- }
747
+
758
748
  // 根据节点的选中态进行复选操作
759
749
  this.toggleFileSelectedDecoration(item);
760
750
  };
@@ -987,29 +977,18 @@ export class FileTreeModelService {
987
977
  if (uris.length === 0) {
988
978
  return;
989
979
  }
990
- // 默认过滤掉根目录的选择
991
980
  if (this.corePreferences['explorer.confirmDelete']) {
992
- const ok = isLinux ? localize('file.confirm.delete.ok') : localize('file.confirm.moveToTrash.ok');
981
+ const ok = localize('file.confirm.delete.ok');
993
982
  const cancel = localize('file.confirm.delete.cancel');
994
- const MAX_FILES = 10;
995
- let deleteFilesMessage = uris
996
- .slice(0, MAX_FILES)
983
+ const deleteFilesMessage = `[ ${uris
984
+ .slice(0, 5)
997
985
  .map((uri) => uri.displayName)
998
- .join(' \n');
999
- if (uris.length > MAX_FILES) {
1000
- deleteFilesMessage += ' \n...';
1001
- }
1002
- if (!isLinux) {
1003
- deleteFilesMessage += `\n\n<small>${localize('file.confirm.deleteTips')}</small>`;
1004
- }
1005
- const confirm = await this.dialogService.open({
1006
- message: toMarkdown(formatLocalize('file.confirm.delete', uris.length, deleteFilesMessage)),
1007
- type: MessageType.Warning,
1008
- props: {
1009
- width: 580,
1010
- },
1011
- buttons: [cancel, ok],
1012
- });
986
+ .join(',')}${uris.length > 5 ? ' ...' : ''} ]`;
987
+
988
+ const confirm = await this.dialogService.warning(formatLocalize('file.confirm.delete', deleteFilesMessage), [
989
+ cancel,
990
+ ok,
991
+ ]);
1013
992
  if (confirm !== ok) {
1014
993
  return;
1015
994
  }
@@ -1730,8 +1709,7 @@ export class FileTreeModelService {
1730
1709
  this._nextLocationTarget = undefined;
1731
1710
  }
1732
1711
  };
1733
-
1734
- public selectChildNode(uris: URI[]) {
1712
+ selectChildNode(uris: URI[]) {
1735
1713
  for (const uri of uris) {
1736
1714
  const file = this.fileTreeService.getNodeByPathOrUri(uri);
1737
1715
 
@@ -1743,7 +1721,7 @@ export class FileTreeModelService {
1743
1721
  const last = children[children.length - 1];
1744
1722
  const firstIndex = this.treeModel.root.getIndexAtTreeNode(first);
1745
1723
  const lastIndex = this.treeModel.root.getIndexAtTreeNode(last);
1746
- this._isMultiSelected = true;
1724
+
1747
1725
  this.activeFileDecorationByRange(firstIndex, lastIndex);
1748
1726
  }
1749
1727
  }
@@ -1,5 +1,5 @@
1
1
  import { ITree, ITreeNode } from '@opensumi/ide-components';
2
- import { BasicEvent, Event, IDisposable, URI } from '@opensumi/ide-core-common';
2
+ import { BasicEvent, IDisposable, URI } from '@opensumi/ide-core-common';
3
3
  import { FileStat } from '@opensumi/ide-file-service';
4
4
 
5
5
  import { Directory, File } from './file-tree-node.define';
@@ -19,8 +19,6 @@ export interface IMoveFileMetadata {
19
19
  }
20
20
 
21
21
  export interface IFileTreeAPI {
22
- onDidResolveChildren: Event<string>;
23
-
24
22
  copyFile(from: URI, to: URI): Promise<FileStat | string | void>;
25
23
  createFile(newUri: URI, content?: string): Promise<string | void>;
26
24
  createDirectory(newUri: URI): Promise<string | void>;