@atlaskit/media-file-preview 0.17.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/AGENTS.md +59 -0
  2. package/CHANGELOG.md +38 -0
  3. package/dist/cjs/getPreview/getPreview.js +89 -36
  4. package/dist/cjs/getPreview/helpers.js +51 -51
  5. package/dist/cjs/getPreview/index.js +6 -0
  6. package/dist/cjs/getPreview/videoSnapshot.js +1 -1
  7. package/dist/cjs/useFilePreview.js +12 -2
  8. package/dist/es2019/getPreview/getPreview.js +54 -5
  9. package/dist/es2019/getPreview/index.js +1 -1
  10. package/dist/es2019/useFilePreview.js +13 -3
  11. package/dist/esm/getPreview/getPreview.js +88 -35
  12. package/dist/esm/getPreview/helpers.js +51 -51
  13. package/dist/esm/getPreview/index.js +1 -1
  14. package/dist/esm/getPreview/videoSnapshot.js +1 -1
  15. package/dist/esm/useFilePreview.js +13 -3
  16. package/dist/types/getPreview/getPreview.d.ts +12 -1
  17. package/dist/types/getPreview/index.d.ts +1 -1
  18. package/dist/types/useFilePreview.d.ts +4 -2
  19. package/errors/package.json +1 -8
  20. package/package.json +16 -19
  21. package/types/package.json +1 -8
  22. package/use-file-preview/package.json +1 -8
  23. package/use-media-image/package.json +1 -8
  24. package/dist/types-ts4.5/analytics.d.ts +0 -30
  25. package/dist/types-ts4.5/errors.d.ts +0 -38
  26. package/dist/types-ts4.5/getPreview/cache.d.ts +0 -25
  27. package/dist/types-ts4.5/getPreview/getPreview.d.ts +0 -11
  28. package/dist/types-ts4.5/getPreview/helpers.d.ts +0 -10
  29. package/dist/types-ts4.5/getPreview/index.d.ts +0 -3
  30. package/dist/types-ts4.5/getPreview/objectURLCache.d.ts +0 -21
  31. package/dist/types-ts4.5/getPreview/videoSnapshot.d.ts +0 -1
  32. package/dist/types-ts4.5/globalScope/getSSRData.d.ts +0 -3
  33. package/dist/types-ts4.5/globalScope/globalScope.d.ts +0 -23
  34. package/dist/types-ts4.5/globalScope/index.d.ts +0 -4
  35. package/dist/types-ts4.5/globalScope/originalScriptCode.d.ts +0 -0
  36. package/dist/types-ts4.5/globalScope/types.d.ts +0 -12
  37. package/dist/types-ts4.5/helpers.d.ts +0 -11
  38. package/dist/types-ts4.5/index.d.ts +0 -7
  39. package/dist/types-ts4.5/types.d.ts +0 -14
  40. package/dist/types-ts4.5/useFilePreview.d.ts +0 -44
  41. package/dist/types-ts4.5/useMediaImage.d.ts +0 -45
@@ -28,9 +28,58 @@ const extendAndCachePreview = (id, mode, preview, mediaBlobUrlAttrs) => {
28
28
  dataURI
29
29
  };
30
30
  };
31
- const getDataUri = (mediaClient, id, params, mediaBlobUrlAttrs) => {
31
+
32
+ /**
33
+ * Allowlist of CDN signing query-param names that we propagate from a
34
+ * pre-signed `previewCdnUrl` onto the URL produced by `getImageUrlSync`.
35
+ * These are the standard CloudFront signed-URL params; if the upstream
36
+ * adds a new one, this list needs updating.
37
+ */
38
+ const SIGNING_PARAM_NAMES = ['token', 'Policy', 'Key-Pair-Id', 'Signature', 'Expires'];
39
+
40
+ /**
41
+ * Pull the CDN-signing query params (token / Policy / Key-Pair-Id / Signature
42
+ * / Expires) out of a pre-signed CDN URL so they can be overlaid on a URL
43
+ * built independently by `getImageUrlSync` (which constructs path, image
44
+ * params, pathBased routing, wmv, etc.). Image-shape params from the cdn URL
45
+ * itself (width/height/mode/...) are intentionally NOT extracted — those come
46
+ * from `imageURLParams` via `getImageUrlSync`.
47
+ *
48
+ * Returns `{}` on parse failure so we degrade rather than throw.
49
+ */
50
+ export const extractCdnSigningParams = cdnUrl => {
51
+ try {
52
+ const url = new URL(cdnUrl);
53
+ const out = {};
54
+ for (const name of SIGNING_PARAM_NAMES) {
55
+ const value = url.searchParams.get(name);
56
+ if (value !== null) {
57
+ out[name] = value;
58
+ }
59
+ }
60
+ return out;
61
+ } catch {
62
+ return {};
63
+ }
64
+ };
65
+ const applyCdnSigningParams = (url, cdnSigningParams) => {
66
+ if (!cdnSigningParams || Object.keys(cdnSigningParams).length === 0) {
67
+ return url;
68
+ }
69
+ try {
70
+ const parsed = new URL(url);
71
+ Object.entries(cdnSigningParams).forEach(([key, value]) => {
72
+ parsed.searchParams.set(key, value);
73
+ });
74
+ return parsed.toString();
75
+ } catch {
76
+ return url;
77
+ }
78
+ };
79
+ const getDataUri = (mediaClient, id, params, mediaBlobUrlAttrs, cdnSigningParams) => {
32
80
  const rawDataURI = mediaClient.getImageUrlSync(id, params);
33
- return mediaBlobUrlAttrs ? addFileAttrsToUrl(rawDataURI, mediaBlobUrlAttrs) : rawDataURI;
81
+ const signedDataURI = applyCdnSigningParams(rawDataURI, cdnSigningParams);
82
+ return mediaBlobUrlAttrs ? addFileAttrsToUrl(signedDataURI, mediaBlobUrlAttrs) : signedDataURI;
34
83
  };
35
84
 
36
85
  /**
@@ -56,19 +105,19 @@ const mergeClientIdIntoAttrs = (clientId, id, mediaBlobUrlAttrs, collectionName)
56
105
  collection: collectionName
57
106
  };
58
107
  };
59
- export const getSSRPreview = (ssr, mediaClient, id, params, mediaBlobUrlAttrs) => {
108
+ export const getSSRPreview = (ssr, mediaClient, id, params, mediaBlobUrlAttrs, cdnSigningParams) => {
60
109
  try {
61
110
  // Synchronously extract clientId from initialAuth and merge into blob URL attrs
62
111
  const clientId = fg('platform_media_cross_client_copy_with_auth') ? mediaClient.getClientIdSync() : undefined;
63
112
  const attrsWithClientId = mergeClientIdIntoAttrs(clientId, id, mediaBlobUrlAttrs, params.collection);
64
- const dataURI = getDataUri(mediaClient, id, params, attrsWithClientId);
113
+ const dataURI = getDataUri(mediaClient, id, params, attrsWithClientId, cdnSigningParams);
65
114
  let srcSet = `${dataURI} 1x`;
66
115
  if (params.width) {
67
116
  const doubleDataURI = getDataUri(mediaClient, id, {
68
117
  ...params,
69
118
  width: params.width * 2,
70
119
  height: params.height && params.height * 2
71
- }, attrsWithClientId);
120
+ }, attrsWithClientId, cdnSigningParams);
72
121
  // We want to embed some meta context into dataURI for Copy/Paste to work.
73
122
  srcSet += `, ${doubleDataURI} 2x`;
74
123
  }
@@ -1,3 +1,3 @@
1
1
  export { mediaFilePreviewCache } from './cache';
2
- export { getSSRPreview, isLocalPreview, isRemotePreview, isSSRPreview, isSSRClientPreview, isSSRDataPreview, getAndCacheRemotePreview, getAndCacheLocalPreview } from './getPreview';
2
+ export { getSSRPreview, isLocalPreview, isRemotePreview, isSSRPreview, isSSRClientPreview, isSSRDataPreview, getAndCacheRemotePreview, getAndCacheLocalPreview, extractCdnSigningParams } from './getPreview';
3
3
  export { isSupportedLocalPreview } from './helpers';
@@ -6,7 +6,7 @@ import { fg } from '@atlaskit/platform-feature-flags';
6
6
  import { useInteractionContext } from '@atlaskit/react-ufo/interaction-context';
7
7
  import { createFailedSSRObject, extractErrorInfo } from './analytics';
8
8
  import { ensureMediaFilePreviewError, ImageLoadError, MediaFilePreviewError } from './errors';
9
- import { getAndCacheLocalPreview, getAndCacheRemotePreview, getSSRPreview, isLocalPreview, isRemotePreview, isSSRClientPreview, isSSRDataPreview, isSSRPreview, isSupportedLocalPreview, mediaFilePreviewCache } from './getPreview';
9
+ import { extractCdnSigningParams, getAndCacheLocalPreview, getAndCacheRemotePreview, getSSRPreview, isLocalPreview, isRemotePreview, isSSRClientPreview, isSSRDataPreview, isSSRPreview, isSupportedLocalPreview, mediaFilePreviewCache } from './getPreview';
10
10
  import { generateScriptProps, getSSRData } from './globalScope';
11
11
  import { createRequestDimensions, isBigger, isWider, useCurrentValueRef } from './helpers';
12
12
  // invisible gif for SSR preview to show the underlying spinner until the src is replaced by
@@ -32,7 +32,8 @@ export const useFilePreview = ({
32
32
  allowAnimated = true,
33
33
  upscale,
34
34
  maxAge,
35
- source
35
+ source,
36
+ initialFileState
36
37
  }) => {
37
38
  const mediaClient = useMediaClient();
38
39
  const [status, setStatus] = useState('loading');
@@ -93,7 +94,15 @@ export const useFilePreview = ({
93
94
  // where no SSR occurred, so we should skip SSR preview generation entirely.
94
95
  if (ssr === 'server' || ssrData) {
95
96
  try {
96
- return getSSRPreview(ssr, mediaClient, identifier.id, imageURLParams, mediaBlobUrlAttrs);
97
+ // When the relay/SSR-seed path provided a pre-signed CDN URL,
98
+ // overlay its CDN-signing query params on the URL produced by
99
+ // getImageUrlSync. This makes the SSR-rendered HTML use the
100
+ // cdn-signed URL directly (no auth-token -> cdn-signed swap on
101
+ // hydration) and the 'ssr-data' rehydration path inherits it
102
+ // automatically via globalScope.
103
+ const seededCdnUrl = initialFileState && initialFileState.status !== 'error' ? initialFileState.previewCdnUrl : undefined;
104
+ const cdnSigningParams = seededCdnUrl && fg('platform_media_ssr_data_seed') ? extractCdnSigningParams(seededCdnUrl) : undefined;
105
+ return getSSRPreview(ssr, mediaClient, identifier.id, imageURLParams, mediaBlobUrlAttrs, cdnSigningParams);
97
106
  } catch (e) {
98
107
  ssrReliabilityRef.current = {
99
108
  ...ssrReliabilityRef.current,
@@ -130,6 +139,7 @@ export const useFilePreview = ({
130
139
  const {
131
140
  fileState
132
141
  } = useFileState(identifier.id, {
142
+ initialFileState,
133
143
  skipRemote,
134
144
  collectionName: identifier.collectionName,
135
145
  occurrenceKey: identifier.occurrenceKey
@@ -1,5 +1,5 @@
1
- import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
1
  import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
3
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
4
  import _regeneratorRuntime from "@babel/runtime/regenerator";
5
5
  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; }
@@ -32,9 +32,62 @@ var extendAndCachePreview = function extendAndCachePreview(id, mode, preview, me
32
32
  dataURI: dataURI
33
33
  });
34
34
  };
35
- var getDataUri = function getDataUri(mediaClient, id, params, mediaBlobUrlAttrs) {
35
+
36
+ /**
37
+ * Allowlist of CDN signing query-param names that we propagate from a
38
+ * pre-signed `previewCdnUrl` onto the URL produced by `getImageUrlSync`.
39
+ * These are the standard CloudFront signed-URL params; if the upstream
40
+ * adds a new one, this list needs updating.
41
+ */
42
+ var SIGNING_PARAM_NAMES = ['token', 'Policy', 'Key-Pair-Id', 'Signature', 'Expires'];
43
+
44
+ /**
45
+ * Pull the CDN-signing query params (token / Policy / Key-Pair-Id / Signature
46
+ * / Expires) out of a pre-signed CDN URL so they can be overlaid on a URL
47
+ * built independently by `getImageUrlSync` (which constructs path, image
48
+ * params, pathBased routing, wmv, etc.). Image-shape params from the cdn URL
49
+ * itself (width/height/mode/...) are intentionally NOT extracted — those come
50
+ * from `imageURLParams` via `getImageUrlSync`.
51
+ *
52
+ * Returns `{}` on parse failure so we degrade rather than throw.
53
+ */
54
+ export var extractCdnSigningParams = function extractCdnSigningParams(cdnUrl) {
55
+ try {
56
+ var url = new URL(cdnUrl);
57
+ var out = {};
58
+ for (var _i = 0, _SIGNING_PARAM_NAMES = SIGNING_PARAM_NAMES; _i < _SIGNING_PARAM_NAMES.length; _i++) {
59
+ var name = _SIGNING_PARAM_NAMES[_i];
60
+ var value = url.searchParams.get(name);
61
+ if (value !== null) {
62
+ out[name] = value;
63
+ }
64
+ }
65
+ return out;
66
+ } catch (_unused) {
67
+ return {};
68
+ }
69
+ };
70
+ var applyCdnSigningParams = function applyCdnSigningParams(url, cdnSigningParams) {
71
+ if (!cdnSigningParams || Object.keys(cdnSigningParams).length === 0) {
72
+ return url;
73
+ }
74
+ try {
75
+ var parsed = new URL(url);
76
+ Object.entries(cdnSigningParams).forEach(function (_ref) {
77
+ var _ref2 = _slicedToArray(_ref, 2),
78
+ key = _ref2[0],
79
+ value = _ref2[1];
80
+ parsed.searchParams.set(key, value);
81
+ });
82
+ return parsed.toString();
83
+ } catch (_unused2) {
84
+ return url;
85
+ }
86
+ };
87
+ var getDataUri = function getDataUri(mediaClient, id, params, mediaBlobUrlAttrs, cdnSigningParams) {
36
88
  var rawDataURI = mediaClient.getImageUrlSync(id, params);
37
- return mediaBlobUrlAttrs ? addFileAttrsToUrl(rawDataURI, mediaBlobUrlAttrs) : rawDataURI;
89
+ var signedDataURI = applyCdnSigningParams(rawDataURI, cdnSigningParams);
90
+ return mediaBlobUrlAttrs ? addFileAttrsToUrl(signedDataURI, mediaBlobUrlAttrs) : signedDataURI;
38
91
  };
39
92
 
40
93
  /**
@@ -59,18 +112,18 @@ var mergeClientIdIntoAttrs = function mergeClientIdIntoAttrs(clientId, id, media
59
112
  collection: collectionName
60
113
  };
61
114
  };
62
- export var getSSRPreview = function getSSRPreview(ssr, mediaClient, id, params, mediaBlobUrlAttrs) {
115
+ export var getSSRPreview = function getSSRPreview(ssr, mediaClient, id, params, mediaBlobUrlAttrs, cdnSigningParams) {
63
116
  try {
64
117
  // Synchronously extract clientId from initialAuth and merge into blob URL attrs
65
118
  var clientId = fg('platform_media_cross_client_copy_with_auth') ? mediaClient.getClientIdSync() : undefined;
66
119
  var attrsWithClientId = mergeClientIdIntoAttrs(clientId, id, mediaBlobUrlAttrs, params.collection);
67
- var dataURI = getDataUri(mediaClient, id, params, attrsWithClientId);
120
+ var dataURI = getDataUri(mediaClient, id, params, attrsWithClientId, cdnSigningParams);
68
121
  var srcSet = "".concat(dataURI, " 1x");
69
122
  if (params.width) {
70
123
  var doubleDataURI = getDataUri(mediaClient, id, _objectSpread(_objectSpread({}, params), {}, {
71
124
  width: params.width * 2,
72
125
  height: params.height && params.height * 2
73
- }), attrsWithClientId);
126
+ }), attrsWithClientId, cdnSigningParams);
74
127
  // We want to embed some meta context into dataURI for Copy/Paste to work.
75
128
  srcSet += ", ".concat(doubleDataURI, " 2x");
76
129
  }
@@ -110,54 +163,54 @@ export var isSSRPreview = function isSSRPreview(preview) {
110
163
  * with it for cross-client copy support.
111
164
  */
112
165
  var enrichAttrsWithClientId = /*#__PURE__*/function () {
113
- var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(mediaClient, id, mediaBlobUrlAttrs, collectionName) {
114
- var clientId;
115
- return _regeneratorRuntime.wrap(function _callee$(_context) {
166
+ var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(mediaClient, id, mediaBlobUrlAttrs, collectionName) {
167
+ var clientId, _t;
168
+ return _regeneratorRuntime.wrap(function (_context) {
116
169
  while (1) switch (_context.prev = _context.next) {
117
170
  case 0:
118
171
  if (fg('platform_media_cross_client_copy_with_auth')) {
119
- _context.next = 2;
172
+ _context.next = 1;
120
173
  break;
121
174
  }
122
175
  return _context.abrupt("return", mediaBlobUrlAttrs);
123
- case 2:
176
+ case 1:
124
177
  // Try sync first, then async fallback
125
178
  clientId = mediaClient.getClientIdSync();
126
179
  if (clientId) {
127
- _context.next = 12;
180
+ _context.next = 5;
128
181
  break;
129
182
  }
130
- _context.prev = 4;
131
- _context.next = 7;
183
+ _context.prev = 2;
184
+ _context.next = 3;
132
185
  return mediaClient.getClientId(collectionName);
133
- case 7:
186
+ case 3:
134
187
  clientId = _context.sent;
135
- _context.next = 12;
188
+ _context.next = 5;
136
189
  break;
137
- case 10:
138
- _context.prev = 10;
139
- _context.t0 = _context["catch"](4);
140
- case 12:
190
+ case 4:
191
+ _context.prev = 4;
192
+ _t = _context["catch"](2);
193
+ case 5:
141
194
  return _context.abrupt("return", mergeClientIdIntoAttrs(clientId, id, mediaBlobUrlAttrs, collectionName));
142
- case 13:
195
+ case 6:
143
196
  case "end":
144
197
  return _context.stop();
145
198
  }
146
- }, _callee, null, [[4, 10]]);
199
+ }, _callee, null, [[2, 4]]);
147
200
  }));
148
201
  return function enrichAttrsWithClientId(_x, _x2, _x3, _x4) {
149
- return _ref.apply(this, arguments);
202
+ return _ref3.apply(this, arguments);
150
203
  };
151
204
  }();
152
205
  export var getAndCacheRemotePreview = /*#__PURE__*/function () {
153
- var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(mediaClient, id, dimensions, params, mediaBlobUrlAttrs, traceContext) {
206
+ var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(mediaClient, id, dimensions, params, mediaBlobUrlAttrs, traceContext) {
154
207
  var _yield$Promise$all, _yield$Promise$all2, remotePreview, enrichedAttrs;
155
- return _regeneratorRuntime.wrap(function _callee2$(_context2) {
208
+ return _regeneratorRuntime.wrap(function (_context2) {
156
209
  while (1) switch (_context2.prev = _context2.next) {
157
210
  case 0:
158
- _context2.next = 2;
211
+ _context2.next = 1;
159
212
  return Promise.all([getRemotePreview(mediaClient, id, params, traceContext), enrichAttrsWithClientId(mediaClient, id, mediaBlobUrlAttrs, params.collection)]);
160
- case 2:
213
+ case 1:
161
214
  _yield$Promise$all = _context2.sent;
162
215
  _yield$Promise$all2 = _slicedToArray(_yield$Promise$all, 2);
163
216
  remotePreview = _yield$Promise$all2[0];
@@ -165,25 +218,25 @@ export var getAndCacheRemotePreview = /*#__PURE__*/function () {
165
218
  return _context2.abrupt("return", extendAndCachePreview(id, params.mode, _objectSpread(_objectSpread({}, remotePreview), {}, {
166
219
  dimensions: dimensions
167
220
  }), enrichedAttrs));
168
- case 7:
221
+ case 2:
169
222
  case "end":
170
223
  return _context2.stop();
171
224
  }
172
225
  }, _callee2);
173
226
  }));
174
227
  return function getAndCacheRemotePreview(_x5, _x6, _x7, _x8, _x9, _x0) {
175
- return _ref2.apply(this, arguments);
228
+ return _ref4.apply(this, arguments);
176
229
  };
177
230
  }();
178
231
  export var getAndCacheLocalPreview = /*#__PURE__*/function () {
179
- var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(mediaClient, id, filePreview, dimensions, mode, mediaBlobUrlAttrs, collectionName) {
232
+ var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(mediaClient, id, filePreview, dimensions, mode, mediaBlobUrlAttrs, collectionName) {
180
233
  var _yield$Promise$all3, _yield$Promise$all4, localPreview, enrichedAttrs;
181
- return _regeneratorRuntime.wrap(function _callee3$(_context3) {
234
+ return _regeneratorRuntime.wrap(function (_context3) {
182
235
  while (1) switch (_context3.prev = _context3.next) {
183
236
  case 0:
184
- _context3.next = 2;
237
+ _context3.next = 1;
185
238
  return Promise.all([getLocalPreview(filePreview), enrichAttrsWithClientId(mediaClient, id, mediaBlobUrlAttrs, collectionName)]);
186
- case 2:
239
+ case 1:
187
240
  _yield$Promise$all3 = _context3.sent;
188
241
  _yield$Promise$all4 = _slicedToArray(_yield$Promise$all3, 2);
189
242
  localPreview = _yield$Promise$all4[0];
@@ -191,13 +244,13 @@ export var getAndCacheLocalPreview = /*#__PURE__*/function () {
191
244
  return _context3.abrupt("return", extendAndCachePreview(id, mode, _objectSpread(_objectSpread({}, localPreview), {}, {
192
245
  dimensions: dimensions
193
246
  }), enrichedAttrs));
194
- case 7:
247
+ case 2:
195
248
  case "end":
196
249
  return _context3.stop();
197
250
  }
198
251
  }, _callee3);
199
252
  }));
200
253
  return function getAndCacheLocalPreview(_x1, _x10, _x11, _x12, _x13, _x14, _x15) {
201
- return _ref3.apply(this, arguments);
254
+ return _ref5.apply(this, arguments);
202
255
  };
203
256
  }();
@@ -14,14 +14,14 @@ export var isSupportedLocalPreview = function isSupportedLocalPreview(mediaType)
14
14
  };
15
15
  var getImageLocalPreview = /*#__PURE__*/function () {
16
16
  var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(value) {
17
- var orientation, dataURI;
18
- return _regeneratorRuntime.wrap(function _callee$(_context) {
17
+ var orientation, dataURI, _t;
18
+ return _regeneratorRuntime.wrap(function (_context) {
19
19
  while (1) switch (_context.prev = _context.next) {
20
20
  case 0:
21
21
  _context.prev = 0;
22
- _context.next = 3;
22
+ _context.next = 1;
23
23
  return getOrientation(value);
24
- case 3:
24
+ case 1:
25
25
  orientation = _context.sent;
26
26
  dataURI = URL.createObjectURL(value);
27
27
  return _context.abrupt("return", {
@@ -29,15 +29,15 @@ var getImageLocalPreview = /*#__PURE__*/function () {
29
29
  orientation: orientation,
30
30
  source: 'local'
31
31
  });
32
- case 8:
33
- _context.prev = 8;
34
- _context.t0 = _context["catch"](0);
35
- throw new LocalPreviewError('local-preview-image', _context.t0 instanceof Error ? _context.t0 : undefined);
36
- case 11:
32
+ case 2:
33
+ _context.prev = 2;
34
+ _t = _context["catch"](0);
35
+ throw new LocalPreviewError('local-preview-image', _t instanceof Error ? _t : undefined);
36
+ case 3:
37
37
  case "end":
38
38
  return _context.stop();
39
39
  }
40
- }, _callee, null, [[0, 8]]);
40
+ }, _callee, null, [[0, 2]]);
41
41
  }));
42
42
  return function getImageLocalPreview(_x) {
43
43
  return _ref.apply(this, arguments);
@@ -45,29 +45,29 @@ var getImageLocalPreview = /*#__PURE__*/function () {
45
45
  }();
46
46
  var getVideoLocalPreview = /*#__PURE__*/function () {
47
47
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(value) {
48
- var dataURI;
49
- return _regeneratorRuntime.wrap(function _callee2$(_context2) {
48
+ var dataURI, _t2;
49
+ return _regeneratorRuntime.wrap(function (_context2) {
50
50
  while (1) switch (_context2.prev = _context2.next) {
51
51
  case 0:
52
52
  _context2.prev = 0;
53
- _context2.next = 3;
53
+ _context2.next = 1;
54
54
  return takeSnapshot(value);
55
- case 3:
55
+ case 1:
56
56
  dataURI = _context2.sent;
57
57
  return _context2.abrupt("return", {
58
58
  dataURI: dataURI,
59
59
  orientation: 1,
60
60
  source: 'local'
61
61
  });
62
- case 7:
63
- _context2.prev = 7;
64
- _context2.t0 = _context2["catch"](0);
65
- throw new LocalPreviewError('local-preview-video', _context2.t0 instanceof Error ? _context2.t0 : undefined);
66
- case 10:
62
+ case 2:
63
+ _context2.prev = 2;
64
+ _t2 = _context2["catch"](0);
65
+ throw new LocalPreviewError('local-preview-video', _t2 instanceof Error ? _t2 : undefined);
66
+ case 3:
67
67
  case "end":
68
68
  return _context2.stop();
69
69
  }
70
- }, _callee2, null, [[0, 7]]);
70
+ }, _callee2, null, [[0, 2]]);
71
71
  }));
72
72
  return function getVideoLocalPreview(_x2) {
73
73
  return _ref2.apply(this, arguments);
@@ -75,25 +75,25 @@ var getVideoLocalPreview = /*#__PURE__*/function () {
75
75
  }();
76
76
  export var getLocalPreview = /*#__PURE__*/function () {
77
77
  var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(filePreview) {
78
- var value, resolvedFilePreview, _value, type, mediaType;
79
- return _regeneratorRuntime.wrap(function _callee3$(_context3) {
78
+ var value, resolvedFilePreview, _value, type, mediaType, _t3, _t4;
79
+ return _regeneratorRuntime.wrap(function (_context3) {
80
80
  while (1) switch (_context3.prev = _context3.next) {
81
81
  case 0:
82
82
  _context3.prev = 0;
83
- _context3.next = 3;
83
+ _context3.next = 1;
84
84
  return filePreview;
85
- case 3:
85
+ case 1:
86
86
  resolvedFilePreview = _context3.sent;
87
87
  value = resolvedFilePreview.value;
88
- _context3.next = 10;
88
+ _context3.next = 3;
89
89
  break;
90
- case 7:
91
- _context3.prev = 7;
92
- _context3.t0 = _context3["catch"](0);
93
- throw new LocalPreviewError('local-preview-rejected', _context3.t0 instanceof Error ? _context3.t0 : undefined);
94
- case 10:
90
+ case 2:
91
+ _context3.prev = 2;
92
+ _t3 = _context3["catch"](0);
93
+ throw new LocalPreviewError('local-preview-rejected', _t3 instanceof Error ? _t3 : undefined);
94
+ case 3:
95
95
  if (!(typeof value === 'string')) {
96
- _context3.next = 14;
96
+ _context3.next = 4;
97
97
  break;
98
98
  }
99
99
  return _context3.abrupt("return", {
@@ -101,29 +101,29 @@ export var getLocalPreview = /*#__PURE__*/function () {
101
101
  orientation: 1,
102
102
  source: 'local'
103
103
  });
104
- case 14:
104
+ case 4:
105
105
  if (!(value instanceof Blob)) {
106
- _context3.next = 23;
106
+ _context3.next = 8;
107
107
  break;
108
108
  }
109
109
  _value = value, type = _value.type;
110
110
  mediaType = getMediaTypeFromMimeType(type);
111
- _context3.t1 = mediaType;
112
- _context3.next = _context3.t1 === 'image' ? 20 : _context3.t1 === 'video' ? 21 : 22;
111
+ _t4 = mediaType;
112
+ _context3.next = _t4 === 'image' ? 5 : _t4 === 'video' ? 6 : 7;
113
113
  break;
114
- case 20:
114
+ case 5:
115
115
  return _context3.abrupt("return", getImageLocalPreview(value));
116
- case 21:
116
+ case 6:
117
117
  return _context3.abrupt("return", getVideoLocalPreview(value));
118
- case 22:
118
+ case 7:
119
119
  throw new LocalPreviewError('local-preview-unsupported');
120
- case 23:
120
+ case 8:
121
121
  throw new LocalPreviewError('local-preview-unsupported');
122
- case 24:
122
+ case 9:
123
123
  case "end":
124
124
  return _context3.stop();
125
125
  }
126
- }, _callee3, null, [[0, 7]]);
126
+ }, _callee3, null, [[0, 2]]);
127
127
  }));
128
128
  return function getLocalPreview(_x3) {
129
129
  return _ref3.apply(this, arguments);
@@ -131,29 +131,29 @@ export var getLocalPreview = /*#__PURE__*/function () {
131
131
  }();
132
132
  export var getRemotePreview = /*#__PURE__*/function () {
133
133
  var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(mediaClient, id, params, traceContext) {
134
- var blob;
135
- return _regeneratorRuntime.wrap(function _callee4$(_context4) {
134
+ var blob, _t5;
135
+ return _regeneratorRuntime.wrap(function (_context4) {
136
136
  while (1) switch (_context4.prev = _context4.next) {
137
137
  case 0:
138
138
  _context4.prev = 0;
139
- _context4.next = 3;
139
+ _context4.next = 1;
140
140
  return mediaClient.getImage(id, params, undefined, undefined, traceContext);
141
- case 3:
141
+ case 1:
142
142
  blob = _context4.sent;
143
143
  return _context4.abrupt("return", {
144
144
  dataURI: URL.createObjectURL(blob),
145
145
  orientation: 1,
146
146
  source: 'remote'
147
147
  });
148
- case 7:
149
- _context4.prev = 7;
150
- _context4.t0 = _context4["catch"](0);
151
- throw new RemotePreviewError('remote-preview-fetch', _context4.t0 instanceof Error ? _context4.t0 : undefined);
152
- case 10:
148
+ case 2:
149
+ _context4.prev = 2;
150
+ _t5 = _context4["catch"](0);
151
+ throw new RemotePreviewError('remote-preview-fetch', _t5 instanceof Error ? _t5 : undefined);
152
+ case 3:
153
153
  case "end":
154
154
  return _context4.stop();
155
155
  }
156
- }, _callee4, null, [[0, 7]]);
156
+ }, _callee4, null, [[0, 2]]);
157
157
  }));
158
158
  return function getRemotePreview(_x4, _x5, _x6, _x7) {
159
159
  return _ref4.apply(this, arguments);
@@ -1,3 +1,3 @@
1
1
  export { mediaFilePreviewCache } from './cache';
2
- export { getSSRPreview, isLocalPreview, isRemotePreview, isSSRPreview, isSSRClientPreview, isSSRDataPreview, getAndCacheRemotePreview, getAndCacheLocalPreview } from './getPreview';
2
+ export { getSSRPreview, isLocalPreview, isRemotePreview, isSSRPreview, isSSRClientPreview, isSSRDataPreview, getAndCacheRemotePreview, getAndCacheLocalPreview, extractCdnSigningParams } from './getPreview';
3
3
  export { isSupportedLocalPreview } from './helpers';
@@ -2,7 +2,7 @@ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
2
  import _regeneratorRuntime from "@babel/runtime/regenerator";
3
3
  export var takeSnapshot = /*#__PURE__*/function () {
4
4
  var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(blob) {
5
- return _regeneratorRuntime.wrap(function _callee$(_context) {
5
+ return _regeneratorRuntime.wrap(function (_context) {
6
6
  while (1) switch (_context.prev = _context.next) {
7
7
  case 0:
8
8
  return _context.abrupt("return", new Promise(function (resolve, reject) {
@@ -10,7 +10,7 @@ import { fg } from '@atlaskit/platform-feature-flags';
10
10
  import { useInteractionContext } from '@atlaskit/react-ufo/interaction-context';
11
11
  import { createFailedSSRObject, extractErrorInfo } from './analytics';
12
12
  import { ensureMediaFilePreviewError, ImageLoadError, MediaFilePreviewError } from './errors';
13
- import { getAndCacheLocalPreview, getAndCacheRemotePreview, getSSRPreview, isLocalPreview, isRemotePreview, isSSRClientPreview, isSSRDataPreview, isSSRPreview, isSupportedLocalPreview, mediaFilePreviewCache } from './getPreview';
13
+ import { extractCdnSigningParams, getAndCacheLocalPreview, getAndCacheRemotePreview, getSSRPreview, isLocalPreview, isRemotePreview, isSSRClientPreview, isSSRDataPreview, isSSRPreview, isSupportedLocalPreview, mediaFilePreviewCache } from './getPreview';
14
14
  import { generateScriptProps, getSSRData } from './globalScope';
15
15
  import { createRequestDimensions, isBigger, isWider, useCurrentValueRef } from './helpers';
16
16
  // invisible gif for SSR preview to show the underlying spinner until the src is replaced by
@@ -38,7 +38,8 @@ export var useFilePreview = function useFilePreview(_ref) {
38
38
  allowAnimated = _ref$allowAnimated === void 0 ? true : _ref$allowAnimated,
39
39
  upscale = _ref.upscale,
40
40
  maxAge = _ref.maxAge,
41
- source = _ref.source;
41
+ source = _ref.source,
42
+ initialFileState = _ref.initialFileState;
42
43
  var mediaClient = useMediaClient();
43
44
  var _useState = useState('loading'),
44
45
  _useState2 = _slicedToArray(_useState, 2),
@@ -115,7 +116,15 @@ export var useFilePreview = function useFilePreview(_ref) {
115
116
  // where no SSR occurred, so we should skip SSR preview generation entirely.
116
117
  if (ssr === 'server' || ssrData) {
117
118
  try {
118
- return getSSRPreview(ssr, mediaClient, identifier.id, imageURLParams, mediaBlobUrlAttrs);
119
+ // When the relay/SSR-seed path provided a pre-signed CDN URL,
120
+ // overlay its CDN-signing query params on the URL produced by
121
+ // getImageUrlSync. This makes the SSR-rendered HTML use the
122
+ // cdn-signed URL directly (no auth-token -> cdn-signed swap on
123
+ // hydration) and the 'ssr-data' rehydration path inherits it
124
+ // automatically via globalScope.
125
+ var seededCdnUrl = initialFileState && initialFileState.status !== 'error' ? initialFileState.previewCdnUrl : undefined;
126
+ var cdnSigningParams = seededCdnUrl && fg('platform_media_ssr_data_seed') ? extractCdnSigningParams(seededCdnUrl) : undefined;
127
+ return getSSRPreview(ssr, mediaClient, identifier.id, imageURLParams, mediaBlobUrlAttrs, cdnSigningParams);
119
128
  } catch (e) {
120
129
  ssrReliabilityRef.current = _objectSpread(_objectSpread({}, ssrReliabilityRef.current), {}, _defineProperty({}, ssr, _objectSpread({
121
130
  status: 'fail'
@@ -147,6 +156,7 @@ export var useFilePreview = function useFilePreview(_ref) {
147
156
  //----------------------------------------------------------------
148
157
 
149
158
  var _useFileState = useFileState(identifier.id, {
159
+ initialFileState: initialFileState,
150
160
  skipRemote: skipRemote,
151
161
  collectionName: identifier.collectionName,
152
162
  occurrenceKey: identifier.occurrenceKey
@@ -1,7 +1,18 @@
1
1
  import { type FilePreview, type MediaBlobUrlAttrs, type MediaClient, type MediaStoreGetFileImageParams } from '@atlaskit/media-client';
2
2
  import { type MediaTraceContext, type SSR } from '@atlaskit/media-common';
3
3
  import { type MediaFilePreview, type MediaFilePreviewDimensions } from '../types';
4
- export declare const getSSRPreview: (ssr: SSR, mediaClient: MediaClient, id: string, params: MediaStoreGetFileImageParams, mediaBlobUrlAttrs?: MediaBlobUrlAttrs) => MediaFilePreview;
4
+ /**
5
+ * Pull the CDN-signing query params (token / Policy / Key-Pair-Id / Signature
6
+ * / Expires) out of a pre-signed CDN URL so they can be overlaid on a URL
7
+ * built independently by `getImageUrlSync` (which constructs path, image
8
+ * params, pathBased routing, wmv, etc.). Image-shape params from the cdn URL
9
+ * itself (width/height/mode/...) are intentionally NOT extracted — those come
10
+ * from `imageURLParams` via `getImageUrlSync`.
11
+ *
12
+ * Returns `{}` on parse failure so we degrade rather than throw.
13
+ */
14
+ export declare const extractCdnSigningParams: (cdnUrl: string) => Record<string, string>;
15
+ export declare const getSSRPreview: (ssr: SSR, mediaClient: MediaClient, id: string, params: MediaStoreGetFileImageParams, mediaBlobUrlAttrs?: MediaBlobUrlAttrs, cdnSigningParams?: Record<string, string>) => MediaFilePreview;
5
16
  export declare const isLocalPreview: (preview: MediaFilePreview) => boolean;
6
17
  export declare const isRemotePreview: (preview: MediaFilePreview) => boolean;
7
18
  export declare const isSSRClientPreview: (preview: MediaFilePreview) => boolean;
@@ -1,3 +1,3 @@
1
1
  export { mediaFilePreviewCache } from './cache';
2
- export { getSSRPreview, isLocalPreview, isRemotePreview, isSSRPreview, isSSRClientPreview, isSSRDataPreview, getAndCacheRemotePreview, getAndCacheLocalPreview, } from './getPreview';
2
+ export { getSSRPreview, isLocalPreview, isRemotePreview, isSSRPreview, isSSRClientPreview, isSSRDataPreview, getAndCacheRemotePreview, getAndCacheLocalPreview, extractCdnSigningParams, } from './getPreview';
3
3
  export { isSupportedLocalPreview } from './helpers';
@@ -1,5 +1,5 @@
1
1
  import { type DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES, type ScriptHTMLAttributes } from 'react';
2
- import { type FileIdentifier, type MediaBlobUrlAttrs, type MediaStoreGetFileImageParams } from '@atlaskit/media-client';
2
+ import { type FileIdentifier, type FileState, type MediaBlobUrlAttrs, type MediaStoreGetFileImageParams } from '@atlaskit/media-client';
3
3
  import { type MediaTraceContext, type SSR } from '@atlaskit/media-common';
4
4
  import { type SSRStatus } from './analytics';
5
5
  import { MediaFilePreviewError } from './errors';
@@ -30,8 +30,10 @@ export interface UseFilePreviewParams {
30
30
  readonly maxAge?: number;
31
31
  /** Defines the source component */
32
32
  readonly source?: string;
33
+ /** Initial file state to be used for the preview. */
34
+ readonly initialFileState?: FileState;
33
35
  }
34
- export declare const useFilePreview: ({ resizeMode, identifier, ssr, dimensions, useSrcSet, traceContext, skipRemote, mediaBlobUrlAttrs, allowAnimated, upscale, maxAge, source, }: UseFilePreviewParams) => {
36
+ export declare const useFilePreview: ({ resizeMode, identifier, ssr, dimensions, useSrcSet, traceContext, skipRemote, mediaBlobUrlAttrs, allowAnimated, upscale, maxAge, source, initialFileState, }: UseFilePreviewParams) => {
35
37
  preview: MediaFilePreview | undefined;
36
38
  status: MediaFilePreviewStatus;
37
39
  error: MediaFilePreviewError | undefined;