@lvce-editor/explorer-view 4.7.0 → 4.8.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.
|
@@ -1727,6 +1727,22 @@ const getPathPartsChildren = async pathparts => {
|
|
|
1727
1727
|
return orderedPathParts;
|
|
1728
1728
|
};
|
|
1729
1729
|
|
|
1730
|
+
const getSiblingFileNames = (items, focusedIndex, root, pathSeparator) => {
|
|
1731
|
+
if (focusedIndex < 0 || focusedIndex >= items.length) {
|
|
1732
|
+
// If no focused item or invalid index, get root level items
|
|
1733
|
+
return items.filter(item => item.depth === 0).map(item => item.name);
|
|
1734
|
+
}
|
|
1735
|
+
const focusedItem = items[focusedIndex];
|
|
1736
|
+
const focusedItemParentPath = focusedItem.path.slice(0, -(focusedItem.name.length + 1));
|
|
1737
|
+
|
|
1738
|
+
// Find all items that are direct children of the same parent as the focused item
|
|
1739
|
+
const siblingItems = items.filter(item => {
|
|
1740
|
+
const itemParentPath = item.path.slice(0, -(item.name.length + 1));
|
|
1741
|
+
return itemParentPath === focusedItemParentPath;
|
|
1742
|
+
});
|
|
1743
|
+
return siblingItems.map(item => item.name);
|
|
1744
|
+
};
|
|
1745
|
+
|
|
1730
1746
|
const mergeTrees = (a, b) => {
|
|
1731
1747
|
return {
|
|
1732
1748
|
...a,
|
|
@@ -1788,6 +1804,7 @@ const CopyRelativePath = 'Copy Relative Path';
|
|
|
1788
1804
|
const Cut = 'Cut';
|
|
1789
1805
|
const Delete = 'Delete';
|
|
1790
1806
|
const FileNameCannotStartWithSlash = 'A file or folder name cannot start with a slash.';
|
|
1807
|
+
const FileOrFolderAlreadyExists = 'A file or folder **{0}** already exists at this location. Please choose a different name.';
|
|
1791
1808
|
const FileOrFolderNameMustBeProvider = 'A file or folder name must be provided.';
|
|
1792
1809
|
const FileCannotStartWithDot = 'A file or folder name cannot start with a dot.';
|
|
1793
1810
|
const FileCannotStartWithBackSlash = 'A file or folder name cannot start with a backslash.';
|
|
@@ -1866,8 +1883,11 @@ const fileCannotStartWithBackSlash = () => {
|
|
|
1866
1883
|
const typeAFileName = () => {
|
|
1867
1884
|
return i18nString(TypeAFileName);
|
|
1868
1885
|
};
|
|
1886
|
+
const fileOrFolderAlreadyExists = () => {
|
|
1887
|
+
return i18nString(FileOrFolderAlreadyExists);
|
|
1888
|
+
};
|
|
1869
1889
|
|
|
1870
|
-
const validateFileName2 = name => {
|
|
1890
|
+
const validateFileName2 = (name, siblingFileNames = []) => {
|
|
1871
1891
|
if (!name) {
|
|
1872
1892
|
const editingErrorMessage = fileOrFolderNameMustBeProvided();
|
|
1873
1893
|
return editingErrorMessage;
|
|
@@ -1881,6 +1901,11 @@ const validateFileName2 = name => {
|
|
|
1881
1901
|
if (name.startsWith(BackSlash)) {
|
|
1882
1902
|
return fileCannotStartWithBackSlash();
|
|
1883
1903
|
}
|
|
1904
|
+
|
|
1905
|
+
// Check if file already exists
|
|
1906
|
+
if (siblingFileNames.includes(name)) {
|
|
1907
|
+
return fileOrFolderAlreadyExists();
|
|
1908
|
+
}
|
|
1884
1909
|
return '';
|
|
1885
1910
|
};
|
|
1886
1911
|
|
|
@@ -1893,7 +1918,8 @@ const acceptCreate = async (state, newDirentType) => {
|
|
|
1893
1918
|
items
|
|
1894
1919
|
} = state;
|
|
1895
1920
|
const newFileName = editingValue;
|
|
1896
|
-
const
|
|
1921
|
+
const siblingFileNames = getSiblingFileNames(items, focusedIndex);
|
|
1922
|
+
const editingErrorMessage = validateFileName2(newFileName, siblingFileNames);
|
|
1897
1923
|
if (editingErrorMessage) {
|
|
1898
1924
|
return {
|
|
1899
1925
|
...state,
|
|
@@ -5077,10 +5103,12 @@ const renameDirent = async state => {
|
|
|
5077
5103
|
};
|
|
5078
5104
|
};
|
|
5079
5105
|
|
|
5080
|
-
const getCss = (scrollBarHeight, uniqueIndents) => {
|
|
5106
|
+
const getCss = (scrollBarHeight, uniqueIndents, errorMessageLeft, errorMessageTop) => {
|
|
5081
5107
|
// TODO each visible item should have an indent property
|
|
5082
5108
|
const rules = [`.Explorer {
|
|
5083
5109
|
--ScrollBarThumbHeight: ${scrollBarHeight}px;
|
|
5110
|
+
--ErrorMessageTop: ${errorMessageTop}px;
|
|
5111
|
+
--ErrorMessageLeft: ${errorMessageLeft}px;
|
|
5084
5112
|
}`];
|
|
5085
5113
|
for (const item of uniqueIndents) {
|
|
5086
5114
|
rules.push(`.Indent-${item} {
|
|
@@ -5105,11 +5133,13 @@ const renderCss = (oldState, newState) => {
|
|
|
5105
5133
|
const {
|
|
5106
5134
|
scrollBarHeight,
|
|
5107
5135
|
uid,
|
|
5108
|
-
visibleExplorerItems
|
|
5136
|
+
visibleExplorerItems,
|
|
5137
|
+
errorMessageLeft,
|
|
5138
|
+
errorMessageTop
|
|
5109
5139
|
} = newState;
|
|
5110
5140
|
const indents = visibleExplorerItems.map(item => item.indent);
|
|
5111
5141
|
const uniqueIndents = getUnique(indents);
|
|
5112
|
-
const css = getCss(scrollBarHeight, uniqueIndents);
|
|
5142
|
+
const css = getCss(scrollBarHeight, uniqueIndents, errorMessageLeft, errorMessageTop);
|
|
5113
5143
|
return [SetCss, uid, css];
|
|
5114
5144
|
};
|
|
5115
5145
|
|
|
@@ -5963,10 +5993,17 @@ const updateEditingValue = async (state, value, inputSource = User) => {
|
|
|
5963
5993
|
const {
|
|
5964
5994
|
editingType,
|
|
5965
5995
|
items,
|
|
5966
|
-
editingIndex
|
|
5996
|
+
editingIndex,
|
|
5997
|
+
focusedIndex
|
|
5967
5998
|
} = state;
|
|
5968
5999
|
const editingIcon = await getEditingIcon(editingType, value, items[editingIndex]?.type);
|
|
5969
|
-
|
|
6000
|
+
|
|
6001
|
+
// Get sibling file names for validation during file/folder creation
|
|
6002
|
+
let siblingFileNames = [];
|
|
6003
|
+
if (editingType === CreateFile || editingType === CreateFolder) {
|
|
6004
|
+
siblingFileNames = getSiblingFileNames(items, focusedIndex);
|
|
6005
|
+
}
|
|
6006
|
+
const editingErrorMessage = validateFileName2(value, siblingFileNames);
|
|
5970
6007
|
return {
|
|
5971
6008
|
...state,
|
|
5972
6009
|
editingValue: value,
|