@atlaskit/media-card 77.6.1 → 77.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/cjs/card/card.js +1 -1
- package/dist/cjs/card/media-card-analytics-error-boundary.js +1 -1
- package/dist/cjs/card/v2/cardV2.js +1 -1
- package/dist/cjs/card/v2/fileCard.js +8 -8
- package/dist/cjs/card/v2/useFilePreview/getPreview/getPreview.js +2 -2
- package/dist/cjs/card/v2/useFilePreview/getPreview/index.js +2 -2
- package/dist/cjs/card/v2/useFilePreview/useFilePreview.js +234 -235
- package/dist/cjs/inline/loader.js +1 -1
- package/dist/cjs/inline/mediaInlineCard.js +5 -7
- package/dist/cjs/utils/ufoExperiences.js +1 -1
- package/dist/es2019/card/card.js +1 -1
- package/dist/es2019/card/media-card-analytics-error-boundary.js +1 -1
- package/dist/es2019/card/v2/cardV2.js +1 -1
- package/dist/es2019/card/v2/fileCard.js +8 -8
- package/dist/es2019/card/v2/useFilePreview/getPreview/getPreview.js +1 -1
- package/dist/es2019/card/v2/useFilePreview/getPreview/index.js +1 -1
- package/dist/es2019/card/v2/useFilePreview/useFilePreview.js +194 -197
- package/dist/es2019/inline/loader.js +1 -1
- package/dist/es2019/inline/mediaInlineCard.js +5 -7
- package/dist/es2019/utils/ufoExperiences.js +1 -1
- package/dist/esm/card/card.js +1 -1
- package/dist/esm/card/media-card-analytics-error-boundary.js +1 -1
- package/dist/esm/card/v2/cardV2.js +1 -1
- package/dist/esm/card/v2/fileCard.js +8 -8
- package/dist/esm/card/v2/useFilePreview/getPreview/getPreview.js +1 -1
- package/dist/esm/card/v2/useFilePreview/getPreview/index.js +1 -1
- package/dist/esm/card/v2/useFilePreview/useFilePreview.js +236 -237
- package/dist/esm/inline/loader.js +1 -1
- package/dist/esm/inline/mediaInlineCard.js +5 -7
- package/dist/esm/utils/ufoExperiences.js +1 -1
- package/dist/types/card/v2/useFilePreview/getPreview/getPreview.d.ts +1 -1
- package/dist/types/card/v2/useFilePreview/getPreview/index.d.ts +1 -1
- package/dist/types/card/v2/useFilePreview/useFilePreview.d.ts +6 -6
- package/dist/types-ts4.5/card/v2/useFilePreview/getPreview/getPreview.d.ts +1 -1
- package/dist/types-ts4.5/card/v2/useFilePreview/getPreview/index.d.ts +1 -1
- package/dist/types-ts4.5/card/v2/useFilePreview/useFilePreview.d.ts +6 -6
- package/package.json +1 -1
|
@@ -14,7 +14,7 @@ var _mediaClient = require("@atlaskit/media-client");
|
|
|
14
14
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
15
15
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
16
16
|
var packageName = "@atlaskit/media-card";
|
|
17
|
-
var packageVersion = "77.6.
|
|
17
|
+
var packageVersion = "77.6.3";
|
|
18
18
|
var concurrentExperience;
|
|
19
19
|
var getExperience = function getExperience(id) {
|
|
20
20
|
if (!concurrentExperience) {
|
package/dist/es2019/card/card.js
CHANGED
|
@@ -27,7 +27,7 @@ import { getMediaCardCursor } from '../utils/getMediaCardCursor';
|
|
|
27
27
|
import { completeUfoExperience, startUfoExperience, abortUfoExperience } from '../utils/ufoExperiences';
|
|
28
28
|
import { generateUniqueId } from '../utils/generateUniqueId';
|
|
29
29
|
const packageName = "@atlaskit/media-card";
|
|
30
|
-
const packageVersion = "77.6.
|
|
30
|
+
const packageVersion = "77.6.3";
|
|
31
31
|
export class CardBase extends Component {
|
|
32
32
|
constructor(props) {
|
|
33
33
|
super(props);
|
|
@@ -66,7 +66,7 @@ class WrappedMediaCardAnalyticsErrorBoundary extends React.Component {
|
|
|
66
66
|
}
|
|
67
67
|
_defineProperty(WrappedMediaCardAnalyticsErrorBoundary, "displayName", 'MediaCardAnalyticsErrorBoundary');
|
|
68
68
|
const packageName = "@atlaskit/media-card";
|
|
69
|
-
const packageVersion = "77.6.
|
|
69
|
+
const packageVersion = "77.6.3";
|
|
70
70
|
const MediaCardAnalyticsErrorBoundary = withMediaAnalyticsContext({
|
|
71
71
|
packageVersion,
|
|
72
72
|
packageName,
|
|
@@ -7,7 +7,7 @@ import { IntlProvider, injectIntl } from 'react-intl-next';
|
|
|
7
7
|
import { ExternalImageCard } from './externalImageCard';
|
|
8
8
|
import { FileCard } from './fileCard';
|
|
9
9
|
const packageName = "@atlaskit/media-card";
|
|
10
|
-
const packageVersion = "77.6.
|
|
10
|
+
const packageVersion = "77.6.3";
|
|
11
11
|
export const CardV2Base = ({
|
|
12
12
|
identifier,
|
|
13
13
|
...otherProps
|
|
@@ -133,7 +133,7 @@ export const FileCard = ({
|
|
|
133
133
|
} : undefined;
|
|
134
134
|
}, [alt, previewDimensions, contextId, fileStateValue, identifier, originalDimensions]);
|
|
135
135
|
const {
|
|
136
|
-
|
|
136
|
+
preview,
|
|
137
137
|
error: previewError,
|
|
138
138
|
nonCriticalError,
|
|
139
139
|
ssrReliabilityRef,
|
|
@@ -278,7 +278,7 @@ export const FileCard = ({
|
|
|
278
278
|
return;
|
|
279
279
|
}
|
|
280
280
|
const isVideo = metadata && metadata.mediaType === 'video';
|
|
281
|
-
if (useInlinePlayer && isVideo && !!
|
|
281
|
+
if (useInlinePlayer && isVideo && !!preview && finalStatus !== 'error') {
|
|
282
282
|
setIsPlayingFile(true);
|
|
283
283
|
setShouldAutoplay(true);
|
|
284
284
|
} else if (shouldOpenMediaViewer) {
|
|
@@ -383,11 +383,11 @@ export const FileCard = ({
|
|
|
383
383
|
|
|
384
384
|
useEffect(() => {
|
|
385
385
|
if (prevStatus !== undefined && finalStatus !== prevStatus) {
|
|
386
|
-
if (finalStatus === 'complete' || fileAttributes.fileMediatype === 'video' && !!
|
|
386
|
+
if (finalStatus === 'complete' || fileAttributes.fileMediatype === 'video' && !!preview && finalStatus === 'processing') {
|
|
387
387
|
fireScreenEventRef.current();
|
|
388
388
|
}
|
|
389
389
|
}
|
|
390
|
-
}, [finalStatus, prevStatus, fileAttributes,
|
|
390
|
+
}, [finalStatus, prevStatus, fileAttributes, preview, fireScreenEventRef]);
|
|
391
391
|
|
|
392
392
|
//----------------------------------------------------------------//
|
|
393
393
|
//----------------- abort UFO experience -------------------------//
|
|
@@ -467,16 +467,16 @@ export const FileCard = ({
|
|
|
467
467
|
// Side note: We should not lazy load if the cardPreview is available from local cache,
|
|
468
468
|
// in order to avoid flickers during re-mount of the component
|
|
469
469
|
// CXP-2723 TODO: Create test cases for the above scenarios
|
|
470
|
-
const nativeLazyLoad = isLazyWithOverride && !isCardVisible &&
|
|
470
|
+
const nativeLazyLoad = isLazyWithOverride && !isCardVisible && preview && isSSRPreview(preview);
|
|
471
471
|
// Force Media Image to always display img for SSR
|
|
472
472
|
const forceSyncDisplay = !!ssr;
|
|
473
|
-
const mediaCardCursor = getMediaCardCursor(!!useInlinePlayer, !!shouldOpenMediaViewer, finalStatus === 'error' || finalStatus === 'failed-processing', !!
|
|
473
|
+
const mediaCardCursor = getMediaCardCursor(!!useInlinePlayer, !!shouldOpenMediaViewer, finalStatus === 'error' || finalStatus === 'failed-processing', !!preview, metadata.mediaType);
|
|
474
474
|
const card = /*#__PURE__*/React.createElement(LoadedCardView, {
|
|
475
475
|
status: cardStatusOverride || finalStatus,
|
|
476
476
|
error: finalError,
|
|
477
477
|
mediaItemType: mediaItemType,
|
|
478
478
|
metadata: metadata,
|
|
479
|
-
cardPreview:
|
|
479
|
+
cardPreview: preview,
|
|
480
480
|
alt: alt,
|
|
481
481
|
resizeMode: resizeMode,
|
|
482
482
|
dimensions: cardDimensions,
|
|
@@ -544,7 +544,7 @@ export const FileCard = ({
|
|
|
544
544
|
selected: selected,
|
|
545
545
|
ref: setCardElement,
|
|
546
546
|
testId: testId,
|
|
547
|
-
cardPreview:
|
|
547
|
+
cardPreview: preview
|
|
548
548
|
})) : renderCard(), mediaViewerSelectedItem ? /*#__PURE__*/ReactDOM.createPortal( /*#__PURE__*/React.createElement(MediaViewer, {
|
|
549
549
|
collectionName: collectionName,
|
|
550
550
|
items: mediaViewerItems || [],
|
|
@@ -33,7 +33,7 @@ const extendAndCachePreview = (id, mode, preview, mediaBlobUrlAttrs) => {
|
|
|
33
33
|
dataURI
|
|
34
34
|
};
|
|
35
35
|
};
|
|
36
|
-
export const
|
|
36
|
+
export const getSSRPreview = (ssr, mediaClient, id, params, mediaBlobUrlAttrs) => {
|
|
37
37
|
let dataURI;
|
|
38
38
|
try {
|
|
39
39
|
const rawDataURI = mediaClient.getImageUrlSync(id, params);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { mediaFilePreviewCache } from './cache';
|
|
2
2
|
export { isPreviewableStatus, extractFilePreviewStatus } from './filePreviewStatus';
|
|
3
|
-
export {
|
|
3
|
+
export { getSSRPreview, isLocalPreview, isSSRClientPreview, isSSRDataPreview, getAndCacheRemotePreview, getAndCacheLocalPreview } from './getPreview';
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { imageResizeModeToFileImageMode, isImageRepresentationReady } from '@atlaskit/media-client';
|
|
2
2
|
import { MediaFileStateError, useFileState, useMediaClient } from '@atlaskit/media-client-react';
|
|
3
3
|
import { isMimeTypeSupportedByBrowser } from '@atlaskit/media-common';
|
|
4
|
-
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
5
5
|
import { ensureMediaFilePreviewError, ImageLoadError, isLocalPreviewError, isUnsupportedLocalPreviewError, MediaFilePreviewError } from './errors';
|
|
6
6
|
import { extractErrorInfo } from './analytics';
|
|
7
7
|
import { isBigger, createRequestDimensions, useCurrentValueRef, usePrevious } from './helpers';
|
|
8
8
|
import { generateScriptProps, getSSRData } from './globalScope';
|
|
9
|
-
import { getAndCacheRemotePreview,
|
|
9
|
+
import { getAndCacheRemotePreview, getSSRPreview, isLocalPreview, isSSRClientPreview, isSSRDataPreview, isPreviewableStatus, extractFilePreviewStatus, mediaFilePreviewCache, getAndCacheLocalPreview } from './getPreview';
|
|
10
10
|
export const useFilePreview = ({
|
|
11
11
|
resizeMode = 'crop',
|
|
12
12
|
identifier,
|
|
@@ -25,54 +25,52 @@ export const useFilePreview = ({
|
|
|
25
25
|
const wasResolvedUpfrontPreviewRef = useRef(false);
|
|
26
26
|
const ssrReliabilityRef = useRef(initialSsrReliability);
|
|
27
27
|
const requestDimensions = useMemo(() => dimensions ? createRequestDimensions(dimensions) : undefined, [dimensions]);
|
|
28
|
+
const requestDimensionsRef = useCurrentValueRef(requestDimensions);
|
|
29
|
+
const prevRequestDimensions = usePrevious(requestDimensions);
|
|
28
30
|
const imageURLParams = useMemo(() => ({
|
|
29
31
|
collection: identifier.collectionName,
|
|
30
32
|
mode: resizeMode === 'stretchy-fit' ? 'full-fit' : resizeMode,
|
|
31
33
|
...requestDimensions,
|
|
32
34
|
allowAnimated: true
|
|
33
35
|
}), [requestDimensions, identifier.collectionName, resizeMode]);
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
...ssrData.error
|
|
40
|
-
};
|
|
36
|
+
const previewInitializer = () => {
|
|
37
|
+
const fileImageMode = imageResizeModeToFileImageMode(resizeMode);
|
|
38
|
+
const preview = mediaFilePreviewCache.get(identifier.id, fileImageMode);
|
|
39
|
+
if (preview) {
|
|
40
|
+
return preview;
|
|
41
41
|
}
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
ssrReliabilityRef.current[ssr] = {
|
|
42
|
+
if (ssr) {
|
|
43
|
+
const ssrData = getSSRData(identifier);
|
|
44
|
+
if (ssrData !== null && ssrData !== void 0 && ssrData.error) {
|
|
45
|
+
ssrReliabilityRef.current.server = {
|
|
47
46
|
status: 'fail',
|
|
48
|
-
...
|
|
47
|
+
...ssrData.error
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (!(ssrData !== null && ssrData !== void 0 && ssrData.dataURI)) {
|
|
51
|
+
try {
|
|
52
|
+
return getSSRPreview(ssr, mediaClient, identifier.id, imageURLParams, mediaBlobUrlAttrs);
|
|
53
|
+
} catch (e) {
|
|
54
|
+
ssrReliabilityRef.current[ssr] = {
|
|
55
|
+
status: 'fail',
|
|
56
|
+
...extractErrorInfo(e)
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
const {
|
|
61
|
+
dimensions,
|
|
62
|
+
dataURI
|
|
63
|
+
} = ssrData;
|
|
64
|
+
return {
|
|
65
|
+
dataURI,
|
|
66
|
+
dimensions,
|
|
67
|
+
source: 'ssr-data'
|
|
49
68
|
};
|
|
50
69
|
}
|
|
51
|
-
} else {
|
|
52
|
-
const {
|
|
53
|
-
dimensions,
|
|
54
|
-
dataURI
|
|
55
|
-
} = ssrData;
|
|
56
|
-
return {
|
|
57
|
-
dataURI,
|
|
58
|
-
dimensions,
|
|
59
|
-
source: 'ssr-data'
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
const cardPreviewInitializer = () => {
|
|
64
|
-
let cardPreview;
|
|
65
|
-
const {
|
|
66
|
-
id
|
|
67
|
-
} = identifier;
|
|
68
|
-
const fileImageMode = imageResizeModeToFileImageMode(resizeMode);
|
|
69
|
-
cardPreview = mediaFilePreviewCache.get(id, fileImageMode);
|
|
70
|
-
if (!cardPreview && ssr) {
|
|
71
|
-
cardPreview = getSSRPreview(ssr, identifier, mediaClient);
|
|
72
70
|
}
|
|
73
|
-
return cardPreview;
|
|
74
71
|
};
|
|
75
|
-
const [
|
|
72
|
+
const [preview, setPreview] = useState(previewInitializer);
|
|
73
|
+
const prevPreview = usePrevious(preview);
|
|
76
74
|
const {
|
|
77
75
|
fileState
|
|
78
76
|
} = useFileState(identifier.id, {
|
|
@@ -80,17 +78,142 @@ export const useFilePreview = ({
|
|
|
80
78
|
collectionName: identifier.collectionName,
|
|
81
79
|
occurrenceKey: identifier.occurrenceKey
|
|
82
80
|
});
|
|
81
|
+
|
|
82
|
+
//----------------------------------------------------------------
|
|
83
|
+
// Update status
|
|
84
|
+
//----------------------------------------------------------------
|
|
85
|
+
|
|
86
|
+
// TOOD: make a full hook reset (remount) on New identifier or client
|
|
83
87
|
useEffect(() => {
|
|
84
88
|
setStatus('loading');
|
|
85
89
|
}, [identifier]);
|
|
90
|
+
const updateFileStateRef = useCurrentValueRef(() => {
|
|
91
|
+
if (fileState) {
|
|
92
|
+
// do not update the status if the status is final
|
|
93
|
+
if (['complete', 'error', 'failed-processing'].includes(status)) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (fileState.status !== 'error') {
|
|
97
|
+
const mediaType = 'mediaType' in fileState ? fileState.mediaType : undefined;
|
|
98
|
+
const isPreviewable = !!mediaType && ['audio', 'video', 'image', 'doc'].indexOf(mediaType) > -1;
|
|
99
|
+
const isPreviewableFileState = !!fileState.preview;
|
|
100
|
+
const isSupportedLocalPreview = mediaType === 'image' || mediaType === 'video';
|
|
101
|
+
const hasLocalPreview = !isBannedLocalPreview && isPreviewableFileState && isSupportedLocalPreview && !!fileState.mimeType && isMimeTypeSupportedByBrowser(fileState.mimeType);
|
|
102
|
+
const hasRemotePreview = isImageRepresentationReady(fileState);
|
|
103
|
+
const hasPreview = hasLocalPreview || hasRemotePreview;
|
|
104
|
+
let newStatus;
|
|
105
|
+
switch (fileState.status) {
|
|
106
|
+
case 'uploading':
|
|
107
|
+
case 'failed-processing':
|
|
108
|
+
case 'processing':
|
|
109
|
+
newStatus = fileState.status;
|
|
110
|
+
break;
|
|
111
|
+
case 'processed':
|
|
112
|
+
if (!isPreviewable || !hasPreview) {
|
|
113
|
+
newStatus = 'complete';
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
newStatus = 'loading-preview';
|
|
117
|
+
break;
|
|
118
|
+
default:
|
|
119
|
+
newStatus = 'loading';
|
|
120
|
+
}
|
|
121
|
+
setStatus(newStatus);
|
|
122
|
+
} else {
|
|
123
|
+
const e = new MediaFileStateError(fileState.id, fileState.reason, fileState.message, fileState.details);
|
|
124
|
+
const errorReason = status === 'uploading' ? 'upload' : 'metadata-fetch';
|
|
125
|
+
setError(new MediaFilePreviewError(errorReason, e));
|
|
126
|
+
setStatus('error');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
updateFileStateRef.current();
|
|
132
|
+
}, [fileState, updateFileStateRef]);
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
if (previewDidRender &&
|
|
135
|
+
// We should't complete if status is uploading
|
|
136
|
+
['loading-preview', 'processing'].includes(status)) {
|
|
137
|
+
setStatus('complete');
|
|
138
|
+
// TODO MEX-788: add test for "do not remove the preview when unsubscribing".
|
|
139
|
+
setIsBannedLocalPreview(false); // CXP-2723 TODO: we might be able to remove this??
|
|
140
|
+
}
|
|
141
|
+
}, [previewDidRender, status]);
|
|
86
142
|
|
|
87
|
-
|
|
88
|
-
//---------------------- Helper Functions -----------------------//
|
|
89
|
-
//----------------------------------------------------------------//
|
|
143
|
+
// CXP-2723 TODO: Create test cases for banning local preview after status is complete
|
|
90
144
|
|
|
91
|
-
|
|
145
|
+
//----------------------------------------------------------------
|
|
146
|
+
// Preview Fetch Helper
|
|
147
|
+
//----------------------------------------------------------------
|
|
148
|
+
const getAndCacheRemotePreviewRef = useCurrentValueRef(() => {
|
|
92
149
|
return getAndCacheRemotePreview(mediaClient, identifier.id, requestDimensions || {}, imageURLParams, mediaBlobUrlAttrs, traceContext);
|
|
93
150
|
});
|
|
151
|
+
|
|
152
|
+
//----------------------------------------------------------------
|
|
153
|
+
// Cache SSR Preview
|
|
154
|
+
//----------------------------------------------------------------
|
|
155
|
+
useEffect(() => {
|
|
156
|
+
if (!skipRemote && ssr && !!preview && isSSRClientPreview(preview)) {
|
|
157
|
+
// Since the SSR preview brings the token in the query params,
|
|
158
|
+
// We need to fetch the remote preview to be able to cache it,
|
|
159
|
+
getAndCacheRemotePreviewRef.current().catch(() => {
|
|
160
|
+
// No need to log this error.
|
|
161
|
+
// If preview fails, it will be refetched later
|
|
162
|
+
//TODO: test this catch
|
|
163
|
+
// https://product-fabric.atlassian.net/browse/MEX-1071
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}, [preview, identifier, skipRemote, ssr, getAndCacheRemotePreviewRef]);
|
|
167
|
+
|
|
168
|
+
//----------------------------------------------------------------
|
|
169
|
+
// Refetch SRR Preview if dimensions from Server have changed and are bigger,
|
|
170
|
+
//----------------------------------------------------------------
|
|
171
|
+
useEffect(() => {
|
|
172
|
+
// CXP-2813 TODO: This is called too many times if the refetch failed. Should be called only once
|
|
173
|
+
if (preview && !skipRemote && isSSRDataPreview(preview) && isBigger(preview.dimensions, requestDimensions)) {
|
|
174
|
+
getAndCacheRemotePreviewRef.current().then(setPreview).catch(e => {
|
|
175
|
+
const wrappedError = ensureMediaFilePreviewError('remote-preview-fetch-ssr', e, true);
|
|
176
|
+
setNonCriticalError(wrappedError);
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}, [getAndCacheRemotePreviewRef, identifier, preview, requestDimensions, skipRemote]);
|
|
180
|
+
|
|
181
|
+
//----------------------------------------------------------------
|
|
182
|
+
// Upfront Preview
|
|
183
|
+
//----------------------------------------------------------------
|
|
184
|
+
useEffect(() => {
|
|
185
|
+
const resolveUpfrontPreview = async () => {
|
|
186
|
+
// We block any possible future call to this method regardless of the outcome (success or fail)
|
|
187
|
+
// If it fails, the normal preview fetch should occur after the file state is fetched anyways
|
|
188
|
+
wasResolvedUpfrontPreviewRef.current = true;
|
|
189
|
+
try {
|
|
190
|
+
const fetchedDimensions = {
|
|
191
|
+
...requestDimensions
|
|
192
|
+
};
|
|
193
|
+
const newPreview = await getAndCacheRemotePreviewRef.current();
|
|
194
|
+
const areValidFetchedDimensions = !isBigger(fetchedDimensions, requestDimensionsRef.current);
|
|
195
|
+
|
|
196
|
+
// If there are new and bigger dimensions in the props, and the upfront preview is still resolving,
|
|
197
|
+
// the fetched preview is no longer valid, and thus, we dismiss it
|
|
198
|
+
if (areValidFetchedDimensions) {
|
|
199
|
+
setPreview(newPreview);
|
|
200
|
+
}
|
|
201
|
+
} catch (e) {
|
|
202
|
+
// NO need to log error. If this call fails, a refetch will happen after
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
// CXP-2723 TODO: `hadSSRPreview` is most likely redundant
|
|
207
|
+
const hadSSRPreview = ssr === 'client' && !!prevPreview && isSSRClientPreview(prevPreview);
|
|
208
|
+
if (!preview && !wasResolvedUpfrontPreviewRef.current && (!skipRemote || hadSSRPreview)) {
|
|
209
|
+
resolveUpfrontPreview();
|
|
210
|
+
}
|
|
211
|
+
}, [preview, requestDimensions, requestDimensionsRef, getAndCacheRemotePreviewRef, identifier, skipRemote, prevPreview, ssr]);
|
|
212
|
+
|
|
213
|
+
//----------------------------------------------------------------
|
|
214
|
+
// Fetch Preview
|
|
215
|
+
//----------------------------------------------------------------
|
|
216
|
+
|
|
94
217
|
const resolvePreviewRef = useCurrentValueRef(async (identifier, fileState) => {
|
|
95
218
|
const filePreview = isBannedLocalPreview ? undefined : fileState.status !== 'error' && 'mimeType' in fileState && isMimeTypeSupportedByBrowser(fileState.mimeType) ? fileState.preview : undefined;
|
|
96
219
|
const isRemotePreviewReady = isImageRepresentationReady(fileState);
|
|
@@ -104,7 +227,7 @@ export const useFilePreview = ({
|
|
|
104
227
|
try {
|
|
105
228
|
if (filePreview) {
|
|
106
229
|
const localPreview = await getAndCacheLocalPreview(identifier.id, filePreview, requestDimensions || {}, mode, mediaBlobUrlAttrs);
|
|
107
|
-
|
|
230
|
+
setPreview(localPreview);
|
|
108
231
|
return;
|
|
109
232
|
}
|
|
110
233
|
} catch (e) {
|
|
@@ -139,8 +262,8 @@ export const useFilePreview = ({
|
|
|
139
262
|
*/
|
|
140
263
|
throw new MediaFilePreviewError('remote-preview-not-ready');
|
|
141
264
|
}
|
|
142
|
-
const remotePreview = await
|
|
143
|
-
|
|
265
|
+
const remotePreview = await getAndCacheRemotePreviewRef.current();
|
|
266
|
+
setPreview(remotePreview);
|
|
144
267
|
return;
|
|
145
268
|
} catch (e) {
|
|
146
269
|
const wrappedError = ensureMediaFilePreviewError('preview-fetch', e);
|
|
@@ -159,165 +282,43 @@ export const useFilePreview = ({
|
|
|
159
282
|
}
|
|
160
283
|
}
|
|
161
284
|
});
|
|
162
|
-
|
|
163
|
-
//----------------------------------------------------------------//
|
|
164
|
-
//------------ resolveUpfrontPreview useEffect -------------------//
|
|
165
|
-
//----------------------------------------------------------------//
|
|
166
|
-
const prevCardPreview = usePrevious(cardPreview);
|
|
167
|
-
const requestDimensionsRef = useCurrentValueRef(requestDimensions);
|
|
168
|
-
useEffect(() => {
|
|
169
|
-
const resolveUpfrontPreview = async identifier => {
|
|
170
|
-
// We block any possible future call to this method regardless of the outcome (success or fail)
|
|
171
|
-
// If it fails, the normal preview fetch should occur after the file state is fetched anyways
|
|
172
|
-
wasResolvedUpfrontPreviewRef.current = true;
|
|
173
|
-
try {
|
|
174
|
-
const fetchedDimensions = {
|
|
175
|
-
...requestDimensions
|
|
176
|
-
};
|
|
177
|
-
const newCardPreview = await fetchRemotePreviewRef.current(identifier);
|
|
178
|
-
const areValidFetchedDimensions = !isBigger(fetchedDimensions, requestDimensionsRef.current);
|
|
179
|
-
|
|
180
|
-
// If there are new and bigger dimensions in the props, and the upfront preview is still resolving,
|
|
181
|
-
// the fetched preview is no longer valid, and thus, we dismiss it
|
|
182
|
-
if (areValidFetchedDimensions) {
|
|
183
|
-
setCardPreview(newCardPreview);
|
|
184
|
-
}
|
|
185
|
-
} catch (e) {
|
|
186
|
-
// NO need to log error. If this call fails, a refetch will happen after
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
const hadSSRCardPreview = ssr === 'client' && !!prevCardPreview && isSSRClientPreview(prevCardPreview);
|
|
190
|
-
|
|
191
|
-
// CXP-2723 TODO: `hadSSRCardPreview` is most likely redundant
|
|
192
|
-
if (!wasResolvedUpfrontPreviewRef.current && (!skipRemote || hadSSRCardPreview) && !cardPreview) {
|
|
193
|
-
resolveUpfrontPreview(identifier);
|
|
194
|
-
}
|
|
195
|
-
}, [cardPreview, requestDimensions, requestDimensionsRef, fetchRemotePreviewRef, identifier, skipRemote, prevCardPreview, ssr]);
|
|
196
|
-
|
|
197
|
-
//----------------------------------------------------------------//
|
|
198
|
-
//---------------- fetch and resolve card preview ----------------//
|
|
199
|
-
//----------------------------------------------------------------//
|
|
200
|
-
|
|
201
|
-
const prevRequestDimensions = usePrevious(requestDimensions);
|
|
202
285
|
useEffect(() => {
|
|
203
|
-
|
|
204
|
-
if (cardPreview && !skipRemote && isSSRDataPreview(cardPreview) && isBigger(cardPreview.dimensions, requestDimensions)) {
|
|
205
|
-
// refetchSRRPreview: If dimensions from Server have changed and are bigger,
|
|
206
|
-
// we need to refetch
|
|
207
|
-
fetchRemotePreviewRef.current(identifier).then(setCardPreview).catch(e => {
|
|
208
|
-
const wrappedError = ensureMediaFilePreviewError('remote-preview-fetch-ssr', e, true);
|
|
209
|
-
setNonCriticalError(wrappedError);
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
// CXP-2723 TODO: The above and below preview fetch logic seem very similar and could be revisted
|
|
213
|
-
// Both compare dimensions, but the above is only for SSR in order to refetchSRRPreview and
|
|
214
|
-
// will swallow any errors. Below logic only applies when there is no card preview or the dimensions
|
|
215
|
-
// are bigger.
|
|
216
|
-
if (fileState && wasResolvedUpfrontPreviewRef.current && isPreviewableStatus(status, extractFilePreviewStatus(fileState, isBannedLocalPreview)) && (!cardPreview || isBigger(prevRequestDimensions, requestDimensions))) {
|
|
286
|
+
if (fileState && wasResolvedUpfrontPreviewRef.current && isPreviewableStatus(status, extractFilePreviewStatus(fileState, isBannedLocalPreview)) && (!preview || isBigger(prevRequestDimensions, requestDimensions))) {
|
|
217
287
|
resolvePreviewRef.current(identifier, fileState);
|
|
218
288
|
}
|
|
219
|
-
|
|
220
|
-
// Since the SSR preview brings the token in the query params,
|
|
221
|
-
// We need to fetch the remote preview to be able to cache it,
|
|
222
|
-
fetchRemotePreviewRef.current(identifier).catch(() => {
|
|
223
|
-
// No need to log this error.
|
|
224
|
-
// If preview fails, it will be refetched later
|
|
225
|
-
//TODO: test this catch
|
|
226
|
-
// https://product-fabric.atlassian.net/browse/MEX-1071
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
}, [cardPreview, requestDimensions, fetchRemotePreviewRef, fileState, identifier, isBannedLocalPreview, prevRequestDimensions, resolvePreviewRef, skipRemote, ssr, status]);
|
|
230
|
-
|
|
231
|
-
//----------------------------------------------------------------//
|
|
232
|
-
//----------------- set complete status --------------------------//
|
|
233
|
-
//----------------------------------------------------------------//
|
|
289
|
+
}, [fileState, identifier, isBannedLocalPreview, prevRequestDimensions, preview, requestDimensions, resolvePreviewRef, status]);
|
|
234
290
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
['loading-preview', 'processing'].includes(status)) {
|
|
239
|
-
setStatus('complete');
|
|
240
|
-
// TODO MEX-788: add test for "do not remove the card preview when unsubscribing".
|
|
241
|
-
setIsBannedLocalPreview(false); // CXP-2723 TODO: we might be able to remove this??
|
|
242
|
-
}
|
|
243
|
-
}, [previewDidRender, status]);
|
|
244
|
-
|
|
245
|
-
// CXP-2723 TODO: Create test cases for banning local preview after status is complete
|
|
246
|
-
|
|
247
|
-
//----------------------------------------------------------------//
|
|
248
|
-
//------------------ Subscribe to file state ---------------------//
|
|
249
|
-
//----------------------------------------------------------------//
|
|
291
|
+
//----------------------------------------------------------------
|
|
292
|
+
// RETURN
|
|
293
|
+
//----------------------------------------------------------------
|
|
250
294
|
|
|
251
|
-
const
|
|
252
|
-
if (
|
|
253
|
-
// do not update the card status if the status is final
|
|
254
|
-
if (['complete', 'error', 'failed-processing'].includes(status)) {
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
if (fileState.status !== 'error') {
|
|
258
|
-
const mediaType = 'mediaType' in fileState ? fileState.mediaType : undefined;
|
|
259
|
-
const isPreviewable = !!mediaType && ['audio', 'video', 'image', 'doc'].indexOf(mediaType) > -1;
|
|
260
|
-
const isPreviewableFileState = !!fileState.preview;
|
|
261
|
-
const isSupportedLocalPreview = mediaType === 'image' || mediaType === 'video';
|
|
262
|
-
const hasLocalPreview = !isBannedLocalPreview && isPreviewableFileState && isSupportedLocalPreview && !!fileState.mimeType && isMimeTypeSupportedByBrowser(fileState.mimeType);
|
|
263
|
-
const hasRemotePreview = isImageRepresentationReady(fileState);
|
|
264
|
-
const hasPreview = hasLocalPreview || hasRemotePreview;
|
|
265
|
-
let newStatus;
|
|
266
|
-
switch (fileState.status) {
|
|
267
|
-
case 'uploading':
|
|
268
|
-
case 'failed-processing':
|
|
269
|
-
case 'processing':
|
|
270
|
-
newStatus = fileState.status;
|
|
271
|
-
break;
|
|
272
|
-
case 'processed':
|
|
273
|
-
if (!isPreviewable || !hasPreview) {
|
|
274
|
-
newStatus = 'complete';
|
|
275
|
-
break;
|
|
276
|
-
}
|
|
277
|
-
newStatus = 'loading-preview';
|
|
278
|
-
break;
|
|
279
|
-
default:
|
|
280
|
-
newStatus = 'loading';
|
|
281
|
-
}
|
|
282
|
-
setStatus(newStatus);
|
|
283
|
-
} else {
|
|
284
|
-
const e = new MediaFileStateError(fileState.id, fileState.reason, fileState.message, fileState.details);
|
|
285
|
-
const errorReason = status === 'uploading' ? 'upload' : 'metadata-fetch';
|
|
286
|
-
setError(new MediaFilePreviewError(errorReason, e));
|
|
287
|
-
setStatus('error');
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
});
|
|
291
|
-
useEffect(() => {
|
|
292
|
-
updateFileStateRef.current();
|
|
293
|
-
}, [fileState, updateFileStateRef]);
|
|
294
|
-
const onImageError = newCardPreview => {
|
|
295
|
-
if (newCardPreview) {
|
|
295
|
+
const onImageError = useCallback(newPreview => {
|
|
296
|
+
if (newPreview) {
|
|
296
297
|
const failedSSRObject = {
|
|
297
298
|
status: 'fail',
|
|
298
|
-
...extractErrorInfo(new ImageLoadError(
|
|
299
|
+
...extractErrorInfo(new ImageLoadError(newPreview.source))
|
|
299
300
|
};
|
|
300
|
-
if (isSSRClientPreview(
|
|
301
|
+
if (isSSRClientPreview(newPreview)) {
|
|
301
302
|
ssrReliabilityRef.current.client = failedSSRObject;
|
|
302
303
|
}
|
|
303
304
|
|
|
304
305
|
/*
|
|
305
|
-
|
|
306
|
+
If the preview failed and it comes from server (global scope / ssrData), it means that we have reused it in client and the error counts for both: server & client.
|
|
306
307
|
*/
|
|
307
308
|
|
|
308
|
-
if (isSSRDataPreview(
|
|
309
|
+
if (isSSRDataPreview(newPreview)) {
|
|
309
310
|
ssrReliabilityRef.current.server = failedSSRObject;
|
|
310
311
|
ssrReliabilityRef.current.client = failedSSRObject;
|
|
311
312
|
}
|
|
312
313
|
}
|
|
313
314
|
|
|
314
315
|
// If the dataURI has been replaced, we can dismiss this error
|
|
315
|
-
if ((
|
|
316
|
+
if ((newPreview === null || newPreview === void 0 ? void 0 : newPreview.dataURI) !== (preview === null || preview === void 0 ? void 0 : preview.dataURI)) {
|
|
316
317
|
return;
|
|
317
318
|
}
|
|
318
|
-
const error = new ImageLoadError(
|
|
319
|
-
const isLocal =
|
|
320
|
-
const isSSR =
|
|
319
|
+
const error = new ImageLoadError(newPreview === null || newPreview === void 0 ? void 0 : newPreview.source);
|
|
320
|
+
const isLocal = newPreview && isLocalPreview(newPreview);
|
|
321
|
+
const isSSR = newPreview && (isSSRClientPreview(newPreview) || isSSRDataPreview(newPreview));
|
|
321
322
|
if (isLocal || isSSR) {
|
|
322
323
|
if (isLocal) {
|
|
323
324
|
setIsBannedLocalPreview(true);
|
|
@@ -325,27 +326,27 @@ export const useFilePreview = ({
|
|
|
325
326
|
}
|
|
326
327
|
const fileImageMode = imageResizeModeToFileImageMode(resizeMode);
|
|
327
328
|
mediaFilePreviewCache.remove(identifier.id, fileImageMode);
|
|
328
|
-
|
|
329
|
+
setPreview(undefined);
|
|
329
330
|
} else {
|
|
330
331
|
if (!['complete', 'error', 'failed-processing'].includes(status)) {
|
|
331
332
|
setStatus('error');
|
|
332
333
|
setError(error);
|
|
333
334
|
}
|
|
334
335
|
}
|
|
335
|
-
};
|
|
336
|
-
const onImageLoad =
|
|
337
|
-
if (
|
|
338
|
-
if (isSSRClientPreview(
|
|
336
|
+
}, [identifier.id, preview === null || preview === void 0 ? void 0 : preview.dataURI, resizeMode, status]);
|
|
337
|
+
const onImageLoad = useCallback(newPreview => {
|
|
338
|
+
if (newPreview) {
|
|
339
|
+
if (isSSRClientPreview(newPreview) && ssrReliabilityRef.current.client.status === 'unknown') {
|
|
339
340
|
ssrReliabilityRef.current.client = {
|
|
340
341
|
status: 'success'
|
|
341
342
|
};
|
|
342
343
|
}
|
|
343
344
|
|
|
344
345
|
/*
|
|
345
|
-
|
|
346
|
+
If the image loads successfully and it comes from server (global scope / ssrData), it means that we have reused it in client and the success counts for both: server & client.
|
|
346
347
|
*/
|
|
347
348
|
|
|
348
|
-
if (isSSRDataPreview(
|
|
349
|
+
if (isSSRDataPreview(newPreview) && ssrReliabilityRef.current.server.status === 'unknown') {
|
|
349
350
|
ssrReliabilityRef.current.server = {
|
|
350
351
|
status: 'success'
|
|
351
352
|
};
|
|
@@ -356,25 +357,21 @@ export const useFilePreview = ({
|
|
|
356
357
|
}
|
|
357
358
|
|
|
358
359
|
// If the dataURI has been replaced, we can dismiss this callback
|
|
359
|
-
if ((
|
|
360
|
+
if ((newPreview === null || newPreview === void 0 ? void 0 : newPreview.dataURI) !== (preview === null || preview === void 0 ? void 0 : preview.dataURI)) {
|
|
360
361
|
return;
|
|
361
362
|
}
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
//----------------------------------------------------------------//
|
|
365
|
-
// RETURN
|
|
366
|
-
//----------------------------------------------------------------//
|
|
363
|
+
}, [preview === null || preview === void 0 ? void 0 : preview.dataURI]);
|
|
367
364
|
|
|
368
365
|
// FOR SSR
|
|
369
366
|
const getScriptProps = () => {
|
|
370
367
|
var _ssrReliabilityRef$cu;
|
|
371
|
-
return generateScriptProps(identifier,
|
|
368
|
+
return generateScriptProps(identifier, preview === null || preview === void 0 ? void 0 : preview.dataURI, requestDimensions, ((_ssrReliabilityRef$cu = ssrReliabilityRef.current.server) === null || _ssrReliabilityRef$cu === void 0 ? void 0 : _ssrReliabilityRef$cu.status) === 'fail' ? ssrReliabilityRef.current.server : undefined);
|
|
372
369
|
};
|
|
373
370
|
|
|
374
371
|
// CXP-2723 TODO: should consider simplifying our analytics, and how
|
|
375
372
|
// we might get rid of ssrReliabiltyRef from our hook
|
|
376
373
|
return {
|
|
377
|
-
|
|
374
|
+
preview,
|
|
378
375
|
error,
|
|
379
376
|
nonCriticalError,
|
|
380
377
|
ssrReliabilityRef,
|
|
@@ -37,7 +37,7 @@ export default class MediaInlineCardLoader extends React.PureComponent {
|
|
|
37
37
|
} = this.state;
|
|
38
38
|
const analyticsContext = {
|
|
39
39
|
packageVersion: "@atlaskit/media-card",
|
|
40
|
-
packageName: "77.6.
|
|
40
|
+
packageName: "77.6.3",
|
|
41
41
|
componentName: 'mediaInlineCard',
|
|
42
42
|
component: 'mediaInlineCard'
|
|
43
43
|
};
|