@iobroker/adapter-react-v5 4.13.4 → 4.13.5

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.
@@ -378,6 +378,17 @@ const styles = (theme) => ({
378
378
  },
379
379
  });
380
380
  const USER_DATA = '0_userdata.0';
381
+ function getParentDir(dir) {
382
+ const parts = (dir || '').split('/');
383
+ parts.length && parts.pop();
384
+ return parts.join('/');
385
+ }
386
+ function isFile(path) {
387
+ const ext = Utils_1.default.getFileExtension(path);
388
+ return !!((ext === null || ext === void 0 ? void 0 : ext.toLowerCase().match(/[a-z]+/)) && ext.length < 5);
389
+ }
390
+ const TABLE = 'Table';
391
+ const TILE = 'Tile';
381
392
  function sortFolders(a, b) {
382
393
  if (a.folder && b.folder) {
383
394
  return a.name > b.name ? 1 : (a.name < b.name ? -1 : 0);
@@ -390,17 +401,6 @@ function sortFolders(a, b) {
390
401
  }
391
402
  return a.name > b.name ? 1 : (a.name < b.name ? -1 : 0);
392
403
  }
393
- function getParentDir(dir) {
394
- const parts = (dir || '').split('/');
395
- parts.length && parts.pop();
396
- return parts.join('/');
397
- }
398
- function isFile(path) {
399
- const ext = Utils_1.default.getFileExtension(path);
400
- return !!((ext === null || ext === void 0 ? void 0 : ext.toLowerCase().match(/[a-z]+/)) && ext.length < 5);
401
- }
402
- const TABLE = 'Table';
403
- const TILE = 'Tile';
404
404
  /**
405
405
  * @extends {React.Component<import('./types').FileBrowserProps>}
406
406
  */
@@ -454,11 +454,11 @@ class FileBrowser extends react_1.Component {
454
454
  return null;
455
455
  }
456
456
  };
457
- let expandedStr = (window._localStorage || window.localStorage).getItem('files.expanded') || '[]';
457
+ const expandedStr = (window._localStorage || window.localStorage).getItem('files.expanded') || '[]';
458
458
  if (this.props.limitPath) {
459
459
  const parts = this.props.limitPath.split('/');
460
460
  this.limitToObjectID = parts[0];
461
- this.limitToPath = !parts.length ? null : (parts.length === 1 && parts[0] === '' ? null : parts.join('/'));
461
+ this.limitToPath = !parts.length ? null : parts.length === 1 && parts[0] === '' ? null : parts.join('/');
462
462
  if (this.limitToPath && this.limitToPath.endsWith('/')) {
463
463
  this.limitToPath.substring(0, this.limitToPath.length - 1);
464
464
  }
@@ -467,7 +467,11 @@ class FileBrowser extends react_1.Component {
467
467
  try {
468
468
  expanded = JSON.parse(expandedStr);
469
469
  if (this.limitToPath) {
470
- expanded = expanded.filter(id => { var _a; return id.startsWith(`${this.limitToPath}/`) || id === this.limitToPath || ((_a = this.limitToPath) === null || _a === void 0 ? void 0 : _a.startsWith(`${id}/`)); });
470
+ expanded = expanded.filter(id => {
471
+ var _a;
472
+ return id.startsWith(`${this.limitToPath}/`) ||
473
+ id === this.limitToPath || ((_a = this.limitToPath) === null || _a === void 0 ? void 0 : _a.startsWith(`${id}/`));
474
+ });
471
475
  }
472
476
  }
473
477
  catch (e) {
@@ -480,8 +484,10 @@ class FileBrowser extends react_1.Component {
480
484
  else {
481
485
  viewType = TABLE;
482
486
  }
483
- let selected = this.props.selected || (window._localStorage || window.localStorage).getItem('files.selected') || USER_DATA;
484
- let currentDir = '';
487
+ let selected = this.props.selected ||
488
+ (window._localStorage || window.localStorage).getItem('files.selected') ||
489
+ USER_DATA;
490
+ let currentDir;
485
491
  if (props.restrictToFolder) {
486
492
  selected = props.restrictToFolder;
487
493
  currentDir = props.restrictToFolder;
@@ -587,14 +593,12 @@ class FileBrowser extends react_1.Component {
587
593
  el && el.scrollIntoView();
588
594
  }
589
595
  }
590
- componentDidMount() {
596
+ async componentDidMount() {
591
597
  this.mounted = true;
592
- this.loadFolders();
593
- return this.props.socket.checkFeatureSupported('BINARY_STATE_EVENT')
594
- .then(result => {
595
- this.supportSubscribes = result;
596
- this.supportSubscribes && this.props.socket.subscribeFiles('*', '*', this.onFileChange);
597
- });
598
+ this.loadFolders()
599
+ .catch(error => console.error(`Cannot load folders: ${error}`));
600
+ this.supportSubscribes = await this.props.socket.checkFeatureSupported('BINARY_STATE_EVENT');
601
+ this.supportSubscribes && (await this.props.socket.subscribeFiles('*', '*', this.onFileChange));
598
602
  }
599
603
  componentWillUnmount() {
600
604
  this.supportSubscribes && this.props.socket.unsubscribeFiles('*', '*', this.onFileChange);
@@ -627,7 +631,7 @@ class FileBrowser extends react_1.Component {
627
631
  let newFoldersNotNull;
628
632
  if (!_newFolders) {
629
633
  newFoldersNotNull = {};
630
- Object.keys(this.state.folders).forEach(folder => newFoldersNotNull[folder] = this.state.folders[folder]);
634
+ Object.keys(this.state.folders).forEach(folder => (newFoldersNotNull[folder] = this.state.folders[folder]));
631
635
  }
632
636
  else {
633
637
  newFoldersNotNull = _newFolders;
@@ -641,7 +645,8 @@ class FileBrowser extends react_1.Component {
641
645
  }
642
646
  readDirSerial(adapter, relPath) {
643
647
  return new Promise((resolve, reject) => {
644
- if (this.browseList) { // if component still mounted
648
+ if (this.browseList) {
649
+ // if component still mounted
645
650
  this.browseList.push({
646
651
  resolve: resolve,
647
652
  reject,
@@ -665,9 +670,11 @@ class FileBrowser extends react_1.Component {
665
670
  this.setState({ queueLength: this.browseList.length });
666
671
  }
667
672
  this.browseList[0].processing = true;
668
- this.props.socket.readDir(this.browseList[0].adapter, this.browseList[0].relPath)
673
+ this.props.socket
674
+ .readDir(this.browseList[0].adapter, this.browseList[0].relPath)
669
675
  .then(files => {
670
- if (this.browseList) { // if component still mounted
676
+ if (this.browseList) {
677
+ // if component still mounted
671
678
  const item = this.browseList.shift();
672
679
  if (item) {
673
680
  const resolve = item.resolve;
@@ -695,7 +702,8 @@ class FileBrowser extends react_1.Component {
695
702
  }
696
703
  })
697
704
  .catch(e => {
698
- if (this.browseList) { // if component still mounted
705
+ if (this.browseList) {
706
+ // if component still mounted
699
707
  const item = this.browseList.shift();
700
708
  if (item) {
701
709
  const reject = item.reject;
@@ -828,7 +836,10 @@ class FileBrowser extends react_1.Component {
828
836
  level,
829
837
  };
830
838
  if (this.state.restrictToFolder) {
831
- if (item.folder && (item.id.startsWith(`${this.state.restrictToFolder}/`) || item.id === this.state.restrictToFolder || this.state.restrictToFolder.startsWith(`${item.id}/`))) {
839
+ if (item.folder &&
840
+ (item.id.startsWith(`${this.state.restrictToFolder}/`) ||
841
+ item.id === this.state.restrictToFolder ||
842
+ this.state.restrictToFolder.startsWith(`${item.id}/`))) {
832
843
  _folders.push(item);
833
844
  }
834
845
  else if (item.id.startsWith(`${this.state.restrictToFolder}/`)) {
@@ -836,7 +847,10 @@ class FileBrowser extends react_1.Component {
836
847
  }
837
848
  }
838
849
  else if (this.limitToPath) {
839
- if (item.folder && (item.id.startsWith(`${this.limitToPath}/`) || item.id === this.limitToPath || this.limitToPath.startsWith(`${item.id}/`))) {
850
+ if (item.folder &&
851
+ (item.id.startsWith(`${this.limitToPath}/`) ||
852
+ item.id === this.limitToPath ||
853
+ this.limitToPath.startsWith(`${item.id}/`))) {
840
854
  _folders.push(item);
841
855
  }
842
856
  else if (item.id.startsWith(`${this.limitToPath}/`)) {
@@ -873,7 +887,9 @@ class FileBrowser extends react_1.Component {
873
887
  if (!item.temp) {
874
888
  this.browseFolder(item.id)
875
889
  .then(folders => this.setState({ expanded, folders }))
876
- .catch(err => window.alert(err === NOT_FOUND ? this.props.t('ra_Cannot find "%s"', item.id) : this.props.t('ra_Cannot read "%s"', item.id)));
890
+ .catch(err => window.alert(err === NOT_FOUND
891
+ ? this.props.t('ra_Cannot find "%s"', item.id)
892
+ : this.props.t('ra_Cannot read "%s"', item.id)));
877
893
  }
878
894
  else {
879
895
  this.setState({ expanded });
@@ -921,7 +937,8 @@ class FileBrowser extends react_1.Component {
921
937
  if (this.props.onSelect) {
922
938
  const ext = Utils_1.default.getFileExtension(id);
923
939
  if ((!this.props.filterFiles || (ext && this.props.filterFiles.includes(ext))) &&
924
- (!this.state.filterByType || (ext && FileViewer_1.EXTENSIONS[this.state.filterByType].includes(ext)))) {
940
+ (!this.state.filterByType ||
941
+ (ext && FileViewer_1.EXTENSIONS[this.state.filterByType].includes(ext)))) {
925
942
  this.props.onSelect(id, false, !!this.state.folders[id]);
926
943
  }
927
944
  else {
@@ -944,34 +961,41 @@ class FileBrowser extends react_1.Component {
944
961
  if (this.state.viewType === TABLE &&
945
962
  this.state.filterEmpty &&
946
963
  (!this.state.folders[item.id] || !this.state.folders[item.id].length) &&
947
- item.id !== USER_DATA && !item.temp) {
964
+ item.id !== USER_DATA &&
965
+ !item.temp) {
948
966
  return null;
949
967
  }
950
- const Icon = expanded ? IconOpen_1.default : IconClosed_1.default;
968
+ const IconEl = expanded ? IconOpen_1.default : IconClosed_1.default;
951
969
  const padding = this.state.viewType === TABLE ? item.level * this.levelPadding : 0;
952
970
  const isUserData = item.name === USER_DATA;
953
971
  const isSpecialData = isUserData || item.name === 'vis.0' || item.name === 'vis-2.0';
954
972
  return react_1.default.createElement("div", { key: item.id, id: item.id, style: this.state.viewType === TABLE ? { marginLeft: padding, width: `calc(100% - ${padding}px` } : {}, onClick: e => (this.state.viewType === TABLE ? this.select(item.id, e) : this.changeFolder(e, item.id)), onDoubleClick: e => this.state.viewType === TABLE && this.toggleFolder(item, e), title: this.getText(item.title), className: Utils_1.default.clsx('browserItem', this.props.classes[`item${this.state.viewType}`], this.props.classes[`itemFolder${this.state.viewType}`], this.state.selected === item.id && this.props.classes.itemSelected, item.temp && this.props.classes.itemFolderTemp) },
955
- react_1.default.createElement(Icon, { className: Utils_1.default.clsx(this.props.classes[`itemFolderIcon${this.state.viewType}`], isSpecialData && this.props.classes.specialFolder), onClick: this.state.viewType === TABLE ? e => this.toggleFolder(item, e) : undefined }),
973
+ react_1.default.createElement(IconEl, { className: Utils_1.default.clsx(this.props.classes[`itemFolderIcon${this.state.viewType}`], isSpecialData && this.props.classes.specialFolder), onClick: this.state.viewType === TABLE ? e => this.toggleFolder(item, e) : undefined }),
956
974
  react_1.default.createElement("div", { className: Utils_1.default.clsx(this.props.classes[`itemName${this.state.viewType}`], this.props.classes[`itemNameFolder${this.state.viewType}`]) }, isUserData ? this.props.t('ra_User files') : item.name),
957
975
  react_1.default.createElement(material_1.Hidden, { smDown: true },
958
- react_1.default.createElement("div", { className: this.props.classes[`itemSize${this.state.viewType}`] }, this.state.viewType === TABLE && this.state.folders[item.id] ? this.state.folders[item.id].length : '')),
976
+ react_1.default.createElement("div", { className: this.props.classes[`itemSize${this.state.viewType}`] }, this.state.viewType === TABLE && this.state.folders[item.id]
977
+ ? this.state.folders[item.id].length
978
+ : '')),
959
979
  react_1.default.createElement(material_1.Hidden, { smDown: true }, this.state.viewType === TABLE && this.props.expertMode ? this.formatAcl(item.acl) : null),
960
- react_1.default.createElement(material_1.Hidden, { smDown: true }, this.state.viewType === TABLE && this.props.expertMode ? react_1.default.createElement("div", { className: this.props.classes[`itemDeleteButton${this.state.viewType}`] }) : null),
961
- this.state.viewType === TABLE && this.props.allowDownload ? react_1.default.createElement("div", { className: this.props.classes[`itemDownloadEmpty${this.state.viewType}`] }) : null,
962
- this.state.viewType === TABLE && this.props.allowDelete && this.state.folders[item.id] && this.state.folders[item.id].length ?
963
- react_1.default.createElement(material_1.IconButton, { "aria-label": "delete", onClick: e => {
964
- e.stopPropagation();
965
- if (this.suppressDeleteConfirm > Date.now()) {
966
- this.deleteItem(item.id);
967
- }
968
- else {
969
- this.setState({ deleteItem: item.id });
970
- }
971
- }, className: this.props.classes[`itemDeleteButton${this.state.viewType}`], size: "large" },
972
- react_1.default.createElement(icons_material_1.Delete, { fontSize: "small" }))
973
- :
974
- (this.state.viewType === TABLE && this.props.allowDelete ? react_1.default.createElement("div", { className: this.props.classes[`itemDeleteButton${this.state.viewType}`] }) : null));
980
+ react_1.default.createElement(material_1.Hidden, { smDown: true }, this.state.viewType === TABLE && this.props.expertMode ?
981
+ react_1.default.createElement("div", { className: this.props.classes[`itemDeleteButton${this.state.viewType}`] }) : null),
982
+ this.state.viewType === TABLE && this.props.allowDownload ?
983
+ react_1.default.createElement("div", { className: this.props.classes[`itemDownloadEmpty${this.state.viewType}`] }) : null,
984
+ this.state.viewType === TABLE &&
985
+ this.props.allowDelete &&
986
+ this.state.folders[item.id] &&
987
+ this.state.folders[item.id].length ? react_1.default.createElement(material_1.IconButton, { "aria-label": "delete", onClick: e => {
988
+ e.stopPropagation();
989
+ if (this.suppressDeleteConfirm > Date.now()) {
990
+ this.deleteItem(item.id);
991
+ }
992
+ else {
993
+ this.setState({ deleteItem: item.id });
994
+ }
995
+ }, className: this.props.classes[`itemDeleteButton${this.state.viewType}`], size: "large" },
996
+ react_1.default.createElement(icons_material_1.Delete, { fontSize: "small" })) :
997
+ this.state.viewType === TABLE && this.props.allowDelete ?
998
+ react_1.default.createElement("div", { className: this.props.classes[`itemDeleteButton${this.state.viewType}`] }) : null);
975
999
  }
976
1000
  renderBackFolder() {
977
1001
  return react_1.default.createElement("div", { key: this.state.currentDir, id: this.state.currentDir, onClick: e => this.changeFolder(e), title: this.props.t('ra_Back to %s', getParentDir(this.state.currentDir)), className: Utils_1.default.clsx('browserItem', this.props.classes[`item${this.state.viewType}`], this.props.classes[`itemFolder${this.state.viewType}`]) },
@@ -983,7 +1007,7 @@ class FileBrowser extends react_1.Component {
983
1007
  return react_1.default.createElement("div", { className: this.props.classes[`itemSize${this.state.viewType}`] }, size || size === 0 ? Utils_1.default.formatBytes(size) : '');
984
1008
  }
985
1009
  formatAcl(acl) {
986
- let access = acl && (acl.permissions || acl.file);
1010
+ const access = acl && (acl.permissions || acl.file);
987
1011
  let accessStr;
988
1012
  if (access) {
989
1013
  accessStr = access.toString(16).padStart(3, '0');
@@ -1040,7 +1064,9 @@ class FileBrowser extends react_1.Component {
1040
1064
  this.setState({ viewer: this.imagePrefix + item.id, formatEditFile: ext });
1041
1065
  }
1042
1066
  else if ((!this.props.filterFiles || (item.ext && this.props.filterFiles.includes(item.ext))) &&
1043
- (!this.state.filterByType || (item.ext && FileViewer_1.EXTENSIONS[this.state.filterByType].includes(item.ext)))) {
1067
+ (!this.state.filterByType ||
1068
+ (item.ext &&
1069
+ FileViewer_1.EXTENSIONS[this.state.filterByType].includes(item.ext)))) {
1044
1070
  this.props.onSelect(item.id, true, !!this.state.folders[item.id]);
1045
1071
  }
1046
1072
  }, onClick: e => this.select(item.id, e), style: this.state.viewType === TABLE ? { marginLeft: padding, width: `calc(100% - ${padding}px)` } : {}, className: Utils_1.default.clsx('browserItem', this.props.classes[`item${this.state.viewType}`], this.props.classes[`itemFile${this.state.viewType}`], this.state.selected === item.id && this.props.classes.itemSelected) },
@@ -1067,8 +1093,11 @@ class FileBrowser extends react_1.Component {
1067
1093
  if (!this.props.onSelect) {
1068
1094
  this.setState({ viewer: this.imagePrefix + item.id, formatEditFile: ext });
1069
1095
  }
1070
- else if ((!this.props.filterFiles || (item.ext && this.props.filterFiles.includes(item.ext))) &&
1071
- (!this.state.filterByType || (item.ext && FileViewer_1.EXTENSIONS[this.state.filterByType].includes(item.ext)))) {
1096
+ else if ((!this.props.filterFiles ||
1097
+ (item.ext && this.props.filterFiles.includes(item.ext))) &&
1098
+ (!this.state.filterByType ||
1099
+ (item.ext &&
1100
+ FileViewer_1.EXTENSIONS[this.state.filterByType].includes(item.ext)))) {
1072
1101
  this.props.onSelect(item.id, true, !!this.state.folders[item.id]);
1073
1102
  }
1074
1103
  }, className: this.props.classes[`itemDeleteButton${this.state.viewType}`], size: "large" },
@@ -1083,23 +1112,19 @@ class FileBrowser extends react_1.Component {
1083
1112
  this.props.allowDelete &&
1084
1113
  item.id !== 'vis.0/' &&
1085
1114
  item.id !== 'vis-2.0/' &&
1086
- item.id !== USER_DATA
1087
- ?
1088
- react_1.default.createElement(material_1.IconButton, { "aria-label": "delete", onClick: e => {
1089
- e.stopPropagation();
1090
- if (this.suppressDeleteConfirm > Date.now()) {
1091
- this.deleteItem(item.id);
1092
- }
1093
- else {
1094
- this.setState({ deleteItem: item.id });
1095
- }
1096
- }, className: this.props.classes[`itemDeleteButton${this.state.viewType}`], size: "large" },
1097
- react_1.default.createElement(icons_material_1.Delete, { fontSize: "small" }))
1115
+ item.id !== USER_DATA ? react_1.default.createElement(material_1.IconButton, { "aria-label": "delete", onClick: e => {
1116
+ e.stopPropagation();
1117
+ if (this.suppressDeleteConfirm > Date.now()) {
1118
+ this.deleteItem(item.id);
1119
+ }
1120
+ else {
1121
+ this.setState({ deleteItem: item.id });
1122
+ }
1123
+ }, className: this.props.classes[`itemDeleteButton${this.state.viewType}`], size: "large" },
1124
+ react_1.default.createElement(icons_material_1.Delete, { fontSize: "small" }))
1098
1125
  :
1099
1126
  (this.state.viewType === TABLE && this.props.allowDelete ?
1100
- react_1.default.createElement("div", { className: this.props.classes[`itemDeleteButton${this.state.viewType}`] })
1101
- :
1102
- null));
1127
+ react_1.default.createElement("div", { className: this.props.classes[`itemDeleteButton${this.state.viewType}`] }) : null));
1103
1128
  }
1104
1129
  renderItems(folderId) {
1105
1130
  if (this.state.folders && this.state.folders[folderId]) {
@@ -1114,7 +1139,9 @@ class FileBrowser extends react_1.Component {
1114
1139
  res.push(this.renderFolder(item));
1115
1140
  }
1116
1141
  else if ((!this.props.filterFiles || (item.ext && this.props.filterFiles.includes(item.ext))) &&
1117
- (!this.state.filterByType || (item.ext && FileViewer_1.EXTENSIONS[this.state.filterByType].includes(item.ext)))) {
1142
+ (!this.state.filterByType ||
1143
+ (item.ext &&
1144
+ FileViewer_1.EXTENSIONS[this.state.filterByType].includes(item.ext)))) {
1118
1145
  res.push(this.renderFile(item));
1119
1146
  }
1120
1147
  });
@@ -1134,7 +1161,7 @@ class FileBrowser extends react_1.Component {
1134
1161
  if (this.state.folders[item.id] && expanded) {
1135
1162
  const items = this.renderItems(item.id);
1136
1163
  if (Array.isArray(items)) {
1137
- items.forEach(item => totalResult.push(item));
1164
+ items.forEach(_item => totalResult.push(_item));
1138
1165
  }
1139
1166
  else {
1140
1167
  totalResult.push(items);
@@ -1142,7 +1169,9 @@ class FileBrowser extends react_1.Component {
1142
1169
  }
1143
1170
  }
1144
1171
  else if ((!this.props.filterFiles || (item.ext && this.props.filterFiles.includes(item.ext))) &&
1145
- (!this.state.filterByType || (item.ext && FileViewer_1.EXTENSIONS[this.state.filterByType].includes(item.ext)))) {
1172
+ (!this.state.filterByType ||
1173
+ (item.ext &&
1174
+ FileViewer_1.EXTENSIONS[this.state.filterByType].includes(item.ext)))) {
1146
1175
  totalResult.push(this.renderFile(item));
1147
1176
  }
1148
1177
  });
@@ -1151,16 +1180,23 @@ class FileBrowser extends react_1.Component {
1151
1180
  return react_1.default.createElement("div", { style: { position: 'relative' } },
1152
1181
  react_1.default.createElement(material_1.CircularProgress, { key: folderId, color: "secondary", size: 24 }),
1153
1182
  react_1.default.createElement("div", { style: {
1154
- position: 'absolute', zIndex: 2, top: 4, width: 24, textAlign: 'center',
1183
+ position: 'absolute',
1184
+ zIndex: 2,
1185
+ top: 4,
1186
+ width: 24,
1187
+ textAlign: 'center',
1155
1188
  } }, this.state.queueLength));
1156
1189
  }
1157
1190
  renderToolbar() {
1158
- const IconType = this.props.showTypeSelector ?
1159
- (FILE_TYPE_ICONS[this.state.filterByType || 'all'] || FILE_TYPE_ICONS.all) :
1160
- null;
1191
+ const IconType = this.props.showTypeSelector
1192
+ ? FILE_TYPE_ICONS[this.state.filterByType || 'all'] ||
1193
+ FILE_TYPE_ICONS.all
1194
+ : null;
1161
1195
  const isInFolder = this.findFirstFolder(this.state.selected);
1162
1196
  return react_1.default.createElement(material_1.Toolbar, { key: "toolbar", variant: "dense" },
1163
- this.props.allowNonRestricted && this.props.restrictToFolder ? react_1.default.createElement(material_1.IconButton, { edge: "start", title: this.state.restrictToFolder ? this.props.t('ra_Show all folders') : this.props.t('ra_Restrict to folder'), className: Utils_1.default.clsx(this.props.classes.menuButton, this.state.restrictToFolder && this.props.classes.menuButtonRestrictActive), "aria-label": "restricted to folder", onClick: () => this.setState({
1197
+ this.props.allowNonRestricted && this.props.restrictToFolder ? react_1.default.createElement(material_1.IconButton, { edge: "start", title: this.state.restrictToFolder
1198
+ ? this.props.t('ra_Show all folders')
1199
+ : this.props.t('ra_Restrict to folder'), className: Utils_1.default.clsx(this.props.classes.menuButton, this.state.restrictToFolder && this.props.classes.menuButtonRestrictActive), "aria-label": "restricted to folder", onClick: () => this.setState({
1164
1200
  restrictToFolder: (this.state.restrictToFolder ? '' : this.props.restrictToFolder) || '',
1165
1201
  loadAllFolders: true,
1166
1202
  }), size: "small" },
@@ -1257,10 +1293,12 @@ class FileBrowser extends react_1.Component {
1257
1293
  window.alert(this.props.t('ra_Invalid parent folder!'));
1258
1294
  return null;
1259
1295
  }
1260
- return react_1.default.createElement(TextInput_1.default, { key: "inputDialog", applyText: this.props.t('ra_Create'), cancelText: this.props.t('ra_Cancel'), titleText: this.props.t('ra_Create new folder in %s', this.state.selected), promptText: this.props.t('ra_If no file will be created in the folder, it will disappear after the browser closed'), labelText: this.props.t('ra_Folder name'), verify: (text) => (this.state.folders[parentFolder].find(item => item.name === text) ? '' : this.props.t('ra_Duplicate name')), onClose: (name) => {
1296
+ return react_1.default.createElement(TextInput_1.default, { key: "inputDialog", applyText: this.props.t('ra_Create'), cancelText: this.props.t('ra_Cancel'), titleText: this.props.t('ra_Create new folder in %s', this.state.selected), promptText: this.props.t('ra_If no file will be created in the folder, it will disappear after the browser closed'), labelText: this.props.t('ra_Folder name'), verify: (text) => (this.state.folders[parentFolder].find(item => item.name === text)
1297
+ ? ''
1298
+ : this.props.t('ra_Duplicate name')), onClose: (name) => {
1261
1299
  if (name) {
1262
1300
  const folders = {};
1263
- Object.keys(this.state.folders).forEach(folder => folders[folder] = this.state.folders[folder]);
1301
+ Object.keys(this.state.folders).forEach(folder => (folders[folder] = this.state.folders[folder]));
1264
1302
  const parent = this.findItem(parentFolder);
1265
1303
  const id = `${parentFolder}/${name}`;
1266
1304
  folders[parentFolder].push({
@@ -1283,7 +1321,7 @@ class FileBrowser extends react_1.Component {
1283
1321
  else {
1284
1322
  this.setState({ addFolder: false });
1285
1323
  }
1286
- }, replace: (text) => text.replace(/[^-_\w\d]/, '_') });
1324
+ }, replace: (text) => text.replace(/[^-_\w]/, '_') });
1287
1325
  }
1288
1326
  return null;
1289
1327
  }
@@ -1297,11 +1335,15 @@ class FileBrowser extends react_1.Component {
1297
1335
  }
1298
1336
  }, 100);
1299
1337
  }
1300
- uploadFile(fileName, data) {
1338
+ async uploadFile(fileName, data) {
1301
1339
  const parts = fileName.split('/');
1302
1340
  const adapter = parts.shift();
1303
- return this.props.socket.writeFile64(adapter || '', parts.join('/'), data)
1304
- .catch(e => window.alert(`Cannot write file: ${e}`));
1341
+ try {
1342
+ return await this.props.socket.writeFile64(adapter || '', parts.join('/'), data);
1343
+ }
1344
+ catch (e) {
1345
+ return window.alert(`Cannot write file: ${e}`);
1346
+ }
1305
1347
  }
1306
1348
  findFirstFolder(id) {
1307
1349
  let parentFolder = id;
@@ -1313,10 +1355,14 @@ class FileBrowser extends react_1.Component {
1313
1355
  parentFolder = '';
1314
1356
  while (parts.length) {
1315
1357
  const _item = this.findItem(parts.join('/'));
1316
- if (_item && _item.folder) {
1358
+ if (_item === null || _item === void 0 ? void 0 : _item.folder) {
1317
1359
  parentFolder = parts.join('/');
1318
1360
  break;
1319
1361
  }
1362
+ parts.pop();
1363
+ }
1364
+ if (!parts.length) {
1365
+ return null;
1320
1366
  }
1321
1367
  }
1322
1368
  return parentFolder;
@@ -1361,7 +1407,8 @@ class FileBrowser extends react_1.Component {
1361
1407
  if (!expanded.includes(parentFolder)) {
1362
1408
  expanded.push(parentFolder);
1363
1409
  expanded.sort();
1364
- (window._localStorage || window.localStorage).setItem('files.expanded', JSON.stringify(expanded));
1410
+ (window._localStorage ||
1411
+ window.localStorage).setItem('files.expanded', JSON.stringify(expanded));
1365
1412
  }
1366
1413
  this.setState({ folders, expanded }, () => this.select(id));
1367
1414
  }), 500);
@@ -1373,13 +1420,14 @@ class FileBrowser extends react_1.Component {
1373
1420
  };
1374
1421
  reader.readAsArrayBuffer(file);
1375
1422
  });
1376
- } }, ({ getRootProps, getInputProps }) => (react_1.default.createElement("div", Object.assign({ className: Utils_1.default.clsx(this.props.classes.uploadDiv, this.state.uploadFile === 'dragging' && this.props.classes.uploadDivDragging) }, getRootProps()),
1423
+ } }, ({ getRootProps, getInputProps }) => react_1.default.createElement("div", Object.assign({ className: Utils_1.default.clsx(this.props.classes.uploadDiv, this.state.uploadFile === 'dragging' && this.props.classes.uploadDivDragging) }, getRootProps()),
1377
1424
  react_1.default.createElement("input", Object.assign({}, getInputProps())),
1378
1425
  react_1.default.createElement("div", { className: this.props.classes.uploadCenterDiv },
1379
1426
  react_1.default.createElement("div", { className: this.props.classes.uploadCenterTextAndIcon },
1380
1427
  react_1.default.createElement(icons_material_1.Publish, { className: this.props.classes.uploadCenterIcon }),
1381
- react_1.default.createElement("div", { className: this.props.classes.uploadCenterText }, this.state.uploadFile === 'dragging' ? this.props.t('ra_Drop file here') :
1382
- this.props.t('ra_Place your files here or click here to open the browse dialog'))))))),
1428
+ react_1.default.createElement("div", { className: this.props.classes.uploadCenterText }, this.state.uploadFile === 'dragging'
1429
+ ? this.props.t('ra_Drop file here')
1430
+ : this.props.t('ra_Place your files here or click here to open the browse dialog')))))),
1383
1431
  ];
1384
1432
  }
1385
1433
  return null;
@@ -1387,14 +1435,15 @@ class FileBrowser extends react_1.Component {
1387
1435
  deleteRecursive(id) {
1388
1436
  const item = this.findItem(id);
1389
1437
  if (item === null || item === void 0 ? void 0 : item.folder) {
1390
- return (this.state.folders[id] ? Promise.all(this.state.folders[id].map(_item => this.deleteRecursive(_item.id))) : Promise.resolve())
1438
+ return (this.state.folders[id]
1439
+ ? Promise.all(this.state.folders[id].map(_item => this.deleteRecursive(_item.id)))
1440
+ : Promise.resolve())
1391
1441
  .then(() => {
1392
1442
  // If it is a folder of second level
1393
1443
  if (item.level >= 1) {
1394
1444
  const parts = id.split('/');
1395
1445
  const adapter = parts.shift();
1396
- this.props.socket.deleteFolder(adapter || '', parts.join('/'))
1397
- .then(() => {
1446
+ this.props.socket.deleteFolder(adapter || '', parts.join('/')).then(() => {
1398
1447
  // remove this folder
1399
1448
  const folders = JSON.parse(JSON.stringify(this.state.folders));
1400
1449
  delete folders[item.id];
@@ -1415,7 +1464,8 @@ class FileBrowser extends react_1.Component {
1415
1464
  const parts = id.split('/');
1416
1465
  const adapter = parts.shift();
1417
1466
  if (parts.length) {
1418
- return this.props.socket.deleteFile(adapter || '', parts.join('/'))
1467
+ return this.props.socket
1468
+ .deleteFile(adapter || '', parts.join('/'))
1419
1469
  .catch(e => window.alert(`Cannot delete file: ${e}`));
1420
1470
  }
1421
1471
  return Promise.resolve();
@@ -1522,7 +1572,11 @@ class FileBrowser extends react_1.Component {
1522
1572
  if (!this.state.folders[folder]) {
1523
1573
  this.browseFolder(folder)
1524
1574
  .then(folders => this.setState({ folders }, () => resolve(true)))
1525
- .catch(err => this.setState({ errorText: err === NOT_FOUND ? this.props.t('ra_Cannot find "%s"', folder) : this.props.t('ra_Cannot read "%s"', folder) }));
1575
+ .catch(err => this.setState({
1576
+ errorText: err === NOT_FOUND
1577
+ ? this.props.t('ra_Cannot find "%s"', folder)
1578
+ : this.props.t('ra_Cannot read "%s"', folder),
1579
+ }));
1526
1580
  }
1527
1581
  else {
1528
1582
  resolve(true);
@@ -1536,7 +1590,9 @@ class FileBrowser extends react_1.Component {
1536
1590
  }, 100);
1537
1591
  }
1538
1592
  renderBreadcrumb() {
1539
- const parts = this.state.currentDir.startsWith('/') ? this.state.currentDir.split('/') : (`/${this.state.currentDir}`).split('/');
1593
+ const parts = this.state.currentDir.startsWith('/')
1594
+ ? this.state.currentDir.split('/')
1595
+ : `/${this.state.currentDir}`.split('/');
1540
1596
  const p = [];
1541
1597
  return react_1.default.createElement(material_1.Breadcrumbs, { style: { paddingLeft: 8 } }, parts.map((part, i) => {
1542
1598
  part && p.push(part);
@@ -1550,10 +1606,10 @@ class FileBrowser extends react_1.Component {
1550
1606
  renderPath() {
1551
1607
  return react_1.default.createElement("div", { key: "path", className: this.props.classes.pathDiv }, this.state.pathFocus ?
1552
1608
  react_1.default.createElement(material_1.Input, { value: this.state.path, onKeyDown: e => {
1553
- if (e.keyCode === 13) {
1609
+ if (e.key === 'Enter') {
1554
1610
  this.changeToPath();
1555
1611
  }
1556
- else if (e.keyCode === 27) {
1612
+ else if (e.key === 'Escape') {
1557
1613
  this.setState({ pathFocus: false });
1558
1614
  }
1559
1615
  }, endAdornment: react_1.default.createElement(material_1.IconButton, { size: "small", onClick: () => this.changeToPath() },
@@ -1570,7 +1626,8 @@ class FileBrowser extends react_1.Component {
1570
1626
  setTimeout(() => {
1571
1627
  this.setState({ loadAllFolders: false, folders: {} }, () => {
1572
1628
  this.foldersLoading = false;
1573
- this.loadFolders();
1629
+ this.loadFolders()
1630
+ .catch(error => console.error(`Cannot load folders: ${error}`));
1574
1631
  });
1575
1632
  }, 300);
1576
1633
  }
@@ -1587,13 +1644,17 @@ class FileBrowser extends react_1.Component {
1587
1644
  }
1588
1645
  }
1589
1646
  } },
1590
- this.state.viewType === TABLE ? this.renderItems('/') : this.renderItems(this.state.currentDir || '/'),
1591
- this.state.viewType !== TABLE ? react_1.default.createElement("div", { className: this.props.classes.filesDivHint }, this.props.t('ra_select_folder_hint')) : null),
1647
+ this.state.viewType === TABLE
1648
+ ? this.renderItems('/')
1649
+ : this.renderItems(this.state.currentDir || '/'),
1650
+ this.state.viewType !== TABLE ? (react_1.default.createElement("div", { className: this.props.classes.filesDivHint }, this.props.t('ra_select_folder_hint'))) : null),
1592
1651
  this.props.allowUpload ? this.renderInputDialog() : null,
1593
1652
  this.props.allowUpload ? this.renderUpload() : null,
1594
1653
  this.props.allowDelete ? this.renderDeleteDialog() : null,
1595
1654
  this.props.allowView ? this.renderViewDialog() : null,
1596
- this.state.modalEditOfAccess && this.props.modalEditOfAccessControl ? this.props.modalEditOfAccessControl(this) : null,
1655
+ this.state.modalEditOfAccess && this.props.modalEditOfAccessControl
1656
+ ? this.props.modalEditOfAccessControl(this)
1657
+ : null,
1597
1658
  this.renderError());
1598
1659
  }
1599
1660
  }
package/README.md CHANGED
@@ -670,7 +670,7 @@ socket.getObjectViewCustom('custom', 'state', 'startKey', 'endKey')
670
670
  -->
671
671
 
672
672
  ## Changelog
673
- ### 4.13.4 (2024-04-02)
673
+ ### 4.13.5 (2024-04-02)
674
674
  * (bluefox) used new connection classes
675
675
  * (bluefox) Improved the `SelectID` dialog
676
676
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iobroker/adapter-react-v5",
3
- "version": "4.13.4",
3
+ "version": "4.13.5",
4
4
  "description": "React classes to develop admin interfaces for ioBroker with react.",
5
5
  "author": {
6
6
  "name": "Denis Haev (bluefox)",