cozy-ui 57.10.0 → 58.0.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,24 @@
1
+ # [58.0.0](https://github.com/cozy/cozy-ui/compare/v57.10.0...v58.0.0) (2021-12-03)
2
+
3
+
4
+ ### Features
5
+
6
+ * Renamed ImageLoader & Exposed it directly ([2ca789b](https://github.com/cozy/cozy-ui/commit/2ca789b))
7
+
8
+
9
+ ### BREAKING CHANGES
10
+
11
+ * `ImageLoader` is rename `FileImageLoader`.
12
+ If you were previously importing `ImageLoader`
13
+ via the `Viewer`like this
14
+ `import ImageLoader from 'cozy-ui/transpiled/react/Viewer/ImageLoader'`
15
+ this no longer works, there is a more direct path:
16
+ `import ImageLoader from 'cozy-ui/transpiled/react/ImageLoader`.
17
+ The method `checkImageSource` has been moved also
18
+ from `Viewer` folder to `ImageLoader` folder.
19
+
20
+ Co-authored-by: JF-Cozy
21
+
1
22
  # [57.10.0](https://github.com/cozy/cozy-ui/compare/v57.9.2...v57.10.0) (2021-11-29)
2
23
 
3
24
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-ui",
3
- "version": "57.10.0",
3
+ "version": "58.0.0",
4
4
  "description": "Cozy apps UI SDK",
5
5
  "main": "./index.js",
6
6
  "bin": {
@@ -140,7 +140,7 @@
140
140
  "stylus": "0.54.7",
141
141
  "stylus-loader": "3.0.2",
142
142
  "svg-sprite-loader": "4.1.6",
143
- "svgstore-cli": "1.3.1",
143
+ "svgstore-cli": "1.3.2",
144
144
  "url-loader": "1.1.2",
145
145
  "webpack": "4.39.3"
146
146
  },
@@ -0,0 +1,48 @@
1
+ ### FileImageLoader
2
+
3
+ A component to get the image in `links` prop of a file, according to its class (could be `image` or `pdf`).
4
+
5
+ ```jsx
6
+ import DemoProvider from '../Viewer/docs/DemoProvider'
7
+
8
+ import FileImageLoader from 'cozy-ui/transpiled/react/FileImageLoader'
9
+ import Icon from 'cozy-ui/transpiled/react/Icon'
10
+ import FileDuotoneIcon from "cozy-ui/transpiled/react/Icons/FileDuotone"
11
+ import BankIcon from "cozy-ui/transpiled/react/Icons/Bank"
12
+
13
+ const file = {
14
+ _id: 'image',
15
+ class: 'image',
16
+ name: 'Demo.img',
17
+ mime: 'application/jpeg',
18
+ links: {
19
+ large: 'https://viewerdemo.cozycloud.cc/IMG_0062.PNG'
20
+ }
21
+ }
22
+
23
+ const onImageError = () => console.info('image errored')
24
+ const onImageLoad = () => console.info('image loaded!')
25
+ const FallbackComp = () => {
26
+ return (
27
+ <div>fallback component</div>
28
+ )
29
+ }
30
+
31
+ ;
32
+
33
+ <DemoProvider>
34
+ <FileImageLoader
35
+ file={file}
36
+ linkType="large"
37
+ onError={onImageError}
38
+ render={src => (
39
+ <img
40
+ src={src}
41
+ height={300}
42
+ onLoad={onImageLoad}
43
+ />
44
+ )}
45
+ renderFallback={() => <FallbackComp />}
46
+ />
47
+ </DemoProvider>
48
+ ```
@@ -1,8 +1,12 @@
1
- const TTL = 10000
2
-
3
- export const checkImageSource = src => {
1
+ /**
2
+ * @param {string} src - Image source
3
+ * @returns {Promise<void>}
4
+ */
5
+ export const checkImageSource = async src => {
6
+ const TTL = 10000
4
7
  let timeout = null
5
8
  let img = null
9
+
6
10
  const cleanImageLoader = () => {
7
11
  clearTimeout(timeout)
8
12
  img.onload = img.onerror = null
@@ -1,4 +1,4 @@
1
- import React from 'react'
1
+ import { Component } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import { withClient } from 'cozy-client'
4
4
  import logger from 'cozy-logger'
@@ -11,7 +11,8 @@ const FAILED = 'FAILED'
11
11
  const GET_LINK = 'GET_LINK'
12
12
 
13
13
  import { checkImageSource } from './checkImageSource'
14
- export class ImageLoader extends React.Component {
14
+
15
+ export class FileImageLoader extends Component {
15
16
  state = {
16
17
  src: null
17
18
  }
@@ -51,6 +52,7 @@ export class ImageLoader extends React.Component {
51
52
  const response = await this.props.client
52
53
  .collection('io.cozy.files')
53
54
  .get(this.getFileId(file))
55
+
54
56
  if (!response.data.links) throw new Error('Could not fetch file links')
55
57
  return response.data.links
56
58
  }
@@ -63,6 +65,7 @@ export class ImageLoader extends React.Component {
63
65
  const link = file.links ? file.links[linkType] : false
64
66
 
65
67
  if (!link) throw new Error(`${linkType} link is not available`)
68
+
66
69
  const src = client.getStackClient().uri + link
67
70
  await checkImageSource(src)
68
71
  if (this._mounted) {
@@ -72,10 +75,10 @@ export class ImageLoader extends React.Component {
72
75
  })
73
76
  }
74
77
  } catch (e) {
75
- logger.error(e)
76
78
  this.loadNextSrc(e)
77
79
  }
78
80
  }
81
+
79
82
  async loadLink() {
80
83
  this.status = LOADING_LINK
81
84
  const { file, linkType, client } = this.props
@@ -105,7 +108,7 @@ export class ImageLoader extends React.Component {
105
108
  const { file, client } = this.props
106
109
 
107
110
  try {
108
- // ImageLoader can also be used for pdf files, because on mobile a preview image is
111
+ // FileImageLoader can also be used for pdf files, because on mobile a preview image is
109
112
  // generated and the pdf is therefore treated as an image.
110
113
  // But the fallback allows to display the original file as an image if there is an error
111
114
  // during the preview recovery. This principle is not possible with a pdf file.
@@ -137,17 +140,17 @@ export class ImageLoader extends React.Component {
137
140
  }
138
141
  }
139
142
 
140
- ImageLoader.propTypes = {
143
+ FileImageLoader.propTypes = {
141
144
  file: PropTypes.object.isRequired,
142
145
  render: PropTypes.func.isRequired,
143
- linkType: PropTypes.oneOf(['small', 'medium', 'large', 'preview']),
146
+ linkType: PropTypes.oneOf(['small', 'medium', 'large', 'preview', 'icon']),
144
147
  onError: PropTypes.func,
145
148
  renderFallback: PropTypes.func
146
149
  }
147
150
 
148
- ImageLoader.defaultProps = {
151
+ FileImageLoader.defaultProps = {
149
152
  linkType: 'small',
150
153
  onError: () => {}
151
154
  }
152
155
 
153
- export default withClient(ImageLoader)
156
+ export default withClient(FileImageLoader)
@@ -4,7 +4,7 @@ import { render, waitFor } from '@testing-library/react'
4
4
  import { createMockClient } from 'cozy-client'
5
5
  import logger from 'cozy-logger'
6
6
 
7
- import { ImageLoader } from './ImageLoader'
7
+ import { FileImageLoader } from '.'
8
8
  import { checkImageSource } from './checkImageSource'
9
9
 
10
10
  jest.mock('./checkImageSource', () => ({
@@ -34,11 +34,18 @@ const file = {
34
34
 
35
35
  const setup = ({ file }) => {
36
36
  const root = render(
37
- <ImageLoader
37
+ <FileImageLoader
38
38
  file={file}
39
39
  linkType="large"
40
40
  key={file.id}
41
41
  render={src => <img alt={file.name} src={src} data-testid="img_image" />}
42
+ renderFallback={() => (
43
+ <img
44
+ alt="render fallback"
45
+ src="http://url.img_image_render_fallback/"
46
+ data-testid="img_image_renderFallback"
47
+ />
48
+ )}
42
49
  client={client}
43
50
  />
44
51
  )
@@ -46,10 +53,11 @@ const setup = ({ file }) => {
46
53
  return { root }
47
54
  }
48
55
 
49
- describe('ImageLoader', () => {
56
+ describe('FileImageLoader', () => {
50
57
  afterEach(() => {
51
58
  jest.restoreAllMocks()
52
59
  })
60
+
53
61
  it('should set the source of image to links.large if no error', async () => {
54
62
  const { root } = setup({ file })
55
63
  const { getByTestId } = root
@@ -115,4 +123,30 @@ describe('ImageLoader', () => {
115
123
  const img = getByTestId('img_image')
116
124
  expect(img.src).toEqual('http://valid/')
117
125
  })
126
+
127
+ it('should render fallback component if other request failed & file is a PDF', async () => {
128
+ const file = {
129
+ _id: 'pdf',
130
+ class: 'pdf',
131
+ name: 'Demo.pdf',
132
+ mime: 'application/pdf',
133
+ links: {
134
+ icon: 'https://url.not.valid.anymore'
135
+ }
136
+ }
137
+ checkImageSource.mockRejectedValueOnce('KO')
138
+ const { root } = setup({ file })
139
+ const { getByTestId } = root
140
+ getMock.mockResolvedValue({
141
+ data: {
142
+ links: {
143
+ icon: 'http://urlnotvalidneither'
144
+ }
145
+ }
146
+ })
147
+ await waitFor(() => getByTestId('img_image_renderFallback'))
148
+
149
+ const img = getByTestId('img_image_renderFallback')
150
+ expect(img.src).toEqual('http://url.img_image_render_fallback/')
151
+ })
118
152
  })
@@ -1,8 +1,9 @@
1
1
  import React, { Component } from 'react'
2
2
  import Hammer from 'hammerjs'
3
3
 
4
+ import FileImageLoader from '../FileImageLoader'
5
+
4
6
  import ViewerSpinner from './ViewerSpinner'
5
- import ImageLoader from './ImageLoader'
6
7
  import NoNetworkViewer from './NoNetworkViewer'
7
8
 
8
9
  import styles from './styles.styl'
@@ -222,7 +223,7 @@ class ImageViewer extends Component {
222
223
  <div className={styles['viewer-imageviewer']}>
223
224
  {loading && <ViewerSpinner />}
224
225
  {file && (
225
- <ImageLoader
226
+ <FileImageLoader
226
227
  file={file}
227
228
  linkType="large"
228
229
  onError={this.onImageError}
@@ -4,11 +4,11 @@ import { render, waitFor } from '@testing-library/react'
4
4
  import { BreakpointsProvider } from '../hooks/useBreakpoints'
5
5
 
6
6
  import DemoProvider from './docs/DemoProvider'
7
- import { checkImageSource } from './checkImageSource'
7
+ import { checkImageSource } from '../FileImageLoader/checkImageSource'
8
8
  import ImageViewer from './ImageViewer'
9
9
 
10
- jest.mock('./checkImageSource', () => ({
11
- ...jest.requireActual('./checkImageSource'),
10
+ jest.mock('../FileImageLoader/checkImageSource', () => ({
11
+ ...jest.requireActual('../FileImageLoader/checkImageSource'),
12
12
  checkImageSource: jest.fn()
13
13
  }))
14
14
 
@@ -7,10 +7,10 @@ import { isMobileApp } from 'cozy-device-helper'
7
7
  import Alerter from '../Alerter'
8
8
  import Spinner from '../Spinner'
9
9
  import Button from '../Button'
10
+ import FileImageLoader from '../FileImageLoader'
10
11
 
11
12
  import { withViewerLocales } from './withViewerLocales'
12
13
  import DownloadButton from './NoViewer/DownloadButton'
13
- import ImageLoader from './ImageLoader'
14
14
  import NoViewer from './NoViewer'
15
15
 
16
16
  import styles from './styles.styl'
@@ -80,7 +80,7 @@ export const PdfMobileViewer = ({ file, t, gestures }) => {
80
80
  <div className={styles['viewer-pdfMobile']}>
81
81
  {loading && <Spinner size="xxlarge" middle noMargin />}
82
82
  {file && (
83
- <ImageLoader
83
+ <FileImageLoader
84
84
  file={file}
85
85
  linkType="preview"
86
86
  onError={onImageError}
package/react/index.js CHANGED
@@ -97,3 +97,4 @@ export { default as Paper } from './Paper'
97
97
  export { default as ProgressionBanner } from './ProgressionBanner'
98
98
  export { default as Fab } from './Fab'
99
99
  export { default as SquareAppIcon } from './SquareAppIcon'
100
+ export { default as FileImageLoader } from './FileImageLoader'
@@ -0,0 +1,49 @@
1
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
2
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
3
+
4
+ /**
5
+ * @param {string} src - Image source
6
+ * @returns {Promise<void>}
7
+ */
8
+ export var checkImageSource = /*#__PURE__*/function () {
9
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(src) {
10
+ var TTL, timeout, img, cleanImageLoader;
11
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
12
+ while (1) {
13
+ switch (_context.prev = _context.next) {
14
+ case 0:
15
+ TTL = 10000;
16
+ timeout = null;
17
+ img = null;
18
+
19
+ cleanImageLoader = function cleanImageLoader() {
20
+ clearTimeout(timeout);
21
+ img.onload = img.onerror = null;
22
+ img.src = '';
23
+ img = null;
24
+ };
25
+
26
+ return _context.abrupt("return", new Promise(function (resolve, reject) {
27
+ img = new Image();
28
+ img.onload = resolve;
29
+ img.onerror = reject;
30
+ img.src = src;
31
+ timeout = setTimeout(function () {
32
+ return reject(new Error('Loading image took too long'));
33
+ }, TTL);
34
+ }).then(function () {
35
+ return cleanImageLoader();
36
+ }));
37
+
38
+ case 5:
39
+ case "end":
40
+ return _context.stop();
41
+ }
42
+ }
43
+ }, _callee);
44
+ }));
45
+
46
+ return function checkImageSource(_x) {
47
+ return _ref.apply(this, arguments);
48
+ };
49
+ }();
@@ -7,7 +7,7 @@ import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
7
7
  import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
8
8
  import _inherits from "@babel/runtime/helpers/inherits";
9
9
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
10
- import React from 'react';
10
+ import { Component } from 'react';
11
11
  import PropTypes from 'prop-types';
12
12
  import { withClient } from 'cozy-client';
13
13
  import logger from 'cozy-logger';
@@ -17,22 +17,22 @@ var LOADING_FALLBACK = 'LOADING_FALLBACK';
17
17
  var LOADED = 'LOADED';
18
18
  var FAILED = 'FAILED';
19
19
  var GET_LINK = 'GET_LINK';
20
- import { checkImageSource } from "cozy-ui/transpiled/react/Viewer/checkImageSource";
21
- export var ImageLoader = /*#__PURE__*/function (_React$Component) {
22
- _inherits(ImageLoader, _React$Component);
20
+ import { checkImageSource } from "cozy-ui/transpiled/react/FileImageLoader/checkImageSource";
21
+ export var FileImageLoader = /*#__PURE__*/function (_Component) {
22
+ _inherits(FileImageLoader, _Component);
23
23
 
24
- function ImageLoader() {
24
+ function FileImageLoader() {
25
25
  var _getPrototypeOf2;
26
26
 
27
27
  var _this;
28
28
 
29
- _classCallCheck(this, ImageLoader);
29
+ _classCallCheck(this, FileImageLoader);
30
30
 
31
31
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
32
32
  args[_key] = arguments[_key];
33
33
  }
34
34
 
35
- _this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(ImageLoader)).call.apply(_getPrototypeOf2, [this].concat(args)));
35
+ _this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(FileImageLoader)).call.apply(_getPrototypeOf2, [this].concat(args)));
36
36
 
37
37
  _defineProperty(_assertThisInitialized(_this), "state", {
38
38
  src: null
@@ -43,7 +43,7 @@ export var ImageLoader = /*#__PURE__*/function (_React$Component) {
43
43
  return _this;
44
44
  }
45
45
 
46
- _createClass(ImageLoader, [{
46
+ _createClass(FileImageLoader, [{
47
47
  key: "componentDidMount",
48
48
  value: function componentDidMount() {
49
49
  this._mounted = true;
@@ -151,16 +151,15 @@ export var ImageLoader = /*#__PURE__*/function (_React$Component) {
151
151
  });
152
152
  }
153
153
 
154
- _context2.next = 16;
154
+ _context2.next = 15;
155
155
  break;
156
156
 
157
157
  case 12:
158
158
  _context2.prev = 12;
159
159
  _context2.t0 = _context2["catch"](2);
160
- logger.error(_context2.t0);
161
160
  this.loadNextSrc(_context2.t0);
162
161
 
163
- case 16:
162
+ case 15:
164
163
  case "end":
165
164
  return _context2.stop();
166
165
  }
@@ -308,17 +307,17 @@ export var ImageLoader = /*#__PURE__*/function (_React$Component) {
308
307
  }
309
308
  }]);
310
309
 
311
- return ImageLoader;
312
- }(React.Component);
313
- ImageLoader.propTypes = {
310
+ return FileImageLoader;
311
+ }(Component);
312
+ FileImageLoader.propTypes = {
314
313
  file: PropTypes.object.isRequired,
315
314
  render: PropTypes.func.isRequired,
316
- linkType: PropTypes.oneOf(['small', 'medium', 'large', 'preview']),
315
+ linkType: PropTypes.oneOf(['small', 'medium', 'large', 'preview', 'icon']),
317
316
  onError: PropTypes.func,
318
317
  renderFallback: PropTypes.func
319
318
  };
320
- ImageLoader.defaultProps = {
319
+ FileImageLoader.defaultProps = {
321
320
  linkType: 'small',
322
321
  onError: function onError() {}
323
322
  };
324
- export default withClient(ImageLoader);
323
+ export default withClient(FileImageLoader);
@@ -8,8 +8,8 @@ import _inherits from "@babel/runtime/helpers/inherits";
8
8
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
9
9
  import React, { Component } from 'react';
10
10
  import Hammer from 'hammerjs';
11
+ import FileImageLoader from "cozy-ui/transpiled/react/FileImageLoader";
11
12
  import ViewerSpinner from "cozy-ui/transpiled/react/Viewer/ViewerSpinner";
12
- import ImageLoader from "cozy-ui/transpiled/react/Viewer/ImageLoader";
13
13
  import NoNetworkViewer from "cozy-ui/transpiled/react/Viewer/NoNetworkViewer";
14
14
  var styles = {
15
15
  "CozyTheme--inverted": "styles__CozyTheme--inverted___1II8o",
@@ -269,7 +269,7 @@ var ImageViewer = /*#__PURE__*/function (_Component) {
269
269
  };
270
270
  return React.createElement("div", {
271
271
  className: styles['viewer-imageviewer']
272
- }, loading && React.createElement(ViewerSpinner, null), file && React.createElement(ImageLoader, {
272
+ }, loading && React.createElement(ViewerSpinner, null), file && React.createElement(FileImageLoader, {
273
273
  file: file,
274
274
  linkType: "large",
275
275
  onError: this.onImageError,
@@ -8,9 +8,9 @@ import { isMobileApp } from 'cozy-device-helper';
8
8
  import Alerter from "cozy-ui/transpiled/react/Alerter";
9
9
  import Spinner from "cozy-ui/transpiled/react/Spinner";
10
10
  import Button from "cozy-ui/transpiled/react/Button";
11
+ import FileImageLoader from "cozy-ui/transpiled/react/FileImageLoader";
11
12
  import { withViewerLocales } from "cozy-ui/transpiled/react/Viewer/withViewerLocales";
12
13
  import DownloadButton from "cozy-ui/transpiled/react/Viewer/NoViewer/DownloadButton";
13
- import ImageLoader from "cozy-ui/transpiled/react/Viewer/ImageLoader";
14
14
  import NoViewer from "cozy-ui/transpiled/react/Viewer/NoViewer";
15
15
  var styles = {
16
16
  "CozyTheme--inverted": "styles__CozyTheme--inverted___1II8o",
@@ -146,7 +146,7 @@ export var PdfMobileViewer = function PdfMobileViewer(_ref) {
146
146
  size: "xxlarge",
147
147
  middle: true,
148
148
  noMargin: true
149
- }), file && React.createElement(ImageLoader, {
149
+ }), file && React.createElement(FileImageLoader, {
150
150
  file: file,
151
151
  linkType: "preview",
152
152
  onError: onImageError,
@@ -74,4 +74,5 @@ export { default as CozyTheme } from './CozyTheme';
74
74
  export { default as Paper } from './Paper';
75
75
  export { default as ProgressionBanner } from './ProgressionBanner';
76
76
  export { default as Fab } from './Fab';
77
- export { default as SquareAppIcon } from './SquareAppIcon';
77
+ export { default as SquareAppIcon } from './SquareAppIcon';
78
+ export { default as FileImageLoader } from './FileImageLoader';
@@ -1,24 +0,0 @@
1
- var TTL = 10000;
2
- export var checkImageSource = function checkImageSource(src) {
3
- var timeout = null;
4
- var img = null;
5
-
6
- var cleanImageLoader = function cleanImageLoader() {
7
- clearTimeout(timeout);
8
- img.onload = img.onerror = null;
9
- img.src = '';
10
- img = null;
11
- };
12
-
13
- return new Promise(function (resolve, reject) {
14
- img = new Image();
15
- img.onload = resolve;
16
- img.onerror = reject;
17
- img.src = src;
18
- timeout = setTimeout(function () {
19
- return reject(new Error('Loading image took too long'));
20
- }, TTL);
21
- }).then(function () {
22
- return cleanImageLoader();
23
- });
24
- };