@nyris/nyris-webapp 0.3.54 → 0.3.56

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.
Files changed (110) hide show
  1. package/build/asset-manifest.json +8 -7
  2. package/build/images/fav2/android-chrome-192x192.png +0 -0
  3. package/build/images/fav2/android-chrome-512x512.png +0 -0
  4. package/build/images/fav2/apple-touch-icon.png +0 -0
  5. package/build/images/fav2/browserconfig.xml +9 -0
  6. package/build/images/fav2/favicon-16x16.png +0 -0
  7. package/build/images/fav2/favicon-32x32.png +0 -0
  8. package/build/images/fav2/favicon.ico +0 -0
  9. package/build/images/fav2/mstile-144x144.png +0 -0
  10. package/build/images/fav2/mstile-150x150.png +0 -0
  11. package/build/images/fav2/mstile-310x150.png +0 -0
  12. package/build/images/fav2/mstile-310x310.png +0 -0
  13. package/build/images/fav2/mstile-70x70.png +0 -0
  14. package/build/images/fav2/safari-pinned-tab.svg +67 -0
  15. package/build/images/fav2/site.webmanifest +19 -0
  16. package/build/index.html +1 -1
  17. package/build/js/settings.example.js +1 -0
  18. package/build/manifest.json +13 -18
  19. package/build/static/css/main.abb86fa9.css +2 -0
  20. package/build/static/css/main.abb86fa9.css.map +1 -0
  21. package/build/static/js/main.2f1ab11c.js +3 -0
  22. package/build/static/js/{main.03fb1bc6.js.LICENSE.txt → main.2f1ab11c.js.LICENSE.txt} +1 -1
  23. package/build/static/js/main.2f1ab11c.js.map +1 -0
  24. package/build/static/media/path.b99a15de38340a04f80828bceeab9884.svg +3 -0
  25. package/package.json +3 -3
  26. package/public/images/fav2/android-chrome-192x192.png +0 -0
  27. package/public/images/fav2/android-chrome-512x512.png +0 -0
  28. package/public/images/fav2/apple-touch-icon.png +0 -0
  29. package/public/images/fav2/browserconfig.xml +9 -0
  30. package/public/images/fav2/favicon-16x16.png +0 -0
  31. package/public/images/fav2/favicon-32x32.png +0 -0
  32. package/public/images/fav2/favicon.ico +0 -0
  33. package/public/images/fav2/mstile-144x144.png +0 -0
  34. package/public/images/fav2/mstile-150x150.png +0 -0
  35. package/public/images/fav2/mstile-310x150.png +0 -0
  36. package/public/images/fav2/mstile-310x310.png +0 -0
  37. package/public/images/fav2/mstile-70x70.png +0 -0
  38. package/public/images/fav2/safari-pinned-tab.svg +67 -0
  39. package/public/images/fav2/site.webmanifest +19 -0
  40. package/public/index.html +8 -90
  41. package/public/js/settings.example.js +1 -0
  42. package/public/manifest.json +13 -18
  43. package/src/Store/Store.ts +0 -1
  44. package/src/Store/search/Search.ts +33 -74
  45. package/src/Store/search/search.initialState.ts +5 -4
  46. package/src/Store/search/types.ts +5 -4
  47. package/src/common/assets/icons/path.svg +3 -0
  48. package/src/components/AppMobile.tsx +0 -1
  49. package/src/components/DragDropFile.tsx +36 -28
  50. package/src/components/Experience-visual-search/ExperienceVisualSearch.scss +3 -4
  51. package/src/components/Experience-visual-search/ExperienceVisualSearch.tsx +14 -7
  52. package/src/components/Feedback.tsx +5 -5
  53. package/src/components/FooterMobile.tsx +4 -5
  54. package/src/components/GoBackButton.tsx +54 -0
  55. package/src/components/Header.tsx +27 -3
  56. package/src/components/HeaderMobile.tsx +29 -12
  57. package/src/components/ImagePreviewMobile.tsx +6 -3
  58. package/src/components/Inquiry/InquiryBanner.tsx +1 -1
  59. package/src/components/Layout.tsx +5 -14
  60. package/src/components/PanelResult/PostFilterAlgolia.tsx +3 -2
  61. package/src/components/ProductDetailView.tsx +338 -330
  62. package/src/components/ProductList/index.tsx +1 -1
  63. package/src/components/appMobile.scss +7 -0
  64. package/src/components/clear-refinements/clear-refinements.tsx +1 -1
  65. package/src/components/common.scss +18 -7
  66. package/src/components/current-refinements/current-refinements.tsx +11 -27
  67. package/src/components/drawer/cameraCustom.tsx +12 -1
  68. package/src/components/input/inputSearch.tsx +79 -21
  69. package/src/components/pre-filter/index.tsx +23 -7
  70. package/src/components/results/ItemResult.tsx +288 -285
  71. package/src/index.tsx +12 -14
  72. package/src/page/landingPage/AppMobile.tsx +3 -9
  73. package/src/page/landingPage/common.scss +170 -48
  74. package/src/page/result/index.tsx +114 -86
  75. package/src/translations.ts +3 -0
  76. package/src/types.ts +1 -0
  77. package/build/images/fav/android-icon-192x192.png +0 -0
  78. package/build/images/fav/apple-icon-114x114.png +0 -0
  79. package/build/images/fav/apple-icon-120x120.png +0 -0
  80. package/build/images/fav/apple-icon-144x144.png +0 -0
  81. package/build/images/fav/apple-icon-152x152.png +0 -0
  82. package/build/images/fav/apple-icon-180x180.png +0 -0
  83. package/build/images/fav/apple-icon-57x57.png +0 -0
  84. package/build/images/fav/apple-icon-60x60.png +0 -0
  85. package/build/images/fav/apple-icon-72x72.png +0 -0
  86. package/build/images/fav/apple-icon-76x76.png +0 -0
  87. package/build/images/fav/browserconfig.xml +0 -2
  88. package/build/images/fav/favicon-16x16.png +0 -0
  89. package/build/images/fav/favicon-32x32.png +0 -0
  90. package/build/images/fav/favicon-96x96.png +0 -0
  91. package/build/images/fav/manifest.json +0 -35
  92. package/build/static/css/main.8c0eb6c0.css +0 -2
  93. package/build/static/css/main.8c0eb6c0.css.map +0 -1
  94. package/build/static/js/main.03fb1bc6.js +0 -3
  95. package/build/static/js/main.03fb1bc6.js.map +0 -1
  96. package/public/images/fav/android-icon-192x192.png +0 -0
  97. package/public/images/fav/apple-icon-114x114.png +0 -0
  98. package/public/images/fav/apple-icon-120x120.png +0 -0
  99. package/public/images/fav/apple-icon-144x144.png +0 -0
  100. package/public/images/fav/apple-icon-152x152.png +0 -0
  101. package/public/images/fav/apple-icon-180x180.png +0 -0
  102. package/public/images/fav/apple-icon-57x57.png +0 -0
  103. package/public/images/fav/apple-icon-60x60.png +0 -0
  104. package/public/images/fav/apple-icon-72x72.png +0 -0
  105. package/public/images/fav/apple-icon-76x76.png +0 -0
  106. package/public/images/fav/browserconfig.xml +0 -2
  107. package/public/images/fav/favicon-16x16.png +0 -0
  108. package/public/images/fav/favicon-32x32.png +0 -0
  109. package/public/images/fav/favicon-96x96.png +0 -0
  110. package/public/images/fav/manifest.json +0 -35
@@ -6,6 +6,7 @@ import React, {
6
6
  useRef,
7
7
  useState,
8
8
  } from 'react';
9
+ import { useHistory } from 'react-router-dom';
9
10
  import ArrowLeftIcon from '@material-ui/icons/ArrowLeft';
10
11
  import ArrowRightIcon from '@material-ui/icons/ArrowRight';
11
12
 
@@ -33,8 +34,13 @@ import {
33
34
  setRequestImage,
34
35
  setSearchResults,
35
36
  setSelectedRegion,
37
+ setShowFeedback,
36
38
  updateResultChangePosition,
37
39
  updateStatusLoading,
40
+ setFirstSearchResults,
41
+ setFirstSearchImage,
42
+ setFirstSearchPrefilters,
43
+ setFirstSearchThumbSearchInput,
38
44
  } from 'Store/search/Search';
39
45
  import { useAppDispatch, useAppSelector } from 'Store/Store';
40
46
  import { showHits } from '../../constants';
@@ -50,6 +56,7 @@ import { useQuery } from 'hooks/useQuery';
50
56
  import { ReactComponent as PoweredByNyrisImage } from 'common/assets/images/powered_by_nyris.svg';
51
57
  import Feedback from 'components/Feedback';
52
58
  import { SelectedPostFilter } from 'components/SelectedPostFilter';
59
+ import { GoBack } from '../../components/GoBackButton';
53
60
 
54
61
  interface Props {
55
62
  allSearchResults: any;
@@ -70,6 +77,10 @@ function ResultComponent(props: Props) {
70
77
  loadingSearchAlgolia,
71
78
  imageThumbSearchInput,
72
79
  results,
80
+ showFeedback,
81
+ firstSearchResults,
82
+ firstSearchImage,
83
+ fetchingResults,
73
84
  } = search;
74
85
 
75
86
  const isMobile = useMediaQuery({ query: '(max-width: 776px)' });
@@ -86,19 +97,17 @@ function ResultComponent(props: Props) {
86
97
  const [isRfqModalOpen, setIsRfqModalOpen] = useState(false);
87
98
  const imageUploadRef = useRef(null);
88
99
  const rfqRef = useRef<any>(null);
89
- const [isScrolled, setIsScrolled] = useState<
90
- 'not-scrolled' | 'scrolled' | 'user-scrolled'
91
- >('not-scrolled');
92
-
93
- const [showFeedback, setShowFeedback] = useState<
94
- 'not-scrolled' | 'scrolled' | 'user-scrolled'
95
- >('not-scrolled');
96
100
 
101
+ const [feedbackStatus, setFeedbackStatus] = useState<
102
+ 'hidden' | 'submitted' | 'visible'
103
+ >();
97
104
  const [showFeedbackSuccess, setShowFeedbackSuccess] = useState(false);
105
+ const [showSearchBar, setShowSearchBar] = useState(false);
98
106
  const query = useQuery();
99
107
  const searchQuery = query.get('query') || search.valueTextSearch.query;
100
108
  const isAlgoliaEnabled = settings.algolia?.enabled;
101
109
  const isPostFilterEnabled = settings.postFilterOption;
110
+ const history = useHistory();
102
111
 
103
112
  useEffect(() => {
104
113
  if (
@@ -119,19 +128,24 @@ function ResultComponent(props: Props) {
119
128
  }
120
129
  }, [imageThumbSearchInput, loadingSearchAlgolia]);
121
130
 
131
+ useEffect(() => {
132
+ if (loadingSearchAlgolia) {
133
+ setFeedbackStatus('hidden');
134
+ setShowFeedbackSuccess(false);
135
+ }
136
+ }, [loadingSearchAlgolia]);
137
+
122
138
  useEffect(() => {
123
139
  if (selectedRegion) {
124
140
  setImageSelection(selectedRegion);
125
141
  setRfqStatus('inactive');
126
- setIsScrolled('not-scrolled');
127
- setShowFeedback('not-scrolled');
142
+ setFeedbackStatus('hidden');
128
143
  }
129
144
  }, [selectedRegion]);
130
145
 
131
146
  useEffect(() => {
132
147
  if (requestImage) {
133
- setIsScrolled('not-scrolled');
134
- setShowFeedback('not-scrolled');
148
+ setFeedbackStatus('hidden');
135
149
  executeScroll();
136
150
  setImageSelection(DEFAULT_REGION);
137
151
  }
@@ -142,7 +156,7 @@ function ResultComponent(props: Props) {
142
156
  const preFilterValues = [
143
157
  {
144
158
  key: settings.visualSearchFilterKey,
145
- values: Object.keys(preFilter) as string[],
159
+ values: Object.keys(preFilter)
146
160
  },
147
161
  ];
148
162
  dispatch(loadingActionResults());
@@ -225,7 +239,7 @@ function ResultComponent(props: Props) {
225
239
  const preFilterValues = [
226
240
  {
227
241
  key: settings.visualSearchFilterKey,
228
- values: Object.keys(preFilter) as string[],
242
+ values: Object.keys(preFilter),
229
243
  },
230
244
  ];
231
245
  find({
@@ -234,6 +248,14 @@ function ResultComponent(props: Props) {
234
248
  region: searchRegion,
235
249
  filters: !isEmpty(preFilter) ? preFilterValues : undefined,
236
250
  }).then((res: any) => {
251
+ if (!firstSearchResults) {
252
+ dispatch(setFirstSearchResults(res));
253
+ dispatch(setFirstSearchImage(image));
254
+ dispatch(setFirstSearchPrefilters(preFilter));
255
+ if (!isMobile) {
256
+ dispatch(setFirstSearchThumbSearchInput(url))
257
+ }
258
+ }
237
259
  dispatch(setSearchResults(res));
238
260
  dispatch(updateStatusLoading(false));
239
261
  return;
@@ -253,6 +275,7 @@ function ResultComponent(props: Props) {
253
275
 
254
276
  useEffect(() => {
255
277
  document.title = 'Search results';
278
+ setFeedbackStatus('hidden');
256
279
 
257
280
  if (requestImage || isEmpty(searchQuery)) return;
258
281
  const preFilterValues = Object.keys(preFilter) as string[];
@@ -302,6 +325,15 @@ function ResultComponent(props: Props) {
302
325
  // eslint-disable-next-line react-hooks/exhaustive-deps
303
326
  }, [filterSkusString, settings.alogoliaFilterField]);
304
327
 
328
+ useEffect(() => {
329
+ if (history.location?.pathname === '/') {
330
+ setShowSearchBar(true);
331
+ } else {
332
+ setShowSearchBar(false);
333
+ }
334
+ // eslint-disable-next-line react-hooks/exhaustive-deps
335
+ }, [history.location]);
336
+
305
337
  // eslint-disable-next-line react-hooks/exhaustive-deps
306
338
  const debouncedOnImageSelectionChange = useCallback(
307
339
  debounce((r: RectCoords) => {
@@ -328,48 +360,41 @@ function ResultComponent(props: Props) {
328
360
  }, [showPostFilter, isPostFilterEnabled, requestImage]);
329
361
 
330
362
  useEffect(() => {
331
- const handleScroll = () => {
332
- setTimeout(() => {
333
- setIsScrolled(s => (s === 'not-scrolled' ? 'scrolled' : s));
334
- setTimeout(() => {
335
- setIsScrolled(s => (s === 'scrolled' ? 'user-scrolled' : s));
336
- }, 5000);
337
- }, 1000);
338
- };
339
- if (requestImage)
340
- window.addEventListener('scroll', handleScroll, { capture: true });
341
-
342
- return () => {
343
- window.removeEventListener('scroll', handleScroll);
344
- };
345
- }, [requestImage]);
346
-
347
- useEffect(() => {
348
- if (!requestImage || !settings.showFeedback) return;
349
-
350
- setTimeout(() => {
351
- setShowFeedback(s => (s === 'not-scrolled' ? 'scrolled' : s));
352
- }, 5000);
363
+ if (!settings.showFeedback || results?.length === 0 || !showFeedback)
364
+ return;
353
365
 
354
366
  const handleScroll = () => {
355
367
  setTimeout(() => {
356
- setShowFeedback(s => (s === 'not-scrolled' ? 'scrolled' : s));
368
+ setFeedbackStatus(s => (s === 'submitted' ? 'submitted' : 'visible'));
369
+ dispatch(setShowFeedback(false));
357
370
  }, 100);
358
371
  };
359
372
 
360
- window.addEventListener('scroll', handleScroll, { capture: true });
373
+ setTimeout(() => {
374
+ window.removeEventListener('scroll', handleScroll, { capture: true });
375
+ setFeedbackStatus(s => (s === 'submitted' ? 'submitted' : 'visible'));
376
+ dispatch(setShowFeedback(false));
377
+ }, 4000);
378
+
379
+ window.addEventListener('scroll', handleScroll, {
380
+ capture: true,
381
+ once: true,
382
+ });
361
383
 
362
384
  return () => {
363
385
  window.removeEventListener('scroll', handleScroll);
364
386
  };
365
- }, [requestImage, selectedRegion, settings.showFeedback]);
387
+ // eslint-disable-next-line react-hooks/exhaustive-deps
388
+ }, [showFeedback, settings.showFeedback]);
366
389
 
367
390
  const submitFeedback = async (data: boolean) => {
368
391
  setShowFeedbackSuccess(true);
369
392
  setTimeout(() => {
370
393
  setShowFeedbackSuccess(false);
371
394
  }, 3000);
372
- setShowFeedback('user-scrolled');
395
+
396
+ setFeedbackStatus('submitted');
397
+ dispatch(setShowFeedback(false));
373
398
  feedbackSuccessEpic(stateGlobal, data);
374
399
  };
375
400
 
@@ -395,7 +420,7 @@ function ResultComponent(props: Props) {
395
420
  <Configure query={searchQuery} filters={filterString}></Configure>
396
421
  )}
397
422
  <div className="box-wrap-result-component">
398
- {!isMobile && (
423
+ {!isMobile && showSearchBar && (
399
424
  <div className="box-search">
400
425
  <CustomSearchBox />
401
426
  </div>
@@ -404,7 +429,7 @@ function ResultComponent(props: Props) {
404
429
  className="box-result"
405
430
  style={{
406
431
  height: settings.showPoweredByNyris
407
- ? 'calc(100vh - 177px)'
432
+ ? 'calc(100vh - 87px)'
408
433
  : 'calc(100vh - 148px)',
409
434
  }}
410
435
  >
@@ -437,6 +462,12 @@ function ResultComponent(props: Props) {
437
462
  flexDirection: 'column',
438
463
  }}
439
464
  >
465
+ {!isMobile && firstSearchResults && requestImage?.canvas !== firstSearchImage && !fetchingResults ? (
466
+ <GoBack />
467
+ ) : (
468
+ ''
469
+ )}
470
+
440
471
  {!isMobile && settings.algolia.enabled && (
441
472
  <div className="wrap-box-refinements">
442
473
  <CurrentRefinements statusSwitchButton={true} />
@@ -466,27 +497,22 @@ function ResultComponent(props: Props) {
466
497
  backgroundColor: '#FAFAFA',
467
498
  }}
468
499
  >
500
+ {isMobile && firstSearchResults && requestImage?.canvas !== firstSearchImage && !fetchingResults ? (
501
+ <div className="go-back-mobile-container">
502
+ <GoBack />
503
+ </div>
504
+ ) : (
505
+ ''
506
+ )}
507
+
469
508
  <div
470
509
  className={'box-item-result ml-auto mr-auto'}
471
- style={{ paddingLeft: isMobile ? 0 : 16 }}
510
+ style={{
511
+ paddingLeft: isMobile ? 0 : 16,
512
+ height: '100%',
513
+ position: 'relative',
514
+ }}
472
515
  >
473
- {showFeedbackSuccess && (
474
- <div className={'box-item-result feedback-floating'}>
475
- <div className="feedback-success">
476
- Thanks for your feedback!
477
- </div>
478
- </div>
479
- )}
480
- {showFeedback === 'scrolled' && !showFeedbackSuccess && (
481
- <div className={'box-item-result feedback-floating'}>
482
- <Feedback
483
- submitFeedback={submitFeedback}
484
- onFeedbackClose={() => {
485
- setShowFeedback('user-scrolled');
486
- }}
487
- />
488
- </div>
489
- )}
490
516
  <div
491
517
  className="box-item-result ml-auto mr-auto"
492
518
  style={{ height: 'fit-content' }}
@@ -501,6 +527,34 @@ function ResultComponent(props: Props) {
501
527
  requestImage={requestImage}
502
528
  searchQuery={searchQuery}
503
529
  />
530
+ <div
531
+ className="box-item-result ml-auto mr-auto"
532
+ style={{ position: 'absolute' }}
533
+ >
534
+ {showFeedbackSuccess && (
535
+ <div className={'feedback-floating'}>
536
+ <div className="feedback-section">
537
+ <div className="feedback-success">
538
+ Thanks for your feedback!
539
+ </div>
540
+ </div>
541
+ </div>
542
+ )}
543
+ {feedbackStatus === 'visible' &&
544
+ !showFeedbackSuccess && (
545
+ <div className={'feedback-floating'}>
546
+ <div className="feedback-section">
547
+ <Feedback
548
+ submitFeedback={submitFeedback}
549
+ onFeedbackClose={() => {
550
+ setFeedbackStatus('submitted');
551
+ dispatch(setShowFeedback(false));
552
+ }}
553
+ />
554
+ </div>
555
+ </div>
556
+ )}
557
+ </div>
504
558
  </div>
505
559
  </div>
506
560
  <div
@@ -539,6 +593,7 @@ function ResultComponent(props: Props) {
539
593
  style={{
540
594
  display: 'flex',
541
595
  flexGrow: 1,
596
+ marginTop: !isAlgoliaEnabled ? '24px' : '',
542
597
  }}
543
598
  >
544
599
  {requestImage &&
@@ -614,33 +669,6 @@ function ResultComponent(props: Props) {
614
669
  </div>
615
670
  </>
616
671
  </div>
617
- {isScrolled === 'scrolled' &&
618
- requestImage &&
619
- isMobile &&
620
- props.allSearchResults.hits.length > 0 &&
621
- settings.rfq &&
622
- settings.rfq.enabled && (
623
- <div
624
- style={{
625
- fontSize: '14px',
626
- fontWeight: 'bold',
627
- letterSpacing: '1.16px',
628
- color: 'white',
629
- borderRadius: '16px',
630
- backgroundColor: '#4B4B4A',
631
- boxShadow: '0px 0px 16px 0px rgba(85, 86, 107, 0.70)',
632
- padding: '8px 16px',
633
- zIndex: 100,
634
- position: 'absolute',
635
- left: '50%',
636
- transform: 'translate(-50%, -50%)',
637
- width: '356px',
638
- bottom: '86px',
639
- }}
640
- >
641
- Scroll down for personalized support
642
- </div>
643
- )}
644
672
  </>
645
673
  );
646
674
  }
@@ -31,6 +31,7 @@ export const translations = {
31
31
  'Clear all': 'Clear all',
32
32
  Cancel: 'Cancel',
33
33
  Apply: 'Apply',
34
+ 'Back to request image': 'Back to request image',
34
35
  },
35
36
  },
36
37
  de: {
@@ -66,6 +67,7 @@ export const translations = {
66
67
  'Clear all': 'Alles löschen',
67
68
  Cancel: 'Abbrechen',
68
69
  Apply: 'Anwenden',
70
+ 'Back to request image': 'Zurück zur Bildanfrage',
69
71
  },
70
72
  },
71
73
  pt: {
@@ -100,6 +102,7 @@ export const translations = {
100
102
  'Clear all': 'Clear all',
101
103
  Cancel: 'Cancel',
102
104
  Apply: 'Apply',
105
+ 'Back to request image': 'Retroceder para imagem inicial',
103
106
  },
104
107
  },
105
108
  };
package/src/types.ts CHANGED
@@ -76,6 +76,7 @@ export interface AppSettings extends NyrisAPISettings {
76
76
  showGroup?: boolean;
77
77
  showPoweredByNyris?: boolean;
78
78
  support?: Support;
79
+ simpleCardView?: boolean;
79
80
  theme: SearchSuiteSettings;
80
81
  visualSearchFilterKey?: string;
81
82
  warehouseVariant?: boolean;
@@ -1,2 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>
Binary file
Binary file
Binary file
@@ -1,35 +0,0 @@
1
- {
2
- "name": "App",
3
- "icons": [
4
- {
5
- "src": "apple-icon-32x32.png",
6
- "sizes": "32x32",
7
- "type": "image\/png",
8
- "density": "0.75"
9
- },
10
- {
11
- "src": "apple-icon-72x72.png",
12
- "sizes": "72x72",
13
- "type": "image\/png",
14
- "density": "1.5"
15
- },
16
- {
17
- "src": "apple-icon-96x96.png",
18
- "sizes": "96x96",
19
- "type": "image\/png",
20
- "density": "2.0"
21
- },
22
- {
23
- "src": "apple-icon-144x144.png",
24
- "sizes": "144x144",
25
- "type": "image\/png",
26
- "density": "3.0"
27
- },
28
- {
29
- "src": "android-icon-192x192.png",
30
- "sizes": "192x192",
31
- "type": "image\/png",
32
- "density": "4.0"
33
- }
34
- ]
35
- }