Skip to content

Commit 41a3427

Browse files
authored
fix: filetree rename file correctly (#3108)
1 parent 4d44ed1 commit 41a3427

3 files changed

Lines changed: 74 additions & 21 deletions

File tree

packages/file-tree-next/src/browser/file-tree.service.ts

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ export class FileTreeService extends Tree implements IFileTreeService {
446446
}
447447
}
448448

449-
// 软链接目录下,文件节点路径不能通过uri去获取,存在偏差
449+
// 软链接目录下,文件节点路径不能通过 uri 去获取,存在偏差
450450
public async moveNodeByPath(
451451
from: Directory,
452452
to: Directory,
@@ -459,8 +459,8 @@ export class FileTreeService extends Tree implements IFileTreeService {
459459
if (oldPath && newPath && newPath !== oldPath) {
460460
const movedNode = from.moveNode(oldPath, newPath);
461461
// 更新节点除了 name 以外的其他属性,如 fileStat,tooltip 等,否则节点数据可能会异常
462-
if (movedNode) {
463-
(movedNode as File).updateMetaData({
462+
if (movedNode && File.is(movedNode)) {
463+
movedNode.updateMetaData({
464464
uri: to.uri.resolve(newName),
465465
fileStat: {
466466
...to.filestat,
@@ -469,11 +469,38 @@ export class FileTreeService extends Tree implements IFileTreeService {
469469
},
470470
tooltip: this.fileTreeAPI.getReadableTooltip(to.uri.resolve(newName)),
471471
});
472+
if (Directory.is(movedNode)) {
473+
this.updateChildren(movedNode);
474+
}
472475
}
473476
return movedNode;
474477
}
475478
}
476479

480+
private async updateChildren(parent: Directory) {
481+
const children = parent.children;
482+
if (!children || children.length === 0) {
483+
return;
484+
}
485+
for (const child of children) {
486+
if (File.is(child)) {
487+
const newUri = parent.uri.resolve(child.uri.displayName);
488+
child.updateMetaData({
489+
uri: newUri,
490+
fileStat: {
491+
...child.filestat,
492+
uri: newUri.toString(),
493+
isDirectory: Directory.is(child) ? true : false,
494+
},
495+
tooltip: this.fileTreeAPI.getReadableTooltip(newUri),
496+
});
497+
if (Directory.is(child)) {
498+
this.updateChildren(child);
499+
}
500+
}
501+
}
502+
}
503+
477504
public async addNode(node: Directory, newName: string, type: TreeNodeType) {
478505
let tempFileStat: FileStat;
479506
let tempName: string;
@@ -527,8 +554,8 @@ export class FileTreeService extends Tree implements IFileTreeService {
527554
const nodes: File[] = [];
528555
for (const uri of uris) {
529556
const node = this.getNodeByPathOrUri(uri);
530-
if (node) {
531-
nodes.push(node as File);
557+
if (node && File.is(node)) {
558+
nodes.push(node);
532559
}
533560
}
534561
for (const node of nodes) {
@@ -660,12 +687,14 @@ export class FileTreeService extends Tree implements IFileTreeService {
660687
/**
661688
* 刷新指定下的所有子节点
662689
*/
663-
async refresh(node: Directory = this.root as Directory) {
690+
async refresh(node: Directory | File = this.root as Directory) {
664691
if (!node) {
665692
return;
666693
}
667-
if (!Directory.is(node) && node.parent) {
668-
node = node.parent as Directory;
694+
if (!Directory.is(node)) {
695+
if (File.is(node) && node.parent) {
696+
node = node.parent as Directory;
697+
}
669698
}
670699

671700
// 队列化刷新动作减少更新成本

packages/file-tree-next/src/browser/services/file-tree-model.service.ts

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,34 +1172,46 @@ export class FileTreeModelService {
11721172
if (promptHandle instanceof RenamePromptHandle) {
11731173
const target = promptHandle.target as File | Directory;
11741174
const nameFragments = (promptHandle.target as File).displayName.split(Path.separator);
1175-
const index = this.activeUri?.displayName ? nameFragments.indexOf(this.activeUri?.displayName) : -1;
1175+
const isCompactNode = target.name.indexOf(Path.separator) > 0;
1176+
if (
1177+
isCompactNode &&
1178+
this.activeUri &&
1179+
!(promptHandle.target as File).uri.toString().includes(this.activeUri.toString())
1180+
) {
1181+
// 当为压缩节点重命名,但 activeUri 与传入的文件不一致时,不允许重命名
1182+
return false;
1183+
}
1184+
const index = this.activeUri
1185+
? nameFragments.length -
1186+
(promptHandle.target as File).uri.toString().replace(this.activeUri.toString(), '').split(Path.separator)
1187+
.length
1188+
: -1;
11761189
const newNameFragments = index === -1 ? [] : nameFragments.slice(0, index).concat(newName);
11771190
let from = target.uri;
11781191
let to = (target.parent as Directory).uri.resolve(newName);
1179-
const isCompactNode = target.name.indexOf(Path.separator) > 0;
11801192
// 无变化,直接返回
11811193
if ((isCompactNode && this.activeUri?.displayName === newName) || (!isCompactNode && newName === target.name)) {
11821194
return true;
11831195
}
11841196
promptHandle.addAddonAfter('loading_indicator');
1185-
if (isCompactNode && newNameFragments.length > 0) {
1197+
if (isCompactNode && newNameFragments.length > 0 && Directory.is(target.parent)) {
11861198
// 压缩目录情况下,需要计算下标进行重命名路径拼接
1187-
from = (target.parent as Directory).uri.resolve(nameFragments.slice(0, index + 1).join(Path.separator));
1188-
to = (target.parent as Directory).uri.resolve(newNameFragments.concat().join(Path.separator));
1199+
from = target.parent.uri.resolve(nameFragments.slice(0, index + 1).join(Path.separator));
1200+
to = target.parent.uri.resolve(newNameFragments.concat().join(Path.separator));
11891201
}
1190-
this.fileTreeService.updateRefreshable(true);
11911202
const error = await this.fileTreeAPI.mv(from, to, target.type === TreeNodeType.CompositeTreeNode);
1192-
promptHandle.removeAddonAfter();
11931203
if (error) {
11941204
this.validateMessage = {
11951205
type: PROMPT_VALIDATE_TYPE.ERROR,
11961206
message: error,
11971207
value: newName,
11981208
};
1199-
this.fileTreeService.updateRefreshable(false);
1209+
this.fileTreeService.updateRefreshable(true);
12001210
promptHandle.addValidateMessage(this.validateMessage);
12011211
return false;
12021212
}
1213+
this.fileTreeService.updateRefreshable(false);
1214+
promptHandle.removeAddonAfter();
12031215
if (!isCompactNode && target.parent) {
12041216
// 重命名节点的情况,直接刷新一下父节点即可
12051217
const node = await this.fileTreeService.moveNodeByPath(
@@ -1212,11 +1224,12 @@ export class FileTreeModelService {
12121224
if (node) {
12131225
this.selectFileDecoration(node as File, false);
12141226
}
1215-
} else {
1227+
this.fileTreeService.updateRefreshable(true);
1228+
} else if (Directory.is(target)) {
12161229
// 更新压缩目录展示名称
12171230
// 由于节点移动时默认仅更新节点路径
12181231
// 我们需要自己更新额外的参数,如uri, filestat等
1219-
(target as Directory).updateMetaData({
1232+
target.updateMetaData({
12201233
name: newNameFragments.concat(nameFragments.slice(index + 1)).join(Path.separator),
12211234
uri: to,
12221235
fileStat: {
@@ -1227,15 +1240,18 @@ export class FileTreeModelService {
12271240
});
12281241
this.treeModel.dispatchChange();
12291242
let promise;
1230-
if ((target.parent as Directory).children?.find((child) => target.path.indexOf(child.path) >= 0)) {
1243+
if (
1244+
Directory.is(target.parent) &&
1245+
target.parent.children?.find((child) => target.path.indexOf(child.path) >= 0)
1246+
) {
12311247
// 当重命名后的压缩节点在父节点中存在子节点时,刷新父节点
12321248
// 如:
12331249
// 压缩节点 001/002 修改为 003/002 时
12341250
// 同时父节点下存在 003 空节点
1235-
promise = this.fileTreeService.refresh(target.parent as Directory);
1251+
promise = this.fileTreeService.refresh(target.parent);
12361252
} else {
12371253
// 压缩节点重命名时,刷新文件夹更新子文件路径
1238-
promise = this.fileTreeService.refresh(target as Directory);
1254+
promise = this.fileTreeService.refresh(target);
12391255
}
12401256
promise.then(() => {
12411257
selectNodeIfNodeExist(to);

packages/file-tree-next/src/common/file-tree-node.define.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ import { URI } from '@opensumi/ide-core-browser';
33
import { FileStat } from '@opensumi/ide-file-service';
44

55
export class Directory extends CompositeTreeNode {
6+
public static is(node: any): node is Directory {
7+
return CompositeTreeNode.is(node);
8+
}
9+
610
constructor(
711
tree: ITree,
812
parent: ICompositeTreeNode | undefined,
@@ -50,6 +54,10 @@ export class Directory extends CompositeTreeNode {
5054
}
5155

5256
export class File extends TreeNode {
57+
public static is(node: any): node is File {
58+
return TreeNode.is(node);
59+
}
60+
5361
constructor(
5462
tree: ITree,
5563
parent: CompositeTreeNode | undefined,

0 commit comments

Comments
 (0)