Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 37 additions & 8 deletions packages/file-tree-next/src/browser/file-tree.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ export class FileTreeService extends Tree implements IFileTreeService {
}
}

// 软链接目录下,文件节点路径不能通过uri去获取,存在偏差
// 软链接目录下,文件节点路径不能通过 uri 去获取,存在偏差
public async moveNodeByPath(
from: Directory,
to: Directory,
Expand All @@ -459,8 +459,8 @@ export class FileTreeService extends Tree implements IFileTreeService {
if (oldPath && newPath && newPath !== oldPath) {
const movedNode = from.moveNode(oldPath, newPath);
// 更新节点除了 name 以外的其他属性,如 fileStat,tooltip 等,否则节点数据可能会异常
if (movedNode) {
(movedNode as File).updateMetaData({
if (movedNode && File.is(movedNode)) {
movedNode.updateMetaData({
uri: to.uri.resolve(newName),
fileStat: {
...to.filestat,
Expand All @@ -469,11 +469,38 @@ export class FileTreeService extends Tree implements IFileTreeService {
},
tooltip: this.fileTreeAPI.getReadableTooltip(to.uri.resolve(newName)),
});
if (Directory.is(movedNode)) {
this.updateChildren(movedNode);
}
}
return movedNode;
}
}

private async updateChildren(parent: Directory) {
const children = parent.children;
if (!children || children.length === 0) {
return;
}
for (const child of children) {
if (File.is(child)) {
const newUri = parent.uri.resolve(child.uri.displayName);
child.updateMetaData({
uri: newUri,
fileStat: {
...child.filestat,
uri: newUri.toString(),
isDirectory: Directory.is(child) ? true : false,
},
tooltip: this.fileTreeAPI.getReadableTooltip(newUri),
});
if (Directory.is(child)) {
this.updateChildren(child);
}
}
}
}

public async addNode(node: Directory, newName: string, type: TreeNodeType) {
let tempFileStat: FileStat;
let tempName: string;
Expand Down Expand Up @@ -527,8 +554,8 @@ export class FileTreeService extends Tree implements IFileTreeService {
const nodes: File[] = [];
for (const uri of uris) {
const node = this.getNodeByPathOrUri(uri);
if (node) {
nodes.push(node as File);
if (node && File.is(node)) {
nodes.push(node);
}
}
for (const node of nodes) {
Expand Down Expand Up @@ -660,12 +687,14 @@ export class FileTreeService extends Tree implements IFileTreeService {
/**
* 刷新指定下的所有子节点
*/
async refresh(node: Directory = this.root as Directory) {
async refresh(node: Directory | File = this.root as Directory) {
if (!node) {
return;
}
if (!Directory.is(node) && node.parent) {
node = node.parent as Directory;
if (!Directory.is(node)) {
if (File.is(node) && node.parent) {
node = node.parent as Directory;
}
}

// 队列化刷新动作减少更新成本
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1172,34 +1172,46 @@ export class FileTreeModelService {
if (promptHandle instanceof RenamePromptHandle) {
const target = promptHandle.target as File | Directory;
const nameFragments = (promptHandle.target as File).displayName.split(Path.separator);
const index = this.activeUri?.displayName ? nameFragments.indexOf(this.activeUri?.displayName) : -1;
const isCompactNode = target.name.indexOf(Path.separator) > 0;
if (
isCompactNode &&
this.activeUri &&
!(promptHandle.target as File).uri.toString().includes(this.activeUri.toString())
) {
// 当为压缩节点重命名,但 activeUri 与传入的文件不一致时,不允许重命名
return false;
}
const index = this.activeUri
? nameFragments.length -
(promptHandle.target as File).uri.toString().replace(this.activeUri.toString(), '').split(Path.separator)
.length
: -1;
const newNameFragments = index === -1 ? [] : nameFragments.slice(0, index).concat(newName);
let from = target.uri;
let to = (target.parent as Directory).uri.resolve(newName);
const isCompactNode = target.name.indexOf(Path.separator) > 0;
// 无变化,直接返回
if ((isCompactNode && this.activeUri?.displayName === newName) || (!isCompactNode && newName === target.name)) {
return true;
}
promptHandle.addAddonAfter('loading_indicator');
if (isCompactNode && newNameFragments.length > 0) {
if (isCompactNode && newNameFragments.length > 0 && Directory.is(target.parent)) {
// 压缩目录情况下,需要计算下标进行重命名路径拼接
from = (target.parent as Directory).uri.resolve(nameFragments.slice(0, index + 1).join(Path.separator));
to = (target.parent as Directory).uri.resolve(newNameFragments.concat().join(Path.separator));
from = target.parent.uri.resolve(nameFragments.slice(0, index + 1).join(Path.separator));
to = target.parent.uri.resolve(newNameFragments.concat().join(Path.separator));
}
this.fileTreeService.updateRefreshable(true);
const error = await this.fileTreeAPI.mv(from, to, target.type === TreeNodeType.CompositeTreeNode);
promptHandle.removeAddonAfter();
if (error) {
this.validateMessage = {
type: PROMPT_VALIDATE_TYPE.ERROR,
message: error,
value: newName,
};
this.fileTreeService.updateRefreshable(false);
this.fileTreeService.updateRefreshable(true);
promptHandle.addValidateMessage(this.validateMessage);
return false;
}
this.fileTreeService.updateRefreshable(false);
promptHandle.removeAddonAfter();
if (!isCompactNode && target.parent) {
// 重命名节点的情况,直接刷新一下父节点即可
const node = await this.fileTreeService.moveNodeByPath(
Expand All @@ -1212,11 +1224,12 @@ export class FileTreeModelService {
if (node) {
this.selectFileDecoration(node as File, false);
}
} else {
this.fileTreeService.updateRefreshable(true);
} else if (Directory.is(target)) {
// 更新压缩目录展示名称
// 由于节点移动时默认仅更新节点路径
// 我们需要自己更新额外的参数,如uri, filestat等
(target as Directory).updateMetaData({
target.updateMetaData({
name: newNameFragments.concat(nameFragments.slice(index + 1)).join(Path.separator),
uri: to,
fileStat: {
Expand All @@ -1227,15 +1240,18 @@ export class FileTreeModelService {
});
this.treeModel.dispatchChange();
let promise;
if ((target.parent as Directory).children?.find((child) => target.path.indexOf(child.path) >= 0)) {
if (
Directory.is(target.parent) &&
target.parent.children?.find((child) => target.path.indexOf(child.path) >= 0)
) {
// 当重命名后的压缩节点在父节点中存在子节点时,刷新父节点
// 如:
// 压缩节点 001/002 修改为 003/002 时
// 同时父节点下存在 003 空节点
promise = this.fileTreeService.refresh(target.parent as Directory);
promise = this.fileTreeService.refresh(target.parent);
} else {
// 压缩节点重命名时,刷新文件夹更新子文件路径
promise = this.fileTreeService.refresh(target as Directory);
promise = this.fileTreeService.refresh(target);
}
promise.then(() => {
selectNodeIfNodeExist(to);
Expand Down
8 changes: 8 additions & 0 deletions packages/file-tree-next/src/common/file-tree-node.define.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { URI } from '@opensumi/ide-core-browser';
import { FileStat } from '@opensumi/ide-file-service';

export class Directory extends CompositeTreeNode {
public static is(node: any): node is Directory {
return CompositeTreeNode.is(node);
}

constructor(
tree: ITree,
parent: ICompositeTreeNode | undefined,
Expand Down Expand Up @@ -50,6 +54,10 @@ export class Directory extends CompositeTreeNode {
}

export class File extends TreeNode {
public static is(node: any): node is File {
return TreeNode.is(node);
}

constructor(
tree: ITree,
parent: CompositeTreeNode | undefined,
Expand Down