@iobroker/adapter-react-v5 7.4.9 → 7.4.12

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.
package/README.md CHANGED
@@ -13,7 +13,7 @@ If you want to create the configuration page with ReactJS:
13
13
  - Change `name` from `src` to `ADAPTERNAME-admin` (Of course replace `ADAPTERNAME` with yours)
14
14
  - Add to devDependencies:
15
15
  ```json
16
- "@iobroker/adapter-react-v5": "^7.4.9",
16
+ "@iobroker/adapter-react-v5": "^7.4.10",
17
17
  ```
18
18
  Versions can be higher.
19
19
  So your `src/package.json` should look like:
@@ -24,7 +24,7 @@ If you want to create the configuration page with ReactJS:
24
24
  "version": "0.1.0",
25
25
  "private": true,
26
26
  "dependencies": {
27
- "@iobroker/adapter-react-v5": "^7.4.9",
27
+ "@iobroker/adapter-react-v5": "^7.4.10",
28
28
  "@iobroker/build-tools": "^1.0.0",
29
29
  "babel-eslint": "^10.1.0",
30
30
  "react-scripts": "^5.0.1"
@@ -94,7 +94,7 @@ export interface FolderOrFileItem {
94
94
  }
95
95
  export type Folders = Record<string, FolderOrFileItem[]>;
96
96
  interface FileBrowserState {
97
- viewType: string;
97
+ viewType: 'Table' | 'Tile';
98
98
  folders: Folders;
99
99
  filterEmpty: boolean;
100
100
  expanded: string[];
@@ -136,6 +136,8 @@ export declare class FileBrowserClass extends Component<FileBrowserProps, FileBr
136
136
  private foldersLoading;
137
137
  private cacheFolders;
138
138
  private readonly localStorage;
139
+ private readonly scrollPositions;
140
+ private readonly refFileDiv;
139
141
  constructor(props: FileBrowserProps);
140
142
  static getDerivedStateFromProps(props: FileBrowserProps, state: FileBrowserState): Partial<FileBrowserState> | null;
141
143
  loadFolders(): Promise<void>;
@@ -8,7 +8,7 @@ import React, { Component } from 'react';
8
8
  import Dropzone from 'react-dropzone';
9
9
  import { LinearProgress, ListItemIcon, ListItemText, Menu, MenuItem, Tooltip, CircularProgress, Toolbar, IconButton, Fab, Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, Button, Input, Breadcrumbs, Box, } from '@mui/material';
10
10
  // MUI Icons
11
- import { Refresh as RefreshIcon, Close as CloseIcon, Bookmark as JsonIcon, BookmarkBorder as CssIcon, Description as HtmlIcon, Edit as EditIcon, Code as JSIcon, InsertDriveFile as FileIcon, Publish as UploadIcon, MusicNote as MusicIcon, SaveAlt as DownloadIcon, CreateNewFolder as AddFolderIcon, FolderOpen as EmptyFilterIcon, List as IconList, ViewModule as IconTile, ArrowBack as IconBack, Delete as DeleteIcon, Brightness6 as Brightness5Icon, Image as TypeIconImages, FontDownload as TypeIconTxt, AudioFile as TypeIconAudio, Videocam as TypeIconVideo, KeyboardReturn as EnterIcon, FolderSpecial as RestrictedIcon, } from '@mui/icons-material';
11
+ import { ArrowBack as IconBack, AudioFile as TypeIconAudio, Bookmark as JsonIcon, BookmarkBorder as CssIcon, Brightness6 as Brightness5Icon, Close as CloseIcon, Code as JSIcon, CreateNewFolder as AddFolderIcon, Delete as DeleteIcon, Description as HtmlIcon, Edit as EditIcon, FolderOpen as EmptyFilterIcon, FolderSpecial as RestrictedIcon, FontDownload as TypeIconTxt, Image as TypeIconImages, InsertDriveFile as FileIcon, KeyboardReturn as EnterIcon, List as IconList, MusicNote as MusicIcon, Publish as UploadIcon, Refresh as RefreshIcon, SaveAlt as DownloadIcon, Videocam as TypeIconVideo, ViewModule as IconTile, } from '@mui/icons-material';
12
12
  import { DialogError } from '../Dialogs/Error';
13
13
  import { Utils } from './Utils';
14
14
  import { DialogTextInput } from '../Dialogs/TextInput';
@@ -41,7 +41,7 @@ const styles = {
41
41
  position: 'relative',
42
42
  },
43
43
  filesDiv: {
44
- width: 'calc(100% - 16px)',
44
+ width: 'calc(100% - 8px)',
45
45
  overflowX: 'hidden',
46
46
  overflowY: 'auto',
47
47
  padding: 8,
@@ -106,7 +106,7 @@ const styles = {
106
106
  top: 22,
107
107
  left: 18,
108
108
  zIndex: 1,
109
- color: theme.palette.mode === 'dark' ? '#FFF' : '#000',
109
+ color: theme.palette.mode === 'dark' ? '#FFF' : '#FFF',
110
110
  }),
111
111
  itemSizeTile: {
112
112
  width: '100%',
@@ -319,6 +319,8 @@ const styles = {
319
319
  overflow: 'hidden',
320
320
  whiteSpace: 'nowrap',
321
321
  backgroundColor: theme.palette.secondary.main,
322
+ color: theme.palette.secondary.contrastText,
323
+ borderRadius: '4px 4px 0 0',
322
324
  }),
323
325
  pathDivInput: {
324
326
  width: '100%',
@@ -327,12 +329,15 @@ const styles = {
327
329
  pl: '2px',
328
330
  pr: '2px',
329
331
  cursor: 'pointer',
332
+ color: 'white',
330
333
  '&:hover': {
331
- background: theme.palette.primary.main,
334
+ backgroundColor: theme.palette.primary.main,
335
+ color: theme.palette.primary.contrastText,
332
336
  },
333
337
  }),
334
338
  pathDivBreadcrumbSelected: {
335
- // todo: add style
339
+ // todo: add style
340
+ color: '#FFF',
336
341
  },
337
342
  backgroundImageLight: {
338
343
  background: 'white',
@@ -394,10 +399,13 @@ export class FileBrowserClass extends Component {
394
399
  foldersLoading = null;
395
400
  cacheFolders = null;
396
401
  localStorage;
402
+ scrollPositions = {};
403
+ refFileDiv;
397
404
  constructor(props) {
398
405
  super(props);
399
406
  this.localStorage = window._localStorage || window.localStorage;
400
407
  const expandedStr = this.localStorage.getItem('files.expanded') || '[]';
408
+ this.refFileDiv = React.createRef();
401
409
  if (this.props.limitPath) {
402
410
  const parts = this.props.limitPath.split('/');
403
411
  this.limitToObjectID = parts[0];
@@ -890,6 +898,10 @@ export class FileBrowserClass extends Component {
890
898
  if (_folder === '/') {
891
899
  _folder = '';
892
900
  }
901
+ // remember scroll position for this folder
902
+ if (this.state.viewType === 'Tile' && this.refFileDiv.current?.scrollTop) {
903
+ this.scrollPositions[this.state.currentDir] = this.refFileDiv.current.scrollTop;
904
+ }
893
905
  this.localStorage.setItem('files.currentDir', _folder);
894
906
  if (folder && e && (e.altKey || e.shiftKey || e.ctrlKey || e.metaKey)) {
895
907
  this.setState({ selected: _folder });
@@ -913,7 +925,19 @@ export class FileBrowserClass extends Component {
913
925
  selected: _folder,
914
926
  path: _folder,
915
927
  pathFocus: false,
916
- }, () => this.props.onSelect && this.props.onSelect(''));
928
+ }, () => {
929
+ if (this.props.onSelect) {
930
+ this.props.onSelect('');
931
+ }
932
+ // scroll to previous position
933
+ if (this.state.viewType === 'Tile' && this.scrollPositions[this.state.currentDir]) {
934
+ const pos = this.scrollPositions[this.state.currentDir];
935
+ delete this.scrollPositions[this.state.currentDir];
936
+ if (this.refFileDiv.current) {
937
+ this.refFileDiv.current.scrollTop = pos;
938
+ }
939
+ }
940
+ });
917
941
  }
918
942
  select(id, e, cb) {
919
943
  if (e) {
@@ -948,9 +972,10 @@ export class FileBrowserClass extends Component {
948
972
  return undefined;
949
973
  }
950
974
  renderFolder(item, expanded) {
951
- if (this.state.viewType === TABLE &&
952
- this.state.filterEmpty &&
953
- (!this.state.folders[item.id] || !this.state.folders[item.id].length) &&
975
+ if (
976
+ // this.state.viewType === TABLE &&
977
+ this.state.filterEmpty &&
978
+ !this.state.folders[item.id]?.length && // if the folder is empty
954
979
  item.id !== USER_DATA &&
955
980
  !item.temp) {
956
981
  return null;
@@ -960,7 +985,9 @@ export class FileBrowserClass extends Component {
960
985
  const isUserData = item.name === USER_DATA;
961
986
  const isSpecialData = isUserData || item.name === 'vis.0' || item.name === 'vis-2.0';
962
987
  const iconStyle = Utils.getStyle(this.props.theme, styles[`itemFolderIcon${this.state.viewType}`], isSpecialData && styles.specialFolder);
963
- return (React.createElement(Box, { component: "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: "browserItem", sx: Utils.getStyle(this.props.theme, styles[`item${this.state.viewType}`], styles[`itemFolder${this.state.viewType}`], this.state.selected === item.id ? styles.itemSelected : {}, item.temp ? styles.itemFolderTemp : {}) },
988
+ return (React.createElement(Box, { component: "div", key: item.id, id: item.id, style: this.state.viewType === TABLE
989
+ ? { marginLeft: padding, width: `calc(100% - ${padding}px` }
990
+ : undefined, 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: "browserItem", sx: Utils.getStyle(this.props.theme, styles[`item${this.state.viewType}`], styles[`itemFolder${this.state.viewType}`], this.state.selected === item.id ? styles.itemSelected : {}, item.temp ? styles.itemFolderTemp : {}) },
964
991
  React.createElement(IconEl, { style: iconStyle, onClick: this.state.viewType === TABLE ? (e) => this.toggleFolder(item, e) : undefined }),
965
992
  React.createElement(Box, { component: "div", sx: Utils.getStyle(this.props.theme, styles[`itemName${this.state.viewType}`], styles[`itemNameFolder${this.state.viewType}`]) }, isUserData ? this.props.t('ra_User files') : item.name),
966
993
  React.createElement(Box, { component: "div", style: styles[`itemSize${this.state.viewType}`], sx: { display: { md: 'inline-block', sm: 'none' } } }, this.state.viewType === TABLE && this.state.folders[item.id]
@@ -1083,7 +1110,9 @@ export class FileBrowserClass extends Component {
1083
1110
  EXTENSIONS[this.state.filterByType].includes(item.ext)))) {
1084
1111
  this.props.onSelect(item.id, true, !!this.state.folders[item.id]);
1085
1112
  }
1086
- }, onClick: e => this.select(item.id, e), style: this.state.viewType === TABLE ? { marginLeft: padding, width: `calc(100% - ${padding}px)` } : {}, className: "browserItem", sx: Utils.getStyle(this.props.theme, styles[`item${this.state.viewType}`], styles[`itemFile${this.state.viewType}`], this.state.selected === item.id ? styles.itemSelected : undefined) },
1113
+ }, onClick: e => this.select(item.id, e), style: this.state.viewType === TABLE
1114
+ ? { marginLeft: padding, width: `calc(100% - ${padding}px)` }
1115
+ : undefined, className: "browserItem", sx: Utils.getStyle(this.props.theme, styles[`item${this.state.viewType}`], styles[`itemFile${this.state.viewType}`], this.state.selected === item.id ? styles.itemSelected : undefined) },
1087
1116
  ext && EXTENSIONS.images.includes(ext) ? (this.state.fileErrors.includes(item.id) ? (React.createElement(IconNoIcon, { style: {
1088
1117
  ...styles[`itemImage${this.state.viewType}`],
1089
1118
  ...this.getStyleBackgroundImage(),
@@ -1131,7 +1160,7 @@ export class FileBrowserClass extends Component {
1131
1160
  React.createElement(DeleteIcon, { fontSize: "small" }))) : this.state.viewType === TABLE && this.props.allowDelete ? (React.createElement(Box, { component: "div", sx: styles[`itemDeleteButton${this.state.viewType}`] })) : null));
1132
1161
  }
1133
1162
  renderItems(folderId) {
1134
- if (this.state.folders && this.state.folders[folderId]) {
1163
+ if (this.state.folders?.[folderId]) {
1135
1164
  // tile
1136
1165
  if (this.state.viewType === TILE) {
1137
1166
  const res = [];
@@ -1151,6 +1180,7 @@ export class FileBrowserClass extends Component {
1151
1180
  });
1152
1181
  return res;
1153
1182
  }
1183
+ // table
1154
1184
  const totalResult = [];
1155
1185
  this.state.folders[folderId].forEach(item => {
1156
1186
  if (item.folder) {
@@ -1602,7 +1632,7 @@ export class FileBrowserClass extends Component {
1602
1632
  ? this.state.currentDir.split('/')
1603
1633
  : `/${this.state.currentDir}`.split('/');
1604
1634
  const p = [];
1605
- return (React.createElement(Breadcrumbs, { style: { paddingLeft: 8 } }, parts.map((part, i) => {
1635
+ return (React.createElement(Breadcrumbs, { style: { paddingLeft: 8, color: '#FFF' } }, parts.map((part, i) => {
1606
1636
  if (part) {
1607
1637
  p.push(part);
1608
1638
  }
@@ -1652,7 +1682,7 @@ export class FileBrowserClass extends Component {
1652
1682
  e.stopPropagation();
1653
1683
  }
1654
1684
  }
1655
- } },
1685
+ }, id: "dev", ref: this.refFileDiv },
1656
1686
  this.state.viewType === TABLE
1657
1687
  ? this.renderItems('/')
1658
1688
  : this.renderItems(this.state.currentDir || '/'),