@atlaskit/media-file-preview 0.0.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/cjs/getPreview/getPreview.js +6 -9
- package/dist/cjs/getPreview/index.js +6 -0
- package/dist/cjs/useFilePreview.js +43 -106
- package/dist/es2019/getPreview/getPreview.js +4 -9
- package/dist/es2019/getPreview/index.js +1 -1
- package/dist/es2019/useFilePreview.js +44 -106
- package/dist/esm/getPreview/getPreview.js +5 -8
- package/dist/esm/getPreview/index.js +1 -1
- package/dist/esm/useFilePreview.js +47 -110
- package/dist/types/getPreview/cache.d.ts +2 -2
- package/dist/types/getPreview/getPreview.d.ts +1 -0
- package/dist/types/getPreview/index.d.ts +1 -1
- package/dist/types/types.d.ts +2 -2
- package/dist/types/useFilePreview.d.ts +13 -7
- package/dist/types-ts4.5/getPreview/cache.d.ts +2 -2
- package/dist/types-ts4.5/getPreview/getPreview.d.ts +1 -0
- package/dist/types-ts4.5/getPreview/index.d.ts +1 -1
- package/dist/types-ts4.5/types.d.ts +2 -2
- package/dist/types-ts4.5/useFilePreview.d.ts +13 -7
- package/package.json +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -1 +1,13 @@
|
|
|
1
1
|
# @atlaskit/media-file-preview
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#65817](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/65817) [`de45ff7a33a9`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/de45ff7a33a9) - Breaking: removed previewDidRender property
|
|
8
|
+
|
|
9
|
+
## 0.1.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [#65749](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/65749) [`cf9674e67f0c`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/cf9674e67f0c) - Breaking: updated prop types
|
|
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.isSSRDataPreview = exports.isSSRClientPreview = exports.isLocalPreview = exports.getSSRPreview = exports.getAndCacheRemotePreview = exports.getAndCacheLocalPreview = void 0;
|
|
7
|
+
exports.isSSRPreview = exports.isSSRDataPreview = exports.isSSRClientPreview = exports.isLocalPreview = exports.getSSRPreview = exports.getAndCacheRemotePreview = exports.getAndCacheLocalPreview = void 0;
|
|
8
8
|
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
9
9
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
10
10
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
@@ -23,12 +23,6 @@ var extendAndCachePreview = function extendAndCachePreview(id, mode, preview, me
|
|
|
23
23
|
case 'remote':
|
|
24
24
|
source = 'cache-remote';
|
|
25
25
|
break;
|
|
26
|
-
case 'ssr-server':
|
|
27
|
-
source = 'cache-ssr-server';
|
|
28
|
-
break;
|
|
29
|
-
case 'ssr-client':
|
|
30
|
-
source = 'cache-ssr-client';
|
|
31
|
-
break;
|
|
32
26
|
default:
|
|
33
27
|
source = preview.source;
|
|
34
28
|
}
|
|
@@ -65,12 +59,15 @@ var isLocalPreview = exports.isLocalPreview = function isLocalPreview(preview) {
|
|
|
65
59
|
return localSources.includes(preview.source);
|
|
66
60
|
};
|
|
67
61
|
var isSSRClientPreview = exports.isSSRClientPreview = function isSSRClientPreview(preview) {
|
|
68
|
-
|
|
69
|
-
return ssrClientSources.includes(preview.source);
|
|
62
|
+
return preview.source === 'ssr-client';
|
|
70
63
|
};
|
|
71
64
|
var isSSRDataPreview = exports.isSSRDataPreview = function isSSRDataPreview(preview) {
|
|
72
65
|
return preview.source === 'ssr-data';
|
|
73
66
|
};
|
|
67
|
+
var isSSRPreview = exports.isSSRPreview = function isSSRPreview(preview) {
|
|
68
|
+
var ssrClientSources = ['ssr-client', 'ssr-server', 'ssr-data'];
|
|
69
|
+
return ssrClientSources.includes(preview.source);
|
|
70
|
+
};
|
|
74
71
|
var getAndCacheRemotePreview = exports.getAndCacheRemotePreview = /*#__PURE__*/function () {
|
|
75
72
|
var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(mediaClient, id, dimensions, params, mediaBlobUrlAttrs, traceContext) {
|
|
76
73
|
var remotePreview;
|
|
@@ -39,6 +39,12 @@ Object.defineProperty(exports, "isSSRDataPreview", {
|
|
|
39
39
|
return _getPreview.isSSRDataPreview;
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
|
+
Object.defineProperty(exports, "isSSRPreview", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
get: function get() {
|
|
45
|
+
return _getPreview.isSSRPreview;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
42
48
|
Object.defineProperty(exports, "isSupportedLocalPreview", {
|
|
43
49
|
enumerable: true,
|
|
44
50
|
get: function get() {
|
|
@@ -25,9 +25,12 @@ var useFilePreview = exports.useFilePreview = function useFilePreview(_ref) {
|
|
|
25
25
|
ssr = _ref.ssr,
|
|
26
26
|
dimensions = _ref.dimensions,
|
|
27
27
|
traceContext = _ref.traceContext,
|
|
28
|
-
previewDidRender = _ref.previewDidRender,
|
|
29
28
|
skipRemote = _ref.skipRemote,
|
|
30
|
-
mediaBlobUrlAttrs = _ref.mediaBlobUrlAttrs
|
|
29
|
+
mediaBlobUrlAttrs = _ref.mediaBlobUrlAttrs,
|
|
30
|
+
_ref$allowAnimated = _ref.allowAnimated,
|
|
31
|
+
allowAnimated = _ref$allowAnimated === void 0 ? true : _ref$allowAnimated,
|
|
32
|
+
upscale = _ref.upscale,
|
|
33
|
+
maxAge = _ref.maxAge;
|
|
31
34
|
var mediaClient = (0, _mediaClientReact.useMediaClient)();
|
|
32
35
|
var _useState = (0, _react.useState)('loading'),
|
|
33
36
|
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
@@ -51,17 +54,16 @@ var useFilePreview = exports.useFilePreview = function useFilePreview(_ref) {
|
|
|
51
54
|
return dimensions ? (0, _helpers.createRequestDimensions)(dimensions) : undefined;
|
|
52
55
|
}, [dimensions]);
|
|
53
56
|
var requestDimensionsRef = (0, _helpers.useCurrentValueRef)(requestDimensions);
|
|
54
|
-
var imageURLParams = (
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
57
|
+
var imageURLParams = _objectSpread(_objectSpread({
|
|
58
|
+
collection: identifier.collectionName,
|
|
59
|
+
mode: resizeMode
|
|
60
|
+
}, requestDimensions), {}, {
|
|
61
|
+
allowAnimated: allowAnimated,
|
|
62
|
+
upscale: upscale,
|
|
63
|
+
'max-age': maxAge
|
|
64
|
+
});
|
|
62
65
|
var previewInitializer = function previewInitializer() {
|
|
63
|
-
var
|
|
64
|
-
var preview = _getPreview.mediaFilePreviewCache.get(identifier.id, fileImageMode);
|
|
66
|
+
var preview = _getPreview.mediaFilePreviewCache.get(identifier.id, resizeMode);
|
|
65
67
|
if (preview) {
|
|
66
68
|
return preview;
|
|
67
69
|
}
|
|
@@ -110,60 +112,15 @@ var useFilePreview = exports.useFilePreview = function useFilePreview(_ref) {
|
|
|
110
112
|
(0, _react.useEffect)(function () {
|
|
111
113
|
setStatus('loading');
|
|
112
114
|
}, [identifier]);
|
|
113
|
-
|
|
114
|
-
if (
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
if (fileState.status !== 'error') {
|
|
120
|
-
var mediaType = 'mediaType' in fileState ? fileState.mediaType : undefined;
|
|
121
|
-
var isPreviewable = !!mediaType && ['audio', 'video', 'image', 'doc'].indexOf(mediaType) > -1;
|
|
122
|
-
var isPreviewableFileState = !!fileState.preview;
|
|
123
|
-
var _isSupportedLocalPreview = mediaType === 'image' || mediaType === 'video';
|
|
124
|
-
var hasLocalPreview = !isBannedLocalPreview && isPreviewableFileState && _isSupportedLocalPreview && !!fileState.mimeType && (0, _mediaCommon.isMimeTypeSupportedByBrowser)(fileState.mimeType);
|
|
125
|
-
var hasRemotePreview = (0, _mediaClient.isImageRepresentationReady)(fileState);
|
|
126
|
-
var hasPreview = hasLocalPreview || hasRemotePreview;
|
|
127
|
-
var newStatus;
|
|
128
|
-
switch (fileState.status) {
|
|
129
|
-
case 'uploading':
|
|
130
|
-
case 'failed-processing':
|
|
131
|
-
case 'processing':
|
|
132
|
-
newStatus = fileState.status;
|
|
133
|
-
break;
|
|
134
|
-
case 'processed':
|
|
135
|
-
if (!isPreviewable || !hasPreview) {
|
|
136
|
-
newStatus = 'complete';
|
|
137
|
-
break;
|
|
138
|
-
}
|
|
139
|
-
newStatus = 'loading-preview';
|
|
140
|
-
break;
|
|
141
|
-
default:
|
|
142
|
-
newStatus = 'loading';
|
|
143
|
-
}
|
|
144
|
-
setStatus(newStatus);
|
|
115
|
+
(0, _react.useEffect)(function () {
|
|
116
|
+
if (status !== 'error') {
|
|
117
|
+
if (!preview) {
|
|
118
|
+
setStatus('loading');
|
|
145
119
|
} else {
|
|
146
|
-
|
|
147
|
-
var errorReason = status === 'uploading' ? 'upload' : 'metadata-fetch';
|
|
148
|
-
setError(new _errors.MediaFilePreviewError(errorReason, e));
|
|
149
|
-
setStatus('error');
|
|
120
|
+
setStatus('complete');
|
|
150
121
|
}
|
|
151
122
|
}
|
|
152
|
-
});
|
|
153
|
-
(0, _react.useEffect)(function () {
|
|
154
|
-
updateFileStateRef.current();
|
|
155
|
-
}, [fileState, updateFileStateRef]);
|
|
156
|
-
(0, _react.useEffect)(function () {
|
|
157
|
-
if (previewDidRender &&
|
|
158
|
-
// We should't complete if status is uploading
|
|
159
|
-
['loading-preview', 'processing'].includes(status)) {
|
|
160
|
-
setStatus('complete');
|
|
161
|
-
// TODO MEX-788: add test for "do not remove the preview when unsubscribing".
|
|
162
|
-
setIsBannedLocalPreview(false); // CXP-2723 TODO: we might be able to remove this??
|
|
163
|
-
}
|
|
164
|
-
}, [previewDidRender, status]);
|
|
165
|
-
|
|
166
|
-
// CXP-2723 TODO: Create test cases for banning local preview after status is complete
|
|
123
|
+
}, [preview, status]);
|
|
167
124
|
|
|
168
125
|
//----------------------------------------------------------------
|
|
169
126
|
// Preview Fetch Helper
|
|
@@ -172,40 +129,14 @@ var useFilePreview = exports.useFilePreview = function useFilePreview(_ref) {
|
|
|
172
129
|
return (0, _getPreview.getAndCacheRemotePreview)(mediaClient, identifier.id, requestDimensions || {}, imageURLParams, mediaBlobUrlAttrs, traceContext);
|
|
173
130
|
});
|
|
174
131
|
|
|
175
|
-
//----------------------------------------------------------------
|
|
176
|
-
// Cache SSR Preview
|
|
177
|
-
//----------------------------------------------------------------
|
|
178
|
-
(0, _react.useEffect)(function () {
|
|
179
|
-
if (!skipRemote && ssr && !!preview && (0, _getPreview.isSSRClientPreview)(preview)) {
|
|
180
|
-
// Since the SSR preview brings the token in the query params,
|
|
181
|
-
// We need to fetch the remote preview to be able to cache it,
|
|
182
|
-
getAndCacheRemotePreviewRef.current().catch(function () {
|
|
183
|
-
// No need to log this error.
|
|
184
|
-
// If preview fails, it will be refetched later
|
|
185
|
-
//TODO: test this catch
|
|
186
|
-
// https://product-fabric.atlassian.net/browse/MEX-1071
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
}, [getAndCacheRemotePreviewRef, preview, skipRemote, ssr]);
|
|
190
|
-
|
|
191
|
-
//----------------------------------------------------------------
|
|
192
|
-
// Refetch SRR Preview if dimensions from Server have changed and are bigger,
|
|
193
|
-
//----------------------------------------------------------------
|
|
194
|
-
(0, _react.useEffect)(function () {
|
|
195
|
-
// CXP-2813 TODO: This is called too many times if the refetch failed. Should be called only once
|
|
196
|
-
if (preview && !skipRemote && (0, _getPreview.isSSRDataPreview)(preview) && (0, _helpers.isBigger)(preview.dimensions, requestDimensions)) {
|
|
197
|
-
getAndCacheRemotePreviewRef.current().then(setPreview).catch(function (e) {
|
|
198
|
-
var wrappedError = (0, _errors.ensureMediaFilePreviewError)('remote-preview-fetch-ssr', e, true);
|
|
199
|
-
setNonCriticalError(wrappedError);
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
}, [getAndCacheRemotePreviewRef, preview, requestDimensions, skipRemote]);
|
|
203
|
-
|
|
204
132
|
//----------------------------------------------------------------
|
|
205
133
|
// Upfront Preview
|
|
206
134
|
//----------------------------------------------------------------
|
|
207
135
|
(0, _react.useEffect)(function () {
|
|
208
|
-
if
|
|
136
|
+
// Only fetch upfront (no file state) if there is no preview in the state already
|
|
137
|
+
if (preview) {
|
|
138
|
+
wasResolvedUpfrontPreviewRef.current = true;
|
|
139
|
+
} else if (!preview && !wasResolvedUpfrontPreviewRef.current && !skipRemote) {
|
|
209
140
|
// We block any possible future call to this method regardless of the outcome (success or fail)
|
|
210
141
|
// If it fails, the normal preview fetch should occur after the file state is fetched anyways
|
|
211
142
|
wasResolvedUpfrontPreviewRef.current = true;
|
|
@@ -227,7 +158,7 @@ var useFilePreview = exports.useFilePreview = function useFilePreview(_ref) {
|
|
|
227
158
|
//----------------------------------------------------------------
|
|
228
159
|
|
|
229
160
|
(0, _react.useEffect)(function () {
|
|
230
|
-
var cachedPreview = _getPreview.mediaFilePreviewCache.get(identifier.id,
|
|
161
|
+
var cachedPreview = _getPreview.mediaFilePreviewCache.get(identifier.id, resizeMode);
|
|
231
162
|
|
|
232
163
|
// Cached Preview ----------------------------------------------------------------
|
|
233
164
|
if (!preview && cachedPreview && !(0, _helpers.isBigger)(cachedPreview === null || cachedPreview === void 0 ? void 0 : cachedPreview.dimensions, requestDimensions)) {
|
|
@@ -239,20 +170,28 @@ var useFilePreview = exports.useFilePreview = function useFilePreview(_ref) {
|
|
|
239
170
|
// For example, SVGs are mime type NOT supported by browser but media type supported by Media Card (image)
|
|
240
171
|
// Then, local Preview NOT available
|
|
241
172
|
|
|
242
|
-
(0, _getPreview.getAndCacheLocalPreview)(identifier.id, fileState.preview, requestDimensions || {},
|
|
173
|
+
(0, _getPreview.getAndCacheLocalPreview)(identifier.id, fileState.preview, requestDimensions || {}, resizeMode, mediaBlobUrlAttrs).then(setPreview).catch(function (e) {
|
|
243
174
|
setIsBannedLocalPreview(true);
|
|
244
175
|
// CXP-2723 TODO: We might have to wrap this error in MediaCardError
|
|
245
176
|
setNonCriticalError(e);
|
|
246
177
|
});
|
|
247
178
|
}
|
|
248
179
|
// Remote Preview ----------------------------------------------------------------
|
|
249
|
-
else if ((!preview || (0, _helpers.isBigger)(preview.dimensions, requestDimensions)
|
|
180
|
+
else if (!error && !nonCriticalError && (!preview || (0, _helpers.isBigger)(preview.dimensions, requestDimensions) ||
|
|
181
|
+
// We always refetch SSR preview to be able to browser-cache a version without the token in the query parameters
|
|
182
|
+
(0, _getPreview.isSSRPreview)(preview)) && !skipRemote && wasResolvedUpfrontPreviewRef.current && !!fileState && (0, _mediaClient.isImageRepresentationReady)(fileState)) {
|
|
250
183
|
getAndCacheRemotePreviewRef.current().then(setPreview).catch(function (e) {
|
|
251
|
-
|
|
252
|
-
|
|
184
|
+
var wrappedError = (0, _errors.ensureMediaFilePreviewError)('preview-fetch', e);
|
|
185
|
+
if (!preview) {
|
|
186
|
+
setStatus('error');
|
|
187
|
+
setError(wrappedError);
|
|
188
|
+
} else {
|
|
189
|
+
// If there is already a preview, we consider it a non-critical error
|
|
190
|
+
setNonCriticalError(wrappedError);
|
|
191
|
+
}
|
|
253
192
|
});
|
|
254
193
|
}
|
|
255
|
-
}, [fileState, getAndCacheRemotePreviewRef, identifier.id,
|
|
194
|
+
}, [error, nonCriticalError, fileState, getAndCacheRemotePreviewRef, identifier.id, resizeMode, isBannedLocalPreview, mediaBlobUrlAttrs, preview, requestDimensions, skipRemote]);
|
|
256
195
|
|
|
257
196
|
//----------------------------------------------------------------
|
|
258
197
|
// RETURN
|
|
@@ -289,16 +228,13 @@ var useFilePreview = exports.useFilePreview = function useFilePreview(_ref) {
|
|
|
289
228
|
setIsBannedLocalPreview(true);
|
|
290
229
|
setNonCriticalError(error);
|
|
291
230
|
}
|
|
292
|
-
|
|
293
|
-
_getPreview.mediaFilePreviewCache.remove(identifier.id, fileImageMode);
|
|
231
|
+
_getPreview.mediaFilePreviewCache.remove(identifier.id, resizeMode);
|
|
294
232
|
setPreview(undefined);
|
|
295
233
|
} else {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
setError(error);
|
|
299
|
-
}
|
|
234
|
+
setStatus('error');
|
|
235
|
+
setError(error);
|
|
300
236
|
}
|
|
301
|
-
}, [identifier.id, preview === null || preview === void 0 ? void 0 : preview.dataURI, resizeMode
|
|
237
|
+
}, [identifier.id, preview === null || preview === void 0 ? void 0 : preview.dataURI, resizeMode]);
|
|
302
238
|
var onImageLoad = (0, _react.useCallback)(function (newPreview) {
|
|
303
239
|
if (newPreview) {
|
|
304
240
|
if ((0, _getPreview.isSSRClientPreview)(newPreview) && ssrReliabilityRef.current.client.status === 'unknown') {
|
|
@@ -337,6 +273,7 @@ var useFilePreview = exports.useFilePreview = function useFilePreview(_ref) {
|
|
|
337
273
|
// we might get rid of ssrReliabiltyRef from our hook
|
|
338
274
|
return {
|
|
339
275
|
preview: preview,
|
|
276
|
+
status: status,
|
|
340
277
|
error: error,
|
|
341
278
|
nonCriticalError: nonCriticalError,
|
|
342
279
|
ssrReliabilityRef: ssrReliabilityRef,
|
|
@@ -11,12 +11,6 @@ const extendAndCachePreview = (id, mode, preview, mediaBlobUrlAttrs) => {
|
|
|
11
11
|
case 'remote':
|
|
12
12
|
source = 'cache-remote';
|
|
13
13
|
break;
|
|
14
|
-
case 'ssr-server':
|
|
15
|
-
source = 'cache-ssr-server';
|
|
16
|
-
break;
|
|
17
|
-
case 'ssr-client':
|
|
18
|
-
source = 'cache-ssr-client';
|
|
19
|
-
break;
|
|
20
14
|
default:
|
|
21
15
|
source = preview.source;
|
|
22
16
|
}
|
|
@@ -54,11 +48,12 @@ export const isLocalPreview = preview => {
|
|
|
54
48
|
const localSources = ['local', 'cache-local'];
|
|
55
49
|
return localSources.includes(preview.source);
|
|
56
50
|
};
|
|
57
|
-
export const isSSRClientPreview = preview =>
|
|
58
|
-
|
|
51
|
+
export const isSSRClientPreview = preview => preview.source === 'ssr-client';
|
|
52
|
+
export const isSSRDataPreview = preview => preview.source === 'ssr-data';
|
|
53
|
+
export const isSSRPreview = preview => {
|
|
54
|
+
const ssrClientSources = ['ssr-client', 'ssr-server', 'ssr-data'];
|
|
59
55
|
return ssrClientSources.includes(preview.source);
|
|
60
56
|
};
|
|
61
|
-
export const isSSRDataPreview = preview => preview.source === 'ssr-data';
|
|
62
57
|
export const getAndCacheRemotePreview = async (mediaClient, id, dimensions, params, mediaBlobUrlAttrs, traceContext) => {
|
|
63
58
|
const remotePreview = await getRemotePreview(mediaClient, id, params, traceContext);
|
|
64
59
|
return extendAndCachePreview(id, params.mode, {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { mediaFilePreviewCache } from './cache';
|
|
2
|
-
export { getSSRPreview, isLocalPreview, isSSRClientPreview, isSSRDataPreview, getAndCacheRemotePreview, getAndCacheLocalPreview } from './getPreview';
|
|
2
|
+
export { getSSRPreview, isLocalPreview, isSSRPreview, isSSRClientPreview, isSSRDataPreview, getAndCacheRemotePreview, getAndCacheLocalPreview } from './getPreview';
|
|
3
3
|
export { isSupportedLocalPreview } from './helpers';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { isImageRepresentationReady } from '@atlaskit/media-client';
|
|
3
|
+
import { useFileState, useMediaClient } from '@atlaskit/media-client-react';
|
|
4
4
|
import { isMimeTypeSupportedByBrowser } from '@atlaskit/media-common';
|
|
5
5
|
import { extractErrorInfo } from './analytics';
|
|
6
|
-
import { ensureMediaFilePreviewError, ImageLoadError
|
|
7
|
-
import { getAndCacheLocalPreview, getAndCacheRemotePreview, getSSRPreview, isLocalPreview, isSSRClientPreview, isSSRDataPreview, isSupportedLocalPreview, mediaFilePreviewCache } from './getPreview';
|
|
6
|
+
import { ensureMediaFilePreviewError, ImageLoadError } from './errors';
|
|
7
|
+
import { getAndCacheLocalPreview, getAndCacheRemotePreview, getSSRPreview, isLocalPreview, isSSRClientPreview, isSSRDataPreview, isSSRPreview, isSupportedLocalPreview, mediaFilePreviewCache } from './getPreview';
|
|
8
8
|
import { generateScriptProps, getSSRData } from './globalScope';
|
|
9
9
|
import { createRequestDimensions, isBigger, useCurrentValueRef } from './helpers';
|
|
10
10
|
export const useFilePreview = ({
|
|
@@ -13,9 +13,11 @@ export const useFilePreview = ({
|
|
|
13
13
|
ssr,
|
|
14
14
|
dimensions,
|
|
15
15
|
traceContext,
|
|
16
|
-
previewDidRender,
|
|
17
16
|
skipRemote,
|
|
18
|
-
mediaBlobUrlAttrs
|
|
17
|
+
mediaBlobUrlAttrs,
|
|
18
|
+
allowAnimated = true,
|
|
19
|
+
upscale,
|
|
20
|
+
maxAge
|
|
19
21
|
}) => {
|
|
20
22
|
const mediaClient = useMediaClient();
|
|
21
23
|
const [status, setStatus] = useState('loading');
|
|
@@ -26,15 +28,16 @@ export const useFilePreview = ({
|
|
|
26
28
|
const ssrReliabilityRef = useRef(initialSsrReliability);
|
|
27
29
|
const requestDimensions = useMemo(() => dimensions ? createRequestDimensions(dimensions) : undefined, [dimensions]);
|
|
28
30
|
const requestDimensionsRef = useCurrentValueRef(requestDimensions);
|
|
29
|
-
const imageURLParams =
|
|
31
|
+
const imageURLParams = {
|
|
30
32
|
collection: identifier.collectionName,
|
|
31
|
-
mode: resizeMode
|
|
33
|
+
mode: resizeMode,
|
|
32
34
|
...requestDimensions,
|
|
33
|
-
allowAnimated
|
|
34
|
-
|
|
35
|
+
allowAnimated,
|
|
36
|
+
upscale,
|
|
37
|
+
'max-age': maxAge
|
|
38
|
+
};
|
|
35
39
|
const previewInitializer = () => {
|
|
36
|
-
const
|
|
37
|
-
const preview = mediaFilePreviewCache.get(identifier.id, fileImageMode);
|
|
40
|
+
const preview = mediaFilePreviewCache.get(identifier.id, resizeMode);
|
|
38
41
|
if (preview) {
|
|
39
42
|
return preview;
|
|
40
43
|
}
|
|
@@ -85,60 +88,15 @@ export const useFilePreview = ({
|
|
|
85
88
|
useEffect(() => {
|
|
86
89
|
setStatus('loading');
|
|
87
90
|
}, [identifier]);
|
|
88
|
-
|
|
89
|
-
if (
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
if (fileState.status !== 'error') {
|
|
95
|
-
const mediaType = 'mediaType' in fileState ? fileState.mediaType : undefined;
|
|
96
|
-
const isPreviewable = !!mediaType && ['audio', 'video', 'image', 'doc'].indexOf(mediaType) > -1;
|
|
97
|
-
const isPreviewableFileState = !!fileState.preview;
|
|
98
|
-
const isSupportedLocalPreview = mediaType === 'image' || mediaType === 'video';
|
|
99
|
-
const hasLocalPreview = !isBannedLocalPreview && isPreviewableFileState && isSupportedLocalPreview && !!fileState.mimeType && isMimeTypeSupportedByBrowser(fileState.mimeType);
|
|
100
|
-
const hasRemotePreview = isImageRepresentationReady(fileState);
|
|
101
|
-
const hasPreview = hasLocalPreview || hasRemotePreview;
|
|
102
|
-
let newStatus;
|
|
103
|
-
switch (fileState.status) {
|
|
104
|
-
case 'uploading':
|
|
105
|
-
case 'failed-processing':
|
|
106
|
-
case 'processing':
|
|
107
|
-
newStatus = fileState.status;
|
|
108
|
-
break;
|
|
109
|
-
case 'processed':
|
|
110
|
-
if (!isPreviewable || !hasPreview) {
|
|
111
|
-
newStatus = 'complete';
|
|
112
|
-
break;
|
|
113
|
-
}
|
|
114
|
-
newStatus = 'loading-preview';
|
|
115
|
-
break;
|
|
116
|
-
default:
|
|
117
|
-
newStatus = 'loading';
|
|
118
|
-
}
|
|
119
|
-
setStatus(newStatus);
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
if (status !== 'error') {
|
|
93
|
+
if (!preview) {
|
|
94
|
+
setStatus('loading');
|
|
120
95
|
} else {
|
|
121
|
-
|
|
122
|
-
const errorReason = status === 'uploading' ? 'upload' : 'metadata-fetch';
|
|
123
|
-
setError(new MediaFilePreviewError(errorReason, e));
|
|
124
|
-
setStatus('error');
|
|
96
|
+
setStatus('complete');
|
|
125
97
|
}
|
|
126
98
|
}
|
|
127
|
-
});
|
|
128
|
-
useEffect(() => {
|
|
129
|
-
updateFileStateRef.current();
|
|
130
|
-
}, [fileState, updateFileStateRef]);
|
|
131
|
-
useEffect(() => {
|
|
132
|
-
if (previewDidRender &&
|
|
133
|
-
// We should't complete if status is uploading
|
|
134
|
-
['loading-preview', 'processing'].includes(status)) {
|
|
135
|
-
setStatus('complete');
|
|
136
|
-
// TODO MEX-788: add test for "do not remove the preview when unsubscribing".
|
|
137
|
-
setIsBannedLocalPreview(false); // CXP-2723 TODO: we might be able to remove this??
|
|
138
|
-
}
|
|
139
|
-
}, [previewDidRender, status]);
|
|
140
|
-
|
|
141
|
-
// CXP-2723 TODO: Create test cases for banning local preview after status is complete
|
|
99
|
+
}, [preview, status]);
|
|
142
100
|
|
|
143
101
|
//----------------------------------------------------------------
|
|
144
102
|
// Preview Fetch Helper
|
|
@@ -147,40 +105,14 @@ export const useFilePreview = ({
|
|
|
147
105
|
return getAndCacheRemotePreview(mediaClient, identifier.id, requestDimensions || {}, imageURLParams, mediaBlobUrlAttrs, traceContext);
|
|
148
106
|
});
|
|
149
107
|
|
|
150
|
-
//----------------------------------------------------------------
|
|
151
|
-
// Cache SSR Preview
|
|
152
|
-
//----------------------------------------------------------------
|
|
153
|
-
useEffect(() => {
|
|
154
|
-
if (!skipRemote && ssr && !!preview && isSSRClientPreview(preview)) {
|
|
155
|
-
// Since the SSR preview brings the token in the query params,
|
|
156
|
-
// We need to fetch the remote preview to be able to cache it,
|
|
157
|
-
getAndCacheRemotePreviewRef.current().catch(() => {
|
|
158
|
-
// No need to log this error.
|
|
159
|
-
// If preview fails, it will be refetched later
|
|
160
|
-
//TODO: test this catch
|
|
161
|
-
// https://product-fabric.atlassian.net/browse/MEX-1071
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
}, [getAndCacheRemotePreviewRef, preview, skipRemote, ssr]);
|
|
165
|
-
|
|
166
|
-
//----------------------------------------------------------------
|
|
167
|
-
// Refetch SRR Preview if dimensions from Server have changed and are bigger,
|
|
168
|
-
//----------------------------------------------------------------
|
|
169
|
-
useEffect(() => {
|
|
170
|
-
// CXP-2813 TODO: This is called too many times if the refetch failed. Should be called only once
|
|
171
|
-
if (preview && !skipRemote && isSSRDataPreview(preview) && isBigger(preview.dimensions, requestDimensions)) {
|
|
172
|
-
getAndCacheRemotePreviewRef.current().then(setPreview).catch(e => {
|
|
173
|
-
const wrappedError = ensureMediaFilePreviewError('remote-preview-fetch-ssr', e, true);
|
|
174
|
-
setNonCriticalError(wrappedError);
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
}, [getAndCacheRemotePreviewRef, preview, requestDimensions, skipRemote]);
|
|
178
|
-
|
|
179
108
|
//----------------------------------------------------------------
|
|
180
109
|
// Upfront Preview
|
|
181
110
|
//----------------------------------------------------------------
|
|
182
111
|
useEffect(() => {
|
|
183
|
-
if
|
|
112
|
+
// Only fetch upfront (no file state) if there is no preview in the state already
|
|
113
|
+
if (preview) {
|
|
114
|
+
wasResolvedUpfrontPreviewRef.current = true;
|
|
115
|
+
} else if (!preview && !wasResolvedUpfrontPreviewRef.current && !skipRemote) {
|
|
184
116
|
// We block any possible future call to this method regardless of the outcome (success or fail)
|
|
185
117
|
// If it fails, the normal preview fetch should occur after the file state is fetched anyways
|
|
186
118
|
wasResolvedUpfrontPreviewRef.current = true;
|
|
@@ -204,7 +136,7 @@ export const useFilePreview = ({
|
|
|
204
136
|
//----------------------------------------------------------------
|
|
205
137
|
|
|
206
138
|
useEffect(() => {
|
|
207
|
-
const cachedPreview = mediaFilePreviewCache.get(identifier.id,
|
|
139
|
+
const cachedPreview = mediaFilePreviewCache.get(identifier.id, resizeMode);
|
|
208
140
|
|
|
209
141
|
// Cached Preview ----------------------------------------------------------------
|
|
210
142
|
if (!preview && cachedPreview && !isBigger(cachedPreview === null || cachedPreview === void 0 ? void 0 : cachedPreview.dimensions, requestDimensions)) {
|
|
@@ -216,20 +148,28 @@ export const useFilePreview = ({
|
|
|
216
148
|
// For example, SVGs are mime type NOT supported by browser but media type supported by Media Card (image)
|
|
217
149
|
// Then, local Preview NOT available
|
|
218
150
|
|
|
219
|
-
getAndCacheLocalPreview(identifier.id, fileState.preview, requestDimensions || {},
|
|
151
|
+
getAndCacheLocalPreview(identifier.id, fileState.preview, requestDimensions || {}, resizeMode, mediaBlobUrlAttrs).then(setPreview).catch(e => {
|
|
220
152
|
setIsBannedLocalPreview(true);
|
|
221
153
|
// CXP-2723 TODO: We might have to wrap this error in MediaCardError
|
|
222
154
|
setNonCriticalError(e);
|
|
223
155
|
});
|
|
224
156
|
}
|
|
225
157
|
// Remote Preview ----------------------------------------------------------------
|
|
226
|
-
else if ((!preview || isBigger(preview.dimensions, requestDimensions)
|
|
158
|
+
else if (!error && !nonCriticalError && (!preview || isBigger(preview.dimensions, requestDimensions) ||
|
|
159
|
+
// We always refetch SSR preview to be able to browser-cache a version without the token in the query parameters
|
|
160
|
+
isSSRPreview(preview)) && !skipRemote && wasResolvedUpfrontPreviewRef.current && !!fileState && isImageRepresentationReady(fileState)) {
|
|
227
161
|
getAndCacheRemotePreviewRef.current().then(setPreview).catch(e => {
|
|
228
|
-
|
|
229
|
-
|
|
162
|
+
const wrappedError = ensureMediaFilePreviewError('preview-fetch', e);
|
|
163
|
+
if (!preview) {
|
|
164
|
+
setStatus('error');
|
|
165
|
+
setError(wrappedError);
|
|
166
|
+
} else {
|
|
167
|
+
// If there is already a preview, we consider it a non-critical error
|
|
168
|
+
setNonCriticalError(wrappedError);
|
|
169
|
+
}
|
|
230
170
|
});
|
|
231
171
|
}
|
|
232
|
-
}, [fileState, getAndCacheRemotePreviewRef, identifier.id,
|
|
172
|
+
}, [error, nonCriticalError, fileState, getAndCacheRemotePreviewRef, identifier.id, resizeMode, isBannedLocalPreview, mediaBlobUrlAttrs, preview, requestDimensions, skipRemote]);
|
|
233
173
|
|
|
234
174
|
//----------------------------------------------------------------
|
|
235
175
|
// RETURN
|
|
@@ -267,16 +207,13 @@ export const useFilePreview = ({
|
|
|
267
207
|
setIsBannedLocalPreview(true);
|
|
268
208
|
setNonCriticalError(error);
|
|
269
209
|
}
|
|
270
|
-
|
|
271
|
-
mediaFilePreviewCache.remove(identifier.id, fileImageMode);
|
|
210
|
+
mediaFilePreviewCache.remove(identifier.id, resizeMode);
|
|
272
211
|
setPreview(undefined);
|
|
273
212
|
} else {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
setError(error);
|
|
277
|
-
}
|
|
213
|
+
setStatus('error');
|
|
214
|
+
setError(error);
|
|
278
215
|
}
|
|
279
|
-
}, [identifier.id, preview === null || preview === void 0 ? void 0 : preview.dataURI, resizeMode
|
|
216
|
+
}, [identifier.id, preview === null || preview === void 0 ? void 0 : preview.dataURI, resizeMode]);
|
|
280
217
|
const onImageLoad = useCallback(newPreview => {
|
|
281
218
|
if (newPreview) {
|
|
282
219
|
if (isSSRClientPreview(newPreview) && ssrReliabilityRef.current.client.status === 'unknown') {
|
|
@@ -315,6 +252,7 @@ export const useFilePreview = ({
|
|
|
315
252
|
// we might get rid of ssrReliabiltyRef from our hook
|
|
316
253
|
return {
|
|
317
254
|
preview,
|
|
255
|
+
status,
|
|
318
256
|
error,
|
|
319
257
|
nonCriticalError,
|
|
320
258
|
ssrReliabilityRef,
|
|
@@ -16,12 +16,6 @@ var extendAndCachePreview = function extendAndCachePreview(id, mode, preview, me
|
|
|
16
16
|
case 'remote':
|
|
17
17
|
source = 'cache-remote';
|
|
18
18
|
break;
|
|
19
|
-
case 'ssr-server':
|
|
20
|
-
source = 'cache-ssr-server';
|
|
21
|
-
break;
|
|
22
|
-
case 'ssr-client':
|
|
23
|
-
source = 'cache-ssr-client';
|
|
24
|
-
break;
|
|
25
19
|
default:
|
|
26
20
|
source = preview.source;
|
|
27
21
|
}
|
|
@@ -58,12 +52,15 @@ export var isLocalPreview = function isLocalPreview(preview) {
|
|
|
58
52
|
return localSources.includes(preview.source);
|
|
59
53
|
};
|
|
60
54
|
export var isSSRClientPreview = function isSSRClientPreview(preview) {
|
|
61
|
-
|
|
62
|
-
return ssrClientSources.includes(preview.source);
|
|
55
|
+
return preview.source === 'ssr-client';
|
|
63
56
|
};
|
|
64
57
|
export var isSSRDataPreview = function isSSRDataPreview(preview) {
|
|
65
58
|
return preview.source === 'ssr-data';
|
|
66
59
|
};
|
|
60
|
+
export var isSSRPreview = function isSSRPreview(preview) {
|
|
61
|
+
var ssrClientSources = ['ssr-client', 'ssr-server', 'ssr-data'];
|
|
62
|
+
return ssrClientSources.includes(preview.source);
|
|
63
|
+
};
|
|
67
64
|
export var getAndCacheRemotePreview = /*#__PURE__*/function () {
|
|
68
65
|
var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(mediaClient, id, dimensions, params, mediaBlobUrlAttrs, traceContext) {
|
|
69
66
|
var remotePreview;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { mediaFilePreviewCache } from './cache';
|
|
2
|
-
export { getSSRPreview, isLocalPreview, isSSRClientPreview, isSSRDataPreview, getAndCacheRemotePreview, getAndCacheLocalPreview } from './getPreview';
|
|
2
|
+
export { getSSRPreview, isLocalPreview, isSSRPreview, isSSRClientPreview, isSSRDataPreview, getAndCacheRemotePreview, getAndCacheLocalPreview } from './getPreview';
|
|
3
3
|
export { isSupportedLocalPreview } from './helpers';
|
|
@@ -3,12 +3,12 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
|
3
3
|
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; }
|
|
4
4
|
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) { _defineProperty(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; }
|
|
5
5
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { isImageRepresentationReady } from '@atlaskit/media-client';
|
|
7
|
+
import { useFileState, useMediaClient } from '@atlaskit/media-client-react';
|
|
8
8
|
import { isMimeTypeSupportedByBrowser } from '@atlaskit/media-common';
|
|
9
9
|
import { extractErrorInfo } from './analytics';
|
|
10
|
-
import { ensureMediaFilePreviewError, ImageLoadError
|
|
11
|
-
import { getAndCacheLocalPreview, getAndCacheRemotePreview, getSSRPreview, isLocalPreview, isSSRClientPreview, isSSRDataPreview, isSupportedLocalPreview, mediaFilePreviewCache } from './getPreview';
|
|
10
|
+
import { ensureMediaFilePreviewError, ImageLoadError } from './errors';
|
|
11
|
+
import { getAndCacheLocalPreview, getAndCacheRemotePreview, getSSRPreview, isLocalPreview, isSSRClientPreview, isSSRDataPreview, isSSRPreview, isSupportedLocalPreview, mediaFilePreviewCache } from './getPreview';
|
|
12
12
|
import { generateScriptProps, getSSRData } from './globalScope';
|
|
13
13
|
import { createRequestDimensions, isBigger, useCurrentValueRef } from './helpers';
|
|
14
14
|
export var useFilePreview = function useFilePreview(_ref) {
|
|
@@ -18,9 +18,12 @@ export var useFilePreview = function useFilePreview(_ref) {
|
|
|
18
18
|
ssr = _ref.ssr,
|
|
19
19
|
dimensions = _ref.dimensions,
|
|
20
20
|
traceContext = _ref.traceContext,
|
|
21
|
-
previewDidRender = _ref.previewDidRender,
|
|
22
21
|
skipRemote = _ref.skipRemote,
|
|
23
|
-
mediaBlobUrlAttrs = _ref.mediaBlobUrlAttrs
|
|
22
|
+
mediaBlobUrlAttrs = _ref.mediaBlobUrlAttrs,
|
|
23
|
+
_ref$allowAnimated = _ref.allowAnimated,
|
|
24
|
+
allowAnimated = _ref$allowAnimated === void 0 ? true : _ref$allowAnimated,
|
|
25
|
+
upscale = _ref.upscale,
|
|
26
|
+
maxAge = _ref.maxAge;
|
|
24
27
|
var mediaClient = useMediaClient();
|
|
25
28
|
var _useState = useState('loading'),
|
|
26
29
|
_useState2 = _slicedToArray(_useState, 2),
|
|
@@ -44,17 +47,16 @@ export var useFilePreview = function useFilePreview(_ref) {
|
|
|
44
47
|
return dimensions ? createRequestDimensions(dimensions) : undefined;
|
|
45
48
|
}, [dimensions]);
|
|
46
49
|
var requestDimensionsRef = useCurrentValueRef(requestDimensions);
|
|
47
|
-
var imageURLParams =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
50
|
+
var imageURLParams = _objectSpread(_objectSpread({
|
|
51
|
+
collection: identifier.collectionName,
|
|
52
|
+
mode: resizeMode
|
|
53
|
+
}, requestDimensions), {}, {
|
|
54
|
+
allowAnimated: allowAnimated,
|
|
55
|
+
upscale: upscale,
|
|
56
|
+
'max-age': maxAge
|
|
57
|
+
});
|
|
55
58
|
var previewInitializer = function previewInitializer() {
|
|
56
|
-
var
|
|
57
|
-
var preview = mediaFilePreviewCache.get(identifier.id, fileImageMode);
|
|
59
|
+
var preview = mediaFilePreviewCache.get(identifier.id, resizeMode);
|
|
58
60
|
if (preview) {
|
|
59
61
|
return preview;
|
|
60
62
|
}
|
|
@@ -103,60 +105,15 @@ export var useFilePreview = function useFilePreview(_ref) {
|
|
|
103
105
|
useEffect(function () {
|
|
104
106
|
setStatus('loading');
|
|
105
107
|
}, [identifier]);
|
|
106
|
-
|
|
107
|
-
if (
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
if (fileState.status !== 'error') {
|
|
113
|
-
var mediaType = 'mediaType' in fileState ? fileState.mediaType : undefined;
|
|
114
|
-
var isPreviewable = !!mediaType && ['audio', 'video', 'image', 'doc'].indexOf(mediaType) > -1;
|
|
115
|
-
var isPreviewableFileState = !!fileState.preview;
|
|
116
|
-
var _isSupportedLocalPreview = mediaType === 'image' || mediaType === 'video';
|
|
117
|
-
var hasLocalPreview = !isBannedLocalPreview && isPreviewableFileState && _isSupportedLocalPreview && !!fileState.mimeType && isMimeTypeSupportedByBrowser(fileState.mimeType);
|
|
118
|
-
var hasRemotePreview = isImageRepresentationReady(fileState);
|
|
119
|
-
var hasPreview = hasLocalPreview || hasRemotePreview;
|
|
120
|
-
var newStatus;
|
|
121
|
-
switch (fileState.status) {
|
|
122
|
-
case 'uploading':
|
|
123
|
-
case 'failed-processing':
|
|
124
|
-
case 'processing':
|
|
125
|
-
newStatus = fileState.status;
|
|
126
|
-
break;
|
|
127
|
-
case 'processed':
|
|
128
|
-
if (!isPreviewable || !hasPreview) {
|
|
129
|
-
newStatus = 'complete';
|
|
130
|
-
break;
|
|
131
|
-
}
|
|
132
|
-
newStatus = 'loading-preview';
|
|
133
|
-
break;
|
|
134
|
-
default:
|
|
135
|
-
newStatus = 'loading';
|
|
136
|
-
}
|
|
137
|
-
setStatus(newStatus);
|
|
108
|
+
useEffect(function () {
|
|
109
|
+
if (status !== 'error') {
|
|
110
|
+
if (!preview) {
|
|
111
|
+
setStatus('loading');
|
|
138
112
|
} else {
|
|
139
|
-
|
|
140
|
-
var errorReason = status === 'uploading' ? 'upload' : 'metadata-fetch';
|
|
141
|
-
setError(new MediaFilePreviewError(errorReason, e));
|
|
142
|
-
setStatus('error');
|
|
113
|
+
setStatus('complete');
|
|
143
114
|
}
|
|
144
115
|
}
|
|
145
|
-
});
|
|
146
|
-
useEffect(function () {
|
|
147
|
-
updateFileStateRef.current();
|
|
148
|
-
}, [fileState, updateFileStateRef]);
|
|
149
|
-
useEffect(function () {
|
|
150
|
-
if (previewDidRender &&
|
|
151
|
-
// We should't complete if status is uploading
|
|
152
|
-
['loading-preview', 'processing'].includes(status)) {
|
|
153
|
-
setStatus('complete');
|
|
154
|
-
// TODO MEX-788: add test for "do not remove the preview when unsubscribing".
|
|
155
|
-
setIsBannedLocalPreview(false); // CXP-2723 TODO: we might be able to remove this??
|
|
156
|
-
}
|
|
157
|
-
}, [previewDidRender, status]);
|
|
158
|
-
|
|
159
|
-
// CXP-2723 TODO: Create test cases for banning local preview after status is complete
|
|
116
|
+
}, [preview, status]);
|
|
160
117
|
|
|
161
118
|
//----------------------------------------------------------------
|
|
162
119
|
// Preview Fetch Helper
|
|
@@ -165,40 +122,14 @@ export var useFilePreview = function useFilePreview(_ref) {
|
|
|
165
122
|
return getAndCacheRemotePreview(mediaClient, identifier.id, requestDimensions || {}, imageURLParams, mediaBlobUrlAttrs, traceContext);
|
|
166
123
|
});
|
|
167
124
|
|
|
168
|
-
//----------------------------------------------------------------
|
|
169
|
-
// Cache SSR Preview
|
|
170
|
-
//----------------------------------------------------------------
|
|
171
|
-
useEffect(function () {
|
|
172
|
-
if (!skipRemote && ssr && !!preview && isSSRClientPreview(preview)) {
|
|
173
|
-
// Since the SSR preview brings the token in the query params,
|
|
174
|
-
// We need to fetch the remote preview to be able to cache it,
|
|
175
|
-
getAndCacheRemotePreviewRef.current().catch(function () {
|
|
176
|
-
// No need to log this error.
|
|
177
|
-
// If preview fails, it will be refetched later
|
|
178
|
-
//TODO: test this catch
|
|
179
|
-
// https://product-fabric.atlassian.net/browse/MEX-1071
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
}, [getAndCacheRemotePreviewRef, preview, skipRemote, ssr]);
|
|
183
|
-
|
|
184
|
-
//----------------------------------------------------------------
|
|
185
|
-
// Refetch SRR Preview if dimensions from Server have changed and are bigger,
|
|
186
|
-
//----------------------------------------------------------------
|
|
187
|
-
useEffect(function () {
|
|
188
|
-
// CXP-2813 TODO: This is called too many times if the refetch failed. Should be called only once
|
|
189
|
-
if (preview && !skipRemote && isSSRDataPreview(preview) && isBigger(preview.dimensions, requestDimensions)) {
|
|
190
|
-
getAndCacheRemotePreviewRef.current().then(setPreview).catch(function (e) {
|
|
191
|
-
var wrappedError = ensureMediaFilePreviewError('remote-preview-fetch-ssr', e, true);
|
|
192
|
-
setNonCriticalError(wrappedError);
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
}, [getAndCacheRemotePreviewRef, preview, requestDimensions, skipRemote]);
|
|
196
|
-
|
|
197
125
|
//----------------------------------------------------------------
|
|
198
126
|
// Upfront Preview
|
|
199
127
|
//----------------------------------------------------------------
|
|
200
128
|
useEffect(function () {
|
|
201
|
-
if
|
|
129
|
+
// Only fetch upfront (no file state) if there is no preview in the state already
|
|
130
|
+
if (preview) {
|
|
131
|
+
wasResolvedUpfrontPreviewRef.current = true;
|
|
132
|
+
} else if (!preview && !wasResolvedUpfrontPreviewRef.current && !skipRemote) {
|
|
202
133
|
// We block any possible future call to this method regardless of the outcome (success or fail)
|
|
203
134
|
// If it fails, the normal preview fetch should occur after the file state is fetched anyways
|
|
204
135
|
wasResolvedUpfrontPreviewRef.current = true;
|
|
@@ -220,7 +151,7 @@ export var useFilePreview = function useFilePreview(_ref) {
|
|
|
220
151
|
//----------------------------------------------------------------
|
|
221
152
|
|
|
222
153
|
useEffect(function () {
|
|
223
|
-
var cachedPreview = mediaFilePreviewCache.get(identifier.id,
|
|
154
|
+
var cachedPreview = mediaFilePreviewCache.get(identifier.id, resizeMode);
|
|
224
155
|
|
|
225
156
|
// Cached Preview ----------------------------------------------------------------
|
|
226
157
|
if (!preview && cachedPreview && !isBigger(cachedPreview === null || cachedPreview === void 0 ? void 0 : cachedPreview.dimensions, requestDimensions)) {
|
|
@@ -232,20 +163,28 @@ export var useFilePreview = function useFilePreview(_ref) {
|
|
|
232
163
|
// For example, SVGs are mime type NOT supported by browser but media type supported by Media Card (image)
|
|
233
164
|
// Then, local Preview NOT available
|
|
234
165
|
|
|
235
|
-
getAndCacheLocalPreview(identifier.id, fileState.preview, requestDimensions || {},
|
|
166
|
+
getAndCacheLocalPreview(identifier.id, fileState.preview, requestDimensions || {}, resizeMode, mediaBlobUrlAttrs).then(setPreview).catch(function (e) {
|
|
236
167
|
setIsBannedLocalPreview(true);
|
|
237
168
|
// CXP-2723 TODO: We might have to wrap this error in MediaCardError
|
|
238
169
|
setNonCriticalError(e);
|
|
239
170
|
});
|
|
240
171
|
}
|
|
241
172
|
// Remote Preview ----------------------------------------------------------------
|
|
242
|
-
else if ((!preview || isBigger(preview.dimensions, requestDimensions)
|
|
173
|
+
else if (!error && !nonCriticalError && (!preview || isBigger(preview.dimensions, requestDimensions) ||
|
|
174
|
+
// We always refetch SSR preview to be able to browser-cache a version without the token in the query parameters
|
|
175
|
+
isSSRPreview(preview)) && !skipRemote && wasResolvedUpfrontPreviewRef.current && !!fileState && isImageRepresentationReady(fileState)) {
|
|
243
176
|
getAndCacheRemotePreviewRef.current().then(setPreview).catch(function (e) {
|
|
244
|
-
|
|
245
|
-
|
|
177
|
+
var wrappedError = ensureMediaFilePreviewError('preview-fetch', e);
|
|
178
|
+
if (!preview) {
|
|
179
|
+
setStatus('error');
|
|
180
|
+
setError(wrappedError);
|
|
181
|
+
} else {
|
|
182
|
+
// If there is already a preview, we consider it a non-critical error
|
|
183
|
+
setNonCriticalError(wrappedError);
|
|
184
|
+
}
|
|
246
185
|
});
|
|
247
186
|
}
|
|
248
|
-
}, [fileState, getAndCacheRemotePreviewRef, identifier.id,
|
|
187
|
+
}, [error, nonCriticalError, fileState, getAndCacheRemotePreviewRef, identifier.id, resizeMode, isBannedLocalPreview, mediaBlobUrlAttrs, preview, requestDimensions, skipRemote]);
|
|
249
188
|
|
|
250
189
|
//----------------------------------------------------------------
|
|
251
190
|
// RETURN
|
|
@@ -282,16 +221,13 @@ export var useFilePreview = function useFilePreview(_ref) {
|
|
|
282
221
|
setIsBannedLocalPreview(true);
|
|
283
222
|
setNonCriticalError(error);
|
|
284
223
|
}
|
|
285
|
-
|
|
286
|
-
mediaFilePreviewCache.remove(identifier.id, fileImageMode);
|
|
224
|
+
mediaFilePreviewCache.remove(identifier.id, resizeMode);
|
|
287
225
|
setPreview(undefined);
|
|
288
226
|
} else {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
setError(error);
|
|
292
|
-
}
|
|
227
|
+
setStatus('error');
|
|
228
|
+
setError(error);
|
|
293
229
|
}
|
|
294
|
-
}, [identifier.id, preview === null || preview === void 0 ? void 0 : preview.dataURI, resizeMode
|
|
230
|
+
}, [identifier.id, preview === null || preview === void 0 ? void 0 : preview.dataURI, resizeMode]);
|
|
295
231
|
var onImageLoad = useCallback(function (newPreview) {
|
|
296
232
|
if (newPreview) {
|
|
297
233
|
if (isSSRClientPreview(newPreview) && ssrReliabilityRef.current.client.status === 'unknown') {
|
|
@@ -330,6 +266,7 @@ export var useFilePreview = function useFilePreview(_ref) {
|
|
|
330
266
|
// we might get rid of ssrReliabiltyRef from our hook
|
|
331
267
|
return {
|
|
332
268
|
preview: preview,
|
|
269
|
+
status: status,
|
|
333
270
|
error: error,
|
|
334
271
|
nonCriticalError: nonCriticalError,
|
|
335
272
|
ssrReliabilityRef: ssrReliabilityRef,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MediaStoreGetFileImageParams } from '@atlaskit/media-client';
|
|
2
2
|
import { MediaFilePreview } from '../types';
|
|
3
3
|
import { ObjectURLCache } from './objectURLCache';
|
|
4
|
-
type Mode =
|
|
4
|
+
type Mode = MediaStoreGetFileImageParams['mode'] | undefined;
|
|
5
5
|
export declare const getCacheKey: (id: string, mode: Mode) => string;
|
|
6
6
|
export interface MediaFilePreviewCache {
|
|
7
7
|
get(id: string, mode: Mode): MediaFilePreview | undefined;
|
|
@@ -5,5 +5,6 @@ export declare const getSSRPreview: (ssr: SSR, mediaClient: MediaClient, id: str
|
|
|
5
5
|
export declare const isLocalPreview: (preview: MediaFilePreview) => boolean;
|
|
6
6
|
export declare const isSSRClientPreview: (preview: MediaFilePreview) => boolean;
|
|
7
7
|
export declare const isSSRDataPreview: (preview: MediaFilePreview) => boolean;
|
|
8
|
+
export declare const isSSRPreview: (preview: MediaFilePreview) => boolean;
|
|
8
9
|
export declare const getAndCacheRemotePreview: (mediaClient: MediaClient, id: string, dimensions: MediaFilePreviewDimensions, params: MediaStoreGetFileImageParams, mediaBlobUrlAttrs?: MediaBlobUrlAttrs, traceContext?: MediaTraceContext) => Promise<MediaFilePreview>;
|
|
9
10
|
export declare const getAndCacheLocalPreview: (id: string, filePreview: FilePreview | Promise<FilePreview>, dimensions: MediaFilePreviewDimensions, mode: MediaStoreGetFileImageParams['mode'], mediaBlobUrlAttrs?: MediaBlobUrlAttrs) => Promise<MediaFilePreview>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { mediaFilePreviewCache } from './cache';
|
|
2
|
-
export { getSSRPreview, isLocalPreview, isSSRClientPreview, isSSRDataPreview, getAndCacheRemotePreview, getAndCacheLocalPreview, } from './getPreview';
|
|
2
|
+
export { getSSRPreview, isLocalPreview, isSSRPreview, isSSRClientPreview, isSSRDataPreview, getAndCacheRemotePreview, getAndCacheLocalPreview, } from './getPreview';
|
|
3
3
|
export { isSupportedLocalPreview } from './helpers';
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type MediaFilePreviewSource = 'local' | 'remote' | 'ssr-server' | 'ssr-client' | 'ssr-data' | 'cache-local' | 'cache-remote' | '
|
|
1
|
+
export type MediaFilePreviewSource = 'local' | 'remote' | 'ssr-server' | 'ssr-client' | 'ssr-data' | 'cache-local' | 'cache-remote' | 'external';
|
|
2
2
|
export type MediaFilePreviewDimensions = {
|
|
3
3
|
width?: number;
|
|
4
4
|
height?: number;
|
|
@@ -9,4 +9,4 @@ export interface MediaFilePreview {
|
|
|
9
9
|
dimensions?: MediaFilePreviewDimensions;
|
|
10
10
|
source: MediaFilePreviewSource;
|
|
11
11
|
}
|
|
12
|
-
export type MediaFilePreviewStatus = '
|
|
12
|
+
export type MediaFilePreviewStatus = 'loading' | 'complete' | 'error';
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import { FileIdentifier,
|
|
2
|
+
import { FileIdentifier, MediaBlobUrlAttrs, MediaStoreGetFileImageParams } from '@atlaskit/media-client';
|
|
3
3
|
import { MediaTraceContext, SSR } from '@atlaskit/media-common';
|
|
4
4
|
import { SSRStatus } from './analytics';
|
|
5
5
|
import { MediaFilePreviewError } from './errors';
|
|
6
|
-
import { MediaFilePreview, MediaFilePreviewDimensions } from './types';
|
|
6
|
+
import { MediaFilePreview, MediaFilePreviewDimensions, MediaFilePreviewStatus } from './types';
|
|
7
7
|
export interface UseFilePreviewParams {
|
|
8
8
|
/** Instance of file identifier. */
|
|
9
9
|
readonly identifier: FileIdentifier;
|
|
10
|
-
/** Resize the media to 'crop' | 'fit' | 'full-fit'
|
|
11
|
-
readonly resizeMode?:
|
|
10
|
+
/** Resize the media to 'crop' | 'fit' | 'full-fit' */
|
|
11
|
+
readonly resizeMode?: MediaStoreGetFileImageParams['mode'];
|
|
12
12
|
/** Dimensions to be requested to the server. Will be scaled x2 in Retina Displays */
|
|
13
13
|
readonly dimensions?: MediaFilePreviewDimensions;
|
|
14
14
|
/** Server-Side-Rendering modes are "server" and "client" */
|
|
@@ -17,13 +17,19 @@ export interface UseFilePreviewParams {
|
|
|
17
17
|
readonly mediaBlobUrlAttrs?: MediaBlobUrlAttrs;
|
|
18
18
|
/** Trace context to be passed to the backend requests */
|
|
19
19
|
readonly traceContext?: MediaTraceContext;
|
|
20
|
-
/** Notify the hook that the preview successfully rendered */
|
|
21
|
-
readonly previewDidRender?: boolean;
|
|
22
20
|
/** Do not fetch a remote preview. Helpful for lazy loading */
|
|
23
21
|
readonly skipRemote?: boolean;
|
|
22
|
+
/** Define whether an animated image is acceptable to return */
|
|
23
|
+
readonly allowAnimated?: boolean;
|
|
24
|
+
/** Define the upscale strategy for this image. */
|
|
25
|
+
readonly upscale?: boolean;
|
|
26
|
+
/** Make the client receive the response with the given max-age cache control header. Minimum: 0, maximum: 9223372036854776000.
|
|
27
|
+
*/
|
|
28
|
+
readonly maxAge?: number;
|
|
24
29
|
}
|
|
25
|
-
export declare const useFilePreview: ({ resizeMode, identifier, ssr, dimensions, traceContext,
|
|
30
|
+
export declare const useFilePreview: ({ resizeMode, identifier, ssr, dimensions, traceContext, skipRemote, mediaBlobUrlAttrs, allowAnimated, upscale, maxAge, }: UseFilePreviewParams) => {
|
|
26
31
|
preview: MediaFilePreview | undefined;
|
|
32
|
+
status: MediaFilePreviewStatus;
|
|
27
33
|
error: MediaFilePreviewError | undefined;
|
|
28
34
|
nonCriticalError: MediaFilePreviewError | undefined;
|
|
29
35
|
ssrReliabilityRef: import("react").MutableRefObject<SSRStatus>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MediaStoreGetFileImageParams } from '@atlaskit/media-client';
|
|
2
2
|
import { MediaFilePreview } from '../types';
|
|
3
3
|
import { ObjectURLCache } from './objectURLCache';
|
|
4
|
-
type Mode =
|
|
4
|
+
type Mode = MediaStoreGetFileImageParams['mode'] | undefined;
|
|
5
5
|
export declare const getCacheKey: (id: string, mode: Mode) => string;
|
|
6
6
|
export interface MediaFilePreviewCache {
|
|
7
7
|
get(id: string, mode: Mode): MediaFilePreview | undefined;
|
|
@@ -5,5 +5,6 @@ export declare const getSSRPreview: (ssr: SSR, mediaClient: MediaClient, id: str
|
|
|
5
5
|
export declare const isLocalPreview: (preview: MediaFilePreview) => boolean;
|
|
6
6
|
export declare const isSSRClientPreview: (preview: MediaFilePreview) => boolean;
|
|
7
7
|
export declare const isSSRDataPreview: (preview: MediaFilePreview) => boolean;
|
|
8
|
+
export declare const isSSRPreview: (preview: MediaFilePreview) => boolean;
|
|
8
9
|
export declare const getAndCacheRemotePreview: (mediaClient: MediaClient, id: string, dimensions: MediaFilePreviewDimensions, params: MediaStoreGetFileImageParams, mediaBlobUrlAttrs?: MediaBlobUrlAttrs, traceContext?: MediaTraceContext) => Promise<MediaFilePreview>;
|
|
9
10
|
export declare const getAndCacheLocalPreview: (id: string, filePreview: FilePreview | Promise<FilePreview>, dimensions: MediaFilePreviewDimensions, mode: MediaStoreGetFileImageParams['mode'], mediaBlobUrlAttrs?: MediaBlobUrlAttrs) => Promise<MediaFilePreview>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { mediaFilePreviewCache } from './cache';
|
|
2
|
-
export { getSSRPreview, isLocalPreview, isSSRClientPreview, isSSRDataPreview, getAndCacheRemotePreview, getAndCacheLocalPreview, } from './getPreview';
|
|
2
|
+
export { getSSRPreview, isLocalPreview, isSSRPreview, isSSRClientPreview, isSSRDataPreview, getAndCacheRemotePreview, getAndCacheLocalPreview, } from './getPreview';
|
|
3
3
|
export { isSupportedLocalPreview } from './helpers';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type MediaFilePreviewSource = 'local' | 'remote' | 'ssr-server' | 'ssr-client' | 'ssr-data' | 'cache-local' | 'cache-remote' | '
|
|
1
|
+
export type MediaFilePreviewSource = 'local' | 'remote' | 'ssr-server' | 'ssr-client' | 'ssr-data' | 'cache-local' | 'cache-remote' | 'external';
|
|
2
2
|
export type MediaFilePreviewDimensions = {
|
|
3
3
|
width?: number;
|
|
4
4
|
height?: number;
|
|
@@ -9,4 +9,4 @@ export interface MediaFilePreview {
|
|
|
9
9
|
dimensions?: MediaFilePreviewDimensions;
|
|
10
10
|
source: MediaFilePreviewSource;
|
|
11
11
|
}
|
|
12
|
-
export type MediaFilePreviewStatus = '
|
|
12
|
+
export type MediaFilePreviewStatus = 'loading' | 'complete' | 'error';
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import { FileIdentifier,
|
|
2
|
+
import { FileIdentifier, MediaBlobUrlAttrs, MediaStoreGetFileImageParams } from '@atlaskit/media-client';
|
|
3
3
|
import { MediaTraceContext, SSR } from '@atlaskit/media-common';
|
|
4
4
|
import { SSRStatus } from './analytics';
|
|
5
5
|
import { MediaFilePreviewError } from './errors';
|
|
6
|
-
import { MediaFilePreview, MediaFilePreviewDimensions } from './types';
|
|
6
|
+
import { MediaFilePreview, MediaFilePreviewDimensions, MediaFilePreviewStatus } from './types';
|
|
7
7
|
export interface UseFilePreviewParams {
|
|
8
8
|
/** Instance of file identifier. */
|
|
9
9
|
readonly identifier: FileIdentifier;
|
|
10
|
-
/** Resize the media to 'crop' | 'fit' | 'full-fit'
|
|
11
|
-
readonly resizeMode?:
|
|
10
|
+
/** Resize the media to 'crop' | 'fit' | 'full-fit' */
|
|
11
|
+
readonly resizeMode?: MediaStoreGetFileImageParams['mode'];
|
|
12
12
|
/** Dimensions to be requested to the server. Will be scaled x2 in Retina Displays */
|
|
13
13
|
readonly dimensions?: MediaFilePreviewDimensions;
|
|
14
14
|
/** Server-Side-Rendering modes are "server" and "client" */
|
|
@@ -17,13 +17,19 @@ export interface UseFilePreviewParams {
|
|
|
17
17
|
readonly mediaBlobUrlAttrs?: MediaBlobUrlAttrs;
|
|
18
18
|
/** Trace context to be passed to the backend requests */
|
|
19
19
|
readonly traceContext?: MediaTraceContext;
|
|
20
|
-
/** Notify the hook that the preview successfully rendered */
|
|
21
|
-
readonly previewDidRender?: boolean;
|
|
22
20
|
/** Do not fetch a remote preview. Helpful for lazy loading */
|
|
23
21
|
readonly skipRemote?: boolean;
|
|
22
|
+
/** Define whether an animated image is acceptable to return */
|
|
23
|
+
readonly allowAnimated?: boolean;
|
|
24
|
+
/** Define the upscale strategy for this image. */
|
|
25
|
+
readonly upscale?: boolean;
|
|
26
|
+
/** Make the client receive the response with the given max-age cache control header. Minimum: 0, maximum: 9223372036854776000.
|
|
27
|
+
*/
|
|
28
|
+
readonly maxAge?: number;
|
|
24
29
|
}
|
|
25
|
-
export declare const useFilePreview: ({ resizeMode, identifier, ssr, dimensions, traceContext,
|
|
30
|
+
export declare const useFilePreview: ({ resizeMode, identifier, ssr, dimensions, traceContext, skipRemote, mediaBlobUrlAttrs, allowAnimated, upscale, maxAge, }: UseFilePreviewParams) => {
|
|
26
31
|
preview: MediaFilePreview | undefined;
|
|
32
|
+
status: MediaFilePreviewStatus;
|
|
27
33
|
error: MediaFilePreviewError | undefined;
|
|
28
34
|
nonCriticalError: MediaFilePreviewError | undefined;
|
|
29
35
|
ssrReliabilityRef: import("react").MutableRefObject<SSRStatus>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/media-file-preview",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A React Hook to fetch and render file previews. It's overloaded with fancy features like SSR, lazy loading, memory cache and local preview.",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"category": "Components"
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
|
-
"repository": "https://bitbucket.org/atlassian/atlassian-frontend",
|
|
19
|
+
"repository": "https://bitbucket.org/atlassian/atlassian-frontend-mirror",
|
|
20
20
|
"main": "dist/cjs/index.js",
|
|
21
21
|
"module": "dist/esm/index.js",
|
|
22
22
|
"module:es2019": "dist/es2019/index.js",
|
|
@@ -49,12 +49,14 @@
|
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@af/integration-testing": "*",
|
|
51
51
|
"@af/visual-regression": "*",
|
|
52
|
+
"@atlaskit/media-state": "^1.0.3",
|
|
53
|
+
"@atlaskit/media-test-data": "^1.1.1",
|
|
52
54
|
"@atlaskit/section-message": "^6.4.17",
|
|
53
55
|
"@atlaskit/ssr": "*",
|
|
54
56
|
"@atlaskit/visual-regression": "*",
|
|
55
|
-
"@atlaskit/webdriver-runner": "*",
|
|
56
57
|
"@atlassian/atlassian-frontend-prettier-config-1.0.0": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.0",
|
|
57
58
|
"@testing-library/react": "^12.1.5",
|
|
59
|
+
"@testing-library/react-hooks": "^8.0.1",
|
|
58
60
|
"react-dom": "^16.8.0",
|
|
59
61
|
"typescript": "~4.9.5",
|
|
60
62
|
"wait-for-expect": "^1.2.0"
|