@lvce-editor/explorer-view 2.11.0 → 2.13.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.
@@ -861,46 +861,6 @@ const WebWorkerRpcClient = {
861
861
  create: create$1
862
862
  };
863
863
 
864
- const RE_CHARACTERS = /^[a-zA-Z.-]+$/;
865
- const compareStringNumeric = (a, b) => {
866
- if (RE_CHARACTERS.test(a) && RE_CHARACTERS.test(b)) {
867
- return a < b ? -1 : 1;
868
- }
869
- return a.localeCompare(b, 'en', {
870
- numeric: true
871
- });
872
- };
873
-
874
- const BlockDevice = 1;
875
- const CharacterDevice = 2;
876
- const Directory = 3;
877
- const DirectoryExpanded = 4;
878
- const DirectoryExpanding = 5;
879
- const File = 7;
880
- const Socket = 8;
881
- const Symlink = 9;
882
- const SymLinkFile = 10;
883
- const SymLinkFolder = 11;
884
- const Unknown = 12;
885
-
886
- const priorityMapFoldersFirst = {
887
- [Directory]: 1,
888
- [SymLinkFolder]: 1,
889
- [File]: 0,
890
- [SymLinkFile]: 0,
891
- [Unknown]: 0,
892
- [Socket]: 0
893
- };
894
- const compareDirentType = (direntA, direntB) => {
895
- return priorityMapFoldersFirst[direntB.type] - priorityMapFoldersFirst[direntA.type];
896
- };
897
- const compareDirentName = (direntA, direntB) => {
898
- return compareStringNumeric(direntA.name, direntB.name);
899
- };
900
- const compareDirent = (direntA, direntB) => {
901
- return compareDirentType(direntA, direntB) || compareDirentName(direntA, direntB);
902
- };
903
-
904
864
  const None$5 = 0;
905
865
  const CreateFile = 1;
906
866
  const CreateFolder = 2;
@@ -991,28 +951,140 @@ const fileOrFolderNameMustBeProvided = () => {
991
951
  const List = 1;
992
952
  const Input$1 = 2;
993
953
 
954
+ // TODO optimize this function to return the minimum number
955
+ // of visible items needed, e.g. when not scrolled 5 items with
956
+ // 20px fill 100px but when scrolled 6 items are needed
957
+ const getNumberOfVisibleItems = (listHeight, itemHeight) => {
958
+ return Math.ceil(listHeight / itemHeight) + 1;
959
+ };
960
+
961
+ const getExplorerMaxLineY = (minLineY, height, itemHeight, direntsLength) => {
962
+ const maxLineY = minLineY + Math.min(getNumberOfVisibleItems(height, itemHeight), direntsLength);
963
+ return maxLineY;
964
+ };
965
+
966
+ const getIconsCached = (dirents, fileIconCache) => {
967
+ return dirents.map(dirent => fileIconCache[dirent]);
968
+ };
969
+
970
+ const getMissingIconRequests = (dirents, fileIconCache) => {
971
+ const missingRequests = [];
972
+ for (const dirent of dirents) {
973
+ if (!(dirent.path in fileIconCache)) {
974
+ missingRequests.push({
975
+ type: dirent.type,
976
+ name: dirent.name,
977
+ path: dirent.path
978
+ });
979
+ }
980
+ }
981
+ return missingRequests;
982
+ };
983
+
984
+ const BlockDevice = 1;
985
+ const CharacterDevice = 2;
986
+ const Directory = 3;
987
+ const DirectoryExpanded = 4;
988
+ const DirectoryExpanding = 5;
989
+ const File = 7;
990
+ const Socket = 8;
991
+ const Symlink = 9;
992
+ const SymLinkFile = 10;
993
+ const SymLinkFolder = 11;
994
+ const Unknown = 12;
995
+
996
+ const RendererWorker = 1;
997
+
998
+ const rpcs = Object.create(null);
999
+ const set$1 = (id, rpc) => {
1000
+ rpcs[id] = rpc;
1001
+ };
1002
+ const get$1 = id => {
1003
+ return rpcs[id];
1004
+ };
1005
+
1006
+ const invoke = (method, ...params) => {
1007
+ const rpc = get$1(RendererWorker);
1008
+ // @ts-ignore
1009
+ return rpc.invoke(method, ...params);
1010
+ };
1011
+
1012
+ const requestFileIcons = async requests => {
1013
+ const promises = requests.map(request => request.type === File ? invoke('IconTheme.getFileIcon', {
1014
+ name: request.name
1015
+ }) : invoke('IconTheme.getFolderIcon', {
1016
+ name: request.name
1017
+ }));
1018
+ return Promise.all(promises);
1019
+ };
1020
+
1021
+ const updateIconCache = (iconCache, missingRequests, newIcons) => {
1022
+ if (missingRequests.length === 0) {
1023
+ return iconCache;
1024
+ }
1025
+ const newFileIconCache = {
1026
+ ...iconCache
1027
+ };
1028
+ for (let i = 0; i < missingRequests.length; i++) {
1029
+ const request = missingRequests[i];
1030
+ const icon = newIcons[i];
1031
+ newFileIconCache[request.path] = icon;
1032
+ }
1033
+ return newFileIconCache;
1034
+ };
1035
+
1036
+ const getFileIcons = async (dirents, fileIconCache) => {
1037
+ const missingRequests = getMissingIconRequests(dirents, fileIconCache);
1038
+ const newIcons = await requestFileIcons(missingRequests);
1039
+ const newFileIconCache = updateIconCache(fileIconCache, missingRequests, newIcons);
1040
+ const paths = dirents.map(dirent => dirent.path);
1041
+ const icons = getIconsCached(paths, newFileIconCache);
1042
+ return {
1043
+ icons,
1044
+ newFileIconCache
1045
+ };
1046
+ };
1047
+
1048
+ const RE_CHARACTERS = /^[a-zA-Z.-]+$/;
1049
+ const compareStringNumeric = (a, b) => {
1050
+ if (RE_CHARACTERS.test(a) && RE_CHARACTERS.test(b)) {
1051
+ return a < b ? -1 : 1;
1052
+ }
1053
+ return a.localeCompare(b, 'en', {
1054
+ numeric: true
1055
+ });
1056
+ };
1057
+
1058
+ const priorityMapFoldersFirst = {
1059
+ [Directory]: 1,
1060
+ [SymLinkFolder]: 1,
1061
+ [File]: 0,
1062
+ [SymLinkFile]: 0,
1063
+ [Unknown]: 0,
1064
+ [Socket]: 0
1065
+ };
1066
+ const compareDirentType = (direntA, direntB) => {
1067
+ return priorityMapFoldersFirst[direntB.type] - priorityMapFoldersFirst[direntA.type];
1068
+ };
1069
+ const compareDirentName = (direntA, direntB) => {
1070
+ return compareStringNumeric(direntA.name, direntB.name);
1071
+ };
1072
+ const compareDirent = (direntA, direntB) => {
1073
+ return compareDirentType(direntA, direntB) || compareDirentName(direntA, direntB);
1074
+ };
1075
+
994
1076
  const getParentFolder = (dirents, index, root) => {
995
1077
  if (index < 0) {
996
1078
  return root;
997
1079
  }
998
1080
  return dirents[index].path;
999
1081
  };
1000
- const acceptCreate = async (state, newDirentType, createFn) => {
1082
+ const getNewDirentsAccept = async (state, newDirentType, createFn) => {
1001
1083
  const {
1002
1084
  focusedIndex,
1003
1085
  editingValue
1004
1086
  } = state;
1005
1087
  const newFileName = editingValue;
1006
- if (!newFileName) {
1007
- // TODO show error message that file name must not be empty
1008
- // below input box
1009
- // await ErrorHandling.showErrorDialog(new Error('file name must not be empty'))
1010
- const editingErrorMessage = fileOrFolderNameMustBeProvided();
1011
- return {
1012
- ...state,
1013
- editingErrorMessage
1014
- };
1015
- }
1016
1088
  const parentFolder = getParentFolder(state.items, focusedIndex, state.root);
1017
1089
  const absolutePath = [parentFolder, newFileName].join(state.pathSeparator);
1018
1090
  // TODO better handle error
@@ -1021,7 +1093,10 @@ const acceptCreate = async (state, newDirentType, createFn) => {
1021
1093
  } catch (error) {
1022
1094
  console.error(new VError(error, `Failed to create file`));
1023
1095
  // TODO display error
1024
- return state;
1096
+ return {
1097
+ dirents: state.items,
1098
+ newFocusedIndex: state.focusedIndex
1099
+ };
1025
1100
  }
1026
1101
  const parentDirent = focusedIndex >= 0 ? state.items[focusedIndex] : {
1027
1102
  depth: 0};
@@ -1073,34 +1148,54 @@ const acceptCreate = async (state, newDirentType, createFn) => {
1073
1148
  // @ts-ignore
1074
1149
  items.splice(insertIndex + 1, 0, newDirent);
1075
1150
  const newDirents = [...items];
1076
- const newMaxlineY = Math.max(state.maxLineY, newDirents.length);
1151
+ return {
1152
+ dirents: newDirents,
1153
+ newFocusedIndex: insertIndex + 1
1154
+ };
1155
+ };
1156
+
1157
+ const acceptCreate = async (state, newDirentType, createFn) => {
1158
+ const {
1159
+ editingValue,
1160
+ minLineY,
1161
+ height,
1162
+ itemHeight,
1163
+ fileIconCache
1164
+ } = state;
1165
+ const newFileName = editingValue;
1166
+ if (!newFileName) {
1167
+ // TODO show error message that file name must not be empty
1168
+ // below input box
1169
+ // await ErrorHandling.showErrorDialog(new Error('file name must not be empty'))
1170
+ const editingErrorMessage = fileOrFolderNameMustBeProvided();
1171
+ return {
1172
+ ...state,
1173
+ editingErrorMessage
1174
+ };
1175
+ }
1176
+ const {
1177
+ dirents,
1178
+ newFocusedIndex
1179
+ } = await getNewDirentsAccept(state, newDirentType, createFn);
1180
+ const maxLineY = getExplorerMaxLineY(minLineY, height, itemHeight, dirents.length);
1181
+ const visible = dirents.slice(minLineY, maxLineY);
1182
+ const {
1183
+ icons,
1184
+ newFileIconCache
1185
+ } = await getFileIcons(visible, fileIconCache);
1077
1186
  return {
1078
1187
  ...state,
1079
- items: newDirents,
1188
+ items: dirents,
1080
1189
  editingIndex: -1,
1081
- focusedIndex: insertIndex + 1,
1190
+ focusedIndex: newFocusedIndex,
1082
1191
  editingType: None$5,
1083
- maxLineY: newMaxlineY,
1084
- focus: List
1192
+ maxLineY,
1193
+ focus: List,
1194
+ icons,
1195
+ fileIconCache: newFileIconCache
1085
1196
  };
1086
1197
  };
1087
1198
 
1088
- const RendererWorker = 1;
1089
-
1090
- const rpcs = Object.create(null);
1091
- const set$1 = (id, rpc) => {
1092
- rpcs[id] = rpc;
1093
- };
1094
- const get$1 = id => {
1095
- return rpcs[id];
1096
- };
1097
-
1098
- const invoke = (method, ...params) => {
1099
- const rpc = get$1(RendererWorker);
1100
- // @ts-ignore
1101
- return rpc.invoke(method, ...params);
1102
- };
1103
-
1104
1199
  const remove = async dirent => {
1105
1200
  return invoke('FileSystem.remove', dirent);
1106
1201
  };
@@ -1263,9 +1358,8 @@ const acceptRename = async state => {
1263
1358
  const oldParentPath = dirname(pathSeparator, oldAbsolutePath);
1264
1359
  const newAbsolutePath = [oldParentPath, editingValue].join(pathSeparator);
1265
1360
  await rename(oldAbsolutePath, newAbsolutePath);
1266
- } catch {
1267
- // TODO
1268
- // await ErrorHandling.showErrorDialog(error)
1361
+ } catch (error) {
1362
+ console.error(new VError(error, `Failed to rename file`));
1269
1363
  return state;
1270
1364
  }
1271
1365
  const {
@@ -1422,7 +1516,8 @@ const create2 = (uid, uri, x, y, width, height, args, parentUid, platform = 0) =
1422
1516
  icons: [],
1423
1517
  platform,
1424
1518
  focus: 0,
1425
- editingErrorMessage: ''
1519
+ editingErrorMessage: '',
1520
+ inputSource: 0
1426
1521
  };
1427
1522
  set(uid, state, state);
1428
1523
  };
@@ -1458,7 +1553,8 @@ const create = (id, uri, x, y, width, height, args, parentUid, platform = 0) =>
1458
1553
  icons: [],
1459
1554
  platform,
1460
1555
  focus: 0,
1461
- editingErrorMessage: ''
1556
+ editingErrorMessage: '',
1557
+ inputSource: 0
1462
1558
  };
1463
1559
  set(state.uid, state, state);
1464
1560
  return state;
@@ -1635,72 +1731,6 @@ const getChildDirents = async (pathSeparator, parentDirent, excluded = []) => {
1635
1731
  return displayDirents;
1636
1732
  };
1637
1733
 
1638
- // TODO optimize this function to return the minimum number
1639
- // of visible items needed, e.g. when not scrolled 5 items with
1640
- // 20px fill 100px but when scrolled 6 items are needed
1641
- const getNumberOfVisibleItems = (listHeight, itemHeight) => {
1642
- return Math.ceil(listHeight / itemHeight) + 1;
1643
- };
1644
-
1645
- const getExplorerMaxLineY = (minLineY, height, itemHeight, direntsLength) => {
1646
- const maxLineY = minLineY + Math.min(getNumberOfVisibleItems(height, itemHeight), direntsLength);
1647
- return maxLineY;
1648
- };
1649
-
1650
- const getIconsCached = (dirents, fileIconCache) => {
1651
- return dirents.map(dirent => fileIconCache[dirent]);
1652
- };
1653
-
1654
- const getMissingIconRequests = (dirents, fileIconCache) => {
1655
- const missingRequests = [];
1656
- for (const dirent of dirents) {
1657
- if (!(dirent.path in fileIconCache)) {
1658
- missingRequests.push({
1659
- type: dirent.type,
1660
- name: dirent.name,
1661
- path: dirent.path
1662
- });
1663
- }
1664
- }
1665
- return missingRequests;
1666
- };
1667
-
1668
- const requestFileIcons = async requests => {
1669
- const promises = requests.map(request => request.type === File ? invoke('IconTheme.getFileIcon', {
1670
- name: request.name
1671
- }) : invoke('IconTheme.getFolderIcon', {
1672
- name: request.name
1673
- }));
1674
- return Promise.all(promises);
1675
- };
1676
-
1677
- const updateIconCache = (iconCache, missingRequests, newIcons) => {
1678
- if (missingRequests.length === 0) {
1679
- return iconCache;
1680
- }
1681
- const newFileIconCache = {
1682
- ...iconCache
1683
- };
1684
- for (let i = 0; i < missingRequests.length; i++) {
1685
- const request = missingRequests[i];
1686
- const icon = newIcons[i];
1687
- newFileIconCache[request.path] = icon;
1688
- }
1689
- return newFileIconCache;
1690
- };
1691
-
1692
- const getFileIcons = async (dirents, fileIconCache) => {
1693
- const missingRequests = getMissingIconRequests(dirents, fileIconCache);
1694
- const newIcons = await requestFileIcons(missingRequests);
1695
- const newFileIconCache = updateIconCache(fileIconCache, missingRequests, newIcons);
1696
- const paths = dirents.map(dirent => dirent.path);
1697
- const icons = getIconsCached(paths, newFileIconCache);
1698
- return {
1699
- icons,
1700
- newFileIconCache
1701
- };
1702
- };
1703
-
1704
1734
  const expandAll = async state => {
1705
1735
  const {
1706
1736
  items,
@@ -3670,27 +3700,31 @@ const getFileIconVirtualDom = icon => {
3670
3700
  };
3671
3701
  };
3672
3702
 
3673
- const label = {
3674
- type: Div,
3675
- className: Label,
3676
- childCount: 1
3677
- };
3678
3703
  const getClassName$1 = hasEditingError => {
3679
3704
  if (hasEditingError) {
3680
3705
  return mergeClassNames(InputBox, InputValidationError);
3681
3706
  }
3682
3707
  return InputBox;
3683
3708
  };
3709
+ const getInputDom = hasEditingError => {
3710
+ return [{
3711
+ type: Input,
3712
+ className: getClassName$1(hasEditingError),
3713
+ id: 'ExplorerInput',
3714
+ onInput: HandleEditingInput,
3715
+ childCount: 0,
3716
+ name: ExplorerInput
3717
+ }];
3718
+ };
3719
+
3720
+ const label = {
3721
+ type: Div,
3722
+ className: Label,
3723
+ childCount: 1
3724
+ };
3684
3725
  const getInputOrLabelDom = (isEditing, hasEditingError, name) => {
3685
3726
  if (isEditing) {
3686
- return [{
3687
- type: Input,
3688
- className: getClassName$1(hasEditingError),
3689
- id: 'ExplorerInput',
3690
- onInput: HandleEditingInput,
3691
- childCount: 0,
3692
- name: ExplorerInput
3693
- }];
3727
+ return getInputDom(hasEditingError);
3694
3728
  }
3695
3729
  return [label, text(name)];
3696
3730
  };
@@ -4356,7 +4390,9 @@ const terminate = () => {
4356
4390
  globalThis.close();
4357
4391
  };
4358
4392
 
4359
- const updateEditingValue = (state, value) => {
4393
+ const User = 1;
4394
+
4395
+ const updateEditingValue = (state, value, inputSource = User) => {
4360
4396
  const editingIcon = '';
4361
4397
  return {
4362
4398
  ...state,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/explorer-view",
3
- "version": "2.11.0",
3
+ "version": "2.13.0",
4
4
  "description": "Explorer Worker",
5
5
  "repository": {
6
6
  "type": "git",