mirror of
https://github.com/multipleof4/GitRight.git
synced 2026-02-04 10:57:56 +00:00
Feat: Recursive copy/cut and visual feedback
This commit is contained in:
54
index.html
54
index.html
@@ -43,6 +43,7 @@
|
|||||||
this.$watch('fileTree', () => this.refreshIcons());
|
this.$watch('fileTree', () => this.refreshIcons());
|
||||||
this.$watch('contextMenu.show', (val) => val && this.refreshIcons());
|
this.$watch('contextMenu.show', (val) => val && this.refreshIcons());
|
||||||
this.$watch('commitModal', (val) => val && this.refreshIcons());
|
this.$watch('commitModal', (val) => val && this.refreshIcons());
|
||||||
|
this.$watch('clipboard', () => this.refreshIcons());
|
||||||
},
|
},
|
||||||
|
|
||||||
refreshIcons() {
|
refreshIcons() {
|
||||||
@@ -144,14 +145,15 @@
|
|||||||
const newName = prompt('Rename to:', oldName);
|
const newName = prompt('Rename to:', oldName);
|
||||||
if (newName && newName !== oldName) {
|
if (newName && newName !== oldName) {
|
||||||
const newPath = oldPath.substring(0, oldPath.lastIndexOf(oldName)) + newName;
|
const newPath = oldPath.substring(0, oldPath.lastIndexOf(oldName)) + newName;
|
||||||
const originalItem = this.fileTree.find(i => i.path === oldPath);
|
|
||||||
|
|
||||||
this.trackChange('rename', newPath, oldPath, originalItem.sha, originalItem.type);
|
const itemsToMove = this.fileTree.filter(i => i.path === oldPath || i.path.startsWith(oldPath + '/'));
|
||||||
|
|
||||||
this.fileTree = this.fileTree.map(item => {
|
this.fileTree = this.fileTree.map(item => {
|
||||||
if (item.path === oldPath) return { ...item, path: newPath };
|
const match = itemsToMove.find(m => m.path === item.path);
|
||||||
if (item.path.startsWith(oldPath + '/')) {
|
if (match) {
|
||||||
return { ...item, path: item.path.replace(oldPath + '/', newPath + '/') };
|
const updatedPath = item.path.replace(oldPath, newPath);
|
||||||
|
this.trackChange('rename', updatedPath, item.path, item.sha, item.type);
|
||||||
|
return { ...item, path: updatedPath };
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
@@ -162,9 +164,14 @@
|
|||||||
deleteItem() {
|
deleteItem() {
|
||||||
if (confirm('Are you sure, Meowster?')) {
|
if (confirm('Are you sure, Meowster?')) {
|
||||||
const target = this.contextMenu.target;
|
const target = this.contextMenu.target;
|
||||||
this.trackChange('delete', target.path, null, target.sha, target.type);
|
const itemsToDelete = this.fileTree.filter(i => i.path === target.path || i.path.startsWith(target.path + '/'));
|
||||||
|
|
||||||
|
itemsToDelete.forEach(item => {
|
||||||
|
this.trackChange('delete', item.path, null, item.sha, item.type);
|
||||||
|
});
|
||||||
|
|
||||||
this.fileTree = this.fileTree.filter(item =>
|
this.fileTree = this.fileTree.filter(item =>
|
||||||
item.path !== target.path && !item.path.startsWith(target.path + '/')
|
!itemsToDelete.some(d => d.path === item.path)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.contextMenu.show = false;
|
this.contextMenu.show = false;
|
||||||
@@ -180,25 +187,33 @@
|
|||||||
|
|
||||||
pasteItem() {
|
pasteItem() {
|
||||||
if (!this.clipboard.item) return;
|
if (!this.clipboard.item) return;
|
||||||
const name = this.clipboard.item.path.split('/').pop();
|
const oldPrefix = this.clipboard.item.path;
|
||||||
const newPath = this.currentPath ? `${this.currentPath}/${name}` : name;
|
const name = oldPrefix.split('/').pop();
|
||||||
|
const newPrefix = this.currentPath ? `${this.currentPath}/${name}` : name;
|
||||||
|
|
||||||
if (this.fileTree.some(i => i.path === newPath)) return alert('Collision detected.');
|
if (this.fileTree.some(i => i.path === newPrefix)) return alert('Collision detected, Meowster.');
|
||||||
|
if (this.clipboard.action === 'copy' && newPrefix.startsWith(oldPrefix + '/')) return alert('Cannot copy a folder into itself, Meowster.');
|
||||||
|
|
||||||
|
const itemsToProcess = this.fileTree.filter(i => i.path === oldPrefix || i.path.startsWith(oldPrefix + '/'));
|
||||||
|
|
||||||
if (this.clipboard.action === 'cut') {
|
if (this.clipboard.action === 'cut') {
|
||||||
const oldPath = this.clipboard.item.path;
|
|
||||||
this.trackChange('move', newPath, oldPath, this.clipboard.item.sha, this.clipboard.item.type);
|
|
||||||
this.fileTree = this.fileTree.map(item => {
|
this.fileTree = this.fileTree.map(item => {
|
||||||
if (item.path === oldPath) return { ...item, path: newPath };
|
const match = itemsToProcess.find(p => p.path === item.path);
|
||||||
if (item.path.startsWith(oldPath + '/')) {
|
if (match) {
|
||||||
return { ...item, path: item.path.replace(oldPath + '/', newPath + '/') };
|
const itemNewPath = item.path.replace(oldPrefix, newPrefix);
|
||||||
|
this.trackChange('move', itemNewPath, item.path, item.sha, item.type);
|
||||||
|
return { ...item, path: itemNewPath };
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
this.clipboard = { item: null, action: null };
|
this.clipboard = { item: null, action: null };
|
||||||
} else {
|
} else {
|
||||||
this.fileTree.push({ ...this.clipboard.item, path: newPath });
|
const newItems = itemsToProcess.map(item => {
|
||||||
this.trackChange('add', newPath, null, this.clipboard.item.sha, this.clipboard.item.type);
|
const itemNewPath = item.path.replace(oldPrefix, newPrefix);
|
||||||
|
this.trackChange('add', itemNewPath, null, item.sha, item.type);
|
||||||
|
return { ...item, path: itemNewPath, sha: item.sha };
|
||||||
|
});
|
||||||
|
this.fileTree.push(...newItems);
|
||||||
}
|
}
|
||||||
this.contextMenu.show = false;
|
this.contextMenu.show = false;
|
||||||
},
|
},
|
||||||
@@ -364,7 +379,10 @@
|
|||||||
@touchend.stop="handlePressEnd()"
|
@touchend.stop="handlePressEnd()"
|
||||||
@mousedown.stop="handlePressStart($event, item, 'item')"
|
@mousedown.stop="handlePressStart($event, item, 'item')"
|
||||||
@mouseup.stop="handlePressEnd()"
|
@mouseup.stop="handlePressEnd()"
|
||||||
class="flex flex-col items-center p-2 rounded-xl hover:bg-white hover:shadow-sm border border-transparent hover:border-slate-200 transition-all group"
|
:class="{
|
||||||
|
'opacity-40 grayscale pointer-events-none': clipboard.item && clipboard.action === 'cut' && (item.path === clipboard.item.path || item.path.startsWith(clipboard.item.path + '/')),
|
||||||
|
'flex flex-col items-center p-2 rounded-xl hover:bg-white hover:shadow-sm border border-transparent hover:border-slate-200 transition-all group': true
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<template x-if="item.type === 'tree'">
|
<template x-if="item.type === 'tree'">
|
||||||
|
|||||||
Reference in New Issue
Block a user