@atlaskit/media-card 70.11.0 → 73.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.
Files changed (197) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/dist/cjs/errors.js +78 -5
  3. package/dist/cjs/files/cardImageView/cardOverlay/styled.js +1 -1
  4. package/dist/cjs/files/cardImageView/index.js +53 -104
  5. package/dist/cjs/files/cardImageView/styled.js +1 -1
  6. package/dist/cjs/files/index.js +0 -6
  7. package/dist/cjs/index.js +12 -6
  8. package/dist/cjs/root/card/cardAnalytics.js +11 -17
  9. package/dist/cjs/root/card/cardLoader.js +66 -124
  10. package/dist/cjs/root/card/cardState.js +50 -0
  11. package/dist/cjs/root/card/getCardPreview/cache.js +6 -1
  12. package/dist/cjs/root/card/getCardPreview/filePreviewStatus.js +53 -0
  13. package/dist/cjs/root/card/getCardPreview/helpers.js +14 -22
  14. package/dist/cjs/root/card/getCardPreview/index.js +176 -102
  15. package/dist/cjs/root/card/getCardStatus.js +7 -1
  16. package/dist/cjs/root/card/index.js +361 -281
  17. package/dist/cjs/root/cardView.js +109 -86
  18. package/dist/cjs/root/index.js +9 -1
  19. package/dist/cjs/root/inline/loader.js +22 -21
  20. package/dist/cjs/root/inline/{inlineMediaCard.js → mediaInlineCard.js} +84 -26
  21. package/dist/cjs/root/inlinePlayer.js +4 -3
  22. package/dist/cjs/root/styled.js +7 -3
  23. package/dist/cjs/root/ui/actionsBar/styled.js +1 -1
  24. package/dist/cjs/root/ui/blanket/styled.js +1 -1
  25. package/dist/cjs/root/ui/common.js +11 -5
  26. package/dist/cjs/root/ui/iconMessage/index.js +16 -7
  27. package/dist/cjs/root/ui/iconWrapper/styled.js +1 -1
  28. package/dist/cjs/root/ui/imageRenderer/imageRenderer.js +34 -124
  29. package/dist/cjs/root/ui/loadingRateLimited/loadingRateLimited.js +6 -4
  30. package/dist/cjs/root/ui/loadingRateLimited/styled.js +1 -1
  31. package/dist/cjs/root/ui/playButton/styled.js +1 -1
  32. package/dist/cjs/root/ui/progressBar/progressBar.js +2 -2
  33. package/dist/cjs/root/ui/progressBar/styled.js +2 -4
  34. package/dist/cjs/root/ui/styled.js +80 -17
  35. package/dist/cjs/root/ui/tickBox/styled.js +1 -1
  36. package/dist/cjs/root/ui/titleBox/failedTitleBox.js +9 -3
  37. package/dist/cjs/root/ui/titleBox/styled.js +2 -4
  38. package/dist/cjs/root/ui/titleBox/titleBox.js +2 -2
  39. package/dist/cjs/styles/index.js +25 -23
  40. package/dist/cjs/styles/mixins.js +1 -1
  41. package/dist/cjs/utils/analytics.js +21 -43
  42. package/dist/cjs/utils/breakpoint.js +1 -1
  43. package/dist/cjs/utils/cardActions/cardActionsDropdownMenu.js +16 -9
  44. package/dist/cjs/utils/cardActions/index.js +10 -10
  45. package/dist/cjs/utils/cardActions/styled.js +1 -1
  46. package/dist/cjs/utils/cardDimensions.js +1 -1
  47. package/dist/cjs/utils/dimensionComparer.js +1 -1
  48. package/dist/cjs/utils/getErrorMessage.js +2 -2
  49. package/dist/cjs/utils/index.js +46 -46
  50. package/dist/cjs/utils/lightCards/styled.js +1 -1
  51. package/dist/cjs/utils/metadata.js +11 -3
  52. package/dist/cjs/utils/objectURLCache.js +7 -1
  53. package/dist/cjs/utils/shouldDisplayImageThumbnail.js +1 -1
  54. package/dist/cjs/utils/viewportDetector.js +1 -1
  55. package/dist/cjs/version.json +1 -1
  56. package/dist/es2019/errors.js +42 -2
  57. package/dist/es2019/files/cardImageView/index.js +8 -61
  58. package/dist/es2019/files/index.js +1 -1
  59. package/dist/es2019/index.js +1 -1
  60. package/dist/es2019/root/card/cardAnalytics.js +7 -15
  61. package/dist/es2019/root/card/cardLoader.js +47 -53
  62. package/dist/es2019/root/card/cardState.js +26 -0
  63. package/dist/es2019/root/card/getCardPreview/cache.js +5 -0
  64. package/dist/es2019/root/card/getCardPreview/filePreviewStatus.js +38 -0
  65. package/dist/es2019/root/card/getCardPreview/helpers.js +2 -12
  66. package/dist/es2019/root/card/getCardPreview/index.js +112 -79
  67. package/dist/es2019/root/card/getCardStatus.js +1 -0
  68. package/dist/es2019/root/card/index.js +285 -190
  69. package/dist/es2019/root/cardView.js +93 -68
  70. package/dist/es2019/root/index.js +2 -1
  71. package/dist/es2019/root/inline/loader.js +16 -15
  72. package/dist/es2019/root/inline/mediaInlineCard.js +143 -0
  73. package/dist/es2019/root/inlinePlayer.js +3 -2
  74. package/dist/es2019/root/styled.js +2 -1
  75. package/dist/es2019/root/ui/common.js +7 -1
  76. package/dist/es2019/root/ui/iconMessage/index.js +8 -5
  77. package/dist/es2019/root/ui/imageRenderer/imageRenderer.js +25 -88
  78. package/dist/es2019/root/ui/loadingRateLimited/loadingRateLimited.js +4 -3
  79. package/dist/es2019/root/ui/progressBar/progressBar.js +1 -1
  80. package/dist/es2019/root/ui/progressBar/styled.js +1 -2
  81. package/dist/es2019/root/ui/styled.js +64 -3
  82. package/dist/es2019/root/ui/titleBox/failedTitleBox.js +6 -3
  83. package/dist/es2019/root/ui/titleBox/styled.js +1 -2
  84. package/dist/es2019/root/ui/titleBox/titleBox.js +1 -1
  85. package/dist/es2019/utils/analytics.js +15 -34
  86. package/dist/es2019/utils/cardActions/cardActionsDropdownMenu.js +8 -4
  87. package/dist/es2019/utils/dimensionComparer.js +1 -1
  88. package/dist/es2019/utils/getErrorMessage.js +1 -1
  89. package/dist/es2019/utils/metadata.js +12 -4
  90. package/dist/es2019/utils/objectURLCache.js +5 -0
  91. package/dist/es2019/utils/shouldDisplayImageThumbnail.js +1 -1
  92. package/dist/es2019/version.json +1 -1
  93. package/dist/esm/errors.js +60 -1
  94. package/dist/esm/files/cardImageView/index.js +51 -102
  95. package/dist/esm/files/index.js +1 -1
  96. package/dist/esm/index.js +1 -1
  97. package/dist/esm/root/card/cardAnalytics.js +7 -16
  98. package/dist/esm/root/card/cardLoader.js +66 -126
  99. package/dist/esm/root/card/cardState.js +32 -0
  100. package/dist/esm/root/card/getCardPreview/cache.js +6 -0
  101. package/dist/esm/root/card/getCardPreview/filePreviewStatus.js +38 -0
  102. package/dist/esm/root/card/getCardPreview/helpers.js +13 -21
  103. package/dist/esm/root/card/getCardPreview/index.js +142 -95
  104. package/dist/esm/root/card/getCardStatus.js +3 -0
  105. package/dist/esm/root/card/index.js +370 -284
  106. package/dist/esm/root/cardView.js +109 -84
  107. package/dist/esm/root/index.js +2 -1
  108. package/dist/esm/root/inline/loader.js +23 -22
  109. package/dist/esm/root/inline/mediaInlineCard.js +156 -0
  110. package/dist/esm/root/inlinePlayer.js +3 -2
  111. package/dist/esm/root/styled.js +3 -2
  112. package/dist/esm/root/ui/common.js +7 -1
  113. package/dist/esm/root/ui/iconMessage/index.js +10 -5
  114. package/dist/esm/root/ui/imageRenderer/imageRenderer.js +27 -118
  115. package/dist/esm/root/ui/loadingRateLimited/loadingRateLimited.js +4 -3
  116. package/dist/esm/root/ui/progressBar/progressBar.js +1 -1
  117. package/dist/esm/root/ui/progressBar/styled.js +1 -2
  118. package/dist/esm/root/ui/styled.js +61 -13
  119. package/dist/esm/root/ui/titleBox/failedTitleBox.js +7 -3
  120. package/dist/esm/root/ui/titleBox/styled.js +1 -2
  121. package/dist/esm/root/ui/titleBox/titleBox.js +1 -1
  122. package/dist/esm/utils/analytics.js +16 -35
  123. package/dist/esm/utils/cardActions/cardActionsDropdownMenu.js +16 -9
  124. package/dist/esm/utils/dimensionComparer.js +1 -1
  125. package/dist/esm/utils/getErrorMessage.js +1 -1
  126. package/dist/esm/utils/metadata.js +12 -4
  127. package/dist/esm/utils/objectURLCache.js +6 -0
  128. package/dist/esm/utils/shouldDisplayImageThumbnail.js +1 -1
  129. package/dist/esm/version.json +1 -1
  130. package/dist/types/errors.d.ts +15 -1
  131. package/dist/types/files/cardImageView/index.d.ts +4 -13
  132. package/dist/types/files/cardImageView/styled.d.ts +1 -1
  133. package/dist/types/files/index.d.ts +1 -1
  134. package/dist/types/index.d.ts +7 -5
  135. package/dist/types/root/card/cardAnalytics.d.ts +2 -6
  136. package/dist/types/root/card/cardLoader.d.ts +5 -19
  137. package/dist/types/root/card/cardState.d.ts +5 -0
  138. package/dist/types/root/card/getCardPreview/cache.d.ts +3 -1
  139. package/dist/types/root/card/getCardPreview/filePreviewStatus.d.ts +5 -0
  140. package/dist/types/root/card/getCardPreview/helpers.d.ts +3 -4
  141. package/dist/types/root/card/getCardPreview/index.d.ts +24 -14
  142. package/dist/types/root/card/getCardStatus.d.ts +1 -0
  143. package/dist/types/root/card/index.d.ts +19 -18
  144. package/dist/types/root/cardView.d.ts +13 -8
  145. package/dist/types/root/index.d.ts +1 -0
  146. package/dist/types/root/inline/loader.d.ts +8 -8
  147. package/dist/types/root/inline/{inlineMediaCard.d.ts → mediaInlineCard.d.ts} +4 -6
  148. package/dist/types/root/inlinePlayer.d.ts +1 -1
  149. package/dist/types/root/styled.d.ts +1 -0
  150. package/dist/types/root/ui/common.d.ts +4 -1
  151. package/dist/types/root/ui/iconMessage/index.d.ts +4 -3
  152. package/dist/types/root/ui/iconWrapper/styled.d.ts +1 -1
  153. package/dist/types/root/ui/imageRenderer/imageRenderer.d.ts +5 -15
  154. package/dist/types/root/ui/loadingRateLimited/loadingRateLimited.d.ts +2 -1
  155. package/dist/types/root/ui/loadingRateLimited/styled.d.ts +1 -1
  156. package/dist/types/root/ui/playButton/playButton.d.ts +1 -0
  157. package/dist/types/root/ui/progressBar/progressBar.d.ts +2 -1
  158. package/dist/types/root/ui/progressBar/styled.d.ts +1 -1
  159. package/dist/types/root/ui/styled.d.ts +10 -3
  160. package/dist/types/root/ui/tickBox/tickBox.d.ts +1 -0
  161. package/dist/types/root/ui/titleBox/failedTitleBox.d.ts +3 -1
  162. package/dist/types/root/ui/titleBox/styled.d.ts +1 -1
  163. package/dist/types/root/ui/titleBox/titleBox.d.ts +2 -10
  164. package/dist/types/styles/mixins.d.ts +1 -1
  165. package/dist/types/types.d.ts +7 -1
  166. package/dist/types/utils/analytics.d.ts +14 -15
  167. package/dist/types/utils/cardDimensions.d.ts +4 -4
  168. package/dist/types/utils/dimensionComparer.d.ts +1 -1
  169. package/dist/types/utils/getErrorMessage.d.ts +1 -0
  170. package/dist/types/utils/metadata.d.ts +2 -2
  171. package/dist/types/utils/objectURLCache.d.ts +2 -1
  172. package/example-helpers/developmentUseMessage.tsx +14 -0
  173. package/example-helpers/index.tsx +55 -4
  174. package/example-helpers/selectableCard.tsx +2 -1
  175. package/package.json +20 -16
  176. package/dist/cjs/root/card/cardSSRView.js +0 -99
  177. package/dist/cjs/root/card/getCardPreview/types.js +0 -5
  178. package/dist/cjs/root/ui/Breakpoint.js +0 -13
  179. package/dist/cjs/root/ui/styledSSR.js +0 -108
  180. package/dist/cjs/utils/fileAttributesContext.js +0 -40
  181. package/dist/es2019/root/card/cardSSRView.js +0 -79
  182. package/dist/es2019/root/card/getCardPreview/types.js +0 -1
  183. package/dist/es2019/root/inline/inlineMediaCard.js +0 -92
  184. package/dist/es2019/root/ui/Breakpoint.js +0 -6
  185. package/dist/es2019/root/ui/styledSSR.js +0 -93
  186. package/dist/es2019/utils/fileAttributesContext.js +0 -19
  187. package/dist/esm/root/card/cardSSRView.js +0 -78
  188. package/dist/esm/root/card/getCardPreview/types.js +0 -1
  189. package/dist/esm/root/inline/inlineMediaCard.js +0 -100
  190. package/dist/esm/root/ui/Breakpoint.js +0 -6
  191. package/dist/esm/root/ui/styledSSR.js +0 -76
  192. package/dist/esm/utils/fileAttributesContext.js +0 -18
  193. package/dist/types/root/card/cardSSRView.d.ts +0 -12
  194. package/dist/types/root/card/getCardPreview/types.d.ts +0 -5
  195. package/dist/types/root/ui/Breakpoint.d.ts +0 -4
  196. package/dist/types/root/ui/styledSSR.d.ts +0 -16
  197. package/dist/types/utils/fileAttributesContext.d.ts +0 -10
@@ -5,22 +5,20 @@ import { version as packageVersion, name as packageName } from '../../version.js
5
5
  import { withAnalyticsEvents } from '@atlaskit/analytics-next';
6
6
  import { withMediaAnalyticsContext } from '@atlaskit/media-common';
7
7
  import DownloadIcon from '@atlaskit/icon/glyph/download';
8
- import { addFileAttrsToUrl, globalMediaEventEmitter, isDifferentIdentifier, isFileIdentifier, isErrorFileState, RECENTS_COLLECTION, isImageRepresentationReady, isExternalImageIdentifier } from '@atlaskit/media-client';
8
+ import { globalMediaEventEmitter, isDifferentIdentifier, isFileIdentifier, RECENTS_COLLECTION, isImageRepresentationReady, isExternalImageIdentifier, imageResizeModeToFileImageMode } from '@atlaskit/media-client';
9
9
  import { MediaViewer } from '@atlaskit/media-viewer';
10
- import { IntlProvider, intlShape } from 'react-intl';
10
+ import { injectIntl, IntlProvider } from 'react-intl-next';
11
11
  import { CardView } from '../cardView';
12
12
  import { ViewportDetector } from '../../utils/viewportDetector';
13
13
  import { getRequestedDimensions } from '../../utils/getDataURIDimension';
14
- import { shouldGetCardPreview, extractFilePreviewStatus, getCardPreview, getCardPreviewFromCache, getFilePreviewFromFileState } from './getCardPreview';
14
+ import { getCardPreview, getCardPreviewFromCache, removeCardPreviewFromCache, getFilePreviewFromFileState, shouldResolvePreview, getSSRCardPreview, isLocalPreview, isSSRPreview, isSSRClientPreview, fetchAndCacheRemotePreview } from './getCardPreview';
15
15
  import { getFileDetails } from '../../utils/metadata';
16
- import { isBigger } from '../../utils/dimensionComparer';
17
- import { getCardStatus } from './getCardStatus';
18
16
  import { InlinePlayer } from '../inlinePlayer';
19
17
  import { getFileAttributes } from '../../utils/analytics';
20
- import { FileAttributesProvider } from '../../utils/fileAttributesContext';
21
- import { isRemotePreviewError, MediaCardError, ensureMediaCardError } from '../../errors';
22
- import { fireOperationalEvent, fireCommencedEvent, relevantFeatureFlagNames, fireCopiedEvent } from './cardAnalytics';
18
+ import { isLocalPreviewError, MediaCardError, ensureMediaCardError, ImageLoadError } from '../../errors';
19
+ import { fireOperationalEvent, fireCommencedEvent, relevantFeatureFlagNames, fireCopiedEvent, fireScreenEvent } from './cardAnalytics';
23
20
  import getDocument from '../../utils/document';
21
+ import { getCardStateFromFileState, createStateUpdater } from './cardState';
24
22
  export class CardBase extends Component {
25
23
  // We initialise timeElapsedTillCommenced
26
24
  // to avoid extra branching on a possibly undefined value.
@@ -31,75 +29,171 @@ export class CardBase extends Component {
31
29
 
32
30
  _defineProperty(this, "timeElapsedTillCommenced", performance.now());
33
31
 
34
- _defineProperty(this, "shouldRefetchImage", (current, next) => {
35
- if (!current || !next) {
36
- return false;
37
- }
38
-
39
- return isBigger(current, next);
40
- });
41
-
42
- _defineProperty(this, "isLatestCardStatusUpdate", cardStatusUpdateTimestamp => !this.lastCardStatusUpdateTimestamp || this.lastCardStatusUpdateTimestamp <= cardStatusUpdateTimestamp);
43
-
44
- _defineProperty(this, "onLocalPreviewError", error => {// TODO: track local preview success rate
45
- // https://product-fabric.atlassian.net/browse/MEX-774
46
- });
32
+ _defineProperty(this, "getImageURLParams", ({
33
+ collectionName: collection
34
+ }) => ({
35
+ collection,
36
+ mode: imageResizeModeToFileImageMode(this.props.resizeMode),
37
+ ...this.requestedDimensions,
38
+ allowAnimated: true
39
+ }));
47
40
 
48
- _defineProperty(this, "createAddContextToDataURI", (fileId, fileState, {
49
- width,
50
- height
51
- }, collectionName) => dataURI => {
41
+ _defineProperty(this, "getMediaBlobUrlAttrs", (identifier, fileState) => {
42
+ const {
43
+ id,
44
+ collectionName: collection
45
+ } = identifier;
52
46
  const {
47
+ originalDimensions,
53
48
  contextId,
54
49
  alt
55
50
  } = this.props;
56
-
57
- if (!contextId) {
58
- return dataURI;
59
- }
60
-
61
- const metadata = getFileDetails(fileState);
62
- return addFileAttrsToUrl(dataURI, {
63
- id: fileId,
64
- collection: collectionName,
51
+ const {
52
+ mimeType,
53
+ name,
54
+ size
55
+ } = getFileDetails(identifier, fileState);
56
+ return contextId ? {
57
+ id,
58
+ collection,
65
59
  contextId,
66
- mimeType: metadata.mimeType,
67
- name: metadata.name,
68
- size: metadata.size,
69
- width,
70
- height,
60
+ mimeType,
61
+ name,
62
+ size,
63
+ ...(originalDimensions || this.requestedDimensions),
71
64
  alt
72
- });
65
+ } : undefined;
73
66
  });
74
67
 
75
- _defineProperty(this, "getCardPreviewParams", (id, collectionName, fileState) => {
68
+ _defineProperty(this, "getCardPreviewParams", (identifier, fileState) => {
69
+ const {
70
+ isBannedLocalPreview
71
+ } = this.state;
72
+ const {
73
+ id
74
+ } = identifier;
76
75
  const {
77
76
  dimensions = {},
78
- originalDimensions,
79
- resizeMode,
80
77
  mediaClient
81
78
  } = this.props;
82
- const {
83
- cardRef
84
- } = this.state;
85
- const requestedDimensions = getRequestedDimensions({
86
- dimensions,
87
- element: cardRef
88
- });
89
79
  return {
90
80
  mediaClient,
91
81
  id,
92
- collectionName,
93
82
  dimensions,
94
- resizeMode,
95
- requestedDimensions,
96
- onLocalPreviewError: this.onLocalPreviewError,
97
- filePreview: getFilePreviewFromFileState(fileState),
83
+ onLocalPreviewError: this.fireLocalPreviewErrorEvent,
84
+ filePreview: isBannedLocalPreview ? undefined : getFilePreviewFromFileState(fileState),
98
85
  isRemotePreviewReady: isImageRepresentationReady(fileState),
99
- addContextToDataURI: this.createAddContextToDataURI(id, fileState, originalDimensions || requestedDimensions, collectionName)
86
+ imageUrlParams: this.getImageURLParams(identifier),
87
+ mediaBlobUrlAttrs: this.getMediaBlobUrlAttrs(identifier, fileState)
100
88
  };
101
89
  });
102
90
 
91
+ _defineProperty(this, "setCacheSSRPreview", identifier => {
92
+ const {
93
+ mediaClient,
94
+ dimensions = {}
95
+ } = this.props;
96
+ fetchAndCacheRemotePreview(mediaClient, identifier.id, dimensions, this.getImageURLParams(identifier), this.getMediaBlobUrlAttrs(identifier)).catch(() => {// No need to log this error.
97
+ // If preview fails, it will be refetched later
98
+ //TODO: test this catch
99
+ // https://product-fabric.atlassian.net/browse/MEX-1071
100
+ });
101
+ });
102
+
103
+ _defineProperty(this, "resolveSSRPreview", (identifier, ssr) => {
104
+ const {
105
+ mediaClient
106
+ } = this.props;
107
+
108
+ try {
109
+ return getSSRCardPreview(ssr, mediaClient, identifier.id, this.getImageURLParams(identifier), this.getMediaBlobUrlAttrs(identifier));
110
+ } catch (e) {// TODO: log SSR reliability 'failed'
111
+ // https://product-fabric.atlassian.net/browse/MEX-770
112
+ }
113
+ });
114
+
115
+ _defineProperty(this, "resolvePreview", async (identifier, fileState) => {
116
+ try {
117
+ const params = this.getCardPreviewParams(identifier, fileState);
118
+ const cardPreview = await getCardPreview(params);
119
+ this.safeSetState({
120
+ cardPreview
121
+ });
122
+ } catch (e) {
123
+ const wrappedError = ensureMediaCardError('preview-fetch', e); // If remote preview fails, we set status 'error'
124
+ // If local preview fails (i.e, no remote preview available),
125
+ // we can stay in the same status until there is a remote preview available
126
+ // If it's any other error we set status 'error'
127
+
128
+ if (isLocalPreviewError(wrappedError)) {
129
+ this.safeSetState({
130
+ isBannedLocalPreview: true
131
+ });
132
+ } else {
133
+ this.safeSetState({
134
+ status: 'error',
135
+ error: wrappedError
136
+ });
137
+ }
138
+ }
139
+ });
140
+
141
+ _defineProperty(this, "getPerformanceAttributes", () => {
142
+ const {
143
+ timeElapsedTillCommenced
144
+ } = this;
145
+ const timeElapsedTillEvent = performance.now();
146
+ const durationSinceCommenced = timeElapsedTillCommenced && timeElapsedTillEvent - timeElapsedTillCommenced;
147
+ return {
148
+ overall: {
149
+ durationSincePageStart: timeElapsedTillEvent,
150
+ durationSinceCommenced
151
+ }
152
+ };
153
+ });
154
+
155
+ _defineProperty(this, "onImageError", () => {
156
+ const {
157
+ cardPreview
158
+ } = this.state;
159
+ const error = new ImageLoadError(cardPreview === null || cardPreview === void 0 ? void 0 : cardPreview.source);
160
+ const isLocal = cardPreview && isLocalPreview(cardPreview);
161
+ const isSSR = cardPreview && isSSRClientPreview(cardPreview);
162
+
163
+ if (isLocal || isSSR) {
164
+ const updateState = {
165
+ cardPreview: undefined
166
+ };
167
+
168
+ if (isLocal) {
169
+ updateState.isBannedLocalPreview = true;
170
+ this.fireLocalPreviewErrorEvent(error);
171
+ }
172
+
173
+ if (isSSR) {// TODO: set SSR-client reliability 'failed'.
174
+ // https://product-fabric.atlassian.net/browse/MEX-770
175
+ }
176
+
177
+ const {
178
+ identifier,
179
+ dimensions = {}
180
+ } = this.props;
181
+ isFileIdentifier(identifier) && removeCardPreviewFromCache(identifier.id, dimensions);
182
+ this.safeSetState(updateState);
183
+ } else {
184
+ this.safeSetState({
185
+ status: 'error',
186
+ error
187
+ });
188
+ }
189
+ });
190
+
191
+ _defineProperty(this, "onImageLoad", () => {
192
+ this.safeSetState({
193
+ previewDidRender: true
194
+ });
195
+ });
196
+
103
197
  _defineProperty(this, "fireCopiedEvent", () => {
104
198
  const {
105
199
  createAnalyticsEvent
@@ -110,9 +204,24 @@ export class CardBase extends Component {
110
204
  cardRef && createAnalyticsEvent && fireCopiedEvent(createAnalyticsEvent, this.metadata.id, cardRef);
111
205
  });
112
206
 
207
+ _defineProperty(this, "fireScreenEvent", () => {
208
+ const {
209
+ createAnalyticsEvent
210
+ } = this.props;
211
+ createAnalyticsEvent && fireScreenEvent(createAnalyticsEvent, this.fileAttributes);
212
+ });
213
+
214
+ _defineProperty(this, "fireLocalPreviewErrorEvent", error => {// TODO: track local preview success rate
215
+ // https://product-fabric.atlassian.net/browse/MEX-774
216
+ });
217
+
113
218
  _defineProperty(this, "safeSetState", state => {
114
219
  if (this.hasBeenMounted) {
115
- this.setState(state);
220
+ // If it's setting the status, we need to use a state updater function,
221
+ // which ensures that no non-final status overrides a final status.
222
+ // If no status is set, we don't need a sate updater
223
+ const updater = !!state.status ? createStateUpdater(state) : state;
224
+ this.setState(updater);
116
225
  }
117
226
  });
118
227
 
@@ -122,8 +231,9 @@ export class CardBase extends Component {
122
231
  }
123
232
 
124
233
  if (this.hasBeenMounted) {
234
+ // TODO MEX-788: add test for "do not remove the card preview when unsubscribing".
125
235
  this.setState({
126
- cardPreview: undefined
236
+ isBannedLocalPreview: false
127
237
  });
128
238
  }
129
239
  });
@@ -285,7 +395,8 @@ export class CardBase extends Component {
285
395
  testId,
286
396
  featureFlags,
287
397
  titleBoxBgColor,
288
- titleBoxIcon
398
+ titleBoxIcon,
399
+ ssr
289
400
  } = this.props;
290
401
  const {
291
402
  mediaItemType
@@ -301,21 +412,26 @@ export class CardBase extends Component {
301
412
  orientation: 1
302
413
  },
303
414
  error,
304
- cardRef
415
+ cardRef,
416
+ isCardVisible
305
417
  } = this.state;
306
418
  const {
307
- metadata,
308
- timeElapsedTillCommenced
419
+ metadata
309
420
  } = this;
310
421
  const {
311
422
  onCardViewClick,
312
423
  onDisplayImage,
313
424
  actions,
314
425
  onMouseEnter
315
- } = this;
426
+ } = this; // Card can be artificially turned visible before entering the viewport
427
+ // For example, when we have the image in cache
428
+
429
+ const nativeLazyLoad = isLazy && !isCardVisible; // Force Media Image to always display img for SSR
430
+
431
+ const forceSyncDisplay = !!ssr;
316
432
  const card = /*#__PURE__*/React.createElement(CardView, {
317
433
  status: status,
318
- error: error && error.secondaryError,
434
+ error: error,
319
435
  mediaItemType: mediaItemType,
320
436
  metadata: metadata,
321
437
  dataURI: dataURI,
@@ -337,7 +453,10 @@ export class CardBase extends Component {
337
453
  featureFlags: featureFlags,
338
454
  titleBoxBgColor: titleBoxBgColor,
339
455
  titleBoxIcon: titleBoxIcon,
340
- timeElapsedTillCommenced: timeElapsedTillCommenced
456
+ onImageError: this.onImageError,
457
+ onImageLoad: this.onImageLoad,
458
+ nativeLazyLoad: nativeLazyLoad,
459
+ forceSyncDisplay: forceSyncDisplay
341
460
  });
342
461
  return isLazy ? /*#__PURE__*/React.createElement(ViewportDetector, {
343
462
  targetRef: cardRef,
@@ -391,7 +510,8 @@ export class CardBase extends Component {
391
510
 
392
511
  const {
393
512
  identifier: _identifier,
394
- dimensions: _dimensions = {}
513
+ dimensions: _dimensions = {},
514
+ ssr: _ssr
395
515
  } = this.props;
396
516
 
397
517
  if (isFileIdentifier(_identifier)) {
@@ -399,9 +519,14 @@ export class CardBase extends Component {
399
519
  id
400
520
  } = _identifier;
401
521
  _cardPreview = getCardPreviewFromCache(id, _dimensions);
522
+
523
+ if (!_cardPreview && _ssr) {
524
+ this.fireCommencedEvent();
525
+ _cardPreview = this.resolveSSRPreview(_identifier, _ssr);
526
+ }
402
527
  } else if (isExternalImageIdentifier(_identifier)) {
403
528
  this.fireCommencedEvent();
404
- _status = 'complete';
529
+ _status = 'loading-preview';
405
530
  const {
406
531
  dataURI
407
532
  } = _identifier;
@@ -410,34 +535,44 @@ export class CardBase extends Component {
410
535
  orientation: 1,
411
536
  source: 'external'
412
537
  };
413
- }
414
- /**
415
- * If cardPreview is available from local cache, `isCardVisible`
416
- * should be true to avoid flickers during re-mount of the component
417
- */
538
+ } // If cardPreview is available from local cache or external, `isCardVisible`
539
+ // should be true to avoid flickers during re-mount of the component
540
+ // should not be visible for SSR preview, otherwise we'll fire the metadata fetch from
541
+ // outside the viewport
542
+
418
543
 
544
+ const _isCardVisible = !this.props.isLazy || !!_cardPreview && !isSSRPreview(_cardPreview);
419
545
 
420
- const isCardVisible = _cardPreview ? true : !this.props.isLazy;
421
546
  this.state = {
422
547
  status: _status,
423
- isCardVisible,
548
+ isCardVisible: _isCardVisible,
424
549
  isPlayingFile: false,
425
550
  cardPreview: _cardPreview,
426
- cardRef: null
551
+ cardRef: null,
552
+ isBannedLocalPreview: false,
553
+ previewDidRender: false
427
554
  };
428
555
  }
429
556
 
430
557
  componentDidMount() {
431
558
  this.hasBeenMounted = true;
432
559
  const {
433
- isCardVisible
560
+ isCardVisible,
561
+ cardPreview
434
562
  } = this.state;
435
563
  const {
436
- identifier
564
+ identifier,
565
+ ssr
437
566
  } = this.props;
438
567
 
439
568
  if (isCardVisible && isFileIdentifier(identifier)) {
440
569
  this.updateStateForIdentifier(identifier);
570
+ }
571
+
572
+ if (isCardVisible && !!ssr && !!cardPreview && isSSRClientPreview(cardPreview) && isFileIdentifier(identifier)) {
573
+ // Since the SSR preview brings the token in the query params,
574
+ // We need to fetch the remote preview to be able to cache it,
575
+ this.setCacheSSRPreview(identifier);
441
576
  } // we add a listener for each of the cards on the page
442
577
  // and then check if the triggered listener is from the card
443
578
  // that contains a div in current window.getSelection()
@@ -459,13 +594,20 @@ export class CardBase extends Component {
459
594
  const {
460
595
  mediaClient,
461
596
  identifier,
462
- dimensions
597
+ dimensions,
598
+ featureFlags
463
599
  } = this.props;
464
600
  const {
465
- isCardVisible
601
+ isCardVisible,
602
+ cardPreview,
603
+ status,
604
+ fileState,
605
+ isBannedLocalPreview,
606
+ previewDidRender
466
607
  } = this.state;
467
608
  const isDifferent = isDifferentIdentifier(prevIdentifier, identifier);
468
609
  const turnedVisible = !prevIsCardVisible && isCardVisible;
610
+ const isNewMediaClient = prevMediaClient !== mediaClient;
469
611
 
470
612
  if (isExternalImageIdentifier(identifier) && isDifferent) {
471
613
  this.fireCommencedEvent();
@@ -473,7 +615,7 @@ export class CardBase extends Component {
473
615
  dataURI
474
616
  } = identifier;
475
617
  this.setState({
476
- status: 'complete',
618
+ status: 'loading-preview',
477
619
  cardPreview: {
478
620
  dataURI,
479
621
  orientation: 1,
@@ -483,13 +625,42 @@ export class CardBase extends Component {
483
625
  });
484
626
  }
485
627
 
486
- if (isFileIdentifier(identifier) && (turnedVisible || prevMediaClient !== mediaClient || isDifferent || // TODO: should not resubscribe on resize. Only refetch
487
- this.shouldRefetchImage(prevDimensions, dimensions))) {
628
+ if (isFileIdentifier(identifier) && (turnedVisible || !!this.subscription && (isNewMediaClient || isDifferent))) {
488
629
  this.updateStateForIdentifier(identifier);
489
630
  }
490
631
 
491
632
  if (this.state.status !== prevState.status) {
492
633
  this.fireOperationalEvent();
634
+
635
+ if (this.state.status === 'complete' || this.fileAttributes.fileMediatype === 'video' && !!cardPreview && this.state.status === 'processing') {
636
+ this.fireScreenEvent();
637
+ }
638
+ }
639
+
640
+ if (isFileIdentifier(identifier) && fileState && shouldResolvePreview({
641
+ status,
642
+ fileState,
643
+ dimensions,
644
+ prevDimensions,
645
+ featureFlags,
646
+ hasCardPreview: !!cardPreview,
647
+ isBannedLocalPreview
648
+ })) {
649
+ this.resolvePreview(identifier, fileState);
650
+ }
651
+
652
+ if (turnedVisible && this.props.ssr && !!cardPreview && isSSRClientPreview(cardPreview) && isFileIdentifier(identifier)) {
653
+ // Since the SSR preview brings the token in the query params,
654
+ // We need to fetch the remote preview to be able to cache it,
655
+ this.setCacheSSRPreview(identifier);
656
+ }
657
+
658
+ if (previewDidRender && // We should't complete if status is uploading
659
+ ['loading-preview', 'processing'].includes(status)) {
660
+ this.safeSetState({
661
+ status: 'complete'
662
+ });
663
+ this.unsubscribe();
493
664
  }
494
665
  }
495
666
 
@@ -508,6 +679,9 @@ export class CardBase extends Component {
508
679
  const {
509
680
  mediaClient
510
681
  } = this.props;
682
+ const {
683
+ isBannedLocalPreview
684
+ } = this.state;
511
685
  const {
512
686
  id,
513
687
  collectionName,
@@ -518,129 +692,58 @@ export class CardBase extends Component {
518
692
  collectionName,
519
693
  occurrenceKey
520
694
  }).subscribe({
521
- next: async fileState => {
522
- this.lastFileState = fileState;
523
- const thisCardStatusUpdateTimestamp = (performance || Date).now();
524
- const filePreviewStatus = extractFilePreviewStatus(fileState, this.props.featureFlags);
525
- let status = getCardStatus(fileState.status, filePreviewStatus);
526
- this.safeSetState({
527
- fileState
528
- });
529
- let cardPreview;
530
- let error;
531
-
532
- if (shouldGetCardPreview(status, filePreviewStatus)) {
533
- try {
534
- cardPreview = await getCardPreview(this.getCardPreviewParams(id, collectionName, fileState));
535
-
536
- if (['loading-preview', 'processing'].includes(status)) {
537
- status = 'complete';
538
- }
539
- } catch (e) {
540
- const wrappedError = ensureMediaCardError('preview-fetch', e);
541
- /**
542
- * If remote preview fails, we set status 'error'
543
- * If the local preview fails (i.e, no remote preview available),
544
- * we can stay in the same status until there is a remote preview available
545
- * */
546
-
547
- if (isRemotePreviewError(wrappedError)) {
548
- status = 'error';
549
- error = wrappedError;
550
- }
551
- }
552
- }
553
-
554
- if (this.isLatestCardStatusUpdate(thisCardStatusUpdateTimestamp)) {
555
- // These status and progress must not override values representing more recent FileState
556
-
557
- /* next() start some await() delay in next() status & progress update
558
- * ------- ------------------ ------------------------
559
- * |----[1]FileState:uploading------>| |
560
- * | | |
561
- * |----[2]FileState:uploading------>| |
562
- * | | |
563
- * | |----[2]FileState:uploading------>| Update status to `uploading`
564
- * |----[3]FileState:processing----->| |
565
- * | |----[3]FileState:processing----->| Update status to `complete`
566
- * | | |
567
- * | |----[1]FileState:uploading------>| We do not want to update status to `uploading` again!
568
- *
569
- */
570
- if (status === 'error' && isErrorFileState(fileState) && !error) {
571
- error = new MediaCardError('error-file-state', new Error(fileState.message));
572
- }
573
-
574
- this.safeSetState({
575
- status,
576
- cardPreview,
577
- progress: status === 'uploading' && fileState.status === 'uploading' ? fileState.progress : 1,
578
- error: status === 'error' && error ? error : undefined
579
- });
580
- this.lastCardStatusUpdateTimestamp = thisCardStatusUpdateTimestamp;
581
- }
695
+ next: fileState => {
696
+ const {
697
+ featureFlags
698
+ } = this.props;
699
+ const newState = getCardStateFromFileState(fileState, isBannedLocalPreview, featureFlags);
700
+ this.safeSetState(newState);
582
701
  },
583
702
  error: e => {
584
- // If file state subscription decides that the card is complete
585
- // and later there is an error, we won't change the card's status.
586
- if (this.state.status === 'complete') {
587
- return;
588
- }
589
-
590
- const errorReason = this.fileAttributes.fileStatus === 'uploading' ? 'upload' : 'metadata-fetch';
703
+ const errorReason = this.state.status === 'uploading' ? 'upload' : 'metadata-fetch';
591
704
  const error = new MediaCardError(errorReason, e);
592
705
  this.safeSetState({
593
706
  error,
594
707
  status: 'error'
595
708
  });
596
- this.lastCardStatusUpdateTimestamp = (performance || Date).now();
597
709
  }
598
710
  });
599
711
  }
600
712
 
601
- get metadata() {
713
+ get requestedDimensions() {
602
714
  const {
603
- identifier
715
+ dimensions
604
716
  } = this.props;
605
- return isFileIdentifier(identifier) ? this.state.fileState ? getFileDetails(this.state.fileState) : {
606
- id: identifier.id
607
- } : {
608
- id: identifier.mediaItemType,
609
- name: identifier.name || identifier.dataURI,
610
- mediaType: 'image'
611
- };
717
+ const {
718
+ cardRef: element
719
+ } = this.state || {};
720
+ return getRequestedDimensions({
721
+ dimensions,
722
+ element
723
+ });
724
+ }
725
+
726
+ get metadata() {
727
+ var _this$state;
728
+
729
+ return getFileDetails(this.props.identifier, (_this$state = this.state) === null || _this$state === void 0 ? void 0 : _this$state.fileState);
612
730
  }
613
731
 
614
732
  get fileAttributes() {
615
- var _this$lastFileState;
733
+ var _this$state2, _this$state2$fileStat;
616
734
 
617
- return getFileAttributes(this.metadata, (_this$lastFileState = this.lastFileState) === null || _this$lastFileState === void 0 ? void 0 : _this$lastFileState.status);
735
+ return getFileAttributes(this.metadata, (_this$state2 = this.state) === null || _this$state2 === void 0 ? void 0 : (_this$state2$fileStat = _this$state2.fileState) === null || _this$state2$fileStat === void 0 ? void 0 : _this$state2$fileStat.status);
618
736
  }
619
737
 
620
738
  fireOperationalEvent() {
621
- const {
622
- timeElapsedTillCommenced
623
- } = this;
624
739
  const {
625
740
  status,
626
- cardPreview,
627
741
  error
628
742
  } = this.state;
629
743
  const {
630
744
  createAnalyticsEvent
631
745
  } = this.props;
632
- const timeElapsedTillEvent = performance.now();
633
- const durationSinceCommenced = timeElapsedTillCommenced && timeElapsedTillEvent - timeElapsedTillCommenced;
634
- const performanceAttributes = {
635
- overall: {
636
- durationSincePageStart: timeElapsedTillEvent,
637
- durationSinceCommenced
638
- }
639
- };
640
- createAnalyticsEvent && fireOperationalEvent(createAnalyticsEvent, status, this.fileAttributes, performanceAttributes, {
641
- cardPreview,
642
- error
643
- });
746
+ createAnalyticsEvent && fireOperationalEvent(createAnalyticsEvent, status, this.fileAttributes, this.getPerformanceAttributes(), error);
644
747
  }
645
748
 
646
749
  fireCommencedEvent() {
@@ -683,19 +786,14 @@ export class CardBase extends Component {
683
786
  }
684
787
 
685
788
  render() {
686
- var _this$lastFileState2;
687
-
688
789
  const {
689
790
  isPlayingFile,
690
791
  mediaViewerSelectedItem
691
792
  } = this.state;
692
793
  const innerContent = /*#__PURE__*/React.createElement(React.Fragment, null, isPlayingFile ? this.renderInlinePlayer() : this.renderCard(), mediaViewerSelectedItem ? this.renderMediaViewer() : null);
693
- const content = this.context.intl ? innerContent : /*#__PURE__*/React.createElement(IntlProvider, {
794
+ return this.props.intl ? innerContent : /*#__PURE__*/React.createElement(IntlProvider, {
694
795
  locale: "en"
695
796
  }, innerContent);
696
- return /*#__PURE__*/React.createElement(FileAttributesProvider, {
697
- data: getFileAttributes(this.metadata, (_this$lastFileState2 = this.lastFileState) === null || _this$lastFileState2 === void 0 ? void 0 : _this$lastFileState2.status)
698
- }, content);
699
797
  }
700
798
 
701
799
  }
@@ -709,11 +807,6 @@ _defineProperty(CardBase, "defaultProps", {
709
807
  featureFlags: {}
710
808
  });
711
809
 
712
- _defineProperty(CardBase, "contextTypes", {
713
- // Required to detect a parent IntlProvider
714
- intl: intlShape
715
- });
716
-
717
810
  export const Card = withMediaAnalyticsContext({
718
811
  packageVersion,
719
812
  packageName,
@@ -721,4 +814,6 @@ export const Card = withMediaAnalyticsContext({
721
814
  component: 'mediaCard'
722
815
  }, {
723
816
  filterFeatureFlags: relevantFeatureFlagNames
724
- })(withAnalyticsEvents()(CardBase));
817
+ })(withAnalyticsEvents()(injectIntl(CardBase, {
818
+ enforceContext: false
819
+ })));