@atlaskit/media-card 71.0.0 → 73.1.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 (204) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/dist/cjs/actions.js +2 -2
  3. package/dist/cjs/errors.js +83 -8
  4. package/dist/cjs/files/cardImageView/cardOverlay/styled.js +1 -1
  5. package/dist/cjs/files/cardImageView/index.js +53 -104
  6. package/dist/cjs/files/cardImageView/styled.js +1 -1
  7. package/dist/cjs/files/index.js +0 -6
  8. package/dist/cjs/index.js +8 -8
  9. package/dist/cjs/root/card/cardAnalytics.js +4 -16
  10. package/dist/cjs/root/card/cardLoader.js +66 -124
  11. package/dist/cjs/root/card/cardState.js +50 -0
  12. package/dist/cjs/root/card/getCardPreview/cache.js +10 -5
  13. package/dist/cjs/root/card/getCardPreview/filePreviewStatus.js +53 -0
  14. package/dist/cjs/root/card/getCardPreview/helpers.js +14 -22
  15. package/dist/cjs/root/card/getCardPreview/index.js +177 -97
  16. package/dist/cjs/root/card/getCardStatus.js +7 -1
  17. package/dist/cjs/root/card/index.js +384 -285
  18. package/dist/cjs/root/cardView.js +113 -88
  19. package/dist/cjs/root/inline/loader.js +47 -15
  20. package/dist/cjs/root/inline/mediaInlineCard.js +33 -12
  21. package/dist/cjs/root/inlinePlayer.js +77 -24
  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 +47 -123
  29. package/dist/cjs/root/ui/loadingRateLimited/loadingRateLimited.js +6 -4
  30. package/dist/cjs/root/ui/loadingRateLimited/styled.js +2 -2
  31. package/dist/cjs/root/ui/playButton/styled.js +1 -1
  32. package/dist/cjs/root/ui/progressBar/progressBar.js +7 -4
  33. package/dist/cjs/root/ui/progressBar/styled.js +8 -9
  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 +7 -44
  42. package/dist/cjs/utils/breakpoint.js +1 -1
  43. package/dist/cjs/utils/cardActions/cardActionsDropdownMenu.js +18 -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 +49 -22
  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/root/card/cardAnalytics.js +3 -14
  60. package/dist/es2019/root/card/cardLoader.js +47 -53
  61. package/dist/es2019/root/card/cardState.js +26 -0
  62. package/dist/es2019/root/card/getCardPreview/cache.js +5 -0
  63. package/dist/es2019/root/card/getCardPreview/filePreviewStatus.js +38 -0
  64. package/dist/es2019/root/card/getCardPreview/helpers.js +2 -12
  65. package/dist/es2019/root/card/getCardPreview/index.js +112 -73
  66. package/dist/es2019/root/card/getCardStatus.js +1 -0
  67. package/dist/es2019/root/card/index.js +308 -190
  68. package/dist/es2019/root/cardView.js +97 -68
  69. package/dist/es2019/root/inline/loader.js +17 -5
  70. package/dist/es2019/root/inline/mediaInlineCard.js +32 -11
  71. package/dist/es2019/root/inlinePlayer.js +56 -4
  72. package/dist/es2019/root/styled.js +2 -1
  73. package/dist/es2019/root/ui/common.js +7 -1
  74. package/dist/es2019/root/ui/iconMessage/index.js +8 -5
  75. package/dist/es2019/root/ui/imageRenderer/imageRenderer.js +35 -88
  76. package/dist/es2019/root/ui/loadingRateLimited/loadingRateLimited.js +4 -3
  77. package/dist/es2019/root/ui/loadingRateLimited/styled.js +1 -1
  78. package/dist/es2019/root/ui/progressBar/progressBar.js +5 -3
  79. package/dist/es2019/root/ui/progressBar/styled.js +7 -6
  80. package/dist/es2019/root/ui/styled.js +65 -4
  81. package/dist/es2019/root/ui/titleBox/failedTitleBox.js +6 -3
  82. package/dist/es2019/root/ui/titleBox/styled.js +1 -2
  83. package/dist/es2019/root/ui/titleBox/titleBox.js +1 -1
  84. package/dist/es2019/utils/analytics.js +5 -34
  85. package/dist/es2019/utils/cardActions/cardActionsDropdownMenu.js +8 -4
  86. package/dist/es2019/utils/dimensionComparer.js +1 -1
  87. package/dist/es2019/utils/getErrorMessage.js +1 -1
  88. package/dist/es2019/utils/metadata.js +12 -4
  89. package/dist/es2019/utils/objectURLCache.js +5 -0
  90. package/dist/es2019/utils/shouldDisplayImageThumbnail.js +1 -1
  91. package/dist/es2019/utils/viewportDetector.js +48 -18
  92. package/dist/es2019/version.json +1 -1
  93. package/dist/esm/actions.js +2 -2
  94. package/dist/esm/errors.js +64 -4
  95. package/dist/esm/files/cardImageView/index.js +51 -102
  96. package/dist/esm/files/index.js +1 -1
  97. package/dist/esm/root/card/cardAnalytics.js +3 -15
  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 +9 -2
  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 +144 -91
  104. package/dist/esm/root/card/getCardStatus.js +3 -0
  105. package/dist/esm/root/card/index.js +396 -288
  106. package/dist/esm/root/cardView.js +113 -86
  107. package/dist/esm/root/inline/loader.js +48 -15
  108. package/dist/esm/root/inline/mediaInlineCard.js +32 -11
  109. package/dist/esm/root/inlinePlayer.js +74 -23
  110. package/dist/esm/root/styled.js +3 -2
  111. package/dist/esm/root/ui/common.js +7 -1
  112. package/dist/esm/root/ui/iconMessage/index.js +10 -5
  113. package/dist/esm/root/ui/imageRenderer/imageRenderer.js +37 -116
  114. package/dist/esm/root/ui/loadingRateLimited/loadingRateLimited.js +4 -3
  115. package/dist/esm/root/ui/loadingRateLimited/styled.js +1 -1
  116. package/dist/esm/root/ui/progressBar/progressBar.js +6 -3
  117. package/dist/esm/root/ui/progressBar/styled.js +7 -7
  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 +5 -36
  123. package/dist/esm/utils/cardActions/cardActionsDropdownMenu.js +17 -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/utils/viewportDetector.js +48 -21
  130. package/dist/esm/version.json +1 -1
  131. package/dist/types/errors.d.ts +15 -1
  132. package/dist/types/files/cardImageView/index.d.ts +4 -13
  133. package/dist/types/files/cardImageView/styled.d.ts +1 -1
  134. package/dist/types/files/index.d.ts +1 -1
  135. package/dist/types/index.d.ts +7 -4
  136. package/dist/types/root/card/cardAnalytics.d.ts +1 -6
  137. package/dist/types/root/card/cardLoader.d.ts +5 -19
  138. package/dist/types/root/card/cardState.d.ts +5 -0
  139. package/dist/types/root/card/getCardPreview/cache.d.ts +3 -1
  140. package/dist/types/root/card/getCardPreview/filePreviewStatus.d.ts +5 -0
  141. package/dist/types/root/card/getCardPreview/helpers.d.ts +3 -4
  142. package/dist/types/root/card/getCardPreview/index.d.ts +24 -14
  143. package/dist/types/root/card/getCardStatus.d.ts +1 -0
  144. package/dist/types/root/card/index.d.ts +20 -18
  145. package/dist/types/root/cardView.d.ts +13 -8
  146. package/dist/types/root/inline/loader.d.ts +2 -0
  147. package/dist/types/root/inline/mediaInlineCard.d.ts +3 -5
  148. package/dist/types/root/inlinePlayer.d.ts +8 -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 +14 -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 +4 -2
  158. package/dist/types/root/ui/progressBar/styled.d.ts +3 -2
  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 +6 -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/dist/types/utils/viewportDetector.d.ts +13 -5
  173. package/example-helpers/developmentUseMessage.tsx +14 -0
  174. package/example-helpers/index.tsx +55 -4
  175. package/example-helpers/selectableCard.tsx +2 -1
  176. package/package.json +18 -16
  177. package/dist/cjs/root/card/cardSSRView.js +0 -112
  178. package/dist/cjs/root/card/getCardPreview/types.js +0 -5
  179. package/dist/cjs/root/ui/Breakpoint.js +0 -13
  180. package/dist/cjs/root/ui/styledSSR.js +0 -108
  181. package/dist/cjs/utils/fileAttributesContext.js +0 -40
  182. package/dist/cjs/utils/lazyContent/index.js +0 -56
  183. package/dist/cjs/utils/lazyContent/styled.js +0 -23
  184. package/dist/es2019/root/card/cardSSRView.js +0 -92
  185. package/dist/es2019/root/card/getCardPreview/types.js +0 -1
  186. package/dist/es2019/root/ui/Breakpoint.js +0 -6
  187. package/dist/es2019/root/ui/styledSSR.js +0 -93
  188. package/dist/es2019/utils/fileAttributesContext.js +0 -19
  189. package/dist/es2019/utils/lazyContent/index.js +0 -18
  190. package/dist/es2019/utils/lazyContent/styled.js +0 -12
  191. package/dist/esm/root/card/cardSSRView.js +0 -91
  192. package/dist/esm/root/card/getCardPreview/types.js +0 -1
  193. package/dist/esm/root/ui/Breakpoint.js +0 -6
  194. package/dist/esm/root/ui/styledSSR.js +0 -76
  195. package/dist/esm/utils/fileAttributesContext.js +0 -18
  196. package/dist/esm/utils/lazyContent/index.js +0 -41
  197. package/dist/esm/utils/lazyContent/styled.js +0 -14
  198. package/dist/types/root/card/cardSSRView.d.ts +0 -13
  199. package/dist/types/root/card/getCardPreview/types.d.ts +0 -5
  200. package/dist/types/root/ui/Breakpoint.d.ts +0 -4
  201. package/dist/types/root/ui/styledSSR.d.ts +0 -16
  202. package/dist/types/utils/fileAttributesContext.d.ts +0 -10
  203. package/dist/types/utils/lazyContent/index.d.ts +0 -11
  204. package/dist/types/utils/lazyContent/styled.d.ts +0 -5
@@ -1,26 +1,26 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
- import React, { Component } from 'react';
2
+ import React, { Component, createRef } from 'react';
3
3
  import ReactDOM from 'react-dom';
4
4
  import { version as packageVersion, name as packageName } from '../../version.json';
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
- import { ViewportDetector } from '../../utils/viewportDetector';
12
+ import { ABS_VIEWPORT_ANCHOR_OFFSET_TOP, ViewportDetector, ViewportAnchor } 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';
18
+ import { isLocalPreviewError, MediaCardError, ensureMediaCardError, ImageLoadError } from '../../errors';
22
19
  import { fireOperationalEvent, fireCommencedEvent, relevantFeatureFlagNames, fireCopiedEvent, fireScreenEvent } from './cardAnalytics';
23
20
  import getDocument from '../../utils/document';
21
+ import { getCardStateFromFileState, createStateUpdater } from './cardState';
22
+ import { isProcessedFileState } from '@atlaskit/media-client';
23
+ import { getMediaFeatureFlag } from '@atlaskit/media-common';
24
24
  export class CardBase extends Component {
25
25
  // We initialise timeElapsedTillCommenced
26
26
  // to avoid extra branching on a possibly undefined value.
@@ -29,77 +29,177 @@ export class CardBase extends Component {
29
29
 
30
30
  _defineProperty(this, "hasBeenMounted", false);
31
31
 
32
- _defineProperty(this, "timeElapsedTillCommenced", performance.now());
32
+ _defineProperty(this, "viewportPreAnchorRef", /*#__PURE__*/createRef());
33
33
 
34
- _defineProperty(this, "shouldRefetchImage", (current, next) => {
35
- if (!current || !next) {
36
- return false;
37
- }
34
+ _defineProperty(this, "viewportPostAnchorRef", /*#__PURE__*/createRef());
38
35
 
39
- return isBigger(current, next);
40
- });
41
-
42
- _defineProperty(this, "isLatestCardStatusUpdate", cardStatusUpdateTimestamp => !this.lastCardStatusUpdateTimestamp || this.lastCardStatusUpdateTimestamp <= cardStatusUpdateTimestamp);
36
+ _defineProperty(this, "timeElapsedTillCommenced", performance.now());
43
37
 
44
- _defineProperty(this, "onLocalPreviewError", error => {// TODO: track local preview success rate
45
- // https://product-fabric.atlassian.net/browse/MEX-774
46
- });
38
+ _defineProperty(this, "getImageURLParams", ({
39
+ collectionName: collection
40
+ }) => ({
41
+ collection,
42
+ mode: imageResizeModeToFileImageMode(this.props.resizeMode),
43
+ ...this.requestedDimensions,
44
+ allowAnimated: true
45
+ }));
47
46
 
48
- _defineProperty(this, "createAddContextToDataURI", (fileId, fileState, {
49
- width,
50
- height
51
- }, collectionName) => dataURI => {
47
+ _defineProperty(this, "getMediaBlobUrlAttrs", (identifier, fileState) => {
48
+ const {
49
+ id,
50
+ collectionName: collection
51
+ } = identifier;
52
52
  const {
53
+ originalDimensions,
53
54
  contextId,
54
55
  alt
55
56
  } = 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,
57
+ const {
58
+ mimeType,
59
+ name,
60
+ size
61
+ } = getFileDetails(identifier, fileState);
62
+ return contextId ? {
63
+ id,
64
+ collection,
65
65
  contextId,
66
- mimeType: metadata.mimeType,
67
- name: metadata.name,
68
- size: metadata.size,
69
- width,
70
- height,
66
+ mimeType,
67
+ name,
68
+ size,
69
+ ...(originalDimensions || this.requestedDimensions),
71
70
  alt
72
- });
71
+ } : undefined;
73
72
  });
74
73
 
75
- _defineProperty(this, "getCardPreviewParams", (id, collectionName, fileState) => {
74
+ _defineProperty(this, "getCardPreviewParams", (identifier, fileState) => {
75
+ const {
76
+ isBannedLocalPreview
77
+ } = this.state;
78
+ const {
79
+ id
80
+ } = identifier;
76
81
  const {
77
82
  dimensions = {},
78
- originalDimensions,
79
- resizeMode,
80
83
  mediaClient
81
84
  } = this.props;
82
- const {
83
- cardRef
84
- } = this.state;
85
- const requestedDimensions = getRequestedDimensions({
86
- dimensions,
87
- element: cardRef
88
- });
89
85
  return {
90
86
  mediaClient,
91
87
  id,
92
- collectionName,
93
88
  dimensions,
94
- resizeMode,
95
- requestedDimensions,
96
- onLocalPreviewError: this.onLocalPreviewError,
97
- filePreview: getFilePreviewFromFileState(fileState),
89
+ onLocalPreviewError: this.fireLocalPreviewErrorEvent,
90
+ filePreview: isBannedLocalPreview ? undefined : getFilePreviewFromFileState(fileState),
98
91
  isRemotePreviewReady: isImageRepresentationReady(fileState),
99
- addContextToDataURI: this.createAddContextToDataURI(id, fileState, originalDimensions || requestedDimensions, collectionName)
92
+ imageUrlParams: this.getImageURLParams(identifier),
93
+ mediaBlobUrlAttrs: this.getMediaBlobUrlAttrs(identifier, fileState)
94
+ };
95
+ });
96
+
97
+ _defineProperty(this, "setCacheSSRPreview", identifier => {
98
+ const {
99
+ mediaClient,
100
+ dimensions = {}
101
+ } = this.props;
102
+ fetchAndCacheRemotePreview(mediaClient, identifier.id, dimensions, this.getImageURLParams(identifier), this.getMediaBlobUrlAttrs(identifier)).catch(() => {// No need to log this error.
103
+ // If preview fails, it will be refetched later
104
+ //TODO: test this catch
105
+ // https://product-fabric.atlassian.net/browse/MEX-1071
106
+ });
107
+ });
108
+
109
+ _defineProperty(this, "resolveSSRPreview", (identifier, ssr) => {
110
+ const {
111
+ mediaClient
112
+ } = this.props;
113
+
114
+ try {
115
+ return getSSRCardPreview(ssr, mediaClient, identifier.id, this.getImageURLParams(identifier), this.getMediaBlobUrlAttrs(identifier));
116
+ } catch (e) {// TODO: log SSR reliability 'failed'
117
+ // https://product-fabric.atlassian.net/browse/MEX-770
118
+ }
119
+ });
120
+
121
+ _defineProperty(this, "resolvePreview", async (identifier, fileState) => {
122
+ try {
123
+ const params = this.getCardPreviewParams(identifier, fileState);
124
+ const cardPreview = await getCardPreview(params);
125
+ this.safeSetState({
126
+ cardPreview
127
+ });
128
+ } catch (e) {
129
+ const wrappedError = ensureMediaCardError('preview-fetch', e); // If remote preview fails, we set status 'error'
130
+ // If local preview fails (i.e, no remote preview available),
131
+ // we can stay in the same status until there is a remote preview available
132
+ // If it's any other error we set status 'error'
133
+
134
+ if (isLocalPreviewError(wrappedError)) {
135
+ this.safeSetState({
136
+ isBannedLocalPreview: true
137
+ });
138
+ } else {
139
+ this.safeSetState({
140
+ status: 'error',
141
+ error: wrappedError
142
+ });
143
+ }
144
+ }
145
+ });
146
+
147
+ _defineProperty(this, "getPerformanceAttributes", () => {
148
+ const {
149
+ timeElapsedTillCommenced
150
+ } = this;
151
+ const timeElapsedTillEvent = performance.now();
152
+ const durationSinceCommenced = timeElapsedTillCommenced && timeElapsedTillEvent - timeElapsedTillCommenced;
153
+ return {
154
+ overall: {
155
+ durationSincePageStart: timeElapsedTillEvent,
156
+ durationSinceCommenced
157
+ }
100
158
  };
101
159
  });
102
160
 
161
+ _defineProperty(this, "onImageError", () => {
162
+ const {
163
+ cardPreview
164
+ } = this.state;
165
+ const error = new ImageLoadError(cardPreview === null || cardPreview === void 0 ? void 0 : cardPreview.source);
166
+ const isLocal = cardPreview && isLocalPreview(cardPreview);
167
+ const isSSR = cardPreview && isSSRClientPreview(cardPreview);
168
+
169
+ if (isLocal || isSSR) {
170
+ const updateState = {
171
+ cardPreview: undefined
172
+ };
173
+
174
+ if (isLocal) {
175
+ updateState.isBannedLocalPreview = true;
176
+ this.fireLocalPreviewErrorEvent(error);
177
+ }
178
+
179
+ if (isSSR) {// TODO: set SSR-client reliability 'failed'.
180
+ // https://product-fabric.atlassian.net/browse/MEX-770
181
+ }
182
+
183
+ const {
184
+ identifier,
185
+ dimensions = {}
186
+ } = this.props;
187
+ isFileIdentifier(identifier) && removeCardPreviewFromCache(identifier.id, dimensions);
188
+ this.safeSetState(updateState);
189
+ } else {
190
+ this.safeSetState({
191
+ status: 'error',
192
+ error
193
+ });
194
+ }
195
+ });
196
+
197
+ _defineProperty(this, "onImageLoad", () => {
198
+ this.safeSetState({
199
+ previewDidRender: true
200
+ });
201
+ });
202
+
103
203
  _defineProperty(this, "fireCopiedEvent", () => {
104
204
  const {
105
205
  createAnalyticsEvent
@@ -117,9 +217,17 @@ export class CardBase extends Component {
117
217
  createAnalyticsEvent && fireScreenEvent(createAnalyticsEvent, this.fileAttributes);
118
218
  });
119
219
 
220
+ _defineProperty(this, "fireLocalPreviewErrorEvent", error => {// TODO: track local preview success rate
221
+ // https://product-fabric.atlassian.net/browse/MEX-774
222
+ });
223
+
120
224
  _defineProperty(this, "safeSetState", state => {
121
225
  if (this.hasBeenMounted) {
122
- this.setState(state);
226
+ // If it's setting the status, we need to use a state updater function,
227
+ // which ensures that no non-final status overrides a final status.
228
+ // If no status is set, we don't need a sate updater
229
+ const updater = !!state.status ? createStateUpdater(state) : state;
230
+ this.setState(updater);
123
231
  }
124
232
  });
125
233
 
@@ -129,8 +237,9 @@ export class CardBase extends Component {
129
237
  }
130
238
 
131
239
  if (this.hasBeenMounted) {
240
+ // TODO MEX-788: add test for "do not remove the card preview when unsubscribing".
132
241
  this.setState({
133
- cardPreview: undefined
242
+ isBannedLocalPreview: false
134
243
  });
135
244
  }
136
245
  });
@@ -157,7 +266,8 @@ export class CardBase extends Component {
157
266
 
158
267
  if (useInlinePlayer && isVideo && !!cardPreview) {
159
268
  this.setState({
160
- isPlayingFile: true
269
+ isPlayingFile: true,
270
+ shouldAutoplay: true
161
271
  });
162
272
  } else if (shouldOpenMediaViewer) {
163
273
  let mediaViewerSelectedItem;
@@ -204,11 +314,15 @@ export class CardBase extends Component {
204
314
  testId,
205
315
  originalDimensions
206
316
  } = this.props;
317
+ const {
318
+ shouldAutoplay
319
+ } = this.state;
207
320
  return /*#__PURE__*/React.createElement(InlinePlayer, {
208
321
  mediaClient: mediaClient,
209
322
  dimensions: dimensions,
210
323
  originalDimensions: originalDimensions,
211
324
  identifier: identifier,
325
+ autoplay: !!shouldAutoplay,
212
326
  onError: this.onInlinePlayerError,
213
327
  onClick: this.onClick,
214
328
  selected: selected,
@@ -292,7 +406,8 @@ export class CardBase extends Component {
292
406
  testId,
293
407
  featureFlags,
294
408
  titleBoxBgColor,
295
- titleBoxIcon
409
+ titleBoxIcon,
410
+ ssr
296
411
  } = this.props;
297
412
  const {
298
413
  mediaItemType
@@ -308,21 +423,26 @@ export class CardBase extends Component {
308
423
  orientation: 1
309
424
  },
310
425
  error,
311
- cardRef
426
+ cardRef,
427
+ isCardVisible
312
428
  } = this.state;
313
429
  const {
314
- metadata,
315
- timeElapsedTillCommenced
430
+ metadata
316
431
  } = this;
317
432
  const {
318
433
  onCardViewClick,
319
434
  onDisplayImage,
320
435
  actions,
321
436
  onMouseEnter
322
- } = this;
437
+ } = this; // Card can be artificially turned visible before entering the viewport
438
+ // For example, when we have the image in cache
439
+
440
+ const nativeLazyLoad = isLazy && !isCardVisible; // Force Media Image to always display img for SSR
441
+
442
+ const forceSyncDisplay = !!ssr;
323
443
  const card = /*#__PURE__*/React.createElement(CardView, {
324
444
  status: status,
325
- error: error && error.secondaryError,
445
+ error: error,
326
446
  mediaItemType: mediaItemType,
327
447
  metadata: metadata,
328
448
  dataURI: dataURI,
@@ -344,12 +464,23 @@ export class CardBase extends Component {
344
464
  featureFlags: featureFlags,
345
465
  titleBoxBgColor: titleBoxBgColor,
346
466
  titleBoxIcon: titleBoxIcon,
347
- timeElapsedTillCommenced: timeElapsedTillCommenced
467
+ onImageError: this.onImageError,
468
+ onImageLoad: this.onImageLoad,
469
+ nativeLazyLoad: nativeLazyLoad,
470
+ forceSyncDisplay: forceSyncDisplay
348
471
  });
349
472
  return isLazy ? /*#__PURE__*/React.createElement(ViewportDetector, {
350
- targetRef: cardRef,
473
+ cardEl: cardRef,
474
+ preAnchorRef: this.viewportPreAnchorRef,
475
+ postAnchorRef: this.viewportPostAnchorRef,
351
476
  onVisible: this.onCardInViewport
352
- }, card) : card;
477
+ }, /*#__PURE__*/React.createElement(ViewportAnchor, {
478
+ ref: this.viewportPreAnchorRef,
479
+ offsetTop: -ABS_VIEWPORT_ANCHOR_OFFSET_TOP
480
+ }), card, /*#__PURE__*/React.createElement(ViewportAnchor, {
481
+ ref: this.viewportPostAnchorRef,
482
+ offsetTop: ABS_VIEWPORT_ANCHOR_OFFSET_TOP
483
+ })) : card;
353
484
  });
354
485
 
355
486
  _defineProperty(this, "onCardInViewport", () => {
@@ -398,7 +529,8 @@ export class CardBase extends Component {
398
529
 
399
530
  const {
400
531
  identifier: _identifier,
401
- dimensions: _dimensions = {}
532
+ dimensions: _dimensions = {},
533
+ ssr: _ssr
402
534
  } = this.props;
403
535
 
404
536
  if (isFileIdentifier(_identifier)) {
@@ -406,9 +538,14 @@ export class CardBase extends Component {
406
538
  id
407
539
  } = _identifier;
408
540
  _cardPreview = getCardPreviewFromCache(id, _dimensions);
541
+
542
+ if (!_cardPreview && _ssr) {
543
+ this.fireCommencedEvent();
544
+ _cardPreview = this.resolveSSRPreview(_identifier, _ssr);
545
+ }
409
546
  } else if (isExternalImageIdentifier(_identifier)) {
410
547
  this.fireCommencedEvent();
411
- _status = 'complete';
548
+ _status = 'loading-preview';
412
549
  const {
413
550
  dataURI
414
551
  } = _identifier;
@@ -417,34 +554,45 @@ export class CardBase extends Component {
417
554
  orientation: 1,
418
555
  source: 'external'
419
556
  };
420
- }
421
- /**
422
- * If cardPreview is available from local cache, `isCardVisible`
423
- * should be true to avoid flickers during re-mount of the component
424
- */
557
+ } // If cardPreview is available from local cache or external, `isCardVisible`
558
+ // should be true to avoid flickers during re-mount of the component
559
+ // should not be visible for SSR preview, otherwise we'll fire the metadata fetch from
560
+ // outside the viewport
425
561
 
426
562
 
427
- const isCardVisible = _cardPreview ? true : !this.props.isLazy;
563
+ const _isCardVisible = !this.props.isLazy || !!_cardPreview && !isSSRPreview(_cardPreview);
564
+
428
565
  this.state = {
429
566
  status: _status,
430
- isCardVisible,
567
+ isCardVisible: _isCardVisible,
431
568
  isPlayingFile: false,
569
+ shouldAutoplay: false,
432
570
  cardPreview: _cardPreview,
433
- cardRef: null
571
+ cardRef: null,
572
+ isBannedLocalPreview: false,
573
+ previewDidRender: false
434
574
  };
435
575
  }
436
576
 
437
577
  componentDidMount() {
438
578
  this.hasBeenMounted = true;
439
579
  const {
440
- isCardVisible
580
+ isCardVisible,
581
+ cardPreview
441
582
  } = this.state;
442
583
  const {
443
- identifier
584
+ identifier,
585
+ ssr
444
586
  } = this.props;
445
587
 
446
588
  if (isCardVisible && isFileIdentifier(identifier)) {
447
589
  this.updateStateForIdentifier(identifier);
590
+ }
591
+
592
+ if (isCardVisible && !!ssr && !!cardPreview && isSSRClientPreview(cardPreview) && isFileIdentifier(identifier)) {
593
+ // Since the SSR preview brings the token in the query params,
594
+ // We need to fetch the remote preview to be able to cache it,
595
+ this.setCacheSSRPreview(identifier);
448
596
  } // we add a listener for each of the cards on the page
449
597
  // and then check if the triggered listener is from the card
450
598
  // that contains a div in current window.getSelection()
@@ -466,14 +614,23 @@ export class CardBase extends Component {
466
614
  const {
467
615
  mediaClient,
468
616
  identifier,
469
- dimensions
617
+ dimensions,
618
+ featureFlags,
619
+ useInlinePlayer,
620
+ disableOverlay
470
621
  } = this.props;
471
622
  const {
472
623
  isCardVisible,
473
- cardPreview
624
+ cardPreview,
625
+ status,
626
+ fileState,
627
+ isBannedLocalPreview,
628
+ previewDidRender,
629
+ isPlayingFile
474
630
  } = this.state;
475
631
  const isDifferent = isDifferentIdentifier(prevIdentifier, identifier);
476
632
  const turnedVisible = !prevIsCardVisible && isCardVisible;
633
+ const isNewMediaClient = prevMediaClient !== mediaClient;
477
634
 
478
635
  if (isExternalImageIdentifier(identifier) && isDifferent) {
479
636
  this.fireCommencedEvent();
@@ -481,7 +638,7 @@ export class CardBase extends Component {
481
638
  dataURI
482
639
  } = identifier;
483
640
  this.setState({
484
- status: 'complete',
641
+ status: 'loading-preview',
485
642
  cardPreview: {
486
643
  dataURI,
487
644
  orientation: 1,
@@ -491,8 +648,7 @@ export class CardBase extends Component {
491
648
  });
492
649
  }
493
650
 
494
- if (isFileIdentifier(identifier) && (turnedVisible || prevMediaClient !== mediaClient || isDifferent || // TODO: should not resubscribe on resize. Only refetch
495
- this.shouldRefetchImage(prevDimensions, dimensions))) {
651
+ if (isFileIdentifier(identifier) && (turnedVisible || !!this.subscription && (isNewMediaClient || isDifferent))) {
496
652
  this.updateStateForIdentifier(identifier);
497
653
  }
498
654
 
@@ -503,6 +659,41 @@ export class CardBase extends Component {
503
659
  this.fireScreenEvent();
504
660
  }
505
661
  }
662
+
663
+ if (isFileIdentifier(identifier) && fileState && shouldResolvePreview({
664
+ status,
665
+ fileState,
666
+ dimensions,
667
+ prevDimensions,
668
+ featureFlags,
669
+ hasCardPreview: !!cardPreview,
670
+ isBannedLocalPreview
671
+ })) {
672
+ this.resolvePreview(identifier, fileState);
673
+ }
674
+
675
+ if (turnedVisible && this.props.ssr && !!cardPreview && isSSRClientPreview(cardPreview) && isFileIdentifier(identifier)) {
676
+ // Since the SSR preview brings the token in the query params,
677
+ // We need to fetch the remote preview to be able to cache it,
678
+ this.setCacheSSRPreview(identifier);
679
+ }
680
+
681
+ if (previewDidRender && // We should't complete if status is uploading
682
+ ['loading-preview', 'processing'].includes(status)) {
683
+ this.safeSetState({
684
+ status: 'complete'
685
+ });
686
+ this.unsubscribe();
687
+ }
688
+
689
+ const isVideo = this.fileAttributes.fileMediatype === 'video';
690
+ const videoAvailableToPlay = fileState && isProcessedFileState(fileState);
691
+
692
+ if (isVideo && !isPlayingFile && disableOverlay && useInlinePlayer && videoAvailableToPlay && getMediaFeatureFlag('timestampOnVideo', this.props.featureFlags)) {
693
+ this.setState({
694
+ isPlayingFile: true
695
+ });
696
+ }
506
697
  }
507
698
 
508
699
  componentWillUnmount() {
@@ -520,6 +711,9 @@ export class CardBase extends Component {
520
711
  const {
521
712
  mediaClient
522
713
  } = this.props;
714
+ const {
715
+ isBannedLocalPreview
716
+ } = this.state;
523
717
  const {
524
718
  id,
525
719
  collectionName,
@@ -530,126 +724,58 @@ export class CardBase extends Component {
530
724
  collectionName,
531
725
  occurrenceKey
532
726
  }).subscribe({
533
- next: async fileState => {
534
- this.lastFileState = fileState;
535
- const thisCardStatusUpdateTimestamp = (performance || Date).now();
536
- const filePreviewStatus = extractFilePreviewStatus(fileState, this.props.featureFlags);
537
- let status = getCardStatus(fileState.status, filePreviewStatus);
538
- this.safeSetState({
539
- fileState
540
- });
541
- let cardPreview;
542
- let error;
543
-
544
- if (shouldGetCardPreview(status, filePreviewStatus)) {
545
- try {
546
- cardPreview = await getCardPreview(this.getCardPreviewParams(id, collectionName, fileState));
547
-
548
- if (['loading-preview', 'processing'].includes(status)) {
549
- status = 'complete';
550
- }
551
- } catch (e) {
552
- const wrappedError = ensureMediaCardError('preview-fetch', e); // If remote preview fails, we set status 'error'
553
- // If the local preview fails (i.e, no remote preview available),
554
- // we can stay in the same status until there is a remote preview available
555
-
556
- if (isRemotePreviewError(wrappedError)) {
557
- status = 'error';
558
- error = wrappedError;
559
- }
560
- }
561
- }
562
-
563
- if (this.isLatestCardStatusUpdate(thisCardStatusUpdateTimestamp)) {
564
- // These status and progress must not override values representing more recent FileState
565
-
566
- /* next() start some await() delay in next() status & progress update
567
- * ------- ------------------ ------------------------
568
- * |----[1]FileState:uploading------>| |
569
- * | | |
570
- * |----[2]FileState:uploading------>| |
571
- * | | |
572
- * | |----[2]FileState:uploading------>| Update status to `uploading`
573
- * |----[3]FileState:processing----->| |
574
- * | |----[3]FileState:processing----->| Update status to `complete`
575
- * | | |
576
- * | |----[1]FileState:uploading------>| We do not want to update status to `uploading` again!
577
- *
578
- */
579
- if (status === 'error' && isErrorFileState(fileState) && !error) {
580
- error = new MediaCardError('error-file-state', new Error(fileState.message));
581
- }
582
-
583
- this.safeSetState({
584
- status,
585
- cardPreview,
586
- progress: status === 'uploading' && fileState.status === 'uploading' ? fileState.progress : 1,
587
- error: status === 'error' && error ? error : undefined
588
- });
589
- this.lastCardStatusUpdateTimestamp = thisCardStatusUpdateTimestamp;
590
- }
727
+ next: fileState => {
728
+ const {
729
+ featureFlags
730
+ } = this.props;
731
+ const newState = getCardStateFromFileState(fileState, isBannedLocalPreview, featureFlags);
732
+ this.safeSetState(newState);
591
733
  },
592
734
  error: e => {
593
- // If file state subscription decides that the card is complete
594
- // and later there is an error, we won't change the card's status.
595
- if (this.state.status === 'complete') {
596
- return;
597
- }
598
-
599
- const errorReason = this.fileAttributes.fileStatus === 'uploading' ? 'upload' : 'metadata-fetch';
735
+ const errorReason = this.state.status === 'uploading' ? 'upload' : 'metadata-fetch';
600
736
  const error = new MediaCardError(errorReason, e);
601
737
  this.safeSetState({
602
738
  error,
603
739
  status: 'error'
604
740
  });
605
- this.lastCardStatusUpdateTimestamp = (performance || Date).now();
606
741
  }
607
742
  });
608
743
  }
609
744
 
610
- get metadata() {
745
+ get requestedDimensions() {
611
746
  const {
612
- identifier
747
+ dimensions
613
748
  } = this.props;
614
- return isFileIdentifier(identifier) ? this.state.fileState ? getFileDetails(this.state.fileState) : {
615
- id: identifier.id
616
- } : {
617
- id: identifier.mediaItemType,
618
- name: identifier.name || identifier.dataURI,
619
- mediaType: 'image'
620
- };
749
+ const {
750
+ cardRef: element
751
+ } = this.state || {};
752
+ return getRequestedDimensions({
753
+ dimensions,
754
+ element
755
+ });
756
+ }
757
+
758
+ get metadata() {
759
+ var _this$state;
760
+
761
+ return getFileDetails(this.props.identifier, (_this$state = this.state) === null || _this$state === void 0 ? void 0 : _this$state.fileState);
621
762
  }
622
763
 
623
764
  get fileAttributes() {
624
- var _this$lastFileState;
765
+ var _this$state2, _this$state2$fileStat;
625
766
 
626
- return getFileAttributes(this.metadata, (_this$lastFileState = this.lastFileState) === null || _this$lastFileState === void 0 ? void 0 : _this$lastFileState.status);
767
+ 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);
627
768
  }
628
769
 
629
770
  fireOperationalEvent() {
630
- const {
631
- timeElapsedTillCommenced
632
- } = this;
633
771
  const {
634
772
  status,
635
- cardPreview,
636
773
  error
637
774
  } = this.state;
638
775
  const {
639
776
  createAnalyticsEvent
640
777
  } = this.props;
641
- const timeElapsedTillEvent = performance.now();
642
- const durationSinceCommenced = timeElapsedTillCommenced && timeElapsedTillEvent - timeElapsedTillCommenced;
643
- const performanceAttributes = {
644
- overall: {
645
- durationSincePageStart: timeElapsedTillEvent,
646
- durationSinceCommenced
647
- }
648
- };
649
- createAnalyticsEvent && fireOperationalEvent(createAnalyticsEvent, status, this.fileAttributes, performanceAttributes, {
650
- cardPreview,
651
- error
652
- });
778
+ createAnalyticsEvent && fireOperationalEvent(createAnalyticsEvent, status, this.fileAttributes, this.getPerformanceAttributes(), error);
653
779
  }
654
780
 
655
781
  fireCommencedEvent() {
@@ -692,19 +818,14 @@ export class CardBase extends Component {
692
818
  }
693
819
 
694
820
  render() {
695
- var _this$lastFileState2;
696
-
697
821
  const {
698
822
  isPlayingFile,
699
823
  mediaViewerSelectedItem
700
824
  } = this.state;
701
825
  const innerContent = /*#__PURE__*/React.createElement(React.Fragment, null, isPlayingFile ? this.renderInlinePlayer() : this.renderCard(), mediaViewerSelectedItem ? this.renderMediaViewer() : null);
702
- const content = this.context.intl ? innerContent : /*#__PURE__*/React.createElement(IntlProvider, {
826
+ return this.props.intl ? innerContent : /*#__PURE__*/React.createElement(IntlProvider, {
703
827
  locale: "en"
704
828
  }, innerContent);
705
- return /*#__PURE__*/React.createElement(FileAttributesProvider, {
706
- data: getFileAttributes(this.metadata, (_this$lastFileState2 = this.lastFileState) === null || _this$lastFileState2 === void 0 ? void 0 : _this$lastFileState2.status)
707
- }, content);
708
829
  }
709
830
 
710
831
  }
@@ -718,11 +839,6 @@ _defineProperty(CardBase, "defaultProps", {
718
839
  featureFlags: {}
719
840
  });
720
841
 
721
- _defineProperty(CardBase, "contextTypes", {
722
- // Required to detect a parent IntlProvider
723
- intl: intlShape
724
- });
725
-
726
842
  export const Card = withMediaAnalyticsContext({
727
843
  packageVersion,
728
844
  packageName,
@@ -730,4 +846,6 @@ export const Card = withMediaAnalyticsContext({
730
846
  component: 'mediaCard'
731
847
  }, {
732
848
  filterFeatureFlags: relevantFeatureFlagNames
733
- })(withAnalyticsEvents()(CardBase));
849
+ })(withAnalyticsEvents()(injectIntl(CardBase, {
850
+ enforceContext: false
851
+ })));