@atlaskit/media-file-preview 0.16.2 → 0.16.4
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 +16 -0
- package/dist/cjs/getPreview/cache.js +8 -0
- package/dist/cjs/getPreview/getPreview.js +102 -23
- package/dist/cjs/getPreview/objectURLCache.js +73 -20
- package/dist/cjs/useFilePreview.js +36 -77
- package/dist/es2019/getPreview/cache.js +8 -0
- package/dist/es2019/getPreview/getPreview.js +56 -7
- package/dist/es2019/getPreview/objectURLCache.js +60 -14
- package/dist/es2019/useFilePreview.js +19 -59
- package/dist/esm/getPreview/cache.js +8 -0
- package/dist/esm/getPreview/getPreview.js +102 -23
- package/dist/esm/getPreview/objectURLCache.js +73 -20
- package/dist/esm/useFilePreview.js +37 -78
- package/dist/types/getPreview/cache.d.ts +4 -0
- package/dist/types/getPreview/getPreview.d.ts +1 -1
- package/dist/types/getPreview/objectURLCache.d.ts +9 -0
- package/dist/types/useFilePreview.d.ts +0 -1
- package/dist/types-ts4.5/getPreview/cache.d.ts +4 -0
- package/dist/types-ts4.5/getPreview/getPreview.d.ts +1 -1
- package/dist/types-ts4.5/getPreview/objectURLCache.d.ts +9 -0
- package/dist/types-ts4.5/useFilePreview.d.ts +0 -1
- package/package.json +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @atlaskit/media-file-preview
|
|
2
2
|
|
|
3
|
+
## 0.16.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`be94d5f05b8ae`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/be94d5f05b8ae) -
|
|
8
|
+
Fix media image blob cache to only evict blobs when they are no longer referenced
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
|
|
11
|
+
## 0.16.3
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [`fa50dabb4be8f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/fa50dabb4be8f) -
|
|
16
|
+
Retrieve clientId synchronously during Media SSR blob URL construction.
|
|
17
|
+
- Updated dependencies
|
|
18
|
+
|
|
3
19
|
## 0.16.2
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
|
@@ -34,6 +34,14 @@ var CardPreviewCacheImpl = exports.CardPreviewCacheImpl = /*#__PURE__*/(0, _crea
|
|
|
34
34
|
(0, _defineProperty2.default)(this, "clear", function () {
|
|
35
35
|
_this.previewCache.clear();
|
|
36
36
|
});
|
|
37
|
+
(0, _defineProperty2.default)(this, "acquire", function (id, mode) {
|
|
38
|
+
var cacheKey = getCacheKey(id, mode);
|
|
39
|
+
_this.previewCache.acquire(cacheKey);
|
|
40
|
+
});
|
|
41
|
+
(0, _defineProperty2.default)(this, "release", function (id, mode) {
|
|
42
|
+
var cacheKey = getCacheKey(id, mode);
|
|
43
|
+
_this.previewCache.release(cacheKey);
|
|
44
|
+
});
|
|
37
45
|
this.previewCache = previewCache;
|
|
38
46
|
});
|
|
39
47
|
var mediaFilePreviewCache = exports.mediaFilePreviewCache = new CardPreviewCacheImpl((0, _objectURLCache.createObjectURLCache)());
|
|
@@ -6,9 +6,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.isSSRPreview = exports.isSSRDataPreview = exports.isSSRClientPreview = exports.isRemotePreview = exports.isLocalPreview = exports.getSSRPreview = exports.getAndCacheRemotePreview = exports.getAndCacheLocalPreview = void 0;
|
|
8
8
|
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
9
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
9
10
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
10
11
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
11
12
|
var _mediaClient = require("@atlaskit/media-client");
|
|
13
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
12
14
|
var _errors = require("../errors");
|
|
13
15
|
var _cache = require("./cache");
|
|
14
16
|
var _helpers = require("./helpers");
|
|
@@ -41,15 +43,41 @@ var getDataUri = function getDataUri(mediaClient, id, params, mediaBlobUrlAttrs)
|
|
|
41
43
|
var rawDataURI = mediaClient.getImageUrlSync(id, params);
|
|
42
44
|
return mediaBlobUrlAttrs ? (0, _mediaClient.addFileAttrsToUrl)(rawDataURI, mediaBlobUrlAttrs) : rawDataURI;
|
|
43
45
|
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Merges a clientId into mediaBlobUrlAttrs for cross-client copy support.
|
|
49
|
+
* Returns the original attrs unchanged if clientId is not available or the feature flag is off.
|
|
50
|
+
*/
|
|
51
|
+
var mergeClientIdIntoAttrs = function mergeClientIdIntoAttrs(clientId, id, mediaBlobUrlAttrs, collectionName) {
|
|
52
|
+
if (!clientId) {
|
|
53
|
+
return mediaBlobUrlAttrs;
|
|
54
|
+
}
|
|
55
|
+
if (mediaBlobUrlAttrs) {
|
|
56
|
+
return _objectSpread(_objectSpread({}, mediaBlobUrlAttrs), {}, {
|
|
57
|
+
clientId: clientId
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Construct minimal attrs when none provided
|
|
62
|
+
return {
|
|
63
|
+
id: id,
|
|
64
|
+
clientId: clientId,
|
|
65
|
+
contextId: collectionName || '',
|
|
66
|
+
collection: collectionName
|
|
67
|
+
};
|
|
68
|
+
};
|
|
44
69
|
var getSSRPreview = exports.getSSRPreview = function getSSRPreview(ssr, mediaClient, id, params, mediaBlobUrlAttrs) {
|
|
45
70
|
try {
|
|
46
|
-
|
|
71
|
+
// Synchronously extract clientId from initialAuth and merge into blob URL attrs
|
|
72
|
+
var clientId = (0, _platformFeatureFlags.fg)('platform_media_cross_client_copy_with_auth') ? mediaClient.getClientIdSync() : undefined;
|
|
73
|
+
var attrsWithClientId = mergeClientIdIntoAttrs(clientId, id, mediaBlobUrlAttrs, params.collection);
|
|
74
|
+
var dataURI = getDataUri(mediaClient, id, params, attrsWithClientId);
|
|
47
75
|
var srcSet = "".concat(dataURI, " 1x");
|
|
48
76
|
if (params.width) {
|
|
49
77
|
var doubleDataURI = getDataUri(mediaClient, id, _objectSpread(_objectSpread({}, params), {}, {
|
|
50
78
|
width: params.width * 2,
|
|
51
79
|
height: params.height && params.height * 2
|
|
52
|
-
}),
|
|
80
|
+
}), attrsWithClientId);
|
|
53
81
|
// We want to embed some meta context into dataURI for Copy/Paste to work.
|
|
54
82
|
srcSet += ", ".concat(doubleDataURI, " 2x");
|
|
55
83
|
}
|
|
@@ -83,49 +111,100 @@ var isSSRPreview = exports.isSSRPreview = function isSSRPreview(preview) {
|
|
|
83
111
|
var ssrClientSources = ['ssr-client', 'ssr-server', 'ssr-data'];
|
|
84
112
|
return ssrClientSources.includes(preview.source);
|
|
85
113
|
};
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Resolves clientId (sync first, async fallback) and enriches mediaBlobUrlAttrs
|
|
117
|
+
* with it for cross-client copy support.
|
|
118
|
+
*/
|
|
119
|
+
var enrichAttrsWithClientId = /*#__PURE__*/function () {
|
|
120
|
+
var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(mediaClient, id, mediaBlobUrlAttrs, collectionName) {
|
|
121
|
+
var clientId;
|
|
89
122
|
return _regenerator.default.wrap(function _callee$(_context) {
|
|
90
123
|
while (1) switch (_context.prev = _context.next) {
|
|
91
124
|
case 0:
|
|
92
|
-
|
|
93
|
-
|
|
125
|
+
if ((0, _platformFeatureFlags.fg)('platform_media_cross_client_copy_with_auth')) {
|
|
126
|
+
_context.next = 2;
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
return _context.abrupt("return", mediaBlobUrlAttrs);
|
|
94
130
|
case 2:
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
131
|
+
// Try sync first, then async fallback
|
|
132
|
+
clientId = mediaClient.getClientIdSync();
|
|
133
|
+
if (clientId) {
|
|
134
|
+
_context.next = 12;
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
_context.prev = 4;
|
|
138
|
+
_context.next = 7;
|
|
139
|
+
return mediaClient.getClientId(collectionName);
|
|
140
|
+
case 7:
|
|
141
|
+
clientId = _context.sent;
|
|
142
|
+
_context.next = 12;
|
|
143
|
+
break;
|
|
144
|
+
case 10:
|
|
145
|
+
_context.prev = 10;
|
|
146
|
+
_context.t0 = _context["catch"](4);
|
|
147
|
+
case 12:
|
|
148
|
+
return _context.abrupt("return", mergeClientIdIntoAttrs(clientId, id, mediaBlobUrlAttrs, collectionName));
|
|
149
|
+
case 13:
|
|
100
150
|
case "end":
|
|
101
151
|
return _context.stop();
|
|
102
152
|
}
|
|
103
|
-
}, _callee);
|
|
153
|
+
}, _callee, null, [[4, 10]]);
|
|
104
154
|
}));
|
|
105
|
-
return function
|
|
155
|
+
return function enrichAttrsWithClientId(_x, _x2, _x3, _x4) {
|
|
106
156
|
return _ref.apply(this, arguments);
|
|
107
157
|
};
|
|
108
158
|
}();
|
|
109
|
-
var
|
|
110
|
-
var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(
|
|
111
|
-
var
|
|
159
|
+
var getAndCacheRemotePreview = exports.getAndCacheRemotePreview = /*#__PURE__*/function () {
|
|
160
|
+
var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(mediaClient, id, dimensions, params, mediaBlobUrlAttrs, traceContext) {
|
|
161
|
+
var _yield$Promise$all, _yield$Promise$all2, remotePreview, enrichedAttrs;
|
|
112
162
|
return _regenerator.default.wrap(function _callee2$(_context2) {
|
|
113
163
|
while (1) switch (_context2.prev = _context2.next) {
|
|
114
164
|
case 0:
|
|
115
165
|
_context2.next = 2;
|
|
116
|
-
return (0, _helpers.
|
|
166
|
+
return Promise.all([(0, _helpers.getRemotePreview)(mediaClient, id, params, traceContext), enrichAttrsWithClientId(mediaClient, id, mediaBlobUrlAttrs, params.collection)]);
|
|
117
167
|
case 2:
|
|
118
|
-
|
|
119
|
-
|
|
168
|
+
_yield$Promise$all = _context2.sent;
|
|
169
|
+
_yield$Promise$all2 = (0, _slicedToArray2.default)(_yield$Promise$all, 2);
|
|
170
|
+
remotePreview = _yield$Promise$all2[0];
|
|
171
|
+
enrichedAttrs = _yield$Promise$all2[1];
|
|
172
|
+
return _context2.abrupt("return", extendAndCachePreview(id, params.mode, _objectSpread(_objectSpread({}, remotePreview), {}, {
|
|
120
173
|
dimensions: dimensions
|
|
121
|
-
}),
|
|
122
|
-
case
|
|
174
|
+
}), enrichedAttrs));
|
|
175
|
+
case 7:
|
|
123
176
|
case "end":
|
|
124
177
|
return _context2.stop();
|
|
125
178
|
}
|
|
126
179
|
}, _callee2);
|
|
127
180
|
}));
|
|
128
|
-
return function
|
|
181
|
+
return function getAndCacheRemotePreview(_x5, _x6, _x7, _x8, _x9, _x0) {
|
|
129
182
|
return _ref2.apply(this, arguments);
|
|
130
183
|
};
|
|
184
|
+
}();
|
|
185
|
+
var getAndCacheLocalPreview = exports.getAndCacheLocalPreview = /*#__PURE__*/function () {
|
|
186
|
+
var _ref3 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(mediaClient, id, filePreview, dimensions, mode, mediaBlobUrlAttrs, collectionName) {
|
|
187
|
+
var _yield$Promise$all3, _yield$Promise$all4, localPreview, enrichedAttrs;
|
|
188
|
+
return _regenerator.default.wrap(function _callee3$(_context3) {
|
|
189
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
190
|
+
case 0:
|
|
191
|
+
_context3.next = 2;
|
|
192
|
+
return Promise.all([(0, _helpers.getLocalPreview)(filePreview), enrichAttrsWithClientId(mediaClient, id, mediaBlobUrlAttrs, collectionName)]);
|
|
193
|
+
case 2:
|
|
194
|
+
_yield$Promise$all3 = _context3.sent;
|
|
195
|
+
_yield$Promise$all4 = (0, _slicedToArray2.default)(_yield$Promise$all3, 2);
|
|
196
|
+
localPreview = _yield$Promise$all4[0];
|
|
197
|
+
enrichedAttrs = _yield$Promise$all4[1];
|
|
198
|
+
return _context3.abrupt("return", extendAndCachePreview(id, mode, _objectSpread(_objectSpread({}, localPreview), {}, {
|
|
199
|
+
dimensions: dimensions
|
|
200
|
+
}), enrichedAttrs));
|
|
201
|
+
case 7:
|
|
202
|
+
case "end":
|
|
203
|
+
return _context3.stop();
|
|
204
|
+
}
|
|
205
|
+
}, _callee3);
|
|
206
|
+
}));
|
|
207
|
+
return function getAndCacheLocalPreview(_x1, _x10, _x11, _x12, _x13, _x14, _x15) {
|
|
208
|
+
return _ref3.apply(this, arguments);
|
|
209
|
+
};
|
|
131
210
|
}();
|
|
@@ -5,52 +5,103 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
7
|
exports.createObjectURLCache = exports.PREVIEW_CACHE_LRU_SIZE = exports.ObjectURLCache = void 0;
|
|
8
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
8
9
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
9
10
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
10
11
|
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
|
|
11
12
|
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
|
|
12
13
|
var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));
|
|
13
14
|
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
|
|
14
|
-
var _eventemitter = require("eventemitter2");
|
|
15
15
|
var _lru_map = require("lru_map");
|
|
16
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
16
17
|
function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); }
|
|
17
18
|
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
|
|
18
19
|
function _superPropGet(t, o, e, r) { var p = (0, _get2.default)((0, _getPrototypeOf2.default)(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; }
|
|
19
20
|
var PREVIEW_CACHE_LRU_SIZE = exports.PREVIEW_CACHE_LRU_SIZE = 50;
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
/**
|
|
22
|
+
* LRU cache that checks whether the oldest entry should be evicted
|
|
23
|
+
* this means that the cache can grow past the softLimit if `shouldEvict` returns false.
|
|
24
|
+
*
|
|
25
|
+
* When `platform_media_safe_blob_url_eviction` is ON the oldest
|
|
26
|
+
* entry is kept if `shouldEvict` returns false.
|
|
27
|
+
* When the flag is OFF the oldest entry is always evicted.
|
|
28
|
+
*/
|
|
29
|
+
var EvictionLRUCache = /*#__PURE__*/function (_LRUMap) {
|
|
30
|
+
function EvictionLRUCache(softLimit, options) {
|
|
22
31
|
var _this;
|
|
23
|
-
(0, _classCallCheck2.default)(this,
|
|
24
|
-
_this = _callSuper(this,
|
|
25
|
-
_this.
|
|
32
|
+
(0, _classCallCheck2.default)(this, EvictionLRUCache);
|
|
33
|
+
_this = _callSuper(this, EvictionLRUCache, [softLimit]);
|
|
34
|
+
_this.shouldEvict = options === null || options === void 0 ? void 0 : options.shouldEvict;
|
|
35
|
+
_this.onEvict = options === null || options === void 0 ? void 0 : options.onEvict;
|
|
26
36
|
return _this;
|
|
27
37
|
}
|
|
28
|
-
(0, _inherits2.default)(
|
|
29
|
-
return (0, _createClass2.default)(
|
|
38
|
+
(0, _inherits2.default)(EvictionLRUCache, _LRUMap);
|
|
39
|
+
return (0, _createClass2.default)(EvictionLRUCache, [{
|
|
30
40
|
key: "shift",
|
|
31
41
|
value: function shift() {
|
|
32
|
-
|
|
33
|
-
|
|
42
|
+
if ((0, _platformFeatureFlags.fg)('platform_media_safe_blob_url_eviction')) {
|
|
43
|
+
var oldest = this.oldest;
|
|
44
|
+
if (oldest && this.shouldEvict && !this.shouldEvict([oldest.key, oldest.value])) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
var entry = _superPropGet(EvictionLRUCache, "shift", this, 3)([]);
|
|
49
|
+
if (entry && this.onEvict) {
|
|
50
|
+
this.onEvict(entry);
|
|
51
|
+
}
|
|
34
52
|
return entry;
|
|
35
53
|
}
|
|
36
|
-
}, {
|
|
37
|
-
key: "on",
|
|
38
|
-
value: function on(event, callback) {
|
|
39
|
-
this.eventEmitter.on(event, callback);
|
|
40
|
-
}
|
|
41
54
|
}]);
|
|
42
55
|
}(_lru_map.LRUMap);
|
|
43
56
|
var ObjectURLCache = exports.ObjectURLCache = /*#__PURE__*/function () {
|
|
44
57
|
function ObjectURLCache(size) {
|
|
58
|
+
var _this2 = this;
|
|
45
59
|
(0, _classCallCheck2.default)(this, ObjectURLCache);
|
|
46
|
-
this
|
|
47
|
-
this.cache
|
|
48
|
-
|
|
49
|
-
|
|
60
|
+
(0, _defineProperty2.default)(this, "activeRefs", new Map());
|
|
61
|
+
this.cache = new EvictionLRUCache(size, {
|
|
62
|
+
shouldEvict: function shouldEvict(entry) {
|
|
63
|
+
return !_this2.isInUse(entry[0]);
|
|
64
|
+
},
|
|
65
|
+
onEvict: function onEvict(entry) {
|
|
66
|
+
if (entry[1].dataURI) {
|
|
67
|
+
var dataURI = (0, _platformFeatureFlags.fg)('platform_media_safe_blob_url_eviction') ? entry[1].dataURI.split('#')[0] : entry[1].dataURI;
|
|
68
|
+
if (dataURI) {
|
|
69
|
+
URL.revokeObjectURL(dataURI);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
50
72
|
}
|
|
51
73
|
});
|
|
52
74
|
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Marks a cache key as actively in use by a consumer.
|
|
78
|
+
* Multiple consumers can acquire the same key; eviction is
|
|
79
|
+
* blocked until all consumers have released it.
|
|
80
|
+
*/
|
|
53
81
|
return (0, _createClass2.default)(ObjectURLCache, [{
|
|
82
|
+
key: "acquire",
|
|
83
|
+
value: function acquire(key) {
|
|
84
|
+
var _this$activeRefs$get;
|
|
85
|
+
this.activeRefs.set(key, ((_this$activeRefs$get = this.activeRefs.get(key)) !== null && _this$activeRefs$get !== void 0 ? _this$activeRefs$get : 0) + 1);
|
|
86
|
+
}
|
|
87
|
+
}, {
|
|
88
|
+
key: "release",
|
|
89
|
+
value: function release(key) {
|
|
90
|
+
var _this$activeRefs$get2;
|
|
91
|
+
var count = (_this$activeRefs$get2 = this.activeRefs.get(key)) !== null && _this$activeRefs$get2 !== void 0 ? _this$activeRefs$get2 : 0;
|
|
92
|
+
if (count <= 1) {
|
|
93
|
+
this.activeRefs.delete(key);
|
|
94
|
+
} else {
|
|
95
|
+
this.activeRefs.set(key, count - 1);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}, {
|
|
99
|
+
key: "isInUse",
|
|
100
|
+
value: function isInUse(key) {
|
|
101
|
+
var _this$activeRefs$get3;
|
|
102
|
+
return ((_this$activeRefs$get3 = this.activeRefs.get(key)) !== null && _this$activeRefs$get3 !== void 0 ? _this$activeRefs$get3 : 0) > 0;
|
|
103
|
+
}
|
|
104
|
+
}, {
|
|
54
105
|
key: "has",
|
|
55
106
|
value: function has(key) {
|
|
56
107
|
return !!this.cache.find(key);
|
|
@@ -69,7 +120,9 @@ var ObjectURLCache = exports.ObjectURLCache = /*#__PURE__*/function () {
|
|
|
69
120
|
key: "remove",
|
|
70
121
|
value: function remove(key) {
|
|
71
122
|
var removed = this.cache.delete(key);
|
|
72
|
-
|
|
123
|
+
this.activeRefs.delete(key);
|
|
124
|
+
var dataURI = (0, _platformFeatureFlags.fg)('platform_media_safe_blob_url_eviction') ? removed === null || removed === void 0 ? void 0 : removed.dataURI.split('#')[0] : removed === null || removed === void 0 ? void 0 : removed.dataURI;
|
|
125
|
+
dataURI && URL.revokeObjectURL(dataURI);
|
|
73
126
|
}
|
|
74
127
|
}, {
|
|
75
128
|
key: "clear",
|
|
@@ -53,54 +53,20 @@ var useFilePreview = exports.useFilePreview = function useFilePreview(_ref) {
|
|
|
53
53
|
setStatus = _useState2[1];
|
|
54
54
|
var _useState3 = (0, _react.useState)(),
|
|
55
55
|
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
// Fetch clientId on mount for cross-client copy
|
|
60
|
-
(0, _react.useEffect)(function () {
|
|
61
|
-
if ((0, _platformFeatureFlags.fg)('platform_media_cross_client_copy_with_auth')) {
|
|
62
|
-
mediaClient.getClientId(identifier.collectionName).then(setClientId).catch(function () {
|
|
63
|
-
// ClientId is optional, silently fail
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
}, [mediaClient, identifier.collectionName]);
|
|
67
|
-
|
|
68
|
-
// Merge clientId into mediaBlobUrlAttrs for embedding in blob URLs
|
|
69
|
-
// If mediaBlobUrlAttrs is not provided, construct minimal attrs from identifier
|
|
70
|
-
var mediaBlobUrlAttrsWithClientId = (0, _react.useMemo)(function () {
|
|
71
|
-
if (!(0, _platformFeatureFlags.fg)('platform_media_cross_client_copy_with_auth') || !clientId) {
|
|
72
|
-
return mediaBlobUrlAttrs;
|
|
73
|
-
}
|
|
74
|
-
if (mediaBlobUrlAttrs) {
|
|
75
|
-
return _objectSpread(_objectSpread({}, mediaBlobUrlAttrs), {}, {
|
|
76
|
-
clientId: clientId
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Construct minimal attrs when none provided (e.g., MediaImage)
|
|
81
|
-
return {
|
|
82
|
-
id: identifier.id,
|
|
83
|
-
clientId: clientId,
|
|
84
|
-
contextId: identifier.collectionName || '',
|
|
85
|
-
collection: identifier.collectionName
|
|
86
|
-
};
|
|
87
|
-
}, [mediaBlobUrlAttrs, clientId, identifier.id, identifier.collectionName]);
|
|
56
|
+
error = _useState4[0],
|
|
57
|
+
setError = _useState4[1];
|
|
88
58
|
var _useState5 = (0, _react.useState)(),
|
|
89
59
|
_useState6 = (0, _slicedToArray2.default)(_useState5, 2),
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
var _useState7 = (0, _react.useState)(),
|
|
60
|
+
nonCriticalError = _useState6[0],
|
|
61
|
+
setNonCriticalError = _useState6[1];
|
|
62
|
+
var _useState7 = (0, _react.useState)(false),
|
|
93
63
|
_useState8 = (0, _slicedToArray2.default)(_useState7, 2),
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
var _useState9 = (0, _react.useState)(
|
|
64
|
+
isBannedLocalPreview = _useState8[0],
|
|
65
|
+
setIsBannedLocalPreview = _useState8[1];
|
|
66
|
+
var _useState9 = (0, _react.useState)('not-resolved'),
|
|
97
67
|
_useState0 = (0, _slicedToArray2.default)(_useState9, 2),
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
var _useState1 = (0, _react.useState)('not-resolved'),
|
|
101
|
-
_useState10 = (0, _slicedToArray2.default)(_useState1, 2),
|
|
102
|
-
upfrontPreviewStatus = _useState10[0],
|
|
103
|
-
setUpfrontPreviewStatus = _useState10[1];
|
|
68
|
+
upfrontPreviewStatus = _useState0[0],
|
|
69
|
+
setUpfrontPreviewStatus = _useState0[1];
|
|
104
70
|
var ssrReliabilityRef = (0, _react.useRef)({
|
|
105
71
|
server: {
|
|
106
72
|
status: 'unknown'
|
|
@@ -110,10 +76,10 @@ var useFilePreview = exports.useFilePreview = function useFilePreview(_ref) {
|
|
|
110
76
|
}
|
|
111
77
|
});
|
|
112
78
|
var ufoContext = (0, _interactionContext.useInteractionContext)();
|
|
113
|
-
var
|
|
114
|
-
|
|
115
|
-
isLoading =
|
|
116
|
-
setIsLoading =
|
|
79
|
+
var _useState1 = (0, _react.useState)(false),
|
|
80
|
+
_useState10 = (0, _slicedToArray2.default)(_useState1, 2),
|
|
81
|
+
isLoading = _useState10[0],
|
|
82
|
+
setIsLoading = _useState10[1];
|
|
117
83
|
(0, _react.useLayoutEffect)(function () {
|
|
118
84
|
if (isLoading && (0, _platformFeatureFlags.fg)('platform_close_image_blindspot_2')) {
|
|
119
85
|
return ufoContext === null || ufoContext === void 0 ? void 0 : ufoContext.hold('img-loading');
|
|
@@ -156,7 +122,7 @@ var useFilePreview = exports.useFilePreview = function useFilePreview(_ref) {
|
|
|
156
122
|
// where no SSR occurred, so we should skip SSR preview generation entirely.
|
|
157
123
|
if (ssr === 'server' || ssrData) {
|
|
158
124
|
try {
|
|
159
|
-
return (0, _getPreview.getSSRPreview)(ssr, mediaClient, identifier.id, imageURLParams,
|
|
125
|
+
return (0, _getPreview.getSSRPreview)(ssr, mediaClient, identifier.id, imageURLParams, mediaBlobUrlAttrs);
|
|
160
126
|
} catch (e) {
|
|
161
127
|
ssrReliabilityRef.current = _objectSpread(_objectSpread({}, ssrReliabilityRef.current), {}, (0, _defineProperty2.default)({}, ssr, _objectSpread({
|
|
162
128
|
status: 'fail'
|
|
@@ -178,10 +144,10 @@ var useFilePreview = exports.useFilePreview = function useFilePreview(_ref) {
|
|
|
178
144
|
}
|
|
179
145
|
}
|
|
180
146
|
};
|
|
181
|
-
var
|
|
182
|
-
|
|
183
|
-
preview =
|
|
184
|
-
setPreview =
|
|
147
|
+
var _useState11 = (0, _react.useState)(previewInitializer),
|
|
148
|
+
_useState12 = (0, _slicedToArray2.default)(_useState11, 2),
|
|
149
|
+
preview = _useState12[0],
|
|
150
|
+
setPreview = _useState12[1];
|
|
185
151
|
|
|
186
152
|
//----------------------------------------------------------------
|
|
187
153
|
// FILE STATE
|
|
@@ -248,29 +214,11 @@ var useFilePreview = exports.useFilePreview = function useFilePreview(_ref) {
|
|
|
248
214
|
}
|
|
249
215
|
}, [preview, identifier, resizeMode]);
|
|
250
216
|
|
|
251
|
-
//----------------------------------------------------------------
|
|
252
|
-
// Update preview with clientId when it becomes available
|
|
253
|
-
//----------------------------------------------------------------
|
|
254
|
-
var previewUpdatedWithClientIdRef = (0, _react.useRef)(null);
|
|
255
|
-
(0, _react.useEffect)(function () {
|
|
256
|
-
// Only update if we have a preview, clientId is available, URL doesn't already have clientId, and feature flag is enabled.
|
|
257
|
-
// Also skip if we've already updated this preview (prevents re-render loops)
|
|
258
|
-
if (preview && clientId && mediaBlobUrlAttrsWithClientId && !preview.dataURI.includes('clientId=') && previewUpdatedWithClientIdRef.current !== identifier.id && (0, _platformFeatureFlags.fg)('platform_media_cross_client_copy_with_auth')) {
|
|
259
|
-
// Mark this preview as updated
|
|
260
|
-
previewUpdatedWithClientIdRef.current = identifier.id;
|
|
261
|
-
var baseUrl = preview.dataURI.split('#')[0]; // Remove any existing hash
|
|
262
|
-
var updatedDataURI = (0, _mediaClient.addFileAttrsToUrl)(baseUrl, mediaBlobUrlAttrsWithClientId);
|
|
263
|
-
setPreview(_objectSpread(_objectSpread({}, preview), {}, {
|
|
264
|
-
dataURI: updatedDataURI
|
|
265
|
-
}));
|
|
266
|
-
}
|
|
267
|
-
}, [clientId, mediaBlobUrlAttrsWithClientId, preview, identifier.id]);
|
|
268
|
-
|
|
269
217
|
//----------------------------------------------------------------
|
|
270
218
|
// Preview Fetch Helper
|
|
271
219
|
//----------------------------------------------------------------
|
|
272
220
|
var getAndCacheRemotePreviewRef = (0, _helpers.useCurrentValueRef)(function () {
|
|
273
|
-
return (0, _getPreview.getAndCacheRemotePreview)(mediaClient, identifier.id, requestDimensions || {}, imageURLParams,
|
|
221
|
+
return (0, _getPreview.getAndCacheRemotePreview)(mediaClient, identifier.id, requestDimensions || {}, imageURLParams, mediaBlobUrlAttrs, traceContext);
|
|
274
222
|
});
|
|
275
223
|
|
|
276
224
|
//----------------------------------------------------------------
|
|
@@ -305,7 +253,7 @@ var useFilePreview = exports.useFilePreview = function useFilePreview(_ref) {
|
|
|
305
253
|
// Cache, Local & Remote Preview
|
|
306
254
|
//----------------------------------------------------------------
|
|
307
255
|
|
|
308
|
-
var mediaBlobUrlAttrsRef = (0, _helpers.useCurrentValueRef)(
|
|
256
|
+
var mediaBlobUrlAttrsRef = (0, _helpers.useCurrentValueRef)(mediaBlobUrlAttrs);
|
|
309
257
|
(0, _react.useEffect)(function () {
|
|
310
258
|
var cachedPreview = _getPreview.mediaFilePreviewCache.get(identifier.id, resizeMode);
|
|
311
259
|
|
|
@@ -319,7 +267,7 @@ var useFilePreview = exports.useFilePreview = function useFilePreview(_ref) {
|
|
|
319
267
|
// For example, SVGs are mime type NOT supported by browser but media type supported by Media Card (image)
|
|
320
268
|
// Then, local Preview NOT available
|
|
321
269
|
setIsLoading(true);
|
|
322
|
-
(0, _getPreview.getAndCacheLocalPreview)(identifier.id, localBinary, requestDimensions || {}, resizeMode, mediaBlobUrlAttrsRef.current).then(setPreview).catch(function (e) {
|
|
270
|
+
(0, _getPreview.getAndCacheLocalPreview)(mediaClient, identifier.id, localBinary, requestDimensions || {}, resizeMode, mediaBlobUrlAttrsRef.current, identifier.collectionName).then(setPreview).catch(function (e) {
|
|
323
271
|
setIsBannedLocalPreview(true);
|
|
324
272
|
// CXP-2723 TODO: We might have to wrap this error in MediaCardError
|
|
325
273
|
setNonCriticalError(e);
|
|
@@ -350,7 +298,19 @@ var useFilePreview = exports.useFilePreview = function useFilePreview(_ref) {
|
|
|
350
298
|
setIsLoading(false);
|
|
351
299
|
});
|
|
352
300
|
}
|
|
353
|
-
}, [error, nonCriticalError, getAndCacheRemotePreviewRef, identifier.id, resizeMode, isBannedLocalPreview, mediaBlobUrlAttrsRef, preview, requestDimensions, skipRemote, isBackendPreviewReady, localBinary, mediaType, mimeType, upfrontPreviewStatus, dimensions]);
|
|
301
|
+
}, [error, nonCriticalError, getAndCacheRemotePreviewRef, identifier.id, identifier.collectionName, resizeMode, isBannedLocalPreview, mediaBlobUrlAttrsRef, mediaClient, preview, requestDimensions, skipRemote, isBackendPreviewReady, localBinary, mediaType, mimeType, upfrontPreviewStatus, dimensions]);
|
|
302
|
+
|
|
303
|
+
//----------------------------------------------------------------
|
|
304
|
+
// Cache ref tracking — prevent blob URL eviction while mounted
|
|
305
|
+
//----------------------------------------------------------------
|
|
306
|
+
(0, _react.useEffect)(function () {
|
|
307
|
+
if (preview) {
|
|
308
|
+
_getPreview.mediaFilePreviewCache.acquire(identifier.id, resizeMode);
|
|
309
|
+
return function () {
|
|
310
|
+
_getPreview.mediaFilePreviewCache.release(identifier.id, resizeMode);
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
}, [preview, identifier.id, resizeMode]);
|
|
354
314
|
|
|
355
315
|
//----------------------------------------------------------------
|
|
356
316
|
// RETURN
|
|
@@ -467,7 +427,6 @@ var useFilePreview = exports.useFilePreview = function useFilePreview(_ref) {
|
|
|
467
427
|
onImageError: onImageError,
|
|
468
428
|
onImageLoad: onImageLoad,
|
|
469
429
|
getSsrScriptProps: getSsrScriptProps,
|
|
470
|
-
copyNodeRef: copyNodeRef
|
|
471
|
-
clientId: clientId
|
|
430
|
+
copyNodeRef: copyNodeRef
|
|
472
431
|
};
|
|
473
432
|
};
|
|
@@ -25,6 +25,14 @@ export class CardPreviewCacheImpl {
|
|
|
25
25
|
_defineProperty(this, "clear", () => {
|
|
26
26
|
this.previewCache.clear();
|
|
27
27
|
});
|
|
28
|
+
_defineProperty(this, "acquire", (id, mode) => {
|
|
29
|
+
const cacheKey = getCacheKey(id, mode);
|
|
30
|
+
this.previewCache.acquire(cacheKey);
|
|
31
|
+
});
|
|
32
|
+
_defineProperty(this, "release", (id, mode) => {
|
|
33
|
+
const cacheKey = getCacheKey(id, mode);
|
|
34
|
+
this.previewCache.release(cacheKey);
|
|
35
|
+
});
|
|
28
36
|
this.previewCache = previewCache;
|
|
29
37
|
}
|
|
30
38
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { addFileAttrsToUrl } from '@atlaskit/media-client';
|
|
2
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
2
3
|
import { SsrPreviewError } from '../errors';
|
|
3
4
|
import { mediaFilePreviewCache } from './cache';
|
|
4
5
|
import { getLocalPreview, getRemotePreview } from './helpers';
|
|
@@ -31,16 +32,43 @@ const getDataUri = (mediaClient, id, params, mediaBlobUrlAttrs) => {
|
|
|
31
32
|
const rawDataURI = mediaClient.getImageUrlSync(id, params);
|
|
32
33
|
return mediaBlobUrlAttrs ? addFileAttrsToUrl(rawDataURI, mediaBlobUrlAttrs) : rawDataURI;
|
|
33
34
|
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Merges a clientId into mediaBlobUrlAttrs for cross-client copy support.
|
|
38
|
+
* Returns the original attrs unchanged if clientId is not available or the feature flag is off.
|
|
39
|
+
*/
|
|
40
|
+
const mergeClientIdIntoAttrs = (clientId, id, mediaBlobUrlAttrs, collectionName) => {
|
|
41
|
+
if (!clientId) {
|
|
42
|
+
return mediaBlobUrlAttrs;
|
|
43
|
+
}
|
|
44
|
+
if (mediaBlobUrlAttrs) {
|
|
45
|
+
return {
|
|
46
|
+
...mediaBlobUrlAttrs,
|
|
47
|
+
clientId
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Construct minimal attrs when none provided
|
|
52
|
+
return {
|
|
53
|
+
id,
|
|
54
|
+
clientId,
|
|
55
|
+
contextId: collectionName || '',
|
|
56
|
+
collection: collectionName
|
|
57
|
+
};
|
|
58
|
+
};
|
|
34
59
|
export const getSSRPreview = (ssr, mediaClient, id, params, mediaBlobUrlAttrs) => {
|
|
35
60
|
try {
|
|
36
|
-
|
|
61
|
+
// Synchronously extract clientId from initialAuth and merge into blob URL attrs
|
|
62
|
+
const clientId = fg('platform_media_cross_client_copy_with_auth') ? mediaClient.getClientIdSync() : undefined;
|
|
63
|
+
const attrsWithClientId = mergeClientIdIntoAttrs(clientId, id, mediaBlobUrlAttrs, params.collection);
|
|
64
|
+
const dataURI = getDataUri(mediaClient, id, params, attrsWithClientId);
|
|
37
65
|
let srcSet = `${dataURI} 1x`;
|
|
38
66
|
if (params.width) {
|
|
39
67
|
const doubleDataURI = getDataUri(mediaClient, id, {
|
|
40
68
|
...params,
|
|
41
69
|
width: params.width * 2,
|
|
42
70
|
height: params.height && params.height * 2
|
|
43
|
-
},
|
|
71
|
+
}, attrsWithClientId);
|
|
44
72
|
// We want to embed some meta context into dataURI for Copy/Paste to work.
|
|
45
73
|
srcSet += `, ${doubleDataURI} 2x`;
|
|
46
74
|
}
|
|
@@ -70,17 +98,38 @@ export const isSSRPreview = preview => {
|
|
|
70
98
|
const ssrClientSources = ['ssr-client', 'ssr-server', 'ssr-data'];
|
|
71
99
|
return ssrClientSources.includes(preview.source);
|
|
72
100
|
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Resolves clientId (sync first, async fallback) and enriches mediaBlobUrlAttrs
|
|
104
|
+
* with it for cross-client copy support.
|
|
105
|
+
*/
|
|
106
|
+
const enrichAttrsWithClientId = async (mediaClient, id, mediaBlobUrlAttrs, collectionName) => {
|
|
107
|
+
if (!fg('platform_media_cross_client_copy_with_auth')) {
|
|
108
|
+
return mediaBlobUrlAttrs;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Try sync first, then async fallback
|
|
112
|
+
let clientId = mediaClient.getClientIdSync();
|
|
113
|
+
if (!clientId) {
|
|
114
|
+
try {
|
|
115
|
+
clientId = await mediaClient.getClientId(collectionName);
|
|
116
|
+
} catch {
|
|
117
|
+
// clientId is optional, silently fail
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return mergeClientIdIntoAttrs(clientId, id, mediaBlobUrlAttrs, collectionName);
|
|
121
|
+
};
|
|
73
122
|
export const getAndCacheRemotePreview = async (mediaClient, id, dimensions, params, mediaBlobUrlAttrs, traceContext) => {
|
|
74
|
-
const remotePreview = await getRemotePreview(mediaClient, id, params, traceContext);
|
|
123
|
+
const [remotePreview, enrichedAttrs] = await Promise.all([getRemotePreview(mediaClient, id, params, traceContext), enrichAttrsWithClientId(mediaClient, id, mediaBlobUrlAttrs, params.collection)]);
|
|
75
124
|
return extendAndCachePreview(id, params.mode, {
|
|
76
125
|
...remotePreview,
|
|
77
126
|
dimensions
|
|
78
|
-
},
|
|
127
|
+
}, enrichedAttrs);
|
|
79
128
|
};
|
|
80
|
-
export const getAndCacheLocalPreview = async (id, filePreview, dimensions, mode, mediaBlobUrlAttrs) => {
|
|
81
|
-
const localPreview = await getLocalPreview(filePreview);
|
|
129
|
+
export const getAndCacheLocalPreview = async (mediaClient, id, filePreview, dimensions, mode, mediaBlobUrlAttrs, collectionName) => {
|
|
130
|
+
const [localPreview, enrichedAttrs] = await Promise.all([getLocalPreview(filePreview), enrichAttrsWithClientId(mediaClient, id, mediaBlobUrlAttrs, collectionName)]);
|
|
82
131
|
return extendAndCachePreview(id, mode, {
|
|
83
132
|
...localPreview,
|
|
84
133
|
dimensions
|
|
85
|
-
},
|
|
134
|
+
}, enrichedAttrs);
|
|
86
135
|
};
|