@atlaskit/media-card 77.5.0 → 77.5.2

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 (107) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cjs/card/card.js +1 -1
  3. package/dist/cjs/card/media-card-analytics-error-boundary.js +1 -1
  4. package/dist/cjs/card/v2/cardV2.js +1 -1
  5. package/dist/cjs/card/v2/cardViewV2.js +7 -6
  6. package/dist/cjs/card/v2/useFilePreview/errors.js +132 -0
  7. package/dist/cjs/card/v2/useFilePreview/getPreview/cache.js +39 -0
  8. package/dist/cjs/card/v2/useFilePreview/getPreview/filePreviewStatus.js +45 -0
  9. package/dist/cjs/card/v2/useFilePreview/getPreview/getPreview.js +119 -0
  10. package/dist/cjs/card/v2/useFilePreview/getPreview/helpers.js +167 -0
  11. package/dist/cjs/card/v2/useFilePreview/getPreview/index.js +62 -0
  12. package/dist/cjs/card/v2/useFilePreview/getPreview/objectURLCache.js +85 -0
  13. package/dist/cjs/card/v2/useFilePreview/getPreview/videoSnapshot.js +58 -0
  14. package/dist/cjs/card/v2/useFilePreview/globalScope/getSSRData.js +14 -0
  15. package/dist/cjs/card/v2/useFilePreview/globalScope/globalScope.js +66 -0
  16. package/dist/cjs/card/v2/useFilePreview/globalScope/index.js +37 -0
  17. package/dist/cjs/card/v2/useFilePreview/globalScope/printScript.js +32 -0
  18. package/dist/cjs/card/v2/useFilePreview/globalScope/types.js +5 -0
  19. package/dist/cjs/card/v2/useFilePreview/helpers.js +64 -0
  20. package/dist/cjs/card/v2/useFilePreview/index.js +12 -0
  21. package/dist/cjs/card/v2/useFilePreview/types.js +5 -0
  22. package/dist/cjs/card/v2/{useFilePreview.js → useFilePreview/useFilePreview.js} +58 -194
  23. package/dist/cjs/inline/loader.js +1 -1
  24. package/dist/cjs/utils/ufoExperiences.js +1 -1
  25. package/dist/es2019/card/card.js +1 -1
  26. package/dist/es2019/card/media-card-analytics-error-boundary.js +1 -1
  27. package/dist/es2019/card/v2/cardV2.js +1 -1
  28. package/dist/es2019/card/v2/cardViewV2.js +7 -6
  29. package/dist/es2019/card/v2/useFilePreview/errors.js +81 -0
  30. package/dist/es2019/card/v2/useFilePreview/getPreview/cache.js +30 -0
  31. package/dist/es2019/card/v2/useFilePreview/getPreview/filePreviewStatus.js +43 -0
  32. package/dist/es2019/card/v2/useFilePreview/getPreview/getPreview.js +75 -0
  33. package/dist/es2019/card/v2/useFilePreview/getPreview/helpers.js +76 -0
  34. package/dist/es2019/card/v2/useFilePreview/getPreview/index.js +3 -0
  35. package/dist/es2019/card/v2/useFilePreview/getPreview/objectURLCache.js +44 -0
  36. package/dist/es2019/card/v2/useFilePreview/getPreview/videoSnapshot.js +36 -0
  37. package/dist/es2019/card/v2/useFilePreview/globalScope/getSSRData.js +8 -0
  38. package/dist/es2019/card/v2/useFilePreview/globalScope/globalScope.js +48 -0
  39. package/dist/es2019/card/v2/useFilePreview/globalScope/index.js +2 -0
  40. package/dist/es2019/card/v2/useFilePreview/globalScope/printScript.js +16 -0
  41. package/dist/es2019/card/v2/useFilePreview/globalScope/types.js +1 -0
  42. package/dist/es2019/card/v2/useFilePreview/helpers.js +61 -0
  43. package/dist/es2019/card/v2/useFilePreview/index.js +1 -0
  44. package/dist/es2019/card/v2/useFilePreview/types.js +1 -0
  45. package/dist/es2019/card/v2/{useFilePreview.js → useFilePreview/useFilePreview.js} +18 -132
  46. package/dist/es2019/inline/loader.js +1 -1
  47. package/dist/es2019/utils/ufoExperiences.js +1 -1
  48. package/dist/esm/card/card.js +1 -1
  49. package/dist/esm/card/media-card-analytics-error-boundary.js +1 -1
  50. package/dist/esm/card/v2/cardV2.js +1 -1
  51. package/dist/esm/card/v2/cardViewV2.js +7 -6
  52. package/dist/esm/card/v2/useFilePreview/errors.js +124 -0
  53. package/dist/esm/card/v2/useFilePreview/getPreview/cache.js +32 -0
  54. package/dist/esm/card/v2/useFilePreview/getPreview/filePreviewStatus.js +40 -0
  55. package/dist/esm/card/v2/useFilePreview/getPreview/getPreview.js +112 -0
  56. package/dist/esm/card/v2/useFilePreview/getPreview/helpers.js +160 -0
  57. package/dist/esm/card/v2/useFilePreview/getPreview/index.js +3 -0
  58. package/dist/esm/card/v2/useFilePreview/getPreview/objectURLCache.js +78 -0
  59. package/dist/esm/card/v2/useFilePreview/getPreview/videoSnapshot.js +51 -0
  60. package/dist/esm/card/v2/useFilePreview/globalScope/getSSRData.js +8 -0
  61. package/dist/esm/card/v2/useFilePreview/globalScope/globalScope.js +56 -0
  62. package/dist/esm/card/v2/useFilePreview/globalScope/index.js +2 -0
  63. package/dist/esm/card/v2/useFilePreview/globalScope/printScript.js +25 -0
  64. package/dist/esm/card/v2/useFilePreview/globalScope/types.js +1 -0
  65. package/dist/esm/card/v2/useFilePreview/helpers.js +57 -0
  66. package/dist/esm/card/v2/useFilePreview/index.js +1 -0
  67. package/dist/esm/card/v2/useFilePreview/types.js +1 -0
  68. package/dist/esm/card/v2/{useFilePreview.js → useFilePreview/useFilePreview.js} +41 -177
  69. package/dist/esm/inline/loader.js +1 -1
  70. package/dist/esm/utils/ufoExperiences.js +1 -1
  71. package/dist/types/card/v2/cardViewV2.d.ts +5 -4
  72. package/dist/types/card/v2/useFilePreview/errors.d.ts +38 -0
  73. package/dist/types/card/v2/useFilePreview/getPreview/cache.d.ts +21 -0
  74. package/dist/types/card/v2/useFilePreview/getPreview/filePreviewStatus.d.ts +4 -0
  75. package/dist/types/card/v2/useFilePreview/getPreview/getPreview.d.ts +9 -0
  76. package/dist/types/card/v2/useFilePreview/getPreview/helpers.d.ts +10 -0
  77. package/dist/types/card/v2/useFilePreview/getPreview/index.d.ts +3 -0
  78. package/dist/types/card/v2/useFilePreview/getPreview/objectURLCache.d.ts +12 -0
  79. package/dist/types/card/v2/useFilePreview/getPreview/videoSnapshot.d.ts +1 -0
  80. package/dist/types/card/v2/useFilePreview/globalScope/getSSRData.d.ts +3 -0
  81. package/dist/types/card/v2/useFilePreview/globalScope/globalScope.d.ts +15 -0
  82. package/dist/types/card/v2/useFilePreview/globalScope/index.d.ts +4 -0
  83. package/dist/types/card/v2/useFilePreview/globalScope/printScript.d.ts +2 -0
  84. package/dist/types/card/v2/useFilePreview/globalScope/types.d.ts +8 -0
  85. package/dist/types/card/v2/useFilePreview/helpers.d.ts +11 -0
  86. package/dist/types/card/v2/useFilePreview/index.d.ts +2 -0
  87. package/dist/types/card/v2/useFilePreview/types.d.ts +18 -0
  88. package/dist/{types-ts4.5/card/v2 → types/card/v2/useFilePreview}/useFilePreview.d.ts +8 -8
  89. package/dist/types-ts4.5/card/v2/cardViewV2.d.ts +5 -4
  90. package/dist/types-ts4.5/card/v2/useFilePreview/errors.d.ts +38 -0
  91. package/dist/types-ts4.5/card/v2/useFilePreview/getPreview/cache.d.ts +21 -0
  92. package/dist/types-ts4.5/card/v2/useFilePreview/getPreview/filePreviewStatus.d.ts +4 -0
  93. package/dist/types-ts4.5/card/v2/useFilePreview/getPreview/getPreview.d.ts +9 -0
  94. package/dist/types-ts4.5/card/v2/useFilePreview/getPreview/helpers.d.ts +10 -0
  95. package/dist/types-ts4.5/card/v2/useFilePreview/getPreview/index.d.ts +3 -0
  96. package/dist/types-ts4.5/card/v2/useFilePreview/getPreview/objectURLCache.d.ts +12 -0
  97. package/dist/types-ts4.5/card/v2/useFilePreview/getPreview/videoSnapshot.d.ts +1 -0
  98. package/dist/types-ts4.5/card/v2/useFilePreview/globalScope/getSSRData.d.ts +3 -0
  99. package/dist/types-ts4.5/card/v2/useFilePreview/globalScope/globalScope.d.ts +15 -0
  100. package/dist/types-ts4.5/card/v2/useFilePreview/globalScope/index.d.ts +4 -0
  101. package/dist/types-ts4.5/card/v2/useFilePreview/globalScope/printScript.d.ts +2 -0
  102. package/dist/types-ts4.5/card/v2/useFilePreview/globalScope/types.d.ts +8 -0
  103. package/dist/types-ts4.5/card/v2/useFilePreview/helpers.d.ts +11 -0
  104. package/dist/types-ts4.5/card/v2/useFilePreview/index.d.ts +2 -0
  105. package/dist/types-ts4.5/card/v2/useFilePreview/types.d.ts +18 -0
  106. package/dist/{types/card/v2 → types-ts4.5/card/v2/useFilePreview}/useFilePreview.d.ts +8 -8
  107. package/package.json +2 -2
@@ -0,0 +1,43 @@
1
+ import { isMimeTypeSupportedByBrowser } from '@atlaskit/media-common';
2
+ import { isPreviewableFileState, isPreviewableType, isImageRepresentationReady } from '@atlaskit/media-client';
3
+ import { isSupportedLocalPreview } from './helpers';
4
+
5
+ // TODO: align these checks with helpers from Media Client
6
+ // https://product-fabric.atlassian.net/browse/BMPT-1300
7
+ export const extractFilePreviewStatus = (fileState, isBannedLocalPreview) => {
8
+ const hasFilesize = 'size' in fileState && !!fileState.size;
9
+ const {
10
+ mediaType
11
+ } = 'mediaType' in fileState && fileState || {};
12
+ const {
13
+ mimeType
14
+ } = 'mimeType' in fileState && fileState || {};
15
+ const isPreviewable = !!mediaType && isPreviewableType(mediaType);
16
+
17
+ // Local preview is available only if it's supported by browser and supported by Media Card (isSupportedLocalPreview)
18
+ // For example, SVGs are mime type NOT supported by browser but media type supported by Media Card (image)
19
+ // Then, local Preview NOT available
20
+ const hasLocalPreview = !isBannedLocalPreview && isPreviewableFileState(fileState) && isSupportedLocalPreview(mediaType) && !!mimeType && isMimeTypeSupportedByBrowser(mimeType);
21
+ const hasRemotePreview = isImageRepresentationReady(fileState);
22
+ const hasPreview = hasLocalPreview || hasRemotePreview;
23
+ const isSupportedByBrowser = !!mimeType && isMimeTypeSupportedByBrowser(mimeType);
24
+ return {
25
+ hasFilesize,
26
+ isPreviewable,
27
+ hasPreview,
28
+ isSupportedByBrowser
29
+ };
30
+ };
31
+
32
+ // CXP-2723 TODO: Review this in relation to removing status from the hook
33
+ export const isPreviewableStatus = (cardStatus, {
34
+ isPreviewable,
35
+ hasPreview,
36
+ isSupportedByBrowser
37
+ }) => {
38
+ return hasPreview && isPreviewable && (cardStatus === 'complete' || cardStatus === 'loading-preview' || cardStatus === 'uploading' ||
39
+ // For Video, we can have local or remote preview while processing.
40
+ // Then, we only want to show the thumbnail if the file is supported by the browser,
41
+ // this way we prevent playing unsupported videos that are not procesed
42
+ cardStatus === 'processing' && isSupportedByBrowser);
43
+ };
@@ -0,0 +1,75 @@
1
+ import { addFileAttrsToUrl } from '@atlaskit/media-client';
2
+ import { mediaFilePreviewCache } from './cache';
3
+ import { getLocalPreview, getRemotePreview } from './helpers';
4
+ import { SsrPreviewError } from '../errors';
5
+ const extendAndCachePreview = (id, mode, preview, mediaBlobUrlAttrs) => {
6
+ let source;
7
+ switch (preview.source) {
8
+ case 'local':
9
+ source = 'cache-local';
10
+ break;
11
+ case 'remote':
12
+ source = 'cache-remote';
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
+ default:
21
+ source = preview.source;
22
+ }
23
+ // We want to embed some meta context into dataURI for Copy/Paste to work.
24
+ const dataURI = mediaBlobUrlAttrs ? addFileAttrsToUrl(preview.dataURI, mediaBlobUrlAttrs) : preview.dataURI;
25
+ // We store new cardPreview into cache
26
+ mediaFilePreviewCache.set(id, mode, {
27
+ ...preview,
28
+ source,
29
+ dataURI
30
+ });
31
+ return {
32
+ ...preview,
33
+ dataURI
34
+ };
35
+ };
36
+ export const getSSRCardPreview = (ssr, mediaClient, id, params, mediaBlobUrlAttrs) => {
37
+ let dataURI;
38
+ try {
39
+ const rawDataURI = mediaClient.getImageUrlSync(id, params);
40
+ // We want to embed some meta context into dataURI for Copy/Paste to work.
41
+ dataURI = mediaBlobUrlAttrs ? addFileAttrsToUrl(rawDataURI, mediaBlobUrlAttrs) : rawDataURI;
42
+ const source = ssr === 'client' ? 'ssr-client' : 'ssr-server';
43
+ return {
44
+ dataURI,
45
+ source,
46
+ orientation: 1
47
+ };
48
+ } catch (e) {
49
+ const reason = ssr === 'server' ? 'ssr-server-uri' : 'ssr-client-uri';
50
+ throw new SsrPreviewError(reason, e instanceof Error ? e : undefined);
51
+ }
52
+ };
53
+ export const isLocalPreview = preview => {
54
+ const localSources = ['local', 'cache-local'];
55
+ return localSources.includes(preview.source);
56
+ };
57
+ export const isSSRClientPreview = preview => {
58
+ const ssrClientSources = ['ssr-client', 'cache-ssr-client'];
59
+ return ssrClientSources.includes(preview.source);
60
+ };
61
+ export const isSSRDataPreview = preview => preview.source === 'ssr-data';
62
+ export const getAndCacheRemotePreview = async (mediaClient, id, dimensions, params, mediaBlobUrlAttrs, traceContext) => {
63
+ const remotePreview = await getRemotePreview(mediaClient, id, params, traceContext);
64
+ return extendAndCachePreview(id, params.mode, {
65
+ ...remotePreview,
66
+ dimensions
67
+ }, mediaBlobUrlAttrs);
68
+ };
69
+ export const getAndCacheLocalPreview = async (id, filePreview, dimensions, mode, mediaBlobUrlAttrs) => {
70
+ const localPreview = await getLocalPreview(filePreview);
71
+ return extendAndCachePreview(id, mode, {
72
+ ...localPreview,
73
+ dimensions
74
+ }, mediaBlobUrlAttrs);
75
+ };
@@ -0,0 +1,76 @@
1
+ import { takeSnapshot } from './videoSnapshot';
2
+ import { getMediaTypeFromMimeType } from '@atlaskit/media-common';
3
+ import { getOrientation } from '@atlaskit/media-ui';
4
+ import { LocalPreviewError, RemotePreviewError } from '../errors';
5
+ /**
6
+ * This method tells the support for the media
7
+ * types covered in getCardPreviewFromFilePreview
8
+ */
9
+ export const isSupportedLocalPreview = mediaType => mediaType === 'image' || mediaType === 'video';
10
+ const getImageLocalPreview = async value => {
11
+ try {
12
+ const orientation = await getOrientation(value);
13
+ const dataURI = URL.createObjectURL(value);
14
+ return {
15
+ dataURI,
16
+ orientation,
17
+ source: 'local'
18
+ };
19
+ } catch (e) {
20
+ throw new LocalPreviewError('local-preview-image', e instanceof Error ? e : undefined);
21
+ }
22
+ };
23
+ const getVideoLocalPreview = async value => {
24
+ try {
25
+ const dataURI = await takeSnapshot(value);
26
+ return {
27
+ dataURI,
28
+ orientation: 1,
29
+ source: 'local'
30
+ };
31
+ } catch (e) {
32
+ throw new LocalPreviewError('local-preview-video', e instanceof Error ? e : undefined);
33
+ }
34
+ };
35
+ export const getLocalPreview = async filePreview => {
36
+ let value;
37
+ try {
38
+ const resolvedFilePreview = await filePreview;
39
+ value = resolvedFilePreview.value;
40
+ } catch (e) {
41
+ throw new LocalPreviewError('local-preview-rejected', e instanceof Error ? e : undefined);
42
+ }
43
+ if (typeof value === 'string') {
44
+ return {
45
+ dataURI: value,
46
+ orientation: 1,
47
+ source: 'local'
48
+ };
49
+ } else if (value instanceof Blob) {
50
+ const {
51
+ type
52
+ } = value;
53
+ const mediaType = getMediaTypeFromMimeType(type);
54
+ switch (mediaType) {
55
+ case 'image':
56
+ return getImageLocalPreview(value);
57
+ case 'video':
58
+ return getVideoLocalPreview(value);
59
+ default:
60
+ throw new LocalPreviewError('local-preview-unsupported');
61
+ }
62
+ }
63
+ throw new LocalPreviewError('local-preview-unsupported');
64
+ };
65
+ export const getRemotePreview = async (mediaClient, id, params, traceContext) => {
66
+ try {
67
+ const blob = await mediaClient.getImage(id, params, undefined, undefined, traceContext);
68
+ return {
69
+ dataURI: URL.createObjectURL(blob),
70
+ orientation: 1,
71
+ source: 'remote'
72
+ };
73
+ } catch (e) {
74
+ throw new RemotePreviewError('remote-preview-fetch', e instanceof Error ? e : undefined);
75
+ }
76
+ };
@@ -0,0 +1,3 @@
1
+ export { mediaFilePreviewCache } from './cache';
2
+ export { isPreviewableStatus, extractFilePreviewStatus } from './filePreviewStatus';
3
+ export { getSSRCardPreview, isLocalPreview, isSSRClientPreview, isSSRDataPreview, getAndCacheRemotePreview, getAndCacheLocalPreview } from './getPreview';
@@ -0,0 +1,44 @@
1
+ import { LRUMap } from 'lru_map';
2
+ import { EventEmitter2 } from 'eventemitter2';
3
+ export const PREVIEW_CACHE_LRU_SIZE = 50;
4
+ class ExtendedLRUCache extends LRUMap {
5
+ constructor(limit) {
6
+ super(limit);
7
+ this.eventEmitter = new EventEmitter2();
8
+ }
9
+ shift() {
10
+ const entry = super.shift();
11
+ this.eventEmitter.emit('shift', entry);
12
+ return entry;
13
+ }
14
+ on(event, callback) {
15
+ this.eventEmitter.on(event, callback);
16
+ }
17
+ }
18
+ export class ObjectURLCache {
19
+ constructor(size) {
20
+ this.cache = new ExtendedLRUCache(size);
21
+ this.cache.on('shift', entry => {
22
+ if (entry && entry[1].dataURI) {
23
+ URL.revokeObjectURL(entry[1].dataURI);
24
+ }
25
+ });
26
+ }
27
+ has(key) {
28
+ return !!this.cache.find(key);
29
+ }
30
+ get(key) {
31
+ return this.cache.get(key);
32
+ }
33
+ set(key, value) {
34
+ this.cache.set(key, value);
35
+ }
36
+ remove(key) {
37
+ const removed = this.cache.delete(key);
38
+ removed && URL.revokeObjectURL(removed.dataURI);
39
+ }
40
+ clear() {
41
+ this.cache.clear();
42
+ }
43
+ }
44
+ export const createObjectURLCache = () => new ObjectURLCache(PREVIEW_CACHE_LRU_SIZE);
@@ -0,0 +1,36 @@
1
+ export const takeSnapshot = async blob => {
2
+ return new Promise((resolve, reject) => {
3
+ const url = URL.createObjectURL(blob);
4
+ const video = document.createElement('video');
5
+ video.preload = 'metadata';
6
+ video.src = url;
7
+ video.muted = true;
8
+ video.play().catch(() => {
9
+ return reject(new Error('failed to play video'));
10
+ });
11
+ video.addEventListener('timeupdate', function timeUpdateHandler() {
12
+ video.removeEventListener('timeupdate', timeUpdateHandler);
13
+ video.pause();
14
+ URL.revokeObjectURL(url);
15
+ //create canvas to draw our first frame on.
16
+
17
+ if (!video.videoWidth && !video.videoHeight) {
18
+ return reject(new Error('error retrieving video dimensions'));
19
+ }
20
+ const canvas = document.createElement('canvas');
21
+ canvas.width = video.videoWidth;
22
+ canvas.height = video.videoHeight;
23
+ const context = canvas.getContext('2d');
24
+ if (!context) {
25
+ return reject(new Error('error creating canvas context'));
26
+ }
27
+ context.drawImage(video, 0, 0, canvas.width, canvas.height);
28
+ const dataURL = canvas.toDataURL('image/jpeg', 0.85);
29
+ resolve(dataURL);
30
+ });
31
+ video.addEventListener('error', () => {
32
+ reject(new Error('failed to load video'));
33
+ URL.revokeObjectURL(url);
34
+ });
35
+ });
36
+ };
@@ -0,0 +1,8 @@
1
+ import { getMediaCardSSR, getKey } from './globalScope';
2
+ export const getSSRData = identifier => {
3
+ const mediaCardSsr = getMediaCardSSR();
4
+ if (!mediaCardSsr) {
5
+ return;
6
+ }
7
+ return mediaCardSsr[getKey(identifier)];
8
+ };
@@ -0,0 +1,48 @@
1
+ import { printFunctionCall, printScript } from './printScript';
2
+ // ----- WARNING -----
3
+ // This is a very sensitive fraction of code.
4
+ // Any changes to this file must be tested directly in product before merging.
5
+ // The scripts printed here might differ from what we observe in our internal tests
6
+ // due to minimification, for example.
7
+ export const GLOBAL_MEDIA_CARD_SSR = 'mediaCardSsr';
8
+ export const GLOBAL_MEDIA_NAMESPACE = '__MEDIA_INTERNAL';
9
+ export function getMediaGlobalScope(globalScope = window) {
10
+ // Must match GLOBAL_MEDIA_NAMESPACE. Can't reference the constant from here.
11
+ const namespace = '__MEDIA_INTERNAL';
12
+ if (!globalScope[namespace]) {
13
+ globalScope[namespace] = {};
14
+ }
15
+ return globalScope[namespace];
16
+ }
17
+ export function getMediaCardSSR(globalScope = window) {
18
+ const globalMedia = getMediaGlobalScope(globalScope);
19
+ // Must match GLOBAL_MEDIA_CARD_SSR. Can't reference the constant from here.
20
+ const key = 'mediaCardSsr';
21
+ if (!globalMedia[key]) {
22
+ globalMedia[key] = {};
23
+ }
24
+ return globalMedia[key];
25
+ }
26
+ const dashed = param => param ? `-${param}` : '';
27
+ export const getKey = ({
28
+ id,
29
+ collectionName,
30
+ occurrenceKey
31
+ }) => `${id}${dashed(collectionName)}${dashed(occurrenceKey)}`;
32
+ export const storeDataURI = (key, dataURI, dimensions, error, globalScope = window) => {
33
+ const mediaCardSsr = getMediaCardSSR(globalScope);
34
+ mediaCardSsr[key] = {
35
+ dataURI,
36
+ dimensions,
37
+ error
38
+ };
39
+ };
40
+ const generateScript = (identifier, dataURI, dimensions, error) => {
41
+ const functionCall = printFunctionCall(storeDataURI, getKey(identifier), dataURI, dimensions, error);
42
+ return printScript([getMediaCardSSR.toString(), getMediaGlobalScope.toString(), functionCall]);
43
+ };
44
+ export const generateScriptProps = (identifier, dataURI, dimensions, error) => ({
45
+ dangerouslySetInnerHTML: {
46
+ __html: generateScript(identifier, dataURI, dimensions, error)
47
+ }
48
+ });
@@ -0,0 +1,2 @@
1
+ export { GLOBAL_MEDIA_NAMESPACE, GLOBAL_MEDIA_CARD_SSR, generateScriptProps, getKey } from './globalScope';
2
+ export { getSSRData } from './getSSRData';
@@ -0,0 +1,16 @@
1
+ const printParam = param => {
2
+ if (typeof param === 'string') {
3
+ return `'${param}'`;
4
+ } else if (typeof param === 'object') {
5
+ return JSON.stringify(param);
6
+ } else if (param === undefined) {
7
+ return 'undefined';
8
+ }
9
+ return param;
10
+ };
11
+ const printParams = args => args.map(arg => printParam(arg)).join(',');
12
+ export const printFunctionCall = (fn, ...args) => `(${fn.toString()})(${printParams(args)});`;
13
+ export const printScript = statements => `(function(){
14
+ ${statements.join(';')}
15
+ })();
16
+ `;
@@ -0,0 +1,61 @@
1
+ import { useRef, useEffect } from 'react';
2
+
3
+ /**
4
+ * Checks if at least one of next dimensions is bigger than current
5
+ * If a single dimension is undefined, returns false
6
+ */
7
+ export const isBigger = (current, next) => {
8
+ const {
9
+ width: currentWidth,
10
+ height: currentHeight
11
+ } = current || {};
12
+ const {
13
+ width: nextWidth,
14
+ height: nextHeight
15
+ } = next || {};
16
+ if (!!currentWidth && !!currentHeight && !!nextWidth && !!nextHeight) {
17
+ const nextIsWider = currentWidth < nextWidth;
18
+ const nextIsHigher = currentHeight < nextHeight;
19
+ return nextIsHigher || nextIsWider;
20
+ } else {
21
+ return false;
22
+ }
23
+ };
24
+
25
+ /** Verifies if the current screen is retina display */
26
+ function isRetina() {
27
+ const mediaQuery = '(-webkit-min-device-pixel-ratio: 1.5), (min--moz-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3/2), (min-resolution: 1.5dppx)';
28
+ return window.devicePixelRatio > 1 || window.matchMedia && window.matchMedia(mediaQuery).matches;
29
+ }
30
+ export const createRequestDimensions = dimensions => {
31
+ if (!dimensions) {
32
+ return;
33
+ }
34
+ const retinaFactor = isRetina() ? 2 : 1;
35
+ const {
36
+ width,
37
+ height
38
+ } = dimensions;
39
+ const result = {};
40
+ if (width) {
41
+ result.width = width * retinaFactor;
42
+ }
43
+ if (height) {
44
+ result.height = height * retinaFactor;
45
+ }
46
+ return result;
47
+ };
48
+
49
+ /** Stores the provided value in a */
50
+ export function useCurrentValueRef(value) {
51
+ const ref = useRef(value);
52
+ ref.current = value;
53
+ return ref;
54
+ }
55
+ export function usePrevious(value) {
56
+ const ref = useRef();
57
+ useEffect(() => {
58
+ ref.current = value;
59
+ }, [value]);
60
+ return ref.current;
61
+ }
@@ -0,0 +1 @@
1
+ export { useFilePreview } from './useFilePreview';
@@ -0,0 +1 @@
1
+ export {};
@@ -1,18 +1,12 @@
1
- import { addFileAttrsToUrl, imageResizeModeToFileImageMode, isImageRepresentationReady } from '@atlaskit/media-client';
1
+ import { imageResizeModeToFileImageMode, isImageRepresentationReady } from '@atlaskit/media-client';
2
2
  import { MediaFileStateError, useFileState, useMediaClient } from '@atlaskit/media-client-react';
3
- import { getMediaTypeFromMimeType, isMimeTypeSupportedByBrowser } from '@atlaskit/media-common';
4
- import { getOrientation } from '@atlaskit/media-ui';
3
+ import { isMimeTypeSupportedByBrowser } from '@atlaskit/media-common';
5
4
  import { useEffect, useMemo, useRef, useState } from 'react';
6
- import { ensureMediaCardError, ImageLoadError, isLocalPreviewError, isUnsupportedLocalPreviewError, LocalPreviewError, MediaCardError } from '../../errors';
7
- import { extractErrorInfo } from '../../utils/analytics';
8
- import { isBigger } from '../../utils/dimensionComparer';
9
- import { isRetina } from '../../utils/isRetina';
10
- import { generateScriptProps, getSSRData } from '../../utils/globalScope';
11
- import { useCurrentValueRef } from '../../utils/useCurrentValueRef';
12
- import { usePrevious } from '../../utils/usePrevious';
13
- import { takeSnapshot } from '../../utils/videoSnapshot';
14
- import { fetchAndCacheRemotePreview, getCardPreviewFromCache, getSSRCardPreview, isLocalPreview, isSSRClientPreview, isSSRDataPreview, removeCardPreviewFromCache, shouldResolvePreview } from '../getCardPreview';
15
- import cardPreviewCache from '../getCardPreview/cache';
5
+ import { ensureMediaFilePreviewError, ImageLoadError, isLocalPreviewError, isUnsupportedLocalPreviewError, MediaFilePreviewError } from './errors';
6
+ import { extractErrorInfo } from '../../../utils/analytics';
7
+ import { isBigger, createRequestDimensions, useCurrentValueRef, usePrevious } from './helpers';
8
+ import { generateScriptProps, getSSRData } from './globalScope';
9
+ import { getAndCacheRemotePreview, getSSRCardPreview, isLocalPreview, isSSRClientPreview, isSSRDataPreview, isPreviewableStatus, extractFilePreviewStatus, mediaFilePreviewCache, getAndCacheLocalPreview } from './getPreview';
16
10
  export const useFilePreview = ({
17
11
  resizeMode = 'crop',
18
12
  identifier,
@@ -72,7 +66,7 @@ export const useFilePreview = ({
72
66
  id
73
67
  } = identifier;
74
68
  const fileImageMode = imageResizeModeToFileImageMode(resizeMode);
75
- cardPreview = getCardPreviewFromCache(id, fileImageMode);
69
+ cardPreview = mediaFilePreviewCache.get(id, fileImageMode);
76
70
  if (!cardPreview && ssr) {
77
71
  cardPreview = getSSRPreview(ssr, identifier, mediaClient);
78
72
  }
@@ -95,104 +89,22 @@ export const useFilePreview = ({
95
89
  //----------------------------------------------------------------//
96
90
 
97
91
  const fetchRemotePreviewRef = useCurrentValueRef(identifier => {
98
- return fetchAndCacheRemotePreview(mediaClient, identifier.id, requestDimensions || {}, imageURLParams, mediaBlobUrlAttrs, traceContext);
92
+ return getAndCacheRemotePreview(mediaClient, identifier.id, requestDimensions || {}, imageURLParams, mediaBlobUrlAttrs, traceContext);
99
93
  });
100
94
  const resolvePreviewRef = useCurrentValueRef(async (identifier, fileState) => {
101
95
  const filePreview = isBannedLocalPreview ? undefined : fileState.status !== 'error' && 'mimeType' in fileState && isMimeTypeSupportedByBrowser(fileState.mimeType) ? fileState.preview : undefined;
102
96
  const isRemotePreviewReady = isImageRepresentationReady(fileState);
103
97
  try {
104
98
  const mode = imageURLParams.mode;
105
- const cachedPreview = cardPreviewCache.get(identifier.id, mode);
99
+ const cachedPreview = mediaFilePreviewCache.get(identifier.id, mode);
106
100
  const dimensionsAreBigger = isBigger(cachedPreview === null || cachedPreview === void 0 ? void 0 : cachedPreview.dimensions, requestDimensions);
107
101
  if (cachedPreview && !dimensionsAreBigger) {
108
102
  return cachedPreview;
109
103
  }
110
- let localPreview;
111
104
  try {
112
105
  if (filePreview) {
113
- let value;
114
- try {
115
- const resolvedFilePreview = await filePreview;
116
- value = resolvedFilePreview.value;
117
- } catch (e) {
118
- throw new LocalPreviewError('local-preview-rejected', e instanceof Error ? e : undefined);
119
- }
120
- if (typeof value === 'string') {
121
- localPreview = {
122
- dataURI: value,
123
- orientation: 1,
124
- source: 'local'
125
- };
126
- } else if (value instanceof Blob) {
127
- const {
128
- type
129
- } = value;
130
- const mediaType = getMediaTypeFromMimeType(type);
131
- switch (mediaType) {
132
- case 'image':
133
- try {
134
- const orientation = await getOrientation(value);
135
- const dataURI = URL.createObjectURL(value);
136
- localPreview = {
137
- dataURI,
138
- orientation,
139
- source: 'local'
140
- };
141
- } catch (e) {
142
- throw new LocalPreviewError('local-preview-image', e instanceof Error ? e : undefined);
143
- }
144
- break;
145
- case 'video':
146
- try {
147
- const dataURI = await takeSnapshot(value);
148
- localPreview = {
149
- dataURI,
150
- orientation: 1,
151
- source: 'local'
152
- };
153
- } catch (e) {
154
- throw new LocalPreviewError('local-preview-video', e instanceof Error ? e : undefined);
155
- }
156
- break;
157
- default:
158
- throw new LocalPreviewError('local-preview-unsupported');
159
- }
160
- } else {
161
- throw new LocalPreviewError('local-preview-unsupported');
162
- }
163
- const preview = {
164
- ...localPreview,
165
- dimensions: requestDimensions
166
- };
167
- let source;
168
- switch (preview.source) {
169
- case 'local':
170
- source = 'cache-local';
171
- break;
172
- case 'remote':
173
- source = 'cache-remote';
174
- break;
175
- case 'ssr-server':
176
- source = 'cache-ssr-server';
177
- break;
178
- case 'ssr-client':
179
- source = 'cache-ssr-client';
180
- break;
181
- default:
182
- source = preview.source;
183
- }
184
- // We want to embed some meta context into dataURI for Copy/Paste to work.
185
- const dataURI = mediaBlobUrlAttrs ? addFileAttrsToUrl(preview.dataURI, mediaBlobUrlAttrs) : preview.dataURI;
186
- // We store new cardPreview into cache
187
- cardPreviewCache.set(identifier.id, mode, {
188
- ...preview,
189
- source,
190
- dataURI
191
- });
192
- setCardPreview({
193
- ...preview,
194
- dataURI
195
- });
106
+ const localPreview = await getAndCacheLocalPreview(identifier.id, filePreview, requestDimensions || {}, mode, mediaBlobUrlAttrs);
107
+ setCardPreview(localPreview);
196
108
  return;
197
109
  }
198
110
  } catch (e) {
@@ -225,13 +137,13 @@ export const useFilePreview = ({
225
137
  * If remote preview is not ready, the call to getCardPreviewFromBackend
226
138
  * will generate a console error due to a 404 code
227
139
  */
228
- throw new MediaCardError('remote-preview-not-ready');
140
+ throw new MediaFilePreviewError('remote-preview-not-ready');
229
141
  }
230
142
  const remotePreview = await fetchRemotePreviewRef.current(identifier);
231
143
  setCardPreview(remotePreview);
232
144
  return;
233
145
  } catch (e) {
234
- const wrappedError = ensureMediaCardError('preview-fetch', e);
146
+ const wrappedError = ensureMediaFilePreviewError('preview-fetch', e);
235
147
  // If remote preview fails, we set status 'error'
236
148
  // If local preview fails (i.e, no remote preview available),
237
149
  // we can stay in the same status until there is a remote preview available
@@ -293,7 +205,7 @@ export const useFilePreview = ({
293
205
  // refetchSRRPreview: If dimensions from Server have changed and are bigger,
294
206
  // we need to refetch
295
207
  fetchRemotePreviewRef.current(identifier).then(setCardPreview).catch(e => {
296
- const wrappedError = ensureMediaCardError('remote-preview-fetch-ssr', e, true);
208
+ const wrappedError = ensureMediaFilePreviewError('remote-preview-fetch-ssr', e, true);
297
209
  setNonCriticalError(wrappedError);
298
210
  });
299
211
  }
@@ -301,15 +213,7 @@ export const useFilePreview = ({
301
213
  // Both compare dimensions, but the above is only for SSR in order to refetchSRRPreview and
302
214
  // will swallow any errors. Below logic only applies when there is no card preview or the dimensions
303
215
  // are bigger.
304
- if (fileState && shouldResolvePreview({
305
- status,
306
- fileState: fileState,
307
- prevDimensions: prevRequestDimensions,
308
- dimensions: requestDimensions,
309
- hasCardPreview: !!cardPreview,
310
- isBannedLocalPreview,
311
- wasResolvedUpfrontPreview: wasResolvedUpfrontPreviewRef.current
312
- })) {
216
+ if (fileState && wasResolvedUpfrontPreviewRef.current && isPreviewableStatus(status, extractFilePreviewStatus(fileState, isBannedLocalPreview)) && (!cardPreview || isBigger(prevRequestDimensions, requestDimensions))) {
313
217
  resolvePreviewRef.current(identifier, fileState);
314
218
  }
315
219
  if (!skipRemote && ssr && !!cardPreview && isSSRClientPreview(cardPreview)) {
@@ -379,7 +283,7 @@ export const useFilePreview = ({
379
283
  } else {
380
284
  const e = new MediaFileStateError(fileState.id, fileState.reason, fileState.message, fileState.details);
381
285
  const errorReason = status === 'uploading' ? 'upload' : 'metadata-fetch';
382
- setError(new MediaCardError(errorReason, e));
286
+ setError(new MediaFilePreviewError(errorReason, e));
383
287
  setStatus('error');
384
288
  }
385
289
  }
@@ -420,7 +324,7 @@ export const useFilePreview = ({
420
324
  setNonCriticalError(error);
421
325
  }
422
326
  const fileImageMode = imageResizeModeToFileImageMode(resizeMode);
423
- removeCardPreviewFromCache(identifier.id, fileImageMode);
327
+ mediaFilePreviewCache.remove(identifier.id, fileImageMode);
424
328
  setCardPreview(undefined);
425
329
  } else {
426
330
  if (!['complete', 'error', 'failed-processing'].includes(status)) {
@@ -479,24 +383,6 @@ export const useFilePreview = ({
479
383
  getScriptProps
480
384
  };
481
385
  };
482
- const createRequestDimensions = dimensions => {
483
- if (!dimensions) {
484
- return;
485
- }
486
- const retinaFactor = isRetina() ? 2 : 1;
487
- const {
488
- width,
489
- height
490
- } = dimensions;
491
- const result = {};
492
- if (width) {
493
- result.width = width * retinaFactor;
494
- }
495
- if (height) {
496
- result.height = height * retinaFactor;
497
- }
498
- return result;
499
- };
500
386
  const initialSsrReliability = {
501
387
  server: {
502
388
  status: 'unknown'
@@ -37,7 +37,7 @@ export default class MediaInlineCardLoader extends React.PureComponent {
37
37
  } = this.state;
38
38
  const analyticsContext = {
39
39
  packageVersion: "@atlaskit/media-card",
40
- packageName: "77.5.0",
40
+ packageName: "77.5.2",
41
41
  componentName: 'mediaInlineCard',
42
42
  component: 'mediaInlineCard'
43
43
  };